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/obj.c,v 1.16 2011/05/16 16:21:58 william Exp $
19  */
20 
21 #define _INCLUDE_FROM_OBJ_C_
22 
23 #include "tgifdefs.h"
24 
25 #include "arc.e"
26 #include "attr.e"
27 #include "auxtext.e"
28 #include "box.e"
29 #include "cmd.e"
30 #include "cursor.e"
31 #include "group.e"
32 #include "msg.e"
33 #include "obj.e"
34 #include "oval.e"
35 #include "page.e"
36 #include "pin.e"
37 #include "poly.e"
38 #include "polygon.e"
39 #include "rcbox.e"
40 #include "rect.e"
41 #include "setup.e"
42 #include "spline.e"
43 #include "stretch.e"
44 #include "text.e"
45 #include "xbitmap.e"
46 #include "xpixmap.e"
47 
48 struct ObjRec *topObj=NULL, *botObj=NULL;
49 
AddObj(PrevPtr,NextPtr,ObjPtr)50 void AddObj(PrevPtr, NextPtr, ObjPtr)
51    struct ObjRec *PrevPtr, *NextPtr, *ObjPtr;
52    /* add ObjPtr between PrevPtr and NextPtr */
53 {
54    ObjPtr->prev = PrevPtr;
55    ObjPtr->next = NextPtr;
56 
57    if (PrevPtr == NULL) {
58       curPage->top = topObj = ObjPtr;
59    } else {
60       PrevPtr->next = ObjPtr;
61    }
62    if (NextPtr == NULL) {
63       curPage->bot = botObj = ObjPtr;
64    } else {
65       NextPtr->prev = ObjPtr;
66    }
67 }
68 
UnlinkObj(ObjPtr)69 void UnlinkObj(ObjPtr)
70    struct ObjRec *ObjPtr;
71 {
72    if (topObj == ObjPtr) {
73       curPage->top = topObj = ObjPtr->next;
74    } else {
75       ObjPtr->prev->next = ObjPtr->next;
76    }
77    if (botObj == ObjPtr) {
78       curPage->bot = botObj = ObjPtr->prev;
79    } else {
80       ObjPtr->next->prev = ObjPtr->prev;
81    }
82 }
83 
ReplaceObj(old_obj,new_obj)84 void ReplaceObj(old_obj, new_obj)
85    struct ObjRec *old_obj, *new_obj;
86 {
87    if (topObj == old_obj) {
88       curPage->top = topObj = new_obj;
89       new_obj->prev = NULL;
90    } else {
91       old_obj->prev->next = new_obj;
92       new_obj->prev = old_obj->prev;
93    }
94    if (botObj == old_obj) {
95       curPage->bot = botObj = new_obj;
96       new_obj->next = NULL;
97    } else {
98       old_obj->next->prev = new_obj;
99       new_obj->next = old_obj->next;
100    }
101 }
102 
FreeObj(ObjPtr)103 void FreeObj(ObjPtr)
104    register struct ObjRec *ObjPtr;
105 {
106    if (ObjPtr == NULL) return;
107 
108    if (ObjPtr->ctm != NULL) {
109       free(ObjPtr->ctm);
110       ObjPtr->ctm = NULL;
111    }
112    if (ObjPtr->creator_full_id != NULL) {
113       free(ObjPtr->creator_full_id);
114       ObjPtr->creator_full_id = NULL;
115    }
116    switch (ObjPtr->type) {
117    case OBJ_POLY: DelAllAttrs(ObjPtr->fattr); FreePolyObj(ObjPtr); break;
118    case OBJ_BOX: DelAllAttrs(ObjPtr->fattr); FreeBoxObj(ObjPtr); break;
119    case OBJ_OVAL: DelAllAttrs(ObjPtr->fattr); FreeOvalObj(ObjPtr); break;
120    case OBJ_TEXT: FreeTextObj(ObjPtr); break;
121    case OBJ_POLYGON: DelAllAttrs(ObjPtr->fattr); FreePolygonObj(ObjPtr); break;
122    case OBJ_ARC: DelAllAttrs(ObjPtr->fattr); FreeArcObj(ObjPtr); break;
123    case OBJ_RCBOX: DelAllAttrs(ObjPtr->fattr); FreeRCBoxObj(ObjPtr); break;
124    case OBJ_XBM: DelAllAttrs(ObjPtr->fattr); FreeXBmObj(ObjPtr); break;
125    case OBJ_XPM: DelAllAttrs(ObjPtr->fattr); FreeXPmObj(ObjPtr); break;
126    case OBJ_GROUP:
127    case OBJ_ICON:
128    case OBJ_SYM:
129    case OBJ_PIN: DelAllAttrs(ObjPtr->fattr); FreeGroupObj(ObjPtr); break;
130    }
131 }
132 
DelObj(ObjPtr)133 void DelObj(ObjPtr)
134    struct ObjRec *ObjPtr;
135 {
136    if (ObjPtr->type == OBJ_POLY) {
137       if (ObjPtr->detail.p->start_conn != NULL) {
138          DelConnFromPoly(ObjPtr->detail.p->start_conn);
139       }
140       if (ObjPtr->detail.p->end_conn != NULL) {
141          DelConnFromPoly(ObjPtr->detail.p->end_conn);
142       }
143    } else if (ObjPtr->type == OBJ_PIN) {
144       while (ObjPtr->detail.r->pin_connected > 0) {
145          DelConnFromPin(ObjPtr->detail.p->end_conn);
146       }
147    }
148    if (topObj == ObjPtr) {
149       curPage->top = topObj = ObjPtr->next;
150    } else {
151       ObjPtr->prev->next = ObjPtr->next;
152    }
153    if (botObj == ObjPtr) {
154       curPage->bot = botObj = ObjPtr->prev;
155    } else {
156       ObjPtr->next->prev = ObjPtr->prev;
157    }
158    FreeObj(ObjPtr);
159 }
160 
DelAllObj()161 void DelAllObj()
162 {
163    register struct ObjRec *ptr, *next_obj;
164 
165    if (topObj == NULL) return;
166 
167    for (ptr=topObj; ptr != NULL; ptr=next_obj) {
168       next_obj = ptr->next;
169       FreeObj(ptr);
170    }
171    if (curPage != NULL) curPage->top = curPage->bot = NULL;
172    topObj = botObj = NULL;
173 }
174 
AdjObjOBBox(ObjPtr)175 void AdjObjOBBox(ObjPtr)
176    struct ObjRec *ObjPtr;
177 {
178    struct ObjRec *obj_ptr;
179    int oltx, olty, orbx, orby;
180 
181    switch (ObjPtr->type) {
182    case OBJ_ARC:
183       CalcArcOBBox(ObjPtr);
184       break;
185    case OBJ_TEXT:
186       SetTextOBBox(ObjPtr, ObjPtr->detail.t->minilines.just,
187             ObjPtr->obbox.rbx-ObjPtr->obbox.ltx,
188             ObjPtr->obbox.rby-ObjPtr->obbox.lty,
189             ObjPtr->detail.t->min_lbearing,
190             ObjPtr->detail.t->max_rextra, ROTATE0);
191       break;
192    case OBJ_GROUP:
193    case OBJ_ICON:
194    case OBJ_SYM:
195       obj_ptr = ObjPtr->detail.r->last;
196       oltx = obj_ptr->obbox.ltx; olty = obj_ptr->obbox.lty;
197       orbx = obj_ptr->obbox.rbx; orby = obj_ptr->obbox.rby;
198       for (obj_ptr = obj_ptr->prev; obj_ptr != NULL; obj_ptr = obj_ptr->prev) {
199          if (obj_ptr->obbox.ltx < oltx) oltx = obj_ptr->obbox.ltx;
200          if (obj_ptr->obbox.lty < olty) olty = obj_ptr->obbox.lty;
201          if (obj_ptr->obbox.rbx > orbx) orbx = obj_ptr->obbox.rbx;
202          if (obj_ptr->obbox.rby > orby) orby = obj_ptr->obbox.rby;
203       }
204       ObjPtr->obbox.ltx = oltx; ObjPtr->obbox.lty = olty;
205       ObjPtr->obbox.rbx = orbx; ObjPtr->obbox.rby = orby;
206       break;
207    case OBJ_PIN:
208       obj_ptr = GetPinObj(ObjPtr);
209       oltx = obj_ptr->obbox.ltx; olty = obj_ptr->obbox.lty;
210       orbx = obj_ptr->obbox.rbx; orby = obj_ptr->obbox.rby;
211       ObjPtr->obbox.ltx = oltx; ObjPtr->obbox.lty = olty;
212       ObjPtr->obbox.rbx = orbx; ObjPtr->obbox.rby = orby;
213       break;
214    }
215 }
216 
AdjObjBBox(ObjPtr)217 void AdjObjBBox(ObjPtr)
218    struct ObjRec *ObjPtr;
219 {
220    register int w=0;
221    register struct ObjRec *obj_ptr;
222    register struct AttrRec *attr_ptr;
223    int ltx, lty, rbx, rby;
224 
225    AdjObjOBBox(ObjPtr);
226 
227    switch (ObjPtr->type) {
228    case OBJ_POLY:
229       CalcPolyBBox(ObjPtr);
230       break;
231    case OBJ_ARC:
232       CalcArcBBox(ObjPtr, ObjPtr->obbox, &(ObjPtr->bbox));
233       break;
234    case OBJ_POLYGON: w = HALF_W(ObjPtr->detail.g->width); break;
235    case OBJ_BOX: w = HALF_W(ObjPtr->detail.b->width); break;
236    case OBJ_OVAL: w = HALF_W(ObjPtr->detail.o->width); break;
237    case OBJ_RCBOX: w = HALF_W(ObjPtr->detail.rcb->width); break;
238    case OBJ_XBM: break;
239    case OBJ_XPM: break;
240 
241    case OBJ_GROUP:
242    case OBJ_ICON:
243    case OBJ_SYM:
244       obj_ptr = ObjPtr->detail.r->last;
245       ltx = obj_ptr->bbox.ltx; lty = obj_ptr->bbox.lty;
246       rbx = obj_ptr->bbox.rbx; rby = obj_ptr->bbox.rby;
247       for (obj_ptr = obj_ptr->prev; obj_ptr != NULL; obj_ptr = obj_ptr->prev) {
248          if (obj_ptr->bbox.ltx < ltx) ltx = obj_ptr->bbox.ltx;
249          if (obj_ptr->bbox.lty < lty) lty = obj_ptr->bbox.lty;
250          if (obj_ptr->bbox.rbx > rbx) rbx = obj_ptr->bbox.rbx;
251          if (obj_ptr->bbox.rby > rby) rby = obj_ptr->bbox.rby;
252       }
253       ObjPtr->bbox.ltx = ltx; ObjPtr->bbox.lty = lty;
254       ObjPtr->bbox.rbx = rbx; ObjPtr->bbox.rby = rby;
255       break;
256    case OBJ_PIN:
257       obj_ptr = GetPinObj(ObjPtr);
258       ltx = obj_ptr->bbox.ltx; lty = obj_ptr->bbox.lty;
259       rbx = obj_ptr->bbox.rbx; rby = obj_ptr->bbox.rby;
260       ObjPtr->bbox.ltx = ltx; ObjPtr->bbox.lty = lty;
261       ObjPtr->bbox.rbx = rbx; ObjPtr->bbox.rby = rby;
262       break;
263    }
264    switch (ObjPtr->type) {
265    case OBJ_POLY:
266    case OBJ_ARC:
267       break;
268    case OBJ_POLYGON:
269    case OBJ_BOX:
270    case OBJ_OVAL:
271    case OBJ_RCBOX:
272    case OBJ_XBM:
273    case OBJ_XPM:
274       ObjPtr->bbox.ltx = ObjPtr->obbox.ltx - w;
275       ObjPtr->bbox.lty = ObjPtr->obbox.lty - w;
276       ObjPtr->bbox.rbx = ObjPtr->obbox.rbx + w;
277       ObjPtr->bbox.rby = ObjPtr->obbox.rby + w;
278       break;
279    case OBJ_TEXT:
280       SetTextBBox(ObjPtr, ObjPtr->detail.t->minilines.just,
281             ObjPtr->obbox.rbx-ObjPtr->obbox.ltx,
282             ObjPtr->obbox.rby-ObjPtr->obbox.lty,
283             ObjPtr->detail.t->min_lbearing,
284             ObjPtr->detail.t->max_rextra, ROTATE0);
285       break;
286    }
287 
288    attr_ptr = ObjPtr->fattr;
289 
290    ltx = ObjPtr->bbox.ltx;
291    lty = ObjPtr->bbox.lty;
292    rbx = ObjPtr->bbox.rbx;
293    rby = ObjPtr->bbox.rby;
294    for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next) {
295       if (attr_ptr->shown) {
296          if (attr_ptr->obj->bbox.ltx < ltx) ltx = attr_ptr->obj->bbox.ltx;
297          if (attr_ptr->obj->bbox.lty < lty) lty = attr_ptr->obj->bbox.lty;
298          if (attr_ptr->obj->bbox.rbx > rbx) rbx = attr_ptr->obj->bbox.rbx;
299          if (attr_ptr->obj->bbox.rby > rby) rby = attr_ptr->obj->bbox.rby;
300       }
301    }
302    ObjPtr->bbox.ltx = ltx;
303    ObjPtr->bbox.lty = lty;
304    ObjPtr->bbox.rbx = rbx;
305    ObjPtr->bbox.rby = rby;
306 
307    if (ObjPtr->type == OBJ_SYM) {
308       if (ObjPtr->obbox.ltx-QUARTER_INCH < ObjPtr->bbox.ltx) {
309          ObjPtr->bbox.ltx = ObjPtr->obbox.ltx - QUARTER_INCH;
310       }
311       if (ObjPtr->obbox.lty-QUARTER_INCH < ObjPtr->bbox.lty) {
312          ObjPtr->bbox.lty = ObjPtr->obbox.lty - QUARTER_INCH;
313       }
314       if (ObjPtr->obbox.rbx+QUARTER_INCH > ObjPtr->bbox.rbx) {
315          ObjPtr->bbox.rbx = ObjPtr->obbox.rbx + QUARTER_INCH;
316       }
317       if (ObjPtr->obbox.rby+QUARTER_INCH > ObjPtr->bbox.rby) {
318          ObjPtr->bbox.rby = ObjPtr->obbox.rby + QUARTER_INCH;
319       }
320    }
321 }
322 
323 static
RecursivelyAdjAnObjBBox(target_obj,owner_obj)324 void RecursivelyAdjAnObjBBox(target_obj, owner_obj)
325    struct ObjRec *target_obj, *owner_obj;
326 {
327    if (target_obj == owner_obj) {
328       AdjObjBBox(target_obj);
329    } else {
330       struct ObjRec *obj_ptr=NULL;
331 
332       switch (owner_obj->type) {
333       case OBJ_GROUP:
334       case OBJ_ICON:
335       case OBJ_SYM:
336       case OBJ_PIN:
337          for (obj_ptr=owner_obj->detail.r->first; obj_ptr!=NULL;
338                obj_ptr=obj_ptr->next) {
339             RecursivelyAdjAnObjBBox(target_obj, obj_ptr);
340          }
341          AdjObjBBox(owner_obj);
342          break;
343       default: break;
344       }
345    }
346 }
347 
RecursivelyAdjObjBBox(sub_obj,owner_obj,top_owner)348 void RecursivelyAdjObjBBox(sub_obj, owner_obj, top_owner)
349    struct ObjRec *sub_obj, *owner_obj, *top_owner;
350 {
351    if (owner_obj == NULL) {
352       RecursivelyAdjAnObjBBox(sub_obj, sub_obj);
353    } else {
354       RecursivelyAdjAnObjBBox(sub_obj, top_owner);
355    }
356 }
357 
358 static
InvalidateObjCache(ObjPtr)359 void InvalidateObjCache(ObjPtr)
360    struct ObjRec *ObjPtr;
361 {
362    int w=0, h=0, num_rows=0, num_cols=0;
363    struct TextRec *text_ptr=NULL;
364    struct XBmRec *xbm_ptr=NULL;
365    struct XPmRec *xpm_ptr=NULL;
366    struct ObjRec *obj_ptr=NULL;
367 
368    w = ObjPtr->obbox.rbx - ObjPtr->obbox.ltx;
369    h = ObjPtr->obbox.rby - ObjPtr->obbox.lty;
370    switch (ObjPtr->type) {
371    case OBJ_POLY:
372       if (NeedsToCachePolyObj(ObjPtr)) {
373          struct PolyRec *poly_ptr=ObjPtr->detail.p;
374 
375          if (poly_ptr->rotated_vlist != NULL) free(poly_ptr->rotated_vlist);
376          if (poly_ptr->rotated_asvlist != NULL) {
377             free(poly_ptr->rotated_asvlist);
378          }
379          poly_ptr->rotated_vlist = poly_ptr->rotated_asvlist = NULL;
380          poly_ptr->rotated_n = poly_ptr->rotated_asn = 0;
381       }
382       break;
383    case OBJ_BOX: break;
384 
385    case OBJ_OVAL:
386       /* atan2(61/112) = 0.498721 rad = 28.5746 deg */
387       if (NeedsToCacheOvalObj(ObjPtr)) {
388          struct OvalRec *oval_ptr=ObjPtr->detail.o;
389 
390          if (oval_ptr->rotated_vlist != NULL) free(oval_ptr->rotated_vlist);
391          oval_ptr->rotated_vlist = NULL;
392          oval_ptr->rotated_n = 0;
393       }
394       break;
395    case OBJ_POLYGON:
396       if (NeedsToCachePolygonObj(ObjPtr)) {
397          struct PolygonRec *polygon_ptr=ObjPtr->detail.g;
398 
399          if (polygon_ptr->rotated_vlist != NULL) {
400             free(polygon_ptr->rotated_vlist);
401          }
402          polygon_ptr->rotated_vlist = NULL;
403          polygon_ptr->rotated_n = 0;
404       }
405       break;
406    case OBJ_ARC:
407       if (NeedsToCacheArcObj(ObjPtr)) {
408          struct ArcRec *arc_ptr=ObjPtr->detail.a;
409 
410          if (arc_ptr->rotated_vlist != NULL) free(arc_ptr->rotated_vlist);
411          if (arc_ptr->rotated_asvlist != NULL) free(arc_ptr->rotated_asvlist);
412          arc_ptr->rotated_vlist = arc_ptr->rotated_asvlist = NULL;
413          arc_ptr->rotated_n = arc_ptr->rotated_asn = 0;
414       }
415       break;
416    case OBJ_RCBOX:
417       if (NeedsToCacheRCBoxObj(ObjPtr)) {
418          struct RCBoxRec *rcbox_ptr=ObjPtr->detail.rcb;
419 
420          if (rcbox_ptr->rotated_vlist != NULL) free(rcbox_ptr->rotated_vlist);
421          rcbox_ptr->rotated_vlist = NULL;
422          rcbox_ptr->rotated_n = 0;
423       }
424       break;
425    case OBJ_TEXT:
426       text_ptr = ObjPtr->detail.t;
427       if (NeedsToCacheTextObj(ObjPtr)) {
428          if (text_ptr->cached_bitmap != None) {
429             XFreePixmap(mainDisplay, text_ptr->cached_bitmap);
430          }
431          if (text_ptr->cached_pixmap != None) {
432             XFreePixmap(mainDisplay, text_ptr->cached_pixmap);
433          }
434          if (text_ptr->cached_bg_bitmap != None) {
435             XFreePixmap(mainDisplay, text_ptr->cached_bg_bitmap);
436          }
437          text_ptr->cached_bitmap = None;
438          text_ptr->cached_pixmap = None;
439          text_ptr->cached_bg_bitmap = None;
440          if (zoomScale != 0) {
441             text_ptr->cached_zoom = 0;
442          }
443       }
444       break;
445    case OBJ_XBM:
446       xbm_ptr = ObjPtr->detail.xbm;
447       num_cols = (zoomedIn) ? (w<<zoomScale) : (w>>zoomScale);
448       num_rows = (zoomedIn) ? (h<<zoomScale) : (h>>zoomScale);
449       if (NeedsToCacheXBmObj(ObjPtr)) {
450          if (xbm_ptr->cached_bitmap != None) {
451             XFreePixmap(mainDisplay, xbm_ptr->cached_bitmap);
452          }
453          xbm_ptr->cached_bitmap = None;
454          if (zoomScale != 0) {
455             xbm_ptr->cached_zoom = 0;
456          }
457       }
458       break;
459    case OBJ_XPM:
460       xpm_ptr = ObjPtr->detail.xpm;
461       num_cols = (zoomedIn) ? (w<<zoomScale) : (w>>zoomScale);
462       num_rows = (zoomedIn) ? (h<<zoomScale) : (h>>zoomScale);
463       if (NeedsToCacheXPmObj(ObjPtr)) {
464          if (xpm_ptr->cached_pixmap != None) {
465             XFreePixmap(mainDisplay, xpm_ptr->cached_pixmap);
466          }
467          xpm_ptr->cached_pixmap = None;
468          if (xpm_ptr->cached_bitmap != None) {
469             XFreePixmap(mainDisplay, xpm_ptr->cached_bitmap);
470          }
471          xpm_ptr->cached_bitmap = None;
472          if (xpm_ptr->clip_mask != None) {
473             XFreePixmap(mainDisplay, xpm_ptr->clip_mask);
474          }
475          xpm_ptr->clip_mask = None;
476          if (zoomScale != 0) {
477             xpm_ptr->cached_zoom = 0;
478          }
479          xpm_ptr->cached_color = (-1);
480       }
481       break;
482 
483    case OBJ_GROUP:
484    case OBJ_ICON:
485    case OBJ_SYM:
486    case OBJ_PIN:
487       for (obj_ptr=ObjPtr->detail.r->first; obj_ptr != NULL;
488             obj_ptr=obj_ptr->next) {
489          InvalidateObjCache(obj_ptr);
490       }
491       break;
492    }
493 }
494 
AdjObjCache(ObjPtr)495 void AdjObjCache(ObjPtr)
496    struct ObjRec *ObjPtr;
497 {
498    register struct ObjRec *obj_ptr;
499    register struct AttrRec *attr_ptr;
500 
501    GetTransformedOBBoxOffsetVs(ObjPtr, ObjPtr->rotated_obbox);
502    switch (ObjPtr->type) {
503    case OBJ_GROUP:
504    case OBJ_ICON:
505    case OBJ_SYM:
506    case OBJ_PIN:
507       for (obj_ptr=ObjPtr->detail.r->first; obj_ptr != NULL;
508             obj_ptr=obj_ptr->next) {
509          AdjObjCache(obj_ptr);
510       }
511       break;
512    default:
513       InvalidateObjCache(ObjPtr);
514       break;
515    }
516    for (attr_ptr=ObjPtr->fattr; attr_ptr!=NULL; attr_ptr=attr_ptr->next) {
517       if (attr_ptr->shown) {
518          AdjObjCache(attr_ptr->obj);
519       }
520    }
521 }
522 
AdjCaches()523 void AdjCaches()
524 {
525    register struct ObjRec *obj_ptr, *ptr;
526    register struct AttrRec *attr_ptr;
527 
528    if (topObj == NULL) return;
529 
530    for (obj_ptr = topObj; obj_ptr != NULL; obj_ptr=obj_ptr->next) {
531       switch (obj_ptr->type) {
532       case OBJ_TEXT:
533       case OBJ_XBM:
534       case OBJ_XPM:
535          AdjObjCache(obj_ptr);
536          break;
537       case OBJ_GROUP:
538       case OBJ_ICON:
539       case OBJ_SYM:
540       case OBJ_PIN:
541          for (ptr=obj_ptr->detail.r->first; ptr != NULL; ptr=ptr->next) {
542             AdjObjCache(ptr);
543          }
544          break;
545       }
546       for (attr_ptr=obj_ptr->fattr; attr_ptr!=NULL; attr_ptr=attr_ptr->next) {
547          if (attr_ptr->shown) {
548             AdjObjCache(attr_ptr->obj);
549          }
550       }
551    }
552 }
553 
554 static int dontAutoRetractArrow=FALSE;
555 
556 #define RETREAT (0.8)
557 
558 static
AdjArcCache(ObjPtr)559 void AdjArcCache(ObjPtr)
560    struct ObjRec *ObjPtr;
561 {
562    struct ArcRec *arc_ptr=ObjPtr->detail.a;
563    int a_angle1, a_angle2;
564 
565    if (arc_ptr->style == LS_PLAIN) return;
566 
567    a_angle1 = arc_ptr->angle1;
568    a_angle2 = arc_ptr->angle2;
569    GetArcArrowInfo(ObjPtr, NULL, NULL, NULL, &a_angle1,
570          NULL, NULL, NULL, &a_angle2);
571    arc_ptr->a_angle1 = a_angle1;
572    arc_ptr->a_angle2 = a_angle2;
573 }
574 
575 static
AdjPolyCache(ObjPtr)576 void AdjPolyCache(ObjPtr)
577    struct ObjRec *ObjPtr;
578 {
579    struct PolyRec *poly_ptr=ObjPtr->detail.p;
580 
581    if (poly_ptr->rotated_vlist != NULL) {
582       free(poly_ptr->rotated_vlist);
583    }
584    if (poly_ptr->rotated_asvlist != NULL) {
585       free(poly_ptr->rotated_asvlist);
586    }
587    poly_ptr->rotated_vlist = poly_ptr->rotated_asvlist = NULL;
588    poly_ptr->rotated_n = poly_ptr->rotated_asn = 0;
589 
590    switch (poly_ptr->curved) {
591    case LT_STRAIGHT:
592    case LT_SPLINE:
593       if (poly_ptr->svlist != NULL) {
594          free(poly_ptr->svlist);
595       }
596       poly_ptr->svlist = MakeMultiSplinePolyVertex(
597             poly_ptr->curved, &(poly_ptr->sn), poly_ptr->smooth,
598             drawOrigX, drawOrigY,
599             poly_ptr->n, poly_ptr->vlist);
600       break;
601    case LT_STRUCT_SPLINE:
602       if (poly_ptr->svlist != NULL) free(poly_ptr->svlist);
603       if (poly_ptr->ssvlist != NULL) free(poly_ptr->ssvlist);
604       if (poly_ptr->ssmooth != NULL) free(poly_ptr->ssmooth);
605       if (poly_ptr->smooth != NULL) free(poly_ptr->smooth);
606       poly_ptr->smooth = NULL;
607       poly_ptr->ssvlist = MakeStructuredSplinePolyVertex(&(poly_ptr->ssn),
608             &(poly_ptr->ssmooth), poly_ptr->n, poly_ptr->vlist);
609       poly_ptr->svlist = MakeMultiSplinePolyVertex(
610             poly_ptr->curved, &(poly_ptr->sn), poly_ptr->ssmooth,
611             drawOrigX, drawOrigY, poly_ptr->ssn, poly_ptr->ssvlist);
612       break;
613    case LT_INTSPLINE:
614       if (poly_ptr->svlist != NULL) {
615          free(poly_ptr->svlist);
616       }
617       if (poly_ptr->intvlist != NULL) {
618          free(poly_ptr->intvlist);
619       }
620       if (!undoingOrRedoing && !dontAutoRetractArrow) {
621          if (AutoRetractedArrowAttr(ObjPtr, FALSE)) {
622             int new_x=0, new_y=0;
623             IntPoint *v=NULL;
624 
625             if (poly_ptr->n != 3) {
626                int x0, y0, x2, y2;
627 
628                v = poly_ptr->vlist;
629                x0 = v[0].x; y0 = v[0].y;
630                x2 = v[poly_ptr->n-1].x; y2 = v[poly_ptr->n-1].y;
631                if (poly_ptr->smooth != NULL) free(poly_ptr->smooth);
632                poly_ptr->smooth = (char*)malloc(4*sizeof(char));
633                if (poly_ptr->smooth == NULL) FailAllocMessage();
634                poly_ptr->smooth[0] = poly_ptr->smooth[1] =
635                      poly_ptr->smooth[2] = FALSE;
636                if (poly_ptr->vlist != NULL) free(poly_ptr->vlist);
637                poly_ptr->vlist = (IntPoint*)malloc(4*sizeof(IntPoint));
638                if (poly_ptr->vlist == NULL) FailAllocMessage();
639                poly_ptr->vlist[0].x = x0; poly_ptr->vlist[0].y = y0;
640                poly_ptr->vlist[2].x = x2; poly_ptr->vlist[2].y = y2;
641                poly_ptr->n = 3;
642             }
643             v = poly_ptr->vlist;
644             CalcAutoRetractedArrowAttrBend(poly_ptr->style,
645                   v[0].x, v[0].y, v[2].x, v[2].y, &new_x, &new_y);
646             v[1].x = new_x;
647             v[1].y = new_y;
648          }
649       }
650       poly_ptr->svlist = MakeIntSplinePolyVertex(
651             &(poly_ptr->sn), &(poly_ptr->intn),
652             &(poly_ptr->intvlist), drawOrigX, drawOrigY,
653             poly_ptr->n, poly_ptr->vlist);
654       break;
655    }
656    if (poly_ptr->style != LS_PLAIN) {
657       IntPoint *v=poly_ptr->vlist, *v_copy;
658       int i, n=poly_ptr->n, dx, dy, aw=poly_ptr->aw, retracted_arrow;
659       double len, sin_val, cos_val;
660 
661       retracted_arrow = (RetractedArrowAttr(ObjPtr) ||
662             AutoRetractedArrowAttr(ObjPtr, TRUE));
663       if (poly_ptr->asvlist != NULL) {
664          free(poly_ptr->asvlist);
665       }
666       switch (poly_ptr->curved) {
667       case LT_STRAIGHT:
668       case LT_SPLINE:
669          v = poly_ptr->vlist;
670          n = poly_ptr->n;
671          break;
672       case LT_STRUCT_SPLINE:
673          v = poly_ptr->ssvlist;
674          n = poly_ptr->ssn;
675          break;
676       case LT_INTSPLINE:
677          v = poly_ptr->intvlist;
678          n = poly_ptr->intn;
679          break;
680       }
681       v_copy = (IntPoint *)malloc((n+1)*sizeof(IntPoint));
682       if (v_copy == NULL) FailAllocMessage();
683       for (i = 0; i < n; i++) {
684          v_copy[i].x = v[i].x;
685          v_copy[i].y = v[i].y;
686       }
687       if (aw == 0) aw = 1;
688 
689       dx = v_copy[1].x - v_copy[0].x;
690       dy = v_copy[1].y - v_copy[0].y;
691       if (!retracted_arrow && (poly_ptr->style & LS_LEFT) &&
692             (dx != 0 || dy != 0)) {
693          len = (double)sqrt((double)(((double)dx)*((double)dx) +
694                ((double)dy)*((double)dy)));
695          sin_val = ((double)dy)/len;
696          cos_val = ((double)dx)/len;
697 
698          v_copy[0].x = round(v_copy[0].x+RETREAT*aw*cos_val);
699          v_copy[0].y = round(v_copy[0].y+RETREAT*aw*sin_val);
700       }
701       dx = v_copy[n-1].x - v_copy[n-2].x;
702       dy = v_copy[n-1].y - v_copy[n-2].y;
703       if (!retracted_arrow && (poly_ptr->style & LS_RIGHT) &&
704             (dx != 0 || dy != 0)) {
705          len = (double)sqrt((double)(((double)dx)*((double)dx) +
706                ((double)dy)*((double)dy)));
707          sin_val = ((double)dy)/len;
708          cos_val = ((double)dx)/len;
709 
710          v_copy[n-1].x = round(v_copy[n-1].x-RETREAT*aw*cos_val);
711          v_copy[n-1].y = round(v_copy[n-1].y-RETREAT*aw*sin_val);
712       }
713       switch (poly_ptr->curved) {
714       case LT_STRAIGHT:
715       case LT_SPLINE:
716          poly_ptr->asvlist = MakeMultiSplinePolyVertex(
717                poly_ptr->curved, &(poly_ptr->asn), poly_ptr->smooth,
718                drawOrigX, drawOrigY, n, v_copy);
719          break;
720       case LT_STRUCT_SPLINE:
721          poly_ptr->asvlist = MakeMultiSplinePolyVertex(
722                poly_ptr->curved, &(poly_ptr->asn), poly_ptr->ssmooth,
723                drawOrigX, drawOrigY, n, v_copy);
724          break;
725       case LT_INTSPLINE:
726          poly_ptr->asvlist = MakeSplinePolyVertex(0, poly_ptr->curved,
727                &(poly_ptr->asn), drawOrigX, drawOrigY, n, v_copy);
728          break;
729       }
730       free(v_copy);
731    }
732 }
733 
734 static
AdjPolygonCache(ObjPtr)735 void AdjPolygonCache(ObjPtr)
736    struct ObjRec *ObjPtr;
737 {
738    struct PolygonRec *polygon_ptr=ObjPtr->detail.g;
739 
740    if (polygon_ptr->rotated_vlist != NULL) {
741       free(polygon_ptr->rotated_vlist);
742    }
743    polygon_ptr->rotated_vlist = NULL;
744    polygon_ptr->rotated_n = 0;
745 
746    switch (polygon_ptr->curved) {
747    case LT_STRAIGHT:
748       if (polygon_ptr->svlist != NULL) {
749          free(polygon_ptr->svlist);
750       }
751       polygon_ptr->svlist = MakeMultiSplinePolygonVertex(
752             polygon_ptr->curved, &(polygon_ptr->sn), polygon_ptr->smooth,
753             drawOrigX, drawOrigY,
754             polygon_ptr->n, polygon_ptr->vlist);
755       break;
756    case LT_SPLINE:
757       if (polygon_ptr->svlist != NULL) {
758          free(polygon_ptr->svlist);
759       }
760       polygon_ptr->svlist = MakeMultiSplinePolygonVertex(
761             polygon_ptr->curved, &(polygon_ptr->sn), polygon_ptr->smooth,
762             drawOrigX, drawOrigY,
763             polygon_ptr->n, polygon_ptr->vlist);
764       break;
765    case LT_STRUCT_SPLINE:
766       if (polygon_ptr->svlist != NULL) free(polygon_ptr->svlist);
767       if (polygon_ptr->ssvlist != NULL) free(polygon_ptr->ssvlist);
768       if (polygon_ptr->ssmooth != NULL) free(polygon_ptr->ssmooth);
769       if (polygon_ptr->smooth != NULL) free(polygon_ptr->smooth);
770 #ifdef _TGIF_DBG /* debug, do not translate */
771       TgAssert(polygon_ptr->n >= 7, "NumPts < 7 in AdjPolygonCache()", NULL);
772 #endif /* _TGIF_DBG */
773       polygon_ptr->smooth = NULL;
774       polygon_ptr->ssvlist = MakeStructuredSplinePolygonVertex(
775             &(polygon_ptr->ssn), &(polygon_ptr->ssmooth), polygon_ptr->n,
776             polygon_ptr->vlist);
777       polygon_ptr->svlist = MakeMultiSplinePolygonVertex(
778             polygon_ptr->curved, &(polygon_ptr->sn), polygon_ptr->ssmooth,
779             drawOrigX, drawOrigY,
780             polygon_ptr->ssn, polygon_ptr->ssvlist);
781       break;
782    case LT_INTSPLINE:
783       if (polygon_ptr->svlist != NULL) {
784          free(polygon_ptr->svlist);
785       }
786       if (polygon_ptr->intvlist != NULL) {
787          free(polygon_ptr->intvlist);
788       }
789       polygon_ptr->svlist = MakeIntSplinePolygonVertex(
790             &(polygon_ptr->sn), &(polygon_ptr->intn),
791             &(polygon_ptr->intvlist), drawOrigX, drawOrigY,
792             polygon_ptr->n, polygon_ptr->vlist);
793       break;
794    }
795 }
796 
AdjObjSplineVs(ObjPtr)797 void AdjObjSplineVs(ObjPtr)
798    struct ObjRec *ObjPtr;
799 {
800    struct ObjRec *obj_ptr;
801 
802    switch (ObjPtr->type) {
803    case OBJ_BOX: break;
804    case OBJ_XBM: break;
805    case OBJ_XPM: break;
806    case OBJ_OVAL: InvalidateObjCache(ObjPtr); break;
807    case OBJ_TEXT: break;
808    case OBJ_RCBOX: InvalidateObjCache(ObjPtr); break;
809    case OBJ_ARC: InvalidateObjCache(ObjPtr); AdjArcCache(ObjPtr); break;
810    case OBJ_POLY: AdjPolyCache(ObjPtr); break;
811    case OBJ_POLYGON: AdjPolygonCache(ObjPtr); break;
812 
813    case OBJ_GROUP:
814    case OBJ_ICON:
815    case OBJ_SYM:
816    case OBJ_PIN:
817       for (obj_ptr=ObjPtr->detail.r->first; obj_ptr != NULL;
818             obj_ptr=obj_ptr->next) {
819          AdjObjSplineVs(obj_ptr);
820       }
821       break;
822    }
823    GetTransformedOBBoxOffsetVs(ObjPtr, ObjPtr->rotated_obbox);
824 }
825 
AdjSplineVs()826 void AdjSplineVs()
827 {
828    register struct ObjRec *obj_ptr, *ptr;
829 
830    if (topObj == NULL) return;
831 
832    dontAutoRetractArrow = TRUE;
833    for (obj_ptr = topObj; obj_ptr != NULL; obj_ptr = obj_ptr->next) {
834       switch (obj_ptr->type) {
835       case OBJ_POLY:
836       case OBJ_BOX:
837       case OBJ_OVAL:
838       case OBJ_TEXT:
839       case OBJ_POLYGON:
840       case OBJ_ARC:
841       case OBJ_RCBOX:
842       case OBJ_XBM:
843       case OBJ_XPM:
844          AdjObjSplineVs(obj_ptr);
845          break;
846       case OBJ_GROUP:
847       case OBJ_ICON:
848       case OBJ_SYM:
849       case OBJ_PIN:
850          for (ptr=obj_ptr->detail.r->first; ptr != NULL; ptr=ptr->next) {
851             AdjObjSplineVs(ptr);
852          }
853          GetTransformedOBBoxOffsetVs(obj_ptr, obj_ptr->rotated_obbox);
854          break;
855       }
856    }
857    dontAutoRetractArrow = FALSE;
858 }
859 
ClearObjCachesInAllPages()860 void ClearObjCachesInAllPages()
861 {
862    struct ObjRec *saved_top_obj=topObj, *saved_bot_obj=botObj;
863    struct PageRec *saved_cur_page=curPage;
864 
865    for (curPage=firstPage; curPage != NULL; curPage=curPage->next) {
866       topObj = curPage->top;
867       botObj = curPage->bot;
868 
869       AdjCaches();
870       AdjSplineVs();
871       curPage->draw_orig_x = drawOrigX;
872       curPage->draw_orig_y = drawOrigY;
873       curPage->zoom_scale = zoomScale;
874       curPage->zoomed_in = zoomedIn;
875    }
876    topObj = saved_top_obj;
877    botObj = saved_bot_obj;
878    curPage = saved_cur_page;
879 }
880 
MoveRotatedObjCache(ObjPtr,AbsDx,AbsDy)881 void MoveRotatedObjCache(ObjPtr, AbsDx, AbsDy)
882    struct ObjRec *ObjPtr;
883    int AbsDx, AbsDy;
884 {
885    register int i;
886    int dx_off, dy_off, n=0;
887    XPoint *v=NULL;
888 
889    if (ObjPtr->ctm == NULL) return;
890 
891    dx_off = ZOOMED_SIZE(AbsDx);
892    dy_off = ZOOMED_SIZE(AbsDy);
893    for (i=0; i < 5; i++) {
894       ObjPtr->rotated_obbox[i].x += dx_off;
895       ObjPtr->rotated_obbox[i].y += dy_off;
896    }
897    ObjPtr->orig_obbox.ltx += AbsDx; ObjPtr->orig_obbox.lty += AbsDy;
898    ObjPtr->orig_obbox.rbx += AbsDx; ObjPtr->orig_obbox.rby += AbsDy;
899    switch (ObjPtr->type) {
900    case OBJ_POLY:
901    case OBJ_POLYGON:
902    case OBJ_OVAL:
903    case OBJ_ARC:
904    case OBJ_RCBOX:
905       switch (ObjPtr->type) {
906       case OBJ_POLY:
907          n = ObjPtr->detail.p->rotated_n;
908          v = ObjPtr->detail.p->rotated_vlist;
909          break;
910       case OBJ_POLYGON:
911          n = ObjPtr->detail.g->rotated_n;
912          v = ObjPtr->detail.g->rotated_vlist;
913          break;
914       case OBJ_OVAL:
915          n = ObjPtr->detail.o->rotated_n;
916          v = ObjPtr->detail.o->rotated_vlist;
917          break;
918       case OBJ_ARC:
919          n = ObjPtr->detail.a->rotated_n;
920          v = ObjPtr->detail.a->rotated_vlist;
921          break;
922       case OBJ_RCBOX:
923          n = ObjPtr->detail.rcb->rotated_n;
924          v = ObjPtr->detail.rcb->rotated_vlist;
925          break;
926       }
927       if (v != NULL) {
928          for (i=0; i < n; i++) {
929             v[i].x += dx_off;
930             v[i].y += dy_off;
931          }
932       }
933       if (ObjPtr->type == OBJ_POLY) {
934          n = ObjPtr->detail.p->rotated_asn;
935          v = ObjPtr->detail.p->rotated_asvlist;
936          if (v != NULL) {
937             for (i=0; i < n; i++) {
938                v[i].x += dx_off;
939                v[i].y += dy_off;
940             }
941          }
942       }
943       break;
944    case OBJ_BOX:
945    case OBJ_GROUP:
946    case OBJ_ICON:
947    case OBJ_SYM:
948    case OBJ_PIN:
949    case OBJ_XBM:
950    case OBJ_XPM:
951       break;
952    case OBJ_TEXT:
953       ObjPtr->detail.t->orig_bbox.ltx += AbsDx;
954       ObjPtr->detail.t->orig_bbox.lty += AbsDy;
955       ObjPtr->detail.t->orig_bbox.rbx += AbsDx;
956       ObjPtr->detail.t->orig_bbox.rby += AbsDy;
957       break;
958    }
959 }
960 
AdjHotSpots()961 void AdjHotSpots()
962 {
963 }
964 
AdjObjHotSpot()965 void AdjObjHotSpot()
966 {
967 }
968 
IsTopLevelObject(ObjPtr)969 int IsTopLevelObject(ObjPtr)
970    struct ObjRec *ObjPtr;
971 {
972    struct ObjRec *obj_ptr=NULL;
973 
974    for (obj_ptr=topObj; obj_ptr != NULL; obj_ptr=obj_ptr->next) {
975       if (obj_ptr == ObjPtr) {
976          return TRUE;
977       }
978    }
979    return FALSE;
980 }
981 
GetTopOwner(ObjPtr)982 struct ObjRec *GetTopOwner(ObjPtr)
983    struct ObjRec *ObjPtr;
984 {
985    struct ObjRec *top_owner=ObjPtr;
986 
987    while (top_owner->tmp_parent != NULL) {
988       top_owner = top_owner->tmp_parent;
989    }
990    return top_owner;
991 }
992