1 /*
2 * Author: William Chia-Wei Cheng (bill.cheng@acm.org)
3 *
4 * Copyright (C) 2001-2009, William Chia-Wei Cheng.
5 *
6 * This file may be distributed under the terms of the Q Public License
7 * as defined by Trolltech AS of Norway and appearing in the file
8 * LICENSE.QPL included in the packaging of this file.
9 *
10 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING
11 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
12 * PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
13 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
14 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
16 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * @(#)$Header: /mm2/home/cvs/bc-src/tgif/select.c,v 1.26 2011/05/16 16:21:59 william Exp $
19 */
20
21 #define _INCLUDE_FROM_SELECT_C_
22
23 #include "tgifdefs.h"
24
25 #include "attr.e"
26 #include "auxtext.e"
27 #include "button.e"
28 #include "choice.e"
29 #include "cmd.e"
30 #include "color.e"
31 #include "cursor.e"
32 #include "dialog.e"
33 #include "drawing.e"
34 #include "dup.e"
35 #include "edit.e"
36 #include "exec.e"
37 #include "file.e"
38 #include "font.e"
39 #include "grid.e"
40 #include "group.e"
41 #include "http.e"
42 #include "mainloop.e"
43 #include "mark.e"
44 #include "menu.e"
45 #include "miniline.e"
46 #include "move.e"
47 #include "msg.e"
48 #include "names.e"
49 #include "navigate.e"
50 #include "obj.e"
51 #include "page.e"
52 #include "pin.e"
53 #include "poly.e"
54 #include "raster.e"
55 #include "rect.e"
56 #include "remote.e"
57 #include "ruler.e"
58 #include "scroll.e"
59 #include "select.e"
60 #include "setup.e"
61 #include "special.e"
62 #include "stk.e"
63 #include "stretch.e"
64 #include "strtbl.e"
65 #include "util.e"
66
67 #define FORWARD 0
68 #define REVERSE 1
69
70 int selLtX=0, selLtY=0, selRbX=0, selRbY=0;
71 int selObjLtX=0, selObjLtY=0, selObjRbX=0, selObjRbY=0;
72 int selNoLockLtX=0, selNoLockLtY=0, selNoLockRbX=0, selNoLockRbY=0;
73 int selNoLockObjLtX=0, selNoLockObjLtY=0;
74 int selNoLockObjRbX=0, selNoLockObjRbY=0;
75 int numObjSelected=0;
76 int numObjLocked=0;
77 struct SelRec *topSel=NULL, *botSel=NULL;
78 struct VSelRec *topVSel=NULL, *botVSel=NULL;
79
GetObjCurved(ObjPtr)80 int GetObjCurved(ObjPtr)
81 struct ObjRec *ObjPtr;
82 {
83 switch (ObjPtr->type) {
84 case OBJ_POLY: return ObjPtr->detail.p->curved;
85 case OBJ_POLYGON: return ObjPtr->detail.g->curved;
86 }
87 #ifdef _TGIF_DBG /* debug, do not translate */
88 TgAssert(FALSE, "Unexpected object type in GetObjCurved()", NULL);
89 #endif /* _TGIF_DBG */
90 return 0;
91 }
92
SelectThisObject(ObjPtr)93 struct SelRec *SelectThisObject(ObjPtr)
94 struct ObjRec *ObjPtr;
95 {
96 struct SelRec *sel_ptr=(struct SelRec *)malloc(sizeof(struct SelRec));
97
98 if (sel_ptr == NULL) FailAllocMessage();
99 memset(sel_ptr, 0, sizeof(struct SelRec));
100 sel_ptr->obj = ObjPtr;
101 return sel_ptr;
102 }
103
CountSelectedVertices()104 int CountSelectedVertices()
105 {
106 struct VSelRec *vsel_ptr;
107 int count = 0;
108
109 for (vsel_ptr=topVSel; vsel_ptr != NULL; vsel_ptr=vsel_ptr->next) {
110 int curved=GetObjCurved(vsel_ptr->obj);
111
112 if (curved == LT_STRUCT_SPLINE) {
113 /* can select at most one vertex for LT_STRUCT_SPLINE */
114 count++;
115 } else {
116 int n=vsel_ptr->n;
117
118 count += n;
119 if (vsel_ptr->obj->type == OBJ_POLYGON) {
120 int i=0;
121
122 for (i=0; i < n; i++) {
123 if (vsel_ptr->v_index[i] == 0) {
124 count--;
125 break;
126 }
127 }
128 }
129 }
130 }
131 return count;
132 }
133
CalcBBox(X1,Y1,X2,Y2,LtX,LtY,RbX,RbY)134 void CalcBBox(X1, Y1, X2, Y2, LtX, LtY, RbX, RbY)
135 int X1, Y1, X2, Y2, * LtX, * LtY, * RbX, * RbY;
136 {
137 if (X1 < X2) {
138 if (Y1 < Y2) {
139 *LtX = X1; *LtY = Y1; *RbX = X2; *RbY = Y2;
140 } else {
141 *LtX = X1; *LtY = Y2; *RbX = X2; *RbY = Y1;
142 }
143 } else {
144 if (Y1 < Y2) {
145 *LtX = X2; *LtY = Y1; *RbX = X1; *RbY = Y2;
146 } else {
147 *LtX = X2; *LtY = Y2; *RbX = X1; *RbY = Y1;
148 }
149 }
150 }
151
CalcVertexBBox(LtX,LtY,RbX,RbY)152 void CalcVertexBBox(LtX, LtY, RbX, RbY)
153 int *LtX, *LtY, *RbX, *RbY;
154 {
155 register int i, *x_ptr, *y_ptr;
156 struct VSelRec *vsel_ptr;
157
158 *LtX = selRbX; *LtY = selRbY; *RbX = selLtX; *RbY = selLtY;
159
160 for (vsel_ptr=topVSel; vsel_ptr!=NULL; vsel_ptr=vsel_ptr->next) {
161 for (i=0, x_ptr=vsel_ptr->x, y_ptr=vsel_ptr->y; i < vsel_ptr->n;
162 i++, x_ptr++, y_ptr++) {
163 if (*x_ptr < *LtX) *LtX = *x_ptr;
164 if (*y_ptr < *LtY) *LtY = *y_ptr;
165 if (*x_ptr > *RbX) *RbX = *x_ptr;
166 if (*y_ptr > *RbY) *RbY = *y_ptr;
167 }
168 }
169 }
170
UnSelNonVertexObjs(highlight,no_locked_obj_only)171 void UnSelNonVertexObjs(highlight, no_locked_obj_only)
172 int highlight, no_locked_obj_only;
173 {
174 register struct ObjRec *obj_ptr;
175 register struct SelRec *sel_ptr, *prev_sel;
176
177 for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=prev_sel) {
178 prev_sel = sel_ptr->prev;
179 obj_ptr = sel_ptr->obj;
180
181 if ((obj_ptr->type==OBJ_POLY || obj_ptr->type==OBJ_POLYGON) &&
182 (!no_locked_obj_only || !obj_ptr->locked)) {
183 continue;
184 }
185 if (highlight) HighLightAnObj(obj_ptr);
186
187 if (sel_ptr->prev == NULL) {
188 topSel = sel_ptr->next;
189 } else {
190 sel_ptr->prev->next = sel_ptr->next;
191 }
192 if (sel_ptr->next == NULL) {
193 botSel = sel_ptr->prev;
194 } else {
195 sel_ptr->next->prev = sel_ptr->prev;
196 }
197 free(sel_ptr);
198 }
199 }
200
FreeTopSel()201 void FreeTopSel()
202 {
203 struct SelRec *sel_ptr=topSel;
204
205 topSel = topSel->next;
206 if (topSel != NULL) {
207 topSel->prev = NULL;
208 } else {
209 botSel = NULL;
210 }
211 free(sel_ptr);
212 numObjSelected--;
213 UpdSelBBox();
214 }
215
JustFreeSel(pTopSel,pBotSel)216 void JustFreeSel(pTopSel, pBotSel)
217 struct SelRec *pTopSel, *pBotSel;
218 {
219 struct SelRec *pNextSel=NULL;
220
221 for ( ; pTopSel != NULL; pTopSel=pNextSel) {
222 pNextSel = pTopSel->next;
223 free(pTopSel);
224 }
225 }
226
UnlinkSel(pSel,ppTopSel,ppBotSel)227 void UnlinkSel(pSel, ppTopSel, ppBotSel)
228 struct SelRec *pSel, **ppTopSel, **ppBotSel;
229 {
230 if ((*ppTopSel) == pSel) {
231 (*ppTopSel) = pSel->next;
232 } else {
233 pSel->prev->next = pSel->next;
234 }
235 if ((*ppBotSel) == pSel) {
236 (*ppBotSel) = pSel->prev;
237 } else {
238 pSel->next->prev = pSel->prev;
239 }
240 }
241
FindObjInSel(pObj,pTopSel,pBotSel)242 struct SelRec *FindObjInSel(pObj, pTopSel, pBotSel)
243 struct ObjRec *pObj;
244 struct SelRec *pTopSel, *pBotSel;
245 {
246 for ( ; pTopSel != NULL; pTopSel=pTopSel->next) {
247 if (pTopSel->obj == pObj) {
248 return pTopSel;
249 }
250 }
251 return NULL;
252 }
253
PrependObjToSel(pObj,ppTopSel,ppBotSel)254 int PrependObjToSel(pObj, ppTopSel, ppBotSel)
255 struct ObjRec *pObj;
256 struct SelRec **ppTopSel, **ppBotSel;
257 {
258 int nReturn=TRUE;
259 struct SelRec *pSel=(struct SelRec *)malloc(sizeof(struct SelRec));
260
261 if (pSel == NULL) {
262 FailAllocMessage();
263 nReturn = FALSE;
264 }
265 memset(pSel, 0, sizeof(struct SelRec));
266 pSel->obj = pObj;
267 pSel->next = (*ppTopSel);
268 pSel->prev = NULL;
269 if ((*ppTopSel) == NULL) {
270 (*ppBotSel) = pSel;
271 } else {
272 (*ppTopSel)->prev = pSel;
273 }
274 (*ppTopSel) = pSel;
275 return nReturn;
276 }
277
AddObjIntoSel(pObj,pPrevSel,pNextSel,ppTopSel,ppBotSel)278 struct SelRec *AddObjIntoSel(pObj, pPrevSel, pNextSel, ppTopSel, ppBotSel)
279 struct ObjRec *pObj;
280 struct SelRec *pPrevSel, *pNextSel, **ppTopSel, **ppBotSel;
281 {
282 struct SelRec *pSel=(struct SelRec *)malloc(sizeof(struct SelRec));
283
284 if (pSel == NULL) {
285 FailAllocMessage();
286 return NULL;
287 }
288 memset(pSel, 0, sizeof(struct SelRec));
289 pSel->obj = pObj;
290 pSel->next = pNextSel;
291 pSel->prev = pPrevSel;
292 if (pPrevSel == NULL) {
293 (*ppTopSel) = pSel;
294 } else {
295 pPrevSel->next = pSel;
296 }
297 if (pNextSel == NULL) {
298 (*ppBotSel) = pSel;
299 } else {
300 pNextSel->prev = pSel;
301 }
302 return pSel;
303 }
304
JustRemoveAllVSel()305 void JustRemoveAllVSel()
306 {
307 register struct VSelRec *next_vsel;
308
309 while (topVSel != NULL) {
310 next_vsel = topVSel->next;
311 free(topVSel->v_index);
312 free(topVSel->x);
313 free(topVSel->y);
314 free(topVSel);
315 topVSel = next_vsel;
316 }
317 botVSel = NULL;
318 }
319
RemoveAllSel()320 void RemoveAllSel()
321 {
322 register struct SelRec *next_sel;
323 register struct VSelRec *next_vsel;
324
325 while (topSel != NULL) {
326 next_sel = topSel->next;
327 free(topSel);
328 topSel = next_sel;
329 }
330 botSel = NULL;
331
332 while (topVSel != NULL) {
333 next_vsel = topVSel->next;
334 free(topVSel->v_index);
335 free(topVSel->x);
336 free(topVSel->y);
337 free(topVSel);
338 topVSel = next_vsel;
339 }
340 botVSel = NULL;
341 numObjSelected = 0;
342 }
343
FindObjAttrWithName(ObjPtr,AttrName)344 struct AttrRec *FindObjAttrWithName(ObjPtr, AttrName)
345 struct ObjRec *ObjPtr;
346 char *AttrName;
347 /* AttrName here must not contain '.' */
348 {
349 register struct AttrRec *attr_ptr;
350 struct AttrRec *found_attr=NULL;
351 int count=1, compare_name=(strchr(AttrName,'=') != NULL);
352
353 if (ObjPtr == NULL) return NULL;
354
355 for (attr_ptr=ObjPtr->fattr; attr_ptr!=NULL; attr_ptr=attr_ptr->next) {
356 if (compare_name) {
357 if (strcmp(attr_ptr->attr_name.s, AttrName) == 0) {
358 found_attr = attr_ptr;
359 break;
360 }
361 } else {
362 if (strcmp(attr_ptr->attr_value.s, AttrName) == 0) {
363 found_attr = attr_ptr;
364 break;
365 }
366 }
367 }
368 if (attr_ptr == NULL) return NULL;
369
370 if (GetTextObjFirstStrSeg(found_attr->obj)->color == colorIndex) {
371 return found_attr;
372 }
373 for (attr_ptr=found_attr->next; attr_ptr!=NULL; attr_ptr=attr_ptr->next) {
374 if (compare_name) {
375 if (strcmp(attr_ptr->attr_name.s, AttrName) == 0) {
376 if (GetTextObjFirstStrSeg(attr_ptr->obj)->color == colorIndex) {
377 break;
378 } else if (GetTextObjFirstStrSeg(attr_ptr->obj)->color ==
379 GetTextObjFirstStrSeg(found_attr->obj)->color) {
380 /* same color as found_attr's color, so don't increase count */
381 } else {
382 count++;
383 }
384 }
385 } else {
386 if (strcmp(attr_ptr->attr_value.s, AttrName) == 0) {
387 if (GetTextObjFirstStrSeg(attr_ptr->obj)->color == colorIndex) {
388 break;
389 } else if (GetTextObjFirstStrSeg(attr_ptr->obj)->color ==
390 GetTextObjFirstStrSeg(found_attr->obj)->color) {
391 /* same color as found_attr's color, so don't increase count */
392 } else {
393 count++;
394 }
395 }
396 }
397 }
398 if (attr_ptr != NULL) {
399 found_attr = attr_ptr;
400 } else if (count != 1) {
401 sprintf(gszMsgBox, TgLoadCachedString(CSTID_CANT_FIND_ATTR_WITH_COLOR),
402 AttrName, colorMenuItems[colorIndex]);
403 Msg(gszMsgBox);
404 return NULL;
405 }
406 return found_attr;
407 }
408
409 static
FindAVertex(XOff,YOff,VIndex,AbsX,AbsY)410 struct ObjRec *FindAVertex(XOff, YOff, VIndex, AbsX, AbsY)
411 int XOff, YOff, *VIndex, *AbsX, *AbsY;
412 /* XOff and YOff are screen offsets */
413 {
414 struct SelRec *sel_ptr;
415
416 for (sel_ptr=topSel; sel_ptr != NULL; sel_ptr=sel_ptr->next) {
417 struct ObjRec *obj_ptr=sel_ptr->obj;
418 struct PolyRec *poly_ptr=NULL;
419 struct PolygonRec *polygon_ptr=NULL;
420 int n=0;
421 IntPoint *vs=NULL;
422
423 if (obj_ptr->type != OBJ_POLY && obj_ptr->type != OBJ_POLYGON) continue;
424 if (!(XOff >= OFFSET_X(obj_ptr->bbox.ltx)-3 &&
425 YOff >= OFFSET_Y(obj_ptr->bbox.lty)-3 &&
426 XOff <= OFFSET_X(obj_ptr->bbox.rbx)+3 &&
427 YOff <= OFFSET_Y(obj_ptr->bbox.rby)+3)) {
428 continue;
429 }
430
431 switch (obj_ptr->type) {
432 case OBJ_POLY:
433 poly_ptr = obj_ptr->detail.p;
434 if (poly_ptr->curved == LT_STRUCT_SPLINE) {
435 n = poly_ptr->ssn;
436 vs = poly_ptr->ssvlist;
437 } else {
438 n = poly_ptr->n;
439 vs = poly_ptr->vlist;
440 }
441 if (PtInPolyMark(obj_ptr, XOff, YOff, n, vs, VIndex)) {
442 if (obj_ptr->ctm == NULL) {
443 *AbsX = vs[*VIndex].x;
444 *AbsY = vs[*VIndex].y;
445 } else {
446 int x, y;
447
448 TransformPointThroughCTM( vs[*VIndex].x-obj_ptr->x,
449 vs[*VIndex].y-obj_ptr->y, obj_ptr->ctm, &x, &y);
450 *AbsX = x+obj_ptr->x;
451 *AbsY = y+obj_ptr->y;
452 }
453 return obj_ptr;
454 }
455 break;
456 case OBJ_POLYGON:
457 polygon_ptr = obj_ptr->detail.g;
458 if (polygon_ptr->curved == LT_STRUCT_SPLINE) {
459 n = polygon_ptr->ssn;
460 vs = polygon_ptr->ssvlist;
461 } else {
462 n = polygon_ptr->n;
463 vs = polygon_ptr->vlist;
464 }
465 if (PtInPolyMark(obj_ptr, XOff, YOff, n, vs, VIndex)) {
466 if (obj_ptr->ctm == NULL) {
467 *AbsX = vs[*VIndex].x;
468 *AbsY = vs[*VIndex].y;
469 } else {
470 int x, y;
471
472 TransformPointThroughCTM(vs[*VIndex].x-obj_ptr->x,
473 vs[*VIndex].y-obj_ptr->y, obj_ptr->ctm, &x, &y);
474 *AbsX = x+obj_ptr->x;
475 *AbsY = y+obj_ptr->y;
476 }
477 return obj_ptr;
478 }
479 break;
480 }
481 }
482 return NULL;
483 }
484
485 static
CandidatePortOwner(obj_ptr)486 int CandidatePortOwner(obj_ptr)
487 struct ObjRec *obj_ptr;
488 {
489 if (obj_ptr->type == OBJ_SYM || obj_ptr->type == OBJ_ICON) {
490 return TRUE;
491 } else if (obj_ptr->type == OBJ_GROUP) {
492 struct AttrRec *attr_ptr=FindAttrWithName(obj_ptr, "type=", NULL);
493
494 if (attr_ptr != NULL && strcmp(attr_ptr->attr_value.s,
495 "tgBroadcastWire") == 0) {
496 return TRUE;
497 }
498 }
499 return FALSE;
500 }
501
FindAnObj(XOff,YOff,OwnerObj,ConnectObj,ReturnedObjName)502 struct ObjRec *FindAnObj(XOff, YOff, OwnerObj, ConnectObj, ReturnedObjName)
503 int XOff, YOff;
504 struct ObjRec **OwnerObj, **ConnectObj;
505 char *ReturnedObjName;
506 /* XOff and YOff are screen offsets */
507 {
508 register struct ObjRec *obj_ptr;
509 register struct AttrRec *attr_ptr;
510 struct ObjRec *sub_obj, *returned_obj=NULL, *actual_obj=NULL;
511 struct ObjRec *owner_obj=NULL;
512 int found_attr=FALSE;
513
514 if (OwnerObj != NULL) *OwnerObj = NULL;
515 if (ConnectObj != NULL) *ConnectObj = NULL;
516 if (ReturnedObjName != NULL) *ReturnedObjName = '\0';
517
518 for (obj_ptr=topObj; returned_obj==NULL && obj_ptr!=NULL;
519 obj_ptr=obj_ptr->next) {
520 obj_ptr->tmp_child = NULL;
521 obj_ptr->tmp_parent = NULL;
522 if (colorLayers && !ObjInVisibleLayer(obj_ptr)) {
523 continue;
524 }
525 actual_obj = obj_ptr;
526 for (attr_ptr=obj_ptr->fattr; returned_obj==NULL && attr_ptr!=NULL;
527 attr_ptr=attr_ptr->next) {
528 if (attr_ptr->shown &&
529 XOff >= OFFSET_X(attr_ptr->obj->bbox.ltx)-3 &&
530 YOff >= OFFSET_Y(attr_ptr->obj->bbox.lty)-3 &&
531 XOff <= OFFSET_X(attr_ptr->obj->bbox.rbx)+3 &&
532 YOff <= OFFSET_Y(attr_ptr->obj->bbox.rby)+3) {
533 owner_obj = obj_ptr;
534 returned_obj = attr_ptr->obj;
535 found_attr = TRUE;
536 break;
537 }
538 }
539 if (returned_obj != NULL) break;
540
541 if (XOff >= OFFSET_X(obj_ptr->bbox.ltx)-3 &&
542 YOff >= OFFSET_Y(obj_ptr->bbox.lty)-3 &&
543 XOff <= OFFSET_X(obj_ptr->bbox.rbx)+3 &&
544 YOff <= OFFSET_Y(obj_ptr->bbox.rby)+3) {
545 struct ObjRec *next_level_child=NULL, *visible_obj=NULL;
546
547 switch (obj_ptr->type) {
548 case OBJ_TEXT:
549 if (FindGoodText(XOff,YOff,obj_ptr)) returned_obj = obj_ptr;
550 break;
551 case OBJ_XBM:
552 if (FindGoodXBm(XOff,YOff,obj_ptr)) returned_obj = obj_ptr;
553 break;
554 case OBJ_XPM:
555 if (FindGoodXPm(XOff,YOff,obj_ptr)) returned_obj = obj_ptr;
556 break;
557 case OBJ_BOX:
558 if (FindGoodBox(XOff,YOff,obj_ptr)) returned_obj = obj_ptr;
559 break;
560 case OBJ_OVAL:
561 if (FindGoodOval(XOff,YOff,obj_ptr)) returned_obj = obj_ptr;
562 break;
563 case OBJ_POLY:
564 if (FindGoodPoly(XOff,YOff,obj_ptr)) returned_obj = obj_ptr;
565 break;
566 case OBJ_POLYGON:
567 if (FindGoodPolygon(XOff,YOff,obj_ptr)) returned_obj = obj_ptr;
568 break;
569 case OBJ_ARC:
570 if (FindGoodArc(XOff,YOff,obj_ptr)) returned_obj = obj_ptr;
571 break;
572 case OBJ_RCBOX:
573 if (FindGoodRCBox(XOff,YOff,obj_ptr)) returned_obj = obj_ptr;
574 break;
575
576 case OBJ_GROUP:
577 case OBJ_ICON:
578 case OBJ_SYM:
579 if (colorLayers) {
580 struct ObjRec *tmp_obj;
581
582 for (tmp_obj=obj_ptr->detail.r->first; tmp_obj != NULL;
583 tmp_obj=tmp_obj->next) {
584 tmp_obj->tmp_parent = obj_ptr;
585 }
586 }
587 if (FindGoodObj(XOff, YOff, obj_ptr->detail.r->first, &sub_obj,
588 &next_level_child)) {
589 obj_ptr->tmp_child = next_level_child;
590 if (sub_obj == NULL) {
591 owner_obj = NULL;
592 returned_obj = obj_ptr;
593 } else {
594 owner_obj = obj_ptr;
595 returned_obj = sub_obj;
596 }
597 }
598 break;
599 case OBJ_PIN:
600 visible_obj = GetPinObj(obj_ptr);
601 if (colorLayers) {
602 struct ObjRec *tmp_obj;
603
604 for (tmp_obj=visible_obj->detail.r->first; tmp_obj != NULL;
605 tmp_obj=tmp_obj->next) {
606 tmp_obj->tmp_parent = visible_obj;
607 }
608 }
609 obj_ptr->tmp_child = visible_obj;
610 if (FindGoodObj(XOff, YOff, GetPinObj(obj_ptr), &sub_obj,
611 &next_level_child)) {
612 visible_obj->tmp_child = next_level_child;
613 if (sub_obj == NULL) {
614 owner_obj = NULL;
615 returned_obj = obj_ptr;
616 } else {
617 owner_obj = obj_ptr;
618 returned_obj = sub_obj;
619 }
620 }
621 break;
622 }
623 }
624 }
625 if (ReturnedObjName != NULL) {
626 char *c_ptr;
627
628 *ReturnedObjName = '\0';
629 c_ptr = ReturnedObjName;
630 if (returned_obj != NULL) {
631 struct ObjRec *prev_obj=NULL;
632 int see_sym_or_icon=FALSE;
633
634 for (obj_ptr=actual_obj; obj_ptr != NULL; obj_ptr=obj_ptr->tmp_child) {
635 /* do not translate -- program constants */
636 if (connectingPortsFromInternalCommand) {
637 /* this is pretty much left for compatibility only */
638 if ((attr_ptr=FindObjAttrWithName(obj_ptr, "name=")) != NULL) {
639 *c_ptr++ = '!';
640 strcpy(c_ptr, attr_ptr->attr_value.s);
641 c_ptr = &c_ptr[strlen(c_ptr)];
642 } else {
643 if (prev_obj != NULL) prev_obj->tmp_child = NULL;
644 break;
645 }
646 } else {
647 int just_seen_sym_or_icon=FALSE;
648
649 if (!see_sym_or_icon) {
650 if (CandidatePortOwner(obj_ptr)) {
651 see_sym_or_icon = TRUE;
652 just_seen_sym_or_icon = TRUE;
653 }
654 }
655 if (see_sym_or_icon) {
656 if ((attr_ptr=FindObjAttrWithName(obj_ptr, "name=")) ==
657 NULL) {
658 /* broken name is invalid */
659 c_ptr = ReturnedObjName;
660 if (prev_obj != NULL) prev_obj->tmp_child = NULL;
661 break;
662 } else if (BlankStr(attr_ptr->attr_value.s)) {
663 /* do not translate -- program constants */
664 *c_ptr++ = '!';
665 strcpy(c_ptr, "(unknown)");
666 c_ptr = &c_ptr[strlen(c_ptr)];
667 } else {
668 *c_ptr++ = '!';
669 strcpy(c_ptr, attr_ptr->attr_value.s);
670 c_ptr = &c_ptr[strlen(c_ptr)];
671 }
672 if (!just_seen_sym_or_icon && CandidatePortOwner(obj_ptr)) {
673 obj_ptr->tmp_child = NULL;
674 prev_obj = obj_ptr;
675 break;
676 }
677 }
678 }
679 prev_obj = obj_ptr;
680 }
681 if (ConnectObj != NULL) *ConnectObj = prev_obj;
682 }
683 if (c_ptr == ReturnedObjName) {
684 *ReturnedObjName = '\0';
685 } else {
686 *c_ptr = '\0';
687 }
688 }
689 if (OwnerObj != NULL) *OwnerObj = owner_obj;
690 return returned_obj;
691 }
692
693 static
VertexAlreadySelected(ObjPtr,VIndex,VSelPtr)694 int VertexAlreadySelected(ObjPtr, VIndex, VSelPtr)
695 register struct ObjRec *ObjPtr;
696 int VIndex;
697 register struct VSelRec **VSelPtr;
698 {
699 register int i;
700
701 for (*VSelPtr=topVSel; *VSelPtr != NULL; *VSelPtr=(*VSelPtr)->next) {
702 if ((*VSelPtr)->obj == ObjPtr) {
703 for (i = 0; i < (*VSelPtr)->n; i++) {
704 if ((*VSelPtr)->v_index[i] == VIndex) {
705 return TRUE;
706 }
707 }
708 return FALSE;
709 }
710 }
711 return FALSE;
712 }
713
AlreadySelected(ObjPtr)714 struct SelRec *AlreadySelected(ObjPtr)
715 register struct ObjRec *ObjPtr;
716 {
717 register struct SelRec *sel_ptr;
718
719 for (sel_ptr=topSel; sel_ptr != NULL; sel_ptr=sel_ptr->next) {
720 if (sel_ptr->obj == ObjPtr) {
721 return sel_ptr;
722 }
723 }
724 return NULL;
725 }
726
AddSel(PrevPtr,NextPtr,SelPtr)727 void AddSel(PrevPtr, NextPtr, SelPtr)
728 struct SelRec *PrevPtr, *NextPtr, *SelPtr;
729 /* add SelPtr between PrevPtr and NextPtr */
730 {
731 SelPtr->prev = PrevPtr;
732 SelPtr->next = NextPtr;
733
734 if (PrevPtr == NULL) {
735 topSel = SelPtr;
736 } else {
737 PrevPtr->next = SelPtr;
738 }
739 if (NextPtr == NULL) {
740 botSel = SelPtr;
741 } else {
742 NextPtr->prev = SelPtr;
743 }
744 numObjSelected++;
745 }
746
AddNewSelObj(ObjPtr)747 void AddNewSelObj(ObjPtr)
748 register struct ObjRec *ObjPtr;
749 {
750 register struct ObjRec *obj_ptr=topObj;
751 register struct SelRec *sel_ptr=topSel, *new_sel_ptr;
752
753 new_sel_ptr = (struct SelRec *)malloc(sizeof(struct SelRec));
754 if (new_sel_ptr == NULL) FailAllocMessage();
755 new_sel_ptr->obj = ObjPtr;
756
757 for ( ; sel_ptr != NULL && obj_ptr != ObjPtr; obj_ptr=obj_ptr->next) {
758 if (obj_ptr == sel_ptr->obj) {
759 sel_ptr = sel_ptr->next;
760 }
761 }
762 if (sel_ptr == NULL) {
763 /* the object is below the last selected object */
764 if (botSel == NULL) {
765 topSel = new_sel_ptr;
766 } else {
767 botSel->next = new_sel_ptr;
768 }
769 new_sel_ptr->prev = botSel;
770 new_sel_ptr->next = NULL;
771 botSel = new_sel_ptr;
772 } else {
773 /* the object is between sel_ptr and sel_ptr->prev */
774 if (sel_ptr->prev == NULL) {
775 topSel = new_sel_ptr;
776 } else {
777 sel_ptr->prev->next = new_sel_ptr;
778 }
779 new_sel_ptr->next = sel_ptr;
780 new_sel_ptr->prev = sel_ptr->prev;
781 sel_ptr->prev = new_sel_ptr;
782 }
783 numObjSelected++;
784 }
785
ExpandCurSelBBoxes(obj_ptr)786 void ExpandCurSelBBoxes(obj_ptr)
787 struct ObjRec *obj_ptr;
788 {
789 if (obj_ptr->bbox.ltx < selLtX) selLtX = obj_ptr->bbox.ltx;
790 if (obj_ptr->bbox.lty < selLtY) selLtY = obj_ptr->bbox.lty;
791 if (obj_ptr->bbox.rbx < selRbX) selRbX = obj_ptr->bbox.rbx;
792 if (obj_ptr->bbox.rby < selRbY) selRbY = obj_ptr->bbox.rby;
793 if (obj_ptr->obbox.ltx < selObjLtX) {
794 selObjLtX = obj_ptr->obbox.ltx;
795 }
796 if (obj_ptr->obbox.lty < selObjLtY) {
797 selObjLtY = obj_ptr->obbox.lty;
798 }
799 if (obj_ptr->obbox.rbx < selObjRbX) {
800 selObjRbX = obj_ptr->obbox.rbx;
801 }
802 if (obj_ptr->obbox.rby < selObjRbY) {
803 selObjRbY = obj_ptr->obbox.rby;
804 }
805 }
806
807 static
SetNoLockBBox(ObjPtr)808 void SetNoLockBBox(ObjPtr)
809 struct ObjRec *ObjPtr;
810 {
811 selNoLockLtX = ObjPtr->bbox.ltx;
812 selNoLockLtY = ObjPtr->bbox.lty;
813 selNoLockRbX = ObjPtr->bbox.rbx;
814 selNoLockRbY = ObjPtr->bbox.rby;
815 selNoLockObjLtX = ObjPtr->obbox.ltx;
816 selNoLockObjLtY = ObjPtr->obbox.lty;
817 selNoLockObjRbX = ObjPtr->obbox.rbx;
818 selNoLockObjRbY = ObjPtr->obbox.rby;
819 }
820
UpdSelBBox()821 void UpdSelBBox()
822 /* update selLtX, selLtY, selRbX, selRbY */
823 {
824 register struct ObjRec *obj_ptr;
825 register struct SelRec *sel_ptr;
826 int seen_no_locked=FALSE;
827
828 numObjSelected = 0;
829 numObjLocked = 0;
830 if ((sel_ptr = topSel) == NULL) return;
831
832 numObjSelected++;
833 obj_ptr = sel_ptr->obj;
834 if (obj_ptr->locked) numObjLocked++;
835 selLtX = obj_ptr->bbox.ltx;
836 selLtY = obj_ptr->bbox.lty;
837 selRbX = obj_ptr->bbox.rbx;
838 selRbY = obj_ptr->bbox.rby;
839 selObjLtX = obj_ptr->obbox.ltx;
840 selObjLtY = obj_ptr->obbox.lty;
841 selObjRbX = obj_ptr->obbox.rbx;
842 selObjRbY = obj_ptr->obbox.rby;
843 if (!obj_ptr->locked) {
844 SetNoLockBBox(obj_ptr);
845 seen_no_locked = TRUE;
846 }
847 for (sel_ptr=topSel->next; sel_ptr != NULL; sel_ptr=sel_ptr->next) {
848 numObjSelected++;
849 obj_ptr = sel_ptr->obj;
850 if (obj_ptr->bbox.ltx < selLtX) selLtX = obj_ptr->bbox.ltx;
851 if (obj_ptr->bbox.lty < selLtY) selLtY = obj_ptr->bbox.lty;
852 if (obj_ptr->bbox.rbx > selRbX) selRbX = obj_ptr->bbox.rbx;
853 if (obj_ptr->bbox.rby > selRbY) selRbY = obj_ptr->bbox.rby;
854 if (obj_ptr->obbox.ltx < selObjLtX) selObjLtX = obj_ptr->obbox.ltx;
855 if (obj_ptr->obbox.lty < selObjLtY) selObjLtY = obj_ptr->obbox.lty;
856 if (obj_ptr->obbox.rbx > selObjRbX) selObjRbX = obj_ptr->obbox.rbx;
857 if (obj_ptr->obbox.rby > selObjRbY) selObjRbY = obj_ptr->obbox.rby;
858 if (obj_ptr->locked) {
859 numObjLocked++;
860 } else {
861 if (seen_no_locked) {
862 if (obj_ptr->bbox.ltx < selNoLockLtX) {
863 selNoLockLtX = obj_ptr->bbox.ltx;
864 }
865 if (obj_ptr->bbox.lty < selNoLockLtY) {
866 selNoLockLtY = obj_ptr->bbox.lty;
867 }
868 if (obj_ptr->bbox.rbx > selNoLockRbX) {
869 selNoLockRbX = obj_ptr->bbox.rbx;
870 }
871 if (obj_ptr->bbox.rby > selNoLockRbY) {
872 selNoLockRbY = obj_ptr->bbox.rby;
873 }
874 if (obj_ptr->obbox.ltx < selNoLockObjLtX) {
875 selNoLockObjLtX = obj_ptr->obbox.ltx;
876 }
877 if (obj_ptr->obbox.lty < selNoLockObjLtY) {
878 selNoLockObjLtY = obj_ptr->obbox.lty;
879 }
880 if (obj_ptr->obbox.rbx > selNoLockObjRbX) {
881 selNoLockObjRbX = obj_ptr->obbox.rbx;
882 }
883 if (obj_ptr->obbox.rby > selNoLockObjRbY) {
884 selNoLockObjRbY = obj_ptr->obbox.rby;
885 }
886 } else {
887 SetNoLockBBox(obj_ptr);
888 seen_no_locked = TRUE;
889 }
890 }
891 }
892 }
893
894 static
SelectOneVertex(XOff,YOff)895 struct VSelRec *SelectOneVertex(XOff, YOff)
896 int XOff, YOff;
897 /* XOff and YOff are screen offsets */
898 {
899 register struct ObjRec *obj_ptr;
900 int v_index, x, y;
901
902 JustRemoveAllVSel();
903 if ((obj_ptr=FindAVertex(XOff, YOff, &v_index, &x, &y)) == NULL) {
904 return NULL;
905 }
906 topVSel = (struct VSelRec *)malloc(sizeof(struct VSelRec));
907 if (topVSel == NULL) FailAllocMessage();
908 memset(topVSel, 0, sizeof(struct VSelRec));
909 topVSel->obj = obj_ptr;
910 topVSel->max_v = 10;
911 topVSel->v_index = (int*)malloc(10*sizeof(int));
912 if (topVSel->v_index == NULL) FailAllocMessage();
913 topVSel->x = (int*)malloc(10*sizeof(int));
914 topVSel->y = (int*)malloc(10*sizeof(int));
915 if (topVSel->x == NULL || topVSel->y == NULL) FailAllocMessage();
916 topVSel->v_index[0] = v_index;
917 topVSel->x[0] = x;
918 topVSel->y[0] = y;
919 if (obj_ptr->type==OBJ_POLYGON && v_index==0) {
920 topVSel->n = 2;
921 topVSel->v_index[1] = obj_ptr->detail.g->n-1;
922 topVSel->x[1] = x;
923 topVSel->y[1] = y;
924 } else {
925 topVSel->n = 1;
926 }
927 topVSel->next = NULL;
928 topVSel->prev = NULL;
929 botVSel = topVSel;
930 UpdSelBBox();
931
932 return topVSel;
933 }
934
935 static
SelectOneObj(XOff,YOff,ppInnerObj)936 struct SelRec *SelectOneObj(XOff, YOff, ppInnerObj)
937 int XOff, YOff;
938 struct ObjRec **ppInnerObj;
939 /* XOff and YOff are screen offsets */
940 {
941 register struct ObjRec *obj_ptr;
942 struct ObjRec *owner_obj;
943
944 RemoveAllSel();
945 if ((obj_ptr=FindAnObj(XOff,YOff,&owner_obj,NULL,NULL)) == NULL) {
946 return NULL;
947 }
948 if (ppInnerObj != NULL) {
949 *ppInnerObj = (owner_obj==NULL ? NULL : obj_ptr);
950 }
951 if (owner_obj != NULL) obj_ptr = owner_obj;
952
953 topSel = (struct SelRec *)malloc(sizeof(struct SelRec));
954 if (topSel == NULL) FailAllocMessage();
955 topSel->next = NULL;
956 topSel->obj = obj_ptr;
957 topSel->prev = NULL;
958 botSel = topSel;
959 UpdSelBBox();
960
961 return topSel;
962 }
963
964 static
FindVertices(X1,Y1,X2,Y2,TopVSel,BotVSel,pn_struct_spline_msg)965 int FindVertices(X1, Y1, X2, Y2, TopVSel, BotVSel, pn_struct_spline_msg)
966 int X1, Y1, X2, Y2, *pn_struct_spline_msg;
967 struct VSelRec **TopVSel, **BotVSel;
968 /* X1, Y1, X2, Y2 are absolute coordinates */
969 {
970 struct SelRec *sel_ptr=NULL;
971 struct BBRec bbox;
972
973 *TopVSel = *BotVSel = NULL;
974
975 bbox.ltx = X1; bbox.lty = Y1;
976 bbox.rbx = X2; bbox.rby = Y2;
977 for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
978 int i=0, n=0, count=0, max_count=0, j=0, curved=(-1);
979 IntPoint *v=NULL;
980 struct ObjRec *obj_ptr=sel_ptr->obj;
981
982 if (obj_ptr->type != OBJ_POLY && obj_ptr->type != OBJ_POLYGON) continue;
983 if (!BBoxIntersect(bbox, obj_ptr->bbox)) continue;
984
985 switch (obj_ptr->type) {
986 case OBJ_POLY:
987 curved = obj_ptr->detail.p->curved;
988 if (curved == LT_STRUCT_SPLINE) {
989 n = obj_ptr->detail.p->ssn;
990 v = obj_ptr->detail.p->ssvlist;
991 } else {
992 n = obj_ptr->detail.p->n;
993 v = obj_ptr->detail.p->vlist;
994 }
995 break;
996 case OBJ_POLYGON:
997 curved = obj_ptr->detail.g->curved;
998 if (curved == LT_STRUCT_SPLINE) {
999 n = obj_ptr->detail.g->ssn;
1000 v = obj_ptr->detail.g->ssvlist;
1001 } else {
1002 n = obj_ptr->detail.g->n;
1003 v = obj_ptr->detail.g->vlist;
1004 }
1005 break;
1006 }
1007 if (obj_ptr->ctm == NULL) {
1008 for (i = 0, count = 0; i < n; i++) {
1009 if (v[i].x >= X1 && v[i].x <= X2 && v[i].y >= Y1 && v[i].y <= Y2) {
1010 count++;
1011 }
1012 }
1013 } else {
1014 for (i = 0, count = 0; i < n; i++) {
1015 int x, y;
1016
1017 TransformPointThroughCTM(v[i].x-obj_ptr->x, v[i].y-obj_ptr->y,
1018 obj_ptr->ctm, &x, &y);
1019 if (x+obj_ptr->x >= X1 && x+obj_ptr->x <= X2 &&
1020 y+obj_ptr->y >= Y1 && y+obj_ptr->y <= Y2) {
1021 count++;
1022 }
1023 }
1024 }
1025 if (count != 0) {
1026 struct VSelRec *vsel_ptr=NULL;
1027
1028 if (curved == LT_STRUCT_SPLINE && count > 1) {
1029 if (!(*pn_struct_spline_msg)) {
1030 *pn_struct_spline_msg = TRUE;
1031 Msg(TgLoadString(STID_ONE_V_STRUCT_SPLINE_IN_V_MODE));
1032 }
1033 count = 1;
1034 }
1035 vsel_ptr = (struct VSelRec *)malloc(sizeof(struct VSelRec));
1036 if (vsel_ptr == NULL) FailAllocMessage();
1037 memset(vsel_ptr, 0, sizeof(struct VSelRec));
1038 vsel_ptr->obj = obj_ptr;
1039 vsel_ptr->next = *TopVSel;
1040 vsel_ptr->prev = NULL;
1041 if (*TopVSel == NULL) {
1042 *BotVSel = vsel_ptr;
1043 } else {
1044 (*TopVSel)->prev = vsel_ptr;
1045 }
1046 *TopVSel = vsel_ptr;
1047 vsel_ptr->n = count;
1048 max_count = ((count%10) == 0) ? 10*((int)(count/10)) :
1049 10*((int)(count/10)+1);
1050 vsel_ptr->max_v = max_count;
1051 vsel_ptr->v_index = (int*)malloc(max_count*sizeof(int));
1052 if (vsel_ptr->v_index == NULL) FailAllocMessage();
1053 vsel_ptr->x = (int*)malloc(max_count*sizeof(int));
1054 vsel_ptr->y = (int*)malloc(max_count*sizeof(int));
1055 if (vsel_ptr->x == NULL || vsel_ptr->y == NULL) FailAllocMessage();
1056
1057 if (obj_ptr->ctm == NULL) {
1058 for (i = 0, j = 0; i < n; i++) {
1059 if (v[i].x >= X1 && v[i].x <= X2 &&
1060 v[i].y >= Y1 && v[i].y <= Y2) {
1061 vsel_ptr->v_index[j] = i;
1062 vsel_ptr->x[j] = v[i].x;
1063 vsel_ptr->y[j] = v[i].y;
1064 j++;
1065 }
1066 }
1067 } else {
1068 for (i = 0, j = 0; i < n; i++) {
1069 int x, y;
1070
1071 TransformPointThroughCTM(v[i].x-obj_ptr->x, v[i].y-obj_ptr->y,
1072 obj_ptr->ctm, &x, &y);
1073 if (x+obj_ptr->x >= X1 && x+obj_ptr->x <= X2 &&
1074 y+obj_ptr->y >= Y1 && y+obj_ptr->y <= Y2) {
1075 vsel_ptr->v_index[j] = i;
1076 vsel_ptr->x[j] = x+obj_ptr->x;
1077 vsel_ptr->y[j] = y+obj_ptr->y;
1078 j++;
1079 }
1080 }
1081 }
1082 }
1083 }
1084 return (*TopVSel != NULL);
1085 }
1086
1087 static
FindObjects(X1,Y1,X2,Y2,TopSel,BotSel)1088 struct SelRec *FindObjects(X1, Y1, X2, Y2, TopSel, BotSel)
1089 int X1, Y1, X2, Y2;
1090 struct SelRec **TopSel, **BotSel;
1091 /* X1, Y1, X2, Y2 are absolute coordinates */
1092 {
1093 struct ObjRec *obj_ptr=NULL;
1094
1095 *TopSel = *BotSel = NULL;
1096
1097 for (obj_ptr=botObj; obj_ptr != NULL; obj_ptr=obj_ptr->prev) {
1098 obj_ptr->tmp_parent = NULL;
1099 if (colorLayers && !ObjInVisibleLayer(obj_ptr)) {
1100 continue;
1101 }
1102 if (X1 <= obj_ptr->bbox.ltx && X2 >= obj_ptr->bbox.rbx &&
1103 Y1 <= obj_ptr->bbox.lty && Y2 >= obj_ptr->bbox.rby) {
1104 AddObjIntoSel(obj_ptr, NULL, *TopSel, TopSel, BotSel);
1105 }
1106 }
1107
1108 return (*TopSel);
1109 }
1110
SelBox(window,gc,x1,y1,x2,y2)1111 void SelBox(window, gc, x1, y1, x2, y2)
1112 Window window;
1113 GC gc;
1114 int x1, y1, x2, y2;
1115 {
1116 XPoint sv[5];
1117
1118 if (x1 == x2 || y1 == y2) {
1119 XDrawLine(mainDisplay, window, gc, x1, y1, x2, y2);
1120 } else {
1121 sv[0].x = (short)x1; sv[0].y = (short)y1;
1122 sv[1].x = (short)x1; sv[1].y = (short)y2;
1123 sv[2].x = (short)x2; sv[2].y = (short)y2;
1124 sv[3].x = (short)x2; sv[3].y = (short)y1;
1125 sv[4].x = (short)x1; sv[4].y = (short)y1;
1126 XDrawLines(mainDisplay, window, gc, sv, 5, CoordModeOrigin);
1127 }
1128 }
1129
1130 static
PtInObjList(XOff,YOff,FirstObjPtr)1131 struct ObjRec *PtInObjList(XOff, YOff, FirstObjPtr)
1132 int XOff, YOff;
1133 struct ObjRec *FirstObjPtr;
1134 /* XOff and YOff are screen offsets */
1135 {
1136 register struct ObjRec *obj_ptr, *obj_ptr1;
1137 register struct AttrRec *attr_ptr;
1138
1139 for (obj_ptr=FirstObjPtr; obj_ptr != NULL; obj_ptr=obj_ptr->next) {
1140 for (attr_ptr=obj_ptr->fattr; attr_ptr!=NULL; attr_ptr=attr_ptr->next) {
1141 if (attr_ptr->shown &&
1142 XOff >= OFFSET_X(attr_ptr->obj->bbox.ltx)-3 &&
1143 YOff >= OFFSET_Y(attr_ptr->obj->bbox.lty)-3 &&
1144 XOff <= OFFSET_X(attr_ptr->obj->bbox.rbx)+3 &&
1145 YOff <= OFFSET_Y(attr_ptr->obj->bbox.rby)+3) {
1146 return attr_ptr->obj;
1147 }
1148 }
1149 if (XOff >= OFFSET_X(obj_ptr->bbox.ltx)-3 &&
1150 YOff >= OFFSET_Y(obj_ptr->bbox.lty)-3 &&
1151 XOff <= OFFSET_X(obj_ptr->bbox.rbx)+3 &&
1152 YOff <= OFFSET_Y(obj_ptr->bbox.rby)+3) {
1153 switch (obj_ptr->type) {
1154 case OBJ_TEXT:
1155 if (FindGoodText(XOff,YOff,obj_ptr)) return obj_ptr; break;
1156 case OBJ_XBM:
1157 if (FindGoodXBm(XOff,YOff,obj_ptr)) return obj_ptr; break;
1158 case OBJ_XPM:
1159 if (FindGoodXPm(XOff,YOff,obj_ptr)) return obj_ptr; break;
1160 case OBJ_BOX:
1161 if (FindGoodBox(XOff,YOff,obj_ptr)) return obj_ptr; break;
1162 case OBJ_OVAL:
1163 if (FindGoodOval(XOff,YOff,obj_ptr)) return obj_ptr; break;
1164 case OBJ_POLY:
1165 if (FindGoodPoly(XOff,YOff,obj_ptr)) return obj_ptr; break;
1166 case OBJ_POLYGON:
1167 if (FindGoodPolygon(XOff,YOff,obj_ptr)) return obj_ptr; break;
1168 case OBJ_ARC:
1169 if (FindGoodArc(XOff,YOff,obj_ptr)) return obj_ptr; break;
1170 case OBJ_RCBOX:
1171 if (FindGoodRCBox(XOff,YOff,obj_ptr)) return obj_ptr; break;
1172
1173 case OBJ_GROUP:
1174 case OBJ_SYM:
1175 case OBJ_ICON:
1176 obj_ptr1 = PtInObjList(XOff, YOff, obj_ptr->detail.r->first);
1177 if (obj_ptr1 != NULL) return obj_ptr1;
1178 break;
1179 case OBJ_PIN:
1180 obj_ptr1 = PtInObjList(XOff, YOff,
1181 GetPinObj(obj_ptr)->detail.r->first);
1182 if (obj_ptr1 != NULL) return obj_ptr1;
1183 break;
1184 }
1185 }
1186 }
1187 return NULL;
1188 }
1189
1190 static
PtInSelected(XOff,YOff)1191 struct ObjRec *PtInSelected(XOff, YOff)
1192 int XOff, YOff;
1193 /* XOff and YOff are screen offsets */
1194 {
1195 register struct SelRec *sel_ptr;
1196 register struct ObjRec *obj_ptr, *obj_ptr1;
1197 register struct AttrRec *attr_ptr;
1198
1199 for (sel_ptr=topSel; sel_ptr != NULL; sel_ptr=sel_ptr->next) {
1200 obj_ptr = sel_ptr->obj;
1201
1202 for (attr_ptr=obj_ptr->fattr; attr_ptr!=NULL; attr_ptr=attr_ptr->next) {
1203 if (attr_ptr->shown &&
1204 XOff >= OFFSET_X(attr_ptr->obj->bbox.ltx)-3 &&
1205 YOff >= OFFSET_Y(attr_ptr->obj->bbox.lty)-3 &&
1206 XOff <= OFFSET_X(attr_ptr->obj->bbox.rbx)+3 &&
1207 YOff <= OFFSET_Y(attr_ptr->obj->bbox.rby)+3) {
1208 return attr_ptr->obj;
1209 }
1210 }
1211 if (XOff >= OFFSET_X(obj_ptr->bbox.ltx)-3 &&
1212 YOff >= OFFSET_Y(obj_ptr->bbox.lty)-3 &&
1213 XOff <= OFFSET_X(obj_ptr->bbox.rbx)+3 &&
1214 YOff <= OFFSET_Y(obj_ptr->bbox.rby)+3) {
1215 switch (obj_ptr->type) {
1216 case OBJ_TEXT:
1217 if (FindGoodText(XOff,YOff,obj_ptr)) return obj_ptr; break;
1218 case OBJ_XBM:
1219 if (FindGoodXBm(XOff,YOff,obj_ptr)) return obj_ptr; break;
1220 case OBJ_XPM:
1221 if (FindGoodXPm(XOff,YOff,obj_ptr)) return obj_ptr; break;
1222 case OBJ_BOX:
1223 if (FindGoodBox(XOff,YOff,obj_ptr)) return obj_ptr; break;
1224 case OBJ_OVAL:
1225 if (FindGoodOval(XOff,YOff,obj_ptr)) return obj_ptr; break;
1226 case OBJ_POLY:
1227 if (FindGoodPoly(XOff,YOff,obj_ptr)) return obj_ptr; break;
1228 case OBJ_POLYGON:
1229 if (FindGoodPolygon(XOff,YOff,obj_ptr)) return obj_ptr; break;
1230 case OBJ_ARC:
1231 if (FindGoodArc(XOff,YOff,obj_ptr)) return obj_ptr; break;
1232 case OBJ_RCBOX:
1233 if (FindGoodRCBox(XOff,YOff,obj_ptr)) return obj_ptr; break;
1234
1235 case OBJ_GROUP:
1236 case OBJ_ICON:
1237 case OBJ_SYM:
1238 obj_ptr1 = PtInObjList(XOff, YOff, obj_ptr->detail.r->first);
1239 if (obj_ptr1 != NULL) return obj_ptr1;
1240 break;
1241 case OBJ_PIN:
1242 obj_ptr1 = PtInObjList(XOff, YOff,
1243 GetPinObj(obj_ptr)->detail.r->first);
1244 if (obj_ptr1 != NULL) return obj_ptr1;
1245 break;
1246 }
1247 }
1248 }
1249 return NULL;
1250 }
1251
1252 static
ToggleVertexSelection(ObjPtr,VIndex,AbsX,AbsY,pn_struct_spline_msg)1253 void ToggleVertexSelection(ObjPtr, VIndex, AbsX, AbsY, pn_struct_spline_msg)
1254 struct ObjRec *ObjPtr;
1255 int VIndex, AbsX, AbsY, *pn_struct_spline_msg;
1256 {
1257 int i, j, n=0, curved=(-1), last_polygon_vertex=FALSE;
1258 struct VSelRec *vsel_ptr=NULL;
1259 char *smooth=NULL;
1260
1261 switch (ObjPtr->type) {
1262 case OBJ_POLY:
1263 curved = ObjPtr->detail.p->curved;
1264 if (curved == LT_STRUCT_SPLINE) {
1265 smooth = ObjPtr->detail.p->ssmooth;
1266 } else {
1267 smooth = ObjPtr->detail.p->smooth;
1268 }
1269 break;
1270 case OBJ_POLYGON:
1271 curved = ObjPtr->detail.g->curved;
1272 if (curved == LT_STRUCT_SPLINE) {
1273 smooth = ObjPtr->detail.g->ssmooth;
1274 if (VIndex == ObjPtr->detail.g->ssn-1) {
1275 last_polygon_vertex = TRUE;
1276 }
1277 } else {
1278 smooth = ObjPtr->detail.g->smooth;
1279 if (VIndex == ObjPtr->detail.g->n-1) {
1280 last_polygon_vertex = TRUE;
1281 }
1282 }
1283 break;
1284 }
1285 if (VertexAlreadySelected(ObjPtr, VIndex, &vsel_ptr)) {
1286 /* de-select a vertex */
1287 if (vsel_ptr->n == 1) {
1288 if (vsel_ptr->prev == NULL) {
1289 topVSel = vsel_ptr->next;
1290 } else {
1291 vsel_ptr->prev->next = vsel_ptr->next;
1292 }
1293 if (vsel_ptr->next == NULL) {
1294 botVSel = vsel_ptr->prev;
1295 } else {
1296 vsel_ptr->next->prev = vsel_ptr->prev;
1297 }
1298 free(vsel_ptr->v_index);
1299 free(vsel_ptr->x);
1300 free(vsel_ptr->y);
1301 free(vsel_ptr);
1302 } else {
1303 for (j = 0; j < vsel_ptr->n; j++) {
1304 if (vsel_ptr->v_index[j] == VIndex) {
1305 break;
1306 }
1307 }
1308 if (j > vsel_ptr->n) {
1309 sprintf(gszMsgBox, TgLoadString(STID_INCONSIS_VERTEX_SEL_IN_FUNC),
1310 "ToggleVertexSelection()");
1311 TgAssert(FALSE, gszMsgBox, NULL);
1312 }
1313 for (i=j; i < vsel_ptr->n-1; i++) {
1314 vsel_ptr->v_index[i] = vsel_ptr->v_index[i+1];
1315 vsel_ptr->x[i] = vsel_ptr->x[i+1];
1316 vsel_ptr->y[i] = vsel_ptr->y[i+1];
1317 }
1318 vsel_ptr->n--;
1319 }
1320 } else {
1321 if (vsel_ptr == NULL) {
1322 /* a new object */
1323 vsel_ptr = (struct VSelRec *)malloc(sizeof(struct VSelRec));
1324 if (vsel_ptr == NULL) FailAllocMessage();
1325 memset(vsel_ptr, 0, sizeof(struct VSelRec));
1326 vsel_ptr->obj = ObjPtr;
1327 n = vsel_ptr->n = 1;
1328 vsel_ptr->max_v = 10;
1329 vsel_ptr->v_index = (int*)malloc(10*sizeof(int));
1330 if (vsel_ptr->v_index == NULL) FailAllocMessage();
1331 vsel_ptr->x = (int*)malloc(10*sizeof(int));
1332 vsel_ptr->y = (int*)malloc(10*sizeof(int));
1333 if (vsel_ptr->x == NULL || vsel_ptr->y == NULL) FailAllocMessage();
1334
1335 vsel_ptr->prev = NULL;
1336 vsel_ptr->next = topVSel;
1337 if (topVSel == NULL) {
1338 botVSel = vsel_ptr;
1339 } else {
1340 topVSel->prev = vsel_ptr;
1341 }
1342 topVSel = vsel_ptr;
1343 } else {
1344 if (!last_polygon_vertex && curved == LT_STRUCT_SPLINE) {
1345 if (!(*pn_struct_spline_msg)) {
1346 *pn_struct_spline_msg = TRUE;
1347 Msg(TgLoadString(STID_ONE_V_STRUCT_SPLINE_IN_V_MODE));
1348 }
1349 return;
1350 } else {
1351 n = ++(vsel_ptr->n);
1352 if (n > vsel_ptr->max_v) {
1353 int max_v;
1354
1355 vsel_ptr->max_v += 10;
1356 max_v = vsel_ptr->max_v;
1357 vsel_ptr->v_index = (int*)realloc(vsel_ptr->v_index,
1358 sizeof(int)*max_v);
1359 vsel_ptr->x = (int*)realloc(vsel_ptr->x, sizeof(int)*max_v);
1360 vsel_ptr->y = (int*)realloc(vsel_ptr->y, sizeof(int)*max_v);
1361 }
1362 }
1363 }
1364 vsel_ptr->v_index[n-1] = VIndex;
1365 vsel_ptr->x[n-1] = AbsX;
1366 vsel_ptr->y[n-1] = AbsY;
1367 }
1368 if (!last_polygon_vertex) {
1369 if (curved != LT_INTSPLINE && curved != (-1) && smooth != NULL) {
1370 if (smooth[VIndex]) {
1371 if (curved == LT_STRUCT_SPLINE) {
1372 MARKHO(drawWindow, revDefaultGC, OFFSET_X(AbsX), OFFSET_Y(AbsY));
1373 } else {
1374 MARKO(drawWindow, revDefaultGC, OFFSET_X(AbsX), OFFSET_Y(AbsY));
1375 }
1376 } else {
1377 if (curved == LT_STRUCT_SPLINE) {
1378 MARKHR(drawWindow, revDefaultGC, OFFSET_X(AbsX), OFFSET_Y(AbsY));
1379 } else {
1380 MARK(drawWindow, revDefaultGC, OFFSET_X(AbsX), OFFSET_Y(AbsY));
1381 }
1382 }
1383 } else {
1384 MARK(drawWindow, revDefaultGC, OFFSET_X(AbsX), OFFSET_Y(AbsY));
1385 }
1386 MARKV(drawWindow, revDefaultGC, OFFSET_X(AbsX), OFFSET_Y(AbsY));
1387 }
1388 }
1389
1390 static
ToggleSelectedObjIfSelectedAlready(ObjPtr)1391 void ToggleSelectedObjIfSelectedAlready(ObjPtr)
1392 register struct ObjRec *ObjPtr;
1393 {
1394 register struct SelRec *sel_ptr;
1395
1396 if ((sel_ptr=AlreadySelected(ObjPtr)) != NULL) {
1397 /* de-select an object */
1398 HighLightAnObj(ObjPtr);
1399
1400 if (sel_ptr->prev == NULL) {
1401 topSel = sel_ptr->next;
1402 } else {
1403 sel_ptr->prev->next = sel_ptr->next;
1404 }
1405 if (sel_ptr->next == NULL) {
1406 botSel = sel_ptr->prev;
1407 } else {
1408 sel_ptr->next->prev = sel_ptr->prev;
1409 }
1410 free(sel_ptr);
1411 numObjSelected--;
1412 } else {
1413 /* add a newly selected object */
1414 AddNewSelObj(ObjPtr);
1415 HighLightAnObj(ObjPtr);
1416 }
1417 }
1418
1419 static
ContinueSel(XOff,YOff,ShiftKeyDown)1420 void ContinueSel(XOff, YOff, ShiftKeyDown)
1421 int XOff, YOff, ShiftKeyDown;
1422 /* XOff and YOff are screen offsets, and they are not on grid */
1423 {
1424 int i, end_x, end_y, v_index, new_end_x, new_end_y;
1425 int done=FALSE, ltx, lty, rbx, rby, dx, dy, x, y;
1426 int struct_spline_msg=FALSE;
1427 char buf[80], w_buf[80], h_buf[80], x_buf[80], y_buf[80];
1428 XEvent input, ev;
1429 XMotionEvent *motion_ev=NULL;
1430 struct SelRec *sel_ptr=NULL, *top_sel_ptr=NULL, *bot_sel_ptr=NULL;
1431 struct VSelRec *vsel_ptr=NULL, *top_vsel_ptr=NULL, *bot_vsel_ptr=NULL;
1432 struct ObjRec *obj_ptr=NULL, *owner_obj=NULL;
1433
1434 end_x = XOff;
1435 end_y = YOff;
1436
1437 SelBox(drawWindow, revDefaultGC, XOff, YOff, end_x, end_y);
1438 PixelToMeasurementUnit(w_buf, 0);
1439 PixelToMeasurementUnit(h_buf, 0);
1440 PixelToMeasurementUnit(x_buf, ABS_X(end_x));
1441 PixelToMeasurementUnit(y_buf, ABS_Y(end_y));
1442 sprintf(buf, "w=%s\nh=%s\nx=%s\ny=%s", w_buf, h_buf, x_buf, y_buf);
1443 StartShowMeasureCursor(end_x, end_y, buf, TRUE);
1444 if (!debugNoPointerGrab) {
1445 XGrabPointer(mainDisplay, drawWindow, False,
1446 PointerMotionMask | ButtonReleaseMask,
1447 GrabModeAsync, GrabModeAsync, None, handCursor, CurrentTime);
1448 }
1449 while (!done) {
1450 XNextEvent(mainDisplay, &input);
1451
1452 if (input.type == Expose || input.type == VisibilityNotify) {
1453 ExposeEventHandler(&input, TRUE);
1454 } else if (input.type == ButtonRelease) {
1455 XUngrabPointer(mainDisplay, CurrentTime);
1456 PixelToMeasurementUnit(w_buf, ABS_SIZE(abs(end_x-XOff)));
1457 PixelToMeasurementUnit(h_buf, ABS_SIZE(abs(end_y-YOff)));
1458 PixelToMeasurementUnit(x_buf, ABS_X(end_x));
1459 PixelToMeasurementUnit(y_buf, ABS_Y(end_y));
1460 sprintf(buf, "w=%s\nh=%s\nx=%s\ny=%s", w_buf, h_buf, x_buf, y_buf);
1461 EndShowMeasureCursor(end_x, end_y, buf, TRUE);
1462 SelBox(drawWindow, revDefaultGC, XOff, YOff, end_x, end_y);
1463 done = TRUE;
1464 } else if (input.type == MotionNotify) {
1465 motion_ev = &(input.xmotion);
1466 new_end_x = motion_ev->x;
1467 new_end_y = motion_ev->y;
1468
1469 PixelToMeasurementUnit(w_buf, ABS_SIZE(abs(end_x-XOff)));
1470 PixelToMeasurementUnit(h_buf, ABS_SIZE(abs(end_y-YOff)));
1471 PixelToMeasurementUnit(x_buf, ABS_X(end_x));
1472 PixelToMeasurementUnit(y_buf, ABS_Y(end_y));
1473 sprintf(buf, "w=%s\nh=%s\nx=%s\ny=%s", w_buf, h_buf, x_buf, y_buf);
1474 ShowMeasureCursor(end_x, end_y, buf, TRUE);
1475 SelBox(drawWindow, revDefaultGC, XOff, YOff, end_x, end_y);
1476 end_x = new_end_x; end_y = new_end_y;
1477 SelBox(drawWindow, revDefaultGC, XOff, YOff, end_x, end_y);
1478 PixelToMeasurementUnit(w_buf, ABS_SIZE(abs(end_x-XOff)));
1479 PixelToMeasurementUnit(h_buf, ABS_SIZE(abs(end_y-YOff)));
1480 PixelToMeasurementUnit(x_buf, ABS_X(end_x));
1481 PixelToMeasurementUnit(y_buf, ABS_Y(end_y));
1482 sprintf(buf, "w=%s\nh=%s\nx=%s\ny=%s", w_buf, h_buf, x_buf, y_buf);
1483 ShowMeasureCursor(end_x, end_y, buf, TRUE);
1484
1485 MarkRulers(end_x, end_y);
1486 while (XCheckMaskEvent(mainDisplay, PointerMotionMask, &ev)) ;
1487 }
1488 }
1489
1490 dx = abs(XOff - end_x);
1491 dy = abs(YOff - end_y);
1492 if (curChoice == VERTEXMODE) {
1493 if (dx <= 2 && dy <= 2) {
1494 if (topSel == NULL) {
1495 if (SelectOneObj(XOff, YOff, NULL) != NULL) {
1496 if ((topSel->obj->type == OBJ_POLY ||
1497 topSel->obj->type == OBJ_POLYGON) &&
1498 !topSel->obj->locked) {
1499 HighLightForward();
1500 } else {
1501 RemoveAllSel();
1502 }
1503 }
1504 } else if (ShiftKeyDown) {
1505 obj_ptr = FindAVertex(XOff, YOff, &v_index, &x, &y);
1506 if (obj_ptr != NULL) {
1507 ToggleVertexSelection(obj_ptr, v_index, x, y,
1508 &struct_spline_msg);
1509 if (obj_ptr->type==OBJ_POLYGON && v_index==0) {
1510 if (obj_ptr->detail.g->curved == LT_STRUCT_SPLINE) {
1511 ToggleVertexSelection(obj_ptr,obj_ptr->detail.g->ssn-1,
1512 x, y, &struct_spline_msg);
1513 } else {
1514 ToggleVertexSelection(obj_ptr,obj_ptr->detail.g->n-1,
1515 x, y, &struct_spline_msg);
1516 }
1517 }
1518 UpdSelBBox();
1519 }
1520 } else {
1521 HighLightReverse();
1522 SelectOneVertex(XOff, YOff);
1523 HighLightForward();
1524 }
1525 } else {
1526 CalcBBox(XOff, YOff, end_x, end_y, <x, <y, &rbx, &rby);
1527 if (topSel == NULL) {
1528 if (FindObjects(ABS_X(ltx), ABS_Y(lty), ABS_X(rbx), ABS_Y(rby),
1529 &top_sel_ptr, &bot_sel_ptr) != NULL) {
1530 topSel = top_sel_ptr;
1531 botSel = bot_sel_ptr;
1532 UnSelNonVertexObjs(FALSE, TRUE); /* do not highlight */
1533 UpdSelBBox();
1534 HighLightForward();
1535 }
1536 } else if (ShiftKeyDown) {
1537 if (FindVertices(ABS_X(ltx), ABS_Y(lty), ABS_X(rbx), ABS_Y(rby),
1538 &top_vsel_ptr, &bot_vsel_ptr, &struct_spline_msg)) {
1539 struct VSelRec *next_vsel;
1540
1541 for (vsel_ptr=top_vsel_ptr; vsel_ptr!=NULL; vsel_ptr=next_vsel) {
1542 obj_ptr = vsel_ptr->obj;
1543 for (i = 0; i < vsel_ptr->n; i++) {
1544 ToggleVertexSelection(obj_ptr, vsel_ptr->v_index[i],
1545 vsel_ptr->x[i], vsel_ptr->y[i], &struct_spline_msg);
1546 }
1547 next_vsel = vsel_ptr->next;
1548 free(vsel_ptr->v_index);
1549 free(vsel_ptr->x);
1550 free(vsel_ptr->y);
1551 free(vsel_ptr);
1552 }
1553 UpdSelBBox();
1554 }
1555 } else {
1556 HighLightReverse();
1557 JustRemoveAllVSel();
1558 if (FindVertices(ABS_X(ltx), ABS_Y(lty), ABS_X(rbx), ABS_Y(rby),
1559 &top_vsel_ptr, &bot_vsel_ptr, &struct_spline_msg)) {
1560 topVSel = top_vsel_ptr;
1561 botVSel = bot_vsel_ptr;
1562 UpdSelBBox();
1563 }
1564 HighLightForward();
1565 }
1566 }
1567 } else {
1568 if (dx <= 2 && dy <= 2) {
1569 if (ShiftKeyDown) {
1570 obj_ptr = FindAnObj(XOff, YOff, &owner_obj, NULL, NULL);
1571 if (obj_ptr != NULL) {
1572 if (owner_obj != NULL) obj_ptr = owner_obj;
1573
1574 ToggleSelectedObjIfSelectedAlready(obj_ptr);
1575 UpdSelBBox();
1576 }
1577 } else {
1578 if (topSel != NULL) HighLightReverse();
1579
1580 if (SelectOneObj(XOff, YOff, NULL) != NULL) {
1581 HighLightForward();
1582 }
1583 }
1584 } else {
1585 CalcBBox(XOff, YOff, end_x, end_y, <x, <y, &rbx, &rby);
1586 if (ShiftKeyDown) {
1587 if (FindObjects(ABS_X(ltx), ABS_Y(lty), ABS_X(rbx), ABS_Y(rby),
1588 &top_sel_ptr, &bot_sel_ptr) != NULL) {
1589 struct SelRec *next_sel;
1590
1591 for (sel_ptr=top_sel_ptr; sel_ptr!=NULL; sel_ptr=next_sel) {
1592 next_sel = sel_ptr->next;
1593 obj_ptr = sel_ptr->obj;
1594 ToggleSelectedObjIfSelectedAlready(obj_ptr);
1595 free(sel_ptr);
1596 }
1597 UpdSelBBox();
1598 }
1599 } else {
1600 if (topSel != NULL) HighLightReverse();
1601 RemoveAllSel();
1602 if (FindObjects(ABS_X(ltx), ABS_Y(lty), ABS_X(rbx), ABS_Y(rby),
1603 &top_sel_ptr, &bot_sel_ptr) != NULL) {
1604 topSel = top_sel_ptr;
1605 botSel = bot_sel_ptr;
1606 UpdSelBBox();
1607 HighLightForward();
1608 }
1609 }
1610 }
1611 }
1612 }
1613
1614 static XComposeStatus c_stat;
1615
1616 static
KeyPressInSelect(key_ev)1617 void KeyPressInSelect(key_ev)
1618 XKeyEvent *key_ev;
1619 {
1620 XButtonEvent button_ev;
1621 char s[80];
1622 KeySym key_sym;
1623 int delta, dx=0, dy=0, has_ch=FALSE;
1624
1625 has_ch = XLookupString(key_ev, s, sizeof(s), &key_sym, &c_stat);
1626 TranslateKeys(s, &key_sym);
1627 if (inSlideShow) {
1628 if (CharIsESC(key_ev, s, key_sym, &has_ch)) {
1629 LeaveSlideShow();
1630 return;
1631 }
1632 switch (key_sym) {
1633 case XK_Left: PrevSlide(); return;
1634 case XK_KP_Left: PrevSlide(); return;
1635 case XK_Up: PrevSlide(); return;
1636 case XK_KP_Up: PrevSlide(); return;
1637 case XK_Right: NextSlide(); return;
1638 case XK_KP_Right: NextSlide(); return;
1639 case XK_Down: NextSlide(); return;
1640 case XK_KP_Down: NextSlide(); return;
1641 default: break;
1642 }
1643 }
1644 button_ev.state = ShiftMask;
1645 if (key_sym == XK_Page_Up || key_sym == XK_KP_Page_Up) {
1646 ScrollUp(&button_ev);
1647 } else if (key_sym == XK_Page_Down || key_sym == XK_KP_Page_Down) {
1648 ScrollDown(&button_ev);
1649 }
1650 if (topSel==NULL && topVSel==NULL) {
1651 if (key_ev->state & ControlMask) {
1652 switch (key_sym) {
1653 case XK_Left: ScrollLeft(&button_ev); break;
1654 case XK_KP_Left: ScrollLeft(&button_ev); break;
1655 case XK_Up: ScrollUp(&button_ev); break;
1656 case XK_KP_Up: ScrollUp(&button_ev); break;
1657 case XK_Right: ScrollRight(&button_ev); break;
1658 case XK_KP_Right: ScrollRight(&button_ev); break;
1659 case XK_Down: ScrollDown(&button_ev); break;
1660 case XK_KP_Down: ScrollDown(&button_ev); break;
1661 }
1662 } else {
1663 switch (key_sym) {
1664 case XK_Left: ScrollLeft(NULL); break;
1665 case XK_KP_Left: ScrollLeft(NULL); break;
1666 case XK_Up: ScrollUp(NULL); break;
1667 case XK_KP_Up: ScrollUp(NULL); break;
1668 case XK_Right: ScrollRight(NULL); break;
1669 case XK_KP_Right: ScrollRight(NULL); break;
1670 case XK_Down: ScrollDown(NULL); break;
1671 case XK_KP_Down: ScrollDown(NULL); break;
1672 }
1673 }
1674 return;
1675 }
1676 if (CharIsDEL(key_ev, s, key_sym, &has_ch)) {
1677 DelAllSelObj();
1678 }
1679 if (key_sym!=XK_Left && key_sym!=XK_Up && key_sym!=XK_Right &&
1680 key_sym!=XK_Down && key_sym!=XK_KP_Left && key_sym!=XK_KP_Up &&
1681 key_sym!=XK_KP_Right && key_sym!=XK_KP_Down) {
1682 return;
1683 }
1684
1685 if (snapOn) {
1686 delta = (gridSystem==ENGLISH_GRID) ? GRID_ABS_SIZE(xyEnglishGrid) :
1687 GRID_ABS_SIZE(xyMetricGrid);
1688 } else {
1689 delta = GRID_ABS_SIZE(1);
1690 }
1691 HighLightReverse();
1692 switch (key_sym) {
1693 case XK_Left: dx = -delta; dy = 0; break;
1694 case XK_KP_Left: dx = -delta; dy = 0; break;
1695 case XK_Up: dx = 0; dy = -delta; break;
1696 case XK_KP_Up: dx = 0; dy = -delta; break;
1697 case XK_Right: dx = delta; dy = 0; break;
1698 case XK_KP_Right: dx = delta; dy = 0; break;
1699 case XK_Down: dx = 0; dy = delta; break;
1700 case XK_KP_Down: dx = 0; dy = delta; break;
1701 }
1702 if (curChoice == VERTEXMODE) {
1703 MoveAllSelVs(dx, dy);
1704 } else if (numObjSelected == numObjLocked) {
1705 HighLightForward();
1706 return;
1707 } else {
1708 MoveAllSel(dx, dy);
1709 }
1710 HighLightForward();
1711 UpdSelBBox();
1712 if (justDupped) {
1713 dupDx += dx;
1714 dupDy += dy;
1715 }
1716 SetFileModified(TRUE);
1717 }
1718
1719 static
PtInObjAboveSelected(XOff,YOff)1720 int PtInObjAboveSelected(XOff, YOff)
1721 int XOff, YOff;
1722 /*
1723 * returns TRUE if there is an object under the mouse that's above all the
1724 * selected objects -- in this case, that object should be selected
1725 */
1726 {
1727 struct ObjRec *obj_ptr=NULL, *owner_obj=NULL, *found_obj=NULL;
1728
1729 found_obj = FindAnObj(XOff, YOff, &owner_obj, NULL, NULL);
1730 if (found_obj == NULL) {
1731 /* no object under the cursor */
1732 return FALSE;
1733 }
1734 if (owner_obj != NULL) found_obj = owner_obj;
1735 if (topSel == NULL) {
1736 return TRUE;
1737 }
1738 for (obj_ptr=topObj; obj_ptr != NULL && obj_ptr != topSel->obj;
1739 obj_ptr=obj_ptr->next) {
1740 if (obj_ptr == found_obj) {
1741 return TRUE;
1742 }
1743 }
1744 return FALSE;
1745 }
1746
Select(input)1747 void Select(input)
1748 XEvent *input;
1749 {
1750 register int i;
1751 XButtonEvent *button_ev;
1752 struct SelRec *sel_ptr;
1753 struct VSelRec *vsel_ptr;
1754 struct ObjRec *obj_ptr;
1755 Time click_time;
1756
1757 if (input->type == KeyPress) {
1758 KeyPressInSelect(&(input->xkey));
1759 return;
1760 } else if (input->type != ButtonPress) {
1761 return;
1762 }
1763
1764 button_ev = &(input->xbutton);
1765 if (button_ev->button == Button1) {
1766 static Time sSelectLastClickTime=(Time)0;
1767 static int snSelectJustClicked=FALSE;
1768
1769 int mouse_x, mouse_y, grid_x, grid_y, corner;
1770
1771 mouse_x = button_ev->x;
1772 mouse_y = button_ev->y;
1773 GridXY(mouse_x, mouse_y, &grid_x, &grid_y);
1774
1775 click_time = button_ev->time;
1776 if (curChoice==VERTEXMODE && topSel!=NULL && snSelectJustClicked &&
1777 (click_time-sSelectLastClickTime) < doubleClickInterval) {
1778 snSelectJustClicked = FALSE;
1779 HighLightReverse();
1780 RemoveAllSel();
1781 return;
1782 } else if (curChoice==NOTHING && topSel!=NULL && snSelectJustClicked &&
1783 (click_time-sSelectLastClickTime) < doubleClickInterval) {
1784 snSelectJustClicked = FALSE;
1785 Teleport(button_ev);
1786 return;
1787 }
1788 snSelectJustClicked = TRUE;
1789 sSelectLastClickTime = click_time;
1790
1791 if (button_ev->state & (ShiftMask | ControlMask)) {
1792 ContinueSel(mouse_x, mouse_y, TRUE);
1793 justDupped = FALSE;
1794 return;
1795 } else if (curChoice == VERTEXMODE && topVSel != NULL) {
1796 int found=FALSE;
1797
1798 for (vsel_ptr=topVSel; vsel_ptr!=NULL && !found;
1799 vsel_ptr=vsel_ptr->next) {
1800 for (i = 0; i < vsel_ptr->n; i++) {
1801 if (PtInMark(mouse_x, mouse_y, OFFSET_X(vsel_ptr->x[i]),
1802 OFFSET_Y(vsel_ptr->y[i]))) {
1803 found = TRUE;
1804 break;
1805 }
1806 }
1807 }
1808 if (found) {
1809 MoveSelVs(grid_x, grid_y);
1810 return;
1811 }
1812 } else if (curChoice == NOTHING) {
1813 struct ObjRec *inner_obj=NULL;
1814
1815 if (topSel != NULL) {
1816 if (oneMotionSelectMove &&
1817 PtInSelMark(mouse_x, mouse_y, &corner) == NULL &&
1818 PtInSelected(mouse_x, mouse_y) == NULL) {
1819 /* may be pointing in not already selected object */
1820 HighLightReverse();
1821 RemoveAllSel();
1822 if (SelectOneObj(mouse_x, mouse_y, &inner_obj) != NULL) {
1823 HighLightForward();
1824 MoveSel(grid_x, grid_y,
1825 (inner_obj==NULL ? topSel->obj : inner_obj), button_ev);
1826 return;
1827 }
1828 } else if ((sel_ptr=PtInSelMark(mouse_x,mouse_y,&corner)) != NULL) {
1829 StretchSel(grid_x, grid_y, sel_ptr->obj, corner);
1830 return;
1831 } else if (!PtInObjAboveSelected(mouse_x, mouse_y) &&
1832 (obj_ptr=PtInSelected(mouse_x, mouse_y)) != NULL) {
1833 MoveSel(grid_x, grid_y, obj_ptr, button_ev);
1834 return;
1835 }
1836 } else if (oneMotionSelectMove &&
1837 SelectOneObj(mouse_x, mouse_y, &inner_obj) != NULL) {
1838 HighLightForward();
1839 MoveSel(grid_x, grid_y,
1840 (inner_obj==NULL ? topSel->obj : inner_obj), button_ev);
1841 return;
1842 }
1843 } else if (curChoice == ROTATEMODE && topSel != NULL) {
1844 if ((sel_ptr=PtInSelMark(mouse_x, mouse_y, &corner)) != NULL) {
1845 RotateShearSel(grid_x, grid_y, sel_ptr->obj, corner);
1846 return;
1847 }
1848 if (!autoRotatePivot && PtInRotatePivot(mouse_x, mouse_y)) {
1849 ContinueMoveRotatePivot(grid_x, grid_y);
1850 return;
1851 }
1852 }
1853 ContinueSel(mouse_x, mouse_y, FALSE);
1854 justDupped = FALSE;
1855 }
1856 }
1857
FindFileAttrWithName(AttrName)1858 struct AttrRec *FindFileAttrWithName(AttrName)
1859 char *AttrName;
1860 {
1861 struct AttrRec *attr_ptr, *found_attr=NULL;
1862 int count=1, compare_name=(strchr(AttrName,'=') != NULL);
1863
1864 if (tgifObj == NULL) return NULL;
1865
1866 for (attr_ptr=tgifObj->fattr; attr_ptr != NULL; attr_ptr=attr_ptr->next) {
1867 if (compare_name) {
1868 if (strcmp(attr_ptr->attr_name.s, AttrName) == 0) {
1869 found_attr = attr_ptr;
1870 break;
1871 }
1872 } else {
1873 if (strcmp(attr_ptr->attr_value.s, AttrName) == 0) {
1874 found_attr = attr_ptr;
1875 break;
1876 }
1877 }
1878 }
1879 if (attr_ptr == NULL) return NULL;
1880
1881 if (GetTextObjFirstStrSeg(found_attr->obj)->color == colorIndex) {
1882 return found_attr;
1883 }
1884 for (attr_ptr=found_attr->next; attr_ptr!=NULL; attr_ptr=attr_ptr->next) {
1885 if (compare_name) {
1886 if (strcmp(attr_ptr->attr_name.s, AttrName) == 0) {
1887 if (GetTextObjFirstStrSeg(attr_ptr->obj)->color == colorIndex) {
1888 break;
1889 } else {
1890 count++;
1891 }
1892 }
1893 } else {
1894 if (strcmp(attr_ptr->attr_value.s, AttrName) == 0) {
1895 if (GetTextObjFirstStrSeg(attr_ptr->obj)->color == colorIndex) {
1896 break;
1897 } else {
1898 count++;
1899 }
1900 }
1901 }
1902 }
1903 if (attr_ptr != NULL) {
1904 found_attr = attr_ptr;
1905 } else if (count != 1) {
1906 sprintf(gszMsgBox,
1907 TgLoadCachedString(CSTID_CANT_FIND_FILEATTR_WITH_COLOR),
1908 AttrName, colorMenuItems[colorIndex]);
1909 Msg(gszMsgBox);
1910 return NULL;
1911 }
1912 return found_attr;
1913 }
1914
FindAttrWithName(ObjPtr,AttrName,pp_top_owner)1915 struct AttrRec *FindAttrWithName(ObjPtr, AttrName, pp_top_owner)
1916 struct ObjRec *ObjPtr, **pp_top_owner;
1917 char *AttrName;
1918 {
1919 struct ObjRec *obj_ptr=NULL;
1920 char *dot_ptr=NULL;
1921
1922 if (AttrName[0] == '!' && AttrName[1] == '*') {
1923 if (topSel == NULL) {
1924 return NULL;
1925 }
1926 if (pp_top_owner != NULL) *pp_top_owner = topSel->obj;
1927 return FindObjAttrWithName(topSel->obj, &AttrName[2]);
1928 }
1929 if ((dot_ptr=strchr(AttrName, '.')) == NULL) {
1930 if (pp_top_owner != NULL) *pp_top_owner = ObjPtr;
1931 return FindObjAttrWithName(ObjPtr, AttrName);
1932 }
1933 *dot_ptr = '\0';
1934 if (strcmp(AttrName, "!") == 0) {
1935 *dot_ptr++ = '.';
1936 if (pp_top_owner != NULL) *pp_top_owner = tgifObj;
1937 return FindFileAttrWithName(dot_ptr);
1938 }
1939 if (AttrName[0] == '#' && AttrName[1] == '#') {
1940 int obj_page_num=0;
1941 char *bang_ptr=strchr(&AttrName[2], '!');
1942
1943 if (bang_ptr == NULL) {
1944 *dot_ptr = '.';
1945 return NULL;
1946 }
1947 *bang_ptr = '\0';
1948 if (sscanf(&AttrName[2], "%d", &obj_page_num) != 1) {
1949 *bang_ptr = '!';
1950 *dot_ptr = '.';
1951 return NULL;
1952 }
1953 if (obj_page_num < 1 || obj_page_num > lastPageNum) {
1954 sprintf(gszMsgBox, TgLoadString(STID_INVALID_PAGE_NUM),
1955 &AttrName[2]),
1956 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1957 *bang_ptr = '!';
1958 *dot_ptr = '.';
1959 return NULL;
1960 }
1961 *bang_ptr = '!';
1962 if (curPageNum == obj_page_num) {
1963 if ((obj_ptr=FindObjWithName(botObj, ObjPtr, bang_ptr, FALSE,
1964 FALSE, NULL, pp_top_owner)) == NULL) {
1965 *dot_ptr = '.';
1966 return NULL;
1967 }
1968 } else {
1969 struct PageRec *page_ptr=NULL;
1970 int page_num=0;
1971
1972 for (page_ptr=firstPage, page_num=1; page_ptr != NULL;
1973 page_ptr=page_ptr->next, page_num++) {
1974 if (page_num == obj_page_num) {
1975 struct PageRec *saved_cur_page_ptr=curPage;
1976 int saved_cur_page_num=curPageNum;
1977
1978 curPageNum = page_num;
1979 curPage = page_ptr;
1980 topObj = curPage->top;
1981 botObj = curPage->bot;
1982 obj_ptr = FindObjWithName(botObj, NULL, bang_ptr,
1983 FALSE, FALSE, NULL, NULL);
1984 curPageNum = saved_cur_page_num;
1985 curPage = saved_cur_page_ptr;
1986 topObj = curPage->top;
1987 botObj = curPage->bot;
1988
1989 if (obj_ptr == NULL) {
1990 *dot_ptr = '.';
1991 return NULL;
1992 }
1993 break;
1994 }
1995 }
1996 if (page_ptr == NULL) {
1997 *dot_ptr++ = '.';
1998 return NULL;
1999 }
2000 }
2001 } else {
2002 if ((obj_ptr=FindObjWithName(botObj, ObjPtr, AttrName, FALSE,
2003 FALSE, NULL, pp_top_owner)) == NULL) {
2004 *dot_ptr++ = '.';
2005 return NULL;
2006 }
2007 }
2008 *dot_ptr++ = '.';
2009 return FindObjAttrWithName(obj_ptr, dot_ptr);
2010 }
2011
ValidAttrArg(c_ptr,obj_ptr,new_c_ptr)2012 struct AttrRec *ValidAttrArg(c_ptr, obj_ptr, new_c_ptr)
2013 char *c_ptr, **new_c_ptr;
2014 struct ObjRec *obj_ptr;
2015 {
2016 char name[MAXSTRING+1], *name_ptr;
2017 struct AttrRec *attr_ptr;
2018
2019 name_ptr = name;
2020 if (c_ptr[0] == '$' && c_ptr[1] == '(') {
2021 for (c_ptr = &c_ptr[2]; *c_ptr != '\0'; c_ptr++) {
2022 switch (*c_ptr) {
2023 case '\\':
2024 c_ptr++;
2025 *name_ptr++ = *c_ptr;
2026 break;
2027 case ')':
2028 *name_ptr++ = '=';
2029 *name_ptr = '\0';
2030 *new_c_ptr = c_ptr;
2031 attr_ptr = FindAttrWithName(obj_ptr, name, NULL);
2032 if (attr_ptr == NULL) {
2033 char msg[MAXSTRING+1];
2034
2035 sprintf(msg, TgLoadCachedString(CSTID_CANT_FIND_NAMED_ATTR),
2036 name);
2037 Msg(msg);
2038 }
2039 return attr_ptr;
2040 default: *name_ptr++ = *c_ptr; break;
2041 }
2042 }
2043 }
2044 return NULL;
2045 }
2046
DoTeleport(teleport_attr)2047 int DoTeleport(teleport_attr)
2048 struct AttrRec *teleport_attr;
2049 {
2050 char file_name[MAXPATHLENGTH+1], msg[MAXSTRING+1], *page_spec=NULL;
2051 char *dest_ptr=NULL;
2052 int do_not_save=FALSE, rc=TRUE, just_goto_page=FALSE, referer_set=FALSE;
2053
2054 while (!DirIsRemote(curDir) && fileModified && !IsFiletUnSavable()) {
2055 XBell(mainDisplay, 0);
2056 switch (MsgBox(TgLoadString(STID_FILE_MOD_SAVE_BEFORE_OPEN), TOOL_NAME,
2057 YNC_MB)) {
2058 case MB_ID_YES: SaveFile(); break;
2059 case MB_ID_NO: do_not_save = TRUE; SetFileModified(FALSE); break;
2060 case MB_ID_CANCEL: return FALSE;
2061 }
2062 }
2063 if (!DirIsRemote(curDir) && fileModified && IsFiletUnSavable()) {
2064 do_not_save = TRUE;
2065 SetFileModified(FALSE);
2066 }
2067 if (!FormNewFileName(curDir, teleport_attr->attr_value.s,
2068 (strcmp(teleport_attr->attr_name.s,TELEPORT_ATTR)==0 ? OBJ_FILE_EXT :
2069 NULL), file_name, &page_spec)) {
2070 sprintf(msg, TgLoadString(STID_INVALID_NAMED_TELEPORT_DEST),
2071 teleport_attr->attr_value.s);
2072 MsgBox(msg, TOOL_NAME, INFO_MB);
2073 if (do_not_save) SetFileModified(TRUE);
2074 rc = FALSE;
2075 }
2076 if (*teleport_attr->attr_value.s == '#') just_goto_page = TRUE;
2077
2078 if (rc && page_spec != NULL && just_goto_page) {
2079 int new_page_num=(-1);
2080
2081 if (!GetPageNumFromPageSpec(page_spec, &new_page_num)) {
2082 sprintf(msg, TgLoadString(STID_INVALID_NAMED_TELEPORT_DEST),
2083 teleport_attr->attr_value.s);
2084 MsgBox(msg, TOOL_NAME, INFO_MB);
2085 if (do_not_save) SetFileModified(TRUE);
2086 rc = FALSE;
2087 } else if (new_page_num != curPageNum) {
2088 BeforeNavigate();
2089 GotoPageNum(new_page_num);
2090 ShowPage();
2091 ClearAndRedrawDrawWindow();
2092 RedrawTitleWindow();
2093 RedrawRulers();
2094 RedrawScrollBars();
2095 CleanUpCmds();
2096 CommitNavigate();
2097 justDupped = FALSE;
2098 }
2099 if (page_spec != NULL) free(page_spec);
2100 return rc;
2101 }
2102 if (!rc) {
2103 if (page_spec != NULL) free(page_spec);
2104 return rc;
2105 }
2106 MakeQuiescent();
2107
2108 if (curFileDefined) {
2109 referer_set = TRUE;
2110 if (*curSymDir == '\0') {
2111 sprintf(gszMsgBox, "%s%c%s", curDir, DIR_SEP, curFileName);
2112 } else {
2113 sprintf(gszMsgBox, "%s%c%s", curSymDir, DIR_SEP, curFileName);
2114 }
2115 HttpSetReferer(gszMsgBox);
2116 }
2117 dest_ptr = UtilStrDup(teleport_attr->attr_value.s);
2118 if (dest_ptr == NULL) FailAllocMessage();
2119 if (FileIsRemote(file_name)) {
2120 char *buf=NULL, *content_type=NULL, final_url[MAXPATHLENGTH+1];
2121 int buf_sz=0, is_html=FALSE;
2122
2123 *final_url = '\0';
2124 SetWatchCursor(drawWindow);
2125 SetWatchCursor(mainWindow);
2126 SaveStatusStrings();
2127 rc = LoadRemoteFileInMem(file_name, &buf, &content_type, &buf_sz,
2128 &is_html, FALSE, final_url, sizeof(final_url));
2129 RestoreStatusStrings();
2130 SetDefaultCursor(mainWindow);
2131 ShowCursor();
2132 if (rc && buf != NULL) {
2133 if (*final_url != '\0') {
2134 UtilStrCpyN(file_name, sizeof(file_name), final_url);
2135 }
2136 LoadRemoteFileFromMem(file_name, buf, content_type, buf_sz, is_html);
2137 } else {
2138 if (do_not_save) SetFileModified(TRUE);
2139 rc = FALSE;
2140 }
2141 if (content_type != NULL) FreeRemoteBuf(content_type);
2142 if (buf != NULL) FreeRemoteBuf(buf);
2143 } else {
2144 int obj_file=FALSE, gzipped=FALSE;
2145 FILE *fp=fopen(file_name, "r");
2146
2147 if (fp == NULL) {
2148 sprintf(gszMsgBox, TgLoadString(STID_Q_FILE_NOT_EXIST_CREATE),
2149 file_name);
2150 switch (MsgBox(gszMsgBox, TOOL_NAME, YNC_MB)) {
2151 case MB_ID_YES:
2152 MakeQuiescent();
2153 SaveNewFile(TRUE, file_name);
2154 break;
2155 case MB_ID_NO: break;
2156 case MB_ID_CANCEL:
2157 if (do_not_save) SetFileModified(TRUE);
2158 rc = FALSE;
2159 break;
2160 }
2161 } else {
2162 fclose(fp);
2163 }
2164 obj_file = FileNameHasExtension(file_name, OBJ_FILE_TYPE, &gzipped,
2165 NULL);
2166 if (rc && !LoadFile(file_name, obj_file, obj_file && gzipped)) {
2167 if (do_not_save) SetFileModified(TRUE);
2168 rc = FALSE;
2169 }
2170 }
2171 /* At this point teleport_attr is no longer valid */
2172 if (rc && page_spec != NULL && !just_goto_page) {
2173 int new_page_num=(-1);
2174
2175 if (!GetPageNumFromPageSpec(page_spec, &new_page_num)) {
2176 sprintf(msg, TgLoadString(STID_INVALID_NAMED_TELEPORT_DEST), dest_ptr);
2177 MsgBox(msg, TOOL_NAME, INFO_MB);
2178 rc = FALSE;
2179 } else if (new_page_num != curPageNum) {
2180 /*
2181 * No need to call BeforeNavigate() here because either
2182 * LoadRemoteFileFromMem() is called (which calls LoadFile())
2183 * or LoadFile() is called directly.
2184 */
2185 GotoPageNum(new_page_num);
2186 ShowPage();
2187 ClearAndRedrawDrawWindow();
2188 RedrawTitleWindow();
2189 RedrawRulers();
2190 RedrawScrollBars();
2191 justDupped = FALSE;
2192 }
2193 }
2194 if (dest_ptr != NULL) free(dest_ptr);
2195 if (page_spec != NULL) free(page_spec);
2196
2197 if (referer_set) {
2198 HttpClearReferer();
2199 }
2200 return rc;
2201 }
2202
2203 #define DO_PAGE_BY_NUM 0
2204 #define DO_PAGE_BY_NAME 1
2205
DoPageTeleport(teleport_attr,do_by_page_name)2206 int DoPageTeleport(teleport_attr, do_by_page_name)
2207 struct AttrRec *teleport_attr;
2208 int do_by_page_name;
2209 {
2210 int i, rc=TRUE;
2211 char msg[MAXSTRING+1];
2212
2213 if (do_by_page_name) {
2214 struct PageRec *page_ptr;
2215
2216 for (i=1, page_ptr=firstPage; page_ptr!=NULL;
2217 page_ptr=page_ptr->next, i++) {
2218 if (page_ptr->name != NULL && strcmp(page_ptr->name,
2219 teleport_attr->attr_value.s) == 0) {
2220 if (curPageNum != i) SetCurPage(i);
2221 return TRUE;
2222 }
2223 }
2224 sprintf(msg, TgLoadString(STID_CANT_FIND_PAGE_NAMED_TO_TEL),
2225 teleport_attr->attr_value.s);
2226 MsgBox(msg, TOOL_NAME, INFO_MB);
2227 rc = FALSE;
2228 } else {
2229 i = atoi(teleport_attr->attr_value.s);
2230 if (i >= 1 && i <= lastPageNum) {
2231 if (curPageNum != i) SetCurPage(i);
2232 } else {
2233 sprintf(msg, TgLoadString(STID_CANT_FIND_PAGE_NUM_TO_TEL), i);
2234 MsgBox(msg, TOOL_NAME, INFO_MB);
2235 rc = FALSE;
2236 }
2237 }
2238 return rc;
2239 }
2240
2241 static
ResetDeckIndices()2242 void ResetDeckIndices()
2243 {
2244 register struct ObjRec *obj_ptr;
2245
2246 for (obj_ptr=botObj; obj_ptr != NULL; obj_ptr=obj_ptr->prev) {
2247 switch (obj_ptr->type) {
2248 case OBJ_GROUP:
2249 case OBJ_ICON:
2250 case OBJ_SYM:
2251 case OBJ_PIN:
2252 obj_ptr->detail.r->deck_index = (-1);
2253 break;
2254 default: break;
2255 }
2256 }
2257 }
2258
DoExecLoop(obj_ptr,exec_attr)2259 void DoExecLoop(obj_ptr, exec_attr)
2260 struct ObjRec *obj_ptr;
2261 struct AttrRec *exec_attr;
2262 {
2263 ResetExec(TRUE);
2264
2265 while (exec_attr != NULL) {
2266 int saved_intr_check_interval=intrCheckInterval;
2267 int one_line_status=FALSE, exec_rc=TRUE, teleport_aborted=FALSE;
2268 int saved_history_depth=historyDepth;
2269 char status_buf[MAX_STATUS_BTNS+1][MAXSTRING+1];
2270
2271 MakeQuiescent();
2272 intrCheckInterval = 1;
2273 ShowInterrupt(1);
2274
2275 ResetDeckIndices();
2276 SaveStatusStringsIntoBuf(status_buf, &one_line_status);
2277 if (cmdToExecAfterHyperJump != NULL) {
2278 free(cmdToExecAfterHyperJump);
2279 cmdToExecAfterHyperJump = NULL;
2280 }
2281 warpToAttr = NULL;
2282 execNavigateBack = FALSE;
2283 exec_rc = DoExec(exec_attr, obj_ptr);
2284 exec_attr = NULL;
2285 RemoveAllSel();
2286 EndExecAnimate();
2287 if (saved_history_depth != historyDepth) RestoreDefaultHistoryDepth();
2288 if (exec_rc == TRUE && warpToAttr != NULL) {
2289 teleport_aborted = !DoTeleport(warpToAttr);
2290 }
2291 RestoreStatusStringsFromBuf(status_buf, one_line_status);
2292
2293 while (HideInterrupt() > 0) ;
2294 intrCheckInterval = saved_intr_check_interval;
2295
2296 if (exec_rc==TRUE && warpToAttr!=NULL && !teleport_aborted) {
2297 if (cmdToExecAfterHyperJump == NULL) {
2298 if ((exec_attr=FindFileAttrWithName("auto_exec=")) == NULL) {
2299 ResetExec(FALSE);
2300 return;
2301 }
2302 obj_ptr = NULL;
2303 continue;
2304 } else {
2305 exec_attr = FindAttrWithName(NULL, cmdToExecAfterHyperJump,
2306 &obj_ptr);
2307 if (exec_attr == NULL) {
2308 sprintf(gszMsgBox, TgLoadString(STID_CANT_FIND_NAMED_ATTR_EXEC),
2309 cmdToExecAfterHyperJump, "hyperjump_then_exec");
2310 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2311 ResetExec(FALSE);
2312 return;
2313 }
2314 continue;
2315 }
2316 }
2317 if (exec_rc==TRUE && execNavigateBack) {
2318 NavigateBack();
2319 }
2320 ResetExec(FALSE);
2321 return;
2322 }
2323 TwoLineMsg(TgLoadCachedString(CSTID_CANT_FIND_INTERPRETABLE_ATTR),
2324 TgLoadCachedString(CSTID_NO_ACTION_TAKEN));
2325 ResetExec(FALSE);
2326 }
2327
Teleport(button_ev)2328 void Teleport(button_ev)
2329 XButtonEvent *button_ev;
2330 {
2331 struct AttrRec *teleport_attr, *launch_attr, *exec_attr;
2332 struct ObjRec *obj_ptr, *owner_obj;
2333 char buf[MAXSTRING+1];
2334 int len;
2335
2336 if ((obj_ptr=FindAnObj(button_ev->x,button_ev->y,&owner_obj,NULL,NULL)) ==
2337 NULL) {
2338 if (inSlideShow) {
2339 NextSlide();
2340 }
2341 return;
2342 }
2343 if (owner_obj != NULL) obj_ptr = owner_obj;
2344
2345 teleport_attr = FindAttrWithName(obj_ptr, TELEPORT_ATTR, NULL);
2346 if (teleport_attr != NULL) {
2347 if (DoTeleport(teleport_attr)) {
2348 if ((exec_attr=FindFileAttrWithName("auto_exec=")) != NULL) {
2349 DoExecLoop(NULL, exec_attr);
2350 }
2351 }
2352 return;
2353 }
2354 teleport_attr = FindAttrWithName(obj_ptr, "href=", NULL);
2355 if (teleport_attr != NULL && *teleport_attr->attr_value.s != '\0') {
2356 if (DoTeleport(teleport_attr)) {
2357 if ((exec_attr=FindFileAttrWithName("auto_exec=")) != NULL) {
2358 DoExecLoop(NULL, exec_attr);
2359 }
2360 }
2361 return;
2362 }
2363 strcpy(buf, TELEPORT_ATTR);
2364 len = strlen(buf);
2365 if (buf[len-1] == '=') {
2366 sprintf(&buf[len-1], "_page#=");
2367 teleport_attr = FindAttrWithName(obj_ptr, buf, NULL);
2368 if (teleport_attr != NULL && *teleport_attr->attr_value.s != '\0') {
2369 DoPageTeleport(teleport_attr, DO_PAGE_BY_NUM);
2370 return;
2371 }
2372 sprintf(&buf[len-1], "_page=");
2373 teleport_attr = FindAttrWithName(obj_ptr, buf, NULL);
2374 if (teleport_attr != NULL && *teleport_attr->attr_value.s != '\0') {
2375 DoPageTeleport(teleport_attr, DO_PAGE_BY_NAME);
2376 return;
2377 }
2378 }
2379 launch_attr = FindAttrWithName(obj_ptr, LAUNCH_ATTR, NULL);
2380 if (launch_attr != NULL) {
2381 DoLaunch(launch_attr, obj_ptr);
2382 return;
2383 }
2384 exec_attr = FindAttrWithName(obj_ptr, EXEC_ATTR, NULL);
2385 if (exec_attr == NULL && inSlideShow) {
2386 NextSlide();
2387 return;
2388 }
2389 DoExecLoop(obj_ptr, exec_attr);
2390 }
2391
SelAllObj(high_light,ignore_slideshow)2392 void SelAllObj(high_light, ignore_slideshow)
2393 int high_light, ignore_slideshow;
2394 {
2395 struct ObjRec *obj_ptr=NULL;
2396
2397 TieLooseEnds();
2398 SetCurChoice(NOTHING);
2399 if (topSel != NULL) {
2400 HighLightReverse();
2401 RemoveAllSel();
2402 }
2403 if (inSlideShow && !ignore_slideshow) {
2404 SetCurChoice(curChoiceBeforeMakeQuiescent);
2405 return;
2406 }
2407 for (obj_ptr=botObj; obj_ptr != NULL; obj_ptr=obj_ptr->prev) {
2408 obj_ptr->tmp_parent = NULL;
2409 if (colorLayers && !ObjInVisibleLayer(obj_ptr)) {
2410 continue;
2411 }
2412 AddObjIntoSel(obj_ptr, NULL, topSel, &topSel, &botSel);
2413 }
2414 UpdSelBBox();
2415 if (high_light) HighLightForward();
2416 justDupped = FALSE;
2417 }
2418
2419 static struct ObjRec *tmpTopObj=NULL, *tmpBotObj=NULL;
2420
2421 static
PushTmpObj(ObjPtr)2422 void PushTmpObj(ObjPtr)
2423 struct ObjRec *ObjPtr;
2424 {
2425 ObjPtr->next = tmpTopObj;
2426 ObjPtr->prev = NULL;
2427
2428 if (tmpBotObj == NULL) {
2429 tmpBotObj = ObjPtr;
2430 } else {
2431 tmpTopObj->prev = ObjPtr;
2432 }
2433 tmpTopObj = ObjPtr;
2434 }
2435
2436 static
BreakSel()2437 void BreakSel()
2438 /* break off selected objects from the main stream objects */
2439 /* when returns, tmpTopObj points to the top of the selected objects */
2440 /* and tmpBotObj points to the bottom of the selected objects */
2441 {
2442 struct SelRec *sel_ptr=NULL;
2443
2444 for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
2445 UnlinkObj(sel_ptr->obj);
2446 PushTmpObj(sel_ptr->obj);
2447 }
2448 }
2449
JustMoveSelToTop()2450 void JustMoveSelToTop()
2451 {
2452 if (topSel == NULL) return;
2453
2454 tmpTopObj = tmpBotObj = NULL;
2455
2456 BreakSel();
2457 tmpBotObj->next = topObj;
2458 if (topObj == NULL) {
2459 curPage->bot = botObj = tmpBotObj;
2460 } else {
2461 topObj->prev = tmpBotObj;
2462 }
2463 curPage->top = topObj = tmpTopObj;
2464 }
2465
MoveSelToTop()2466 void MoveSelToTop()
2467 {
2468 if (topSel == NULL) {
2469 MsgBox(TgLoadCachedString(CSTID_NO_OBJ_SELECTED), TOOL_NAME, INFO_MB);
2470 return;
2471 }
2472 PrepareToRecord(CMD_REPLACE, topSel, botSel, numObjSelected);
2473 JustMoveSelToTop();
2474 RecordCmd(CMD_REPLACE, NULL, topSel, botSel, numObjSelected);
2475 }
2476
MoveSelToBot()2477 void MoveSelToBot()
2478 {
2479 if (topSel == NULL) {
2480 MsgBox(TgLoadCachedString(CSTID_NO_OBJ_SELECTED), TOOL_NAME, INFO_MB);
2481 return;
2482 }
2483 PrepareToRecord(CMD_REPLACE, topSel, botSel, numObjSelected);
2484 tmpTopObj = tmpBotObj = NULL;
2485
2486 BreakSel();
2487 tmpTopObj->prev = botObj;
2488 if (topObj == NULL) {
2489 curPage->top = topObj = tmpTopObj;
2490 } else {
2491 botObj->next = tmpTopObj;
2492 }
2493 curPage->bot = botObj = tmpBotObj;
2494 RecordCmd(CMD_REPLACE, NULL, topSel, botSel, numObjSelected);
2495 }
2496
2497 static
DeleteObjectInsteadOfVertex(obj_ptr)2498 void DeleteObjectInsteadOfVertex(obj_ptr)
2499 struct ObjRec *obj_ptr;
2500 {
2501 struct SelRec *sel_ptr=NULL, *saved_top_sel=NULL, *saved_bot_sel=NULL;
2502
2503 for (sel_ptr=botSel; sel_ptr!=NULL; sel_ptr=sel_ptr->prev) {
2504 if (sel_ptr->obj == obj_ptr) {
2505 break;
2506 }
2507 }
2508 if (sel_ptr->prev == NULL) {
2509 topSel = sel_ptr->next;
2510 } else {
2511 sel_ptr->prev->next = sel_ptr->next;
2512 }
2513 if (sel_ptr->next == NULL) {
2514 botSel = sel_ptr->prev;
2515 } else {
2516 sel_ptr->next->prev = sel_ptr->prev;
2517 }
2518 saved_top_sel = topSel;
2519 saved_bot_sel = botSel;
2520 topSel = botSel = sel_ptr;
2521 sel_ptr->next = sel_ptr->prev = NULL;
2522 DelObj(obj_ptr);
2523 topSel = saved_top_sel;
2524 botSel = saved_bot_sel;
2525
2526 free(sel_ptr);
2527 ChangeReplaceOneCmdToDeleteCmd();
2528 }
2529
DelAllSelObj()2530 void DelAllSelObj()
2531 {
2532 struct ObjRec *obj_ptr=NULL;
2533 struct SelRec *sel_ptr=NULL;
2534 int j, i;
2535 struct VSelRec *vsel_ptr=NULL;
2536 IntPoint *vlist=NULL;
2537 struct PolyRec *poly_ptr=NULL;
2538 struct PolygonRec *polygon_ptr=NULL;
2539 int n=0;
2540 short *mark=NULL;
2541
2542 if (topSel==NULL && topVSel==NULL) {
2543 MsgBox(TgLoadCachedString(CSTID_NO_OBJ_SELECTED), TOOL_NAME, INFO_MB);
2544 return;
2545 }
2546 HighLightReverse();
2547 if (curChoice == VERTEXMODE) {
2548 StartCompositeCmd();
2549 for (vsel_ptr=botVSel; vsel_ptr!=NULL; vsel_ptr=vsel_ptr->prev) {
2550 int delete_it=FALSE, extra_vertex=FALSE, curved=(-1), ssn=0;
2551 char *smooth=NULL, *ssmooth=NULL;
2552 IntPoint *ssvlist=NULL;
2553
2554 obj_ptr = vsel_ptr->obj;
2555
2556 switch (obj_ptr->type) {
2557 case OBJ_POLY:
2558 poly_ptr = obj_ptr->detail.p;
2559 curved = poly_ptr->curved;
2560 if (curved == LT_STRUCT_SPLINE) {
2561 ssvlist = poly_ptr->ssvlist;
2562 ssn = poly_ptr->ssn;
2563 ssmooth = poly_ptr->ssmooth;
2564 } else {
2565 vlist = poly_ptr->vlist;
2566 n = poly_ptr->n;
2567 smooth = poly_ptr->smooth;
2568 }
2569 if (vsel_ptr->n >= n-1) delete_it = TRUE;
2570 break;
2571 case OBJ_POLYGON:
2572 polygon_ptr = obj_ptr->detail.g;
2573 curved = polygon_ptr->curved;
2574 if (curved == LT_STRUCT_SPLINE) {
2575 ssvlist = polygon_ptr->ssvlist;
2576 ssn = polygon_ptr->ssn;
2577 ssmooth = polygon_ptr->ssmooth;
2578 } else {
2579 vlist = polygon_ptr->vlist;
2580 n = polygon_ptr->n;
2581 smooth = polygon_ptr->smooth;
2582 }
2583 for (j=0; j < vsel_ptr->n; j++) {
2584 if (vsel_ptr->v_index[j] == 0) {
2585 extra_vertex = TRUE;
2586 break;
2587 }
2588 }
2589 if ((!extra_vertex && n-vsel_ptr->n <= 3) ||
2590 (extra_vertex && n-vsel_ptr->n <= 2)) {
2591 delete_it = TRUE;
2592 }
2593 break;
2594 }
2595 if (curved == LT_STRUCT_SPLINE) {
2596 PrepareToReplaceAnObj(obj_ptr);
2597 if (DeleteStructuredSplinePoint(vsel_ptr->v_index[0], poly_ptr,
2598 polygon_ptr)) {
2599 AdjObjSplineVs(obj_ptr);
2600 if (poly_ptr != NULL) {
2601 UpdPolyBBox(obj_ptr, poly_ptr->n, poly_ptr->vlist);
2602 } else if (polygon_ptr != NULL) {
2603 UpdPolyBBox(obj_ptr, polygon_ptr->n,
2604 polygon_ptr->vlist);
2605 }
2606 AdjObjBBox(obj_ptr);
2607 RecordReplaceAnObj(obj_ptr);
2608 } else {
2609 /* delete the object */
2610 DeleteObjectInsteadOfVertex(obj_ptr);
2611 }
2612 } else {
2613 PrepareToReplaceAnObj(obj_ptr);
2614 if (delete_it) {
2615 /* delete the object */
2616 DeleteObjectInsteadOfVertex(obj_ptr);
2617 } else {
2618 mark = (short *)malloc(n*sizeof(short));
2619 if (mark == NULL) FailAllocMessage();
2620 for (j=0; j < n; j++) mark[j] = FALSE;
2621 for (j=0; j < vsel_ptr->n; j++) {
2622 mark[vsel_ptr->v_index[j]] = TRUE;
2623 }
2624 switch (obj_ptr->type) {
2625 case OBJ_POLY:
2626 for (i=n-1; i >= 0; i--) {
2627 if (mark[i]) {
2628 for (j=i+1; j < n; j++) {
2629 vlist[j-1] = vlist[j];
2630 if (smooth != NULL) smooth[j-1] = smooth[j];
2631 }
2632 if (smooth != NULL) {
2633 if (i == 0) {
2634 smooth[0] = FALSE;
2635 } else if (i == n-1) {
2636 smooth[n-2] = FALSE;
2637 }
2638 }
2639 n--;
2640 }
2641 }
2642 poly_ptr->n -= vsel_ptr->n;
2643 AdjObjSplineVs(obj_ptr);
2644 if (poly_ptr->curved != LT_INTSPLINE) {
2645 UpdPolyBBox(obj_ptr, poly_ptr->n, poly_ptr->vlist);
2646 } else {
2647 UpdPolyBBox(obj_ptr, poly_ptr->intn, poly_ptr->intvlist);
2648 }
2649 break;
2650 case OBJ_POLYGON:
2651 for (i=n-2; i >= 0; i--) {
2652 if (mark[i]) {
2653 for (j=i+1; j < n; j++) {
2654 vlist[j-1] = vlist[j];
2655 if (smooth != NULL) smooth[j-1] = smooth[j];
2656 }
2657 n--;
2658 if (smooth != NULL && i == 0) {
2659 smooth[n-1] = smooth[0];
2660 }
2661 }
2662 }
2663 polygon_ptr->n -= vsel_ptr->n;
2664 if (extra_vertex) vlist[polygon_ptr->n++] = vlist[0];
2665 AdjObjSplineVs(obj_ptr);
2666 if (polygon_ptr->curved != LT_INTSPLINE) {
2667 UpdPolyBBox(obj_ptr, polygon_ptr->n, polygon_ptr->vlist);
2668 } else {
2669 UpdPolyBBox(obj_ptr, polygon_ptr->intn,
2670 polygon_ptr->intvlist);
2671 }
2672 break;
2673 }
2674 free(mark);
2675 AdjObjBBox(obj_ptr);
2676 RecordReplaceAnObj(obj_ptr);
2677 }
2678 }
2679 }
2680 EndCompositeCmd();
2681 JustRemoveAllVSel();
2682 } else {
2683 struct SelRec *first_extra_poly_sel=NULL, *last_extra_poly_sel=NULL;
2684 struct BBRec extra_bbox;
2685 int extra_poly_count=0, delete_extra_poly=FALSE;
2686
2687 delete_extra_poly = FindExtraPoly(topSel, botSel,
2688 &first_extra_poly_sel, &last_extra_poly_sel, &extra_poly_count,
2689 &extra_bbox);
2690 StartCompositeCmd();
2691 PrepareToRecord(CMD_DELETE, topSel, botSel, numObjSelected);
2692 for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
2693 UnlinkObj(sel_ptr->obj);
2694 FreeObj(sel_ptr->obj);
2695 }
2696 RemoveAllSel();
2697 RecordCmd(CMD_DELETE, NULL, NULL, NULL, 0);
2698 if (delete_extra_poly) {
2699 /*
2700 * Please note that FindExtraPoly() returns the poly in the
2701 * correct stacking order!
2702 */
2703 PrepareToRecord(CMD_DELETE, first_extra_poly_sel, last_extra_poly_sel,
2704 extra_poly_count);
2705 for (sel_ptr=last_extra_poly_sel; sel_ptr != NULL;
2706 sel_ptr=sel_ptr->prev) {
2707 UnlinkObj(sel_ptr->obj);
2708 FreeObj(sel_ptr->obj);
2709 }
2710 JustFreeSel(first_extra_poly_sel, last_extra_poly_sel);
2711 RecordCmd(CMD_DELETE, NULL, NULL, NULL, 0);
2712
2713 ExpandExtents(&extra_bbox, &selLtX, &selLtY, &selRbX, &selRbY);
2714 }
2715 EndCompositeCmd();
2716 }
2717 RedrawAnArea(botObj, selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
2718 selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
2719 HighLightForward();
2720 SetFileModified(TRUE);
2721 justDupped = FALSE;
2722 }
2723
GroupSingleObj(ForcePromoteAttrs)2724 void GroupSingleObj(ForcePromoteAttrs)
2725 int ForcePromoteAttrs;
2726 {
2727 tmpTopObj = tmpBotObj = NULL;
2728
2729 BreakSel();
2730 CreateGroupObj(tmpTopObj, tmpBotObj);
2731 RemoveAllSel();
2732 if (tmpTopObj == tmpBotObj && tmpTopObj->fattr != NULL &&
2733 (ForcePromoteAttrs ||
2734 !(tmpTopObj->type == OBJ_GROUP || tmpTopObj->type == OBJ_SYM ||
2735 tmpTopObj->type == OBJ_ICON || tmpTopObj->type == OBJ_PIN))) {
2736 struct AttrRec *attr_ptr;
2737
2738 topObj->fattr = tmpTopObj->fattr;
2739 topObj->lattr = tmpTopObj->lattr;
2740 tmpTopObj->fattr = tmpTopObj->lattr = NULL;
2741 for (attr_ptr=topObj->fattr; attr_ptr != NULL; attr_ptr=attr_ptr->next) {
2742 attr_ptr->owner = topObj;
2743 }
2744 }
2745 topSel = botSel = (struct SelRec *)malloc(sizeof(struct SelRec));
2746 if (topSel == NULL) FailAllocMessage();
2747 topSel->obj = topObj;
2748 topSel->next = topSel->prev = NULL;
2749 numObjSelected = 1;
2750 }
2751
GroupSelObj(highlight,record_cmd,redraw)2752 void GroupSelObj(highlight, record_cmd, redraw)
2753 int highlight, record_cmd, redraw;
2754 {
2755 if (topSel == NULL) {
2756 MsgBox(TgLoadCachedString(CSTID_NO_OBJ_SELECTED), TOOL_NAME, INFO_MB);
2757 return;
2758 }
2759 if (curChoice==VERTEXMODE && topSel!=NULL) {
2760 MsgBox(TgLoadString(STID_CANT_GROUP_IN_VERTEX_MODE), TOOL_NAME, INFO_MB);
2761 return;
2762 }
2763 if (topSel == botSel && topSel->obj->type != OBJ_POLY &&
2764 topSel->obj->type != OBJ_POLYGON) {
2765 MsgBox(TgLoadString(STID_CANT_GROUP_SINGLE_OBJECT), TOOL_NAME, INFO_MB);
2766 return;
2767 }
2768
2769 tmpTopObj = tmpBotObj = NULL;
2770
2771 if (highlight) HighLightReverse();
2772 if (record_cmd) PrepareToRecord(CMD_REPLACE, topSel, botSel, numObjSelected);
2773 BreakSel();
2774
2775 CreateGroupObj(tmpTopObj, tmpBotObj);
2776
2777 RemoveAllSel();
2778 topSel = botSel = (struct SelRec *)malloc(sizeof(struct SelRec));
2779 if (topSel == NULL) FailAllocMessage();
2780 topSel->obj = topObj;
2781 topSel->next = topSel->prev = NULL;
2782 UpdSelBBox();
2783
2784 if (record_cmd) RecordCmd(CMD_MANY_TO_ONE, NULL, topSel, botSel, 1);
2785 if (redraw) {
2786 RedrawAnArea(botObj, selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
2787 selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
2788 }
2789 if (highlight) HighLightForward();
2790 SetFileModified(TRUE);
2791 justDupped = FALSE;
2792 }
2793
SelectTopObj()2794 void SelectTopObj()
2795 {
2796 if (topObj == NULL) return;
2797
2798 topSel = botSel = (struct SelRec *)malloc(sizeof(struct SelRec));
2799 if (topSel == NULL) FailAllocMessage();
2800 topSel->obj = topObj;
2801 topSel->next = topSel->prev = NULL;
2802 UpdSelBBox();
2803
2804 HighLightForward();
2805 justDupped = FALSE;
2806 }
2807