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/rcbox.c,v 1.12 2011/06/09 16:11:42 cvsps Exp $
19  */
20 
21 #define _INCLUDE_FROM_RCBOX_C_
22 
23 #include "tgifdefs.h"
24 
25 #include "attr.e"
26 #include "auxtext.e"
27 #include "box.e"
28 #include "cmd.e"
29 #include "color.e"
30 #include "choice.e"
31 #include "cursor.e"
32 #include "cutpaste.e"
33 #include "dialog.e"
34 #include "drawing.e"
35 #include "dup.e"
36 #include "file.e"
37 #include "grid.e"
38 #include "mainloop.e"
39 #include "mark.e"
40 #include "msg.e"
41 #include "obj.e"
42 #include "pattern.e"
43 #include "poly.e"
44 #include "ps.e"
45 #include "raster.e"
46 #include "rect.e"
47 #include "rcbox.e"
48 #include "ruler.e"
49 #include "select.e"
50 #include "setup.e"
51 #include "spline.e"
52 #include "strtbl.e"
53 #include "util.e"
54 #include "xpixmap.e"
55 
56 int rcBoxDrawn=FALSE;
57 
58 static XSegment rcbSegs[4];
59 static XArc rcbArcs[4];
60 static int rcbArcsInitialized=FALSE;
61 
SetRCBoxVertex(x1,y1,x2,y2,r)62 void SetRCBoxVertex(x1, y1, x2, y2, r)
63    int x1, y1, x2, y2, r;
64 {
65    register int inc_x, inc_y, d=2*r;
66 
67    inc_x = (x2 > x1);
68    inc_y = (y2 > y1);
69    rcbSegs[0].x1 = (inc_x) ? (x1+r) : (x1-r); rcbSegs[0].y1 = y1;
70    rcbSegs[0].x2 = (inc_x) ? (x2-r) : (x2+r); rcbSegs[0].y2 = y1;
71    rcbSegs[1].x1 = x2; rcbSegs[1].y1 = (inc_y) ? (y1+r) : (y1-r);
72    rcbSegs[1].x2 = x2; rcbSegs[1].y2 = (inc_y) ? (y2-r) : (y2+r);
73    rcbSegs[2].x1 = (inc_x) ? (x1+r) : (x1-r); rcbSegs[2].y1 = y2;
74    rcbSegs[2].x2 = (inc_x) ? (x2-r) : (x2+r); rcbSegs[2].y2 = y2;
75    rcbSegs[3].x1 = x1; rcbSegs[3].y1 = (inc_y) ? (y1+r) : (y1-r);
76    rcbSegs[3].x2 = x1; rcbSegs[3].y2 = (inc_y) ? (y2-r) : (y2+r);
77 
78    if (!rcbArcsInitialized) {
79       rcbArcsInitialized = TRUE;
80 
81       rcbArcs[0].angle1 = 90*64;   rcbArcs[0].angle2 = 90*64;
82       rcbArcs[1].angle1 = 0;       rcbArcs[1].angle2 = 90*64;
83       rcbArcs[2].angle1 = -90*64;  rcbArcs[2].angle2 = 90*64;
84       rcbArcs[3].angle1 = -180*64; rcbArcs[3].angle2 = 90*64;
85    }
86    rcbArcs[0].width=rcbArcs[1].width=rcbArcs[2].width=rcbArcs[3].width=d;
87    rcbArcs[0].height=rcbArcs[1].height=rcbArcs[2].height=rcbArcs[3].height=d;
88 
89    if (inc_x) {
90       if (inc_y) {
91          rcbArcs[0].x=x1; rcbArcs[0].y=y1;
92          rcbArcs[1].x=x2-d; rcbArcs[1].y=y1;
93          rcbArcs[2].x=x2-d; rcbArcs[2].y=y2-d;
94          rcbArcs[3].x=x1; rcbArcs[3].y=y2-d;
95       } else {
96          rcbArcs[0].x=x1; rcbArcs[0].y=y2;
97          rcbArcs[1].x=x2-d; rcbArcs[1].y=y2;
98          rcbArcs[2].x=x2-d; rcbArcs[2].y=y1-d;
99          rcbArcs[3].x=x1; rcbArcs[3].y=y1-d;
100       }
101    } else {
102       if (inc_y) {
103          rcbArcs[0].x=x2; rcbArcs[0].y=y1;
104          rcbArcs[1].x=x1-d; rcbArcs[1].y=y1;
105          rcbArcs[2].x=x1-d; rcbArcs[2].y=y2-d;
106          rcbArcs[3].x=x2; rcbArcs[3].y=y2-d;
107       } else {
108          rcbArcs[0].x=x2; rcbArcs[0].y=y2;
109          rcbArcs[1].x=x1-d; rcbArcs[1].y=y2;
110          rcbArcs[2].x=x1-d; rcbArcs[2].y=y1-d;
111          rcbArcs[3].x=x2; rcbArcs[3].y=y1-d;
112       }
113    }
114 }
115 
MyRCBox(window,gc,x1,y1,x2,y2,r)116 void MyRCBox(window, gc, x1, y1, x2, y2, r)
117    Window window;
118    GC gc;
119    int x1, y1, x2, y2, r;
120 {
121    if (abs(x1-x2) < 2*r || abs(y1-y2) < 2*r) {
122       MyBox(window, gc, x1, y1, x2, y2);
123    } else {
124       XDrawSegments(mainDisplay, window, gc, rcbSegs, 4);
125       XDrawArcs(mainDisplay, window, gc, rcbArcs, 4);
126    }
127 }
128 
129 static
MyFillRCBox(window,gc,x1,y1,x2,y2,r)130 void MyFillRCBox(window, gc, x1, y1, x2, y2, r)
131    Window window;
132    GC gc;
133    int x1, y1, x2, y2, r;
134 {
135    if (abs(x1-x2) < 2*r || abs(y1-y2) < 2*r) {
136       XFillRectangle(mainDisplay, window, gc, x1, y1, x2-x1, y2-y1);
137    } else {
138       XFillRectangle(mainDisplay, window, gc, x1+r, y1, x2-x1-2*r, y2-y1);
139       XFillRectangle(mainDisplay, window, gc, x1, y1+r, x2-x1, y2-y1-2*r);
140       XFillArcs(mainDisplay, window, gc, rcbArcs, 4);
141    }
142 }
143 
144 static
DumpRCBoxPSPath(FP,ltx,lty,rbx,rby,r,blank1,blank2)145 void DumpRCBoxPSPath(FP, ltx, lty, rbx, rby, r, blank1, blank2)
146    FILE *FP;
147    int ltx, lty, rbx, rby, r;
148    char *blank1, *blank2;
149 {
150    if (abs(ltx-rbx) < 2*r || abs(lty-rby) < 2*r) {
151       fprintf(FP, "%s%s\n%s%1d %1d %s ", blank1,
152             gPsCmd[PS_NEWPATH], blank2, rbx, lty, gPsCmd[PS_MOVETO]);
153       fprintf(FP, "%1d %1d %s ", rbx, rby, gPsCmd[PS_LINETO]);
154       fprintf(FP, "%1d %1d %s ", ltx, rby, gPsCmd[PS_LINETO]);
155       fprintf(FP, "%1d %1d %s\n", ltx, lty, gPsCmd[PS_LINETO]);
156    } else {
157       fprintf(FP, "%s%s\n%s%1d %1d %s\n", blank1,
158             gPsCmd[PS_NEWPATH], blank2, rbx-r, lty, gPsCmd[PS_MOVETO]);
159       fprintf(FP, "%s%1d %1d %1d %1d %1d %s\n", blank2,
160             rbx, lty, rbx, rby, r, gPsCmd[PS_ARCTO4]);
161       fprintf(FP, "%s%1d %1d %s\n", blank2, rbx, rby-r, gPsCmd[PS_LINETO]);
162       fprintf(FP, "%s%1d %1d %1d %1d %1d %s\n", blank2,
163             rbx, rby, ltx, rby, r, gPsCmd[PS_ARCTO4]);
164       fprintf(FP, "%s%1d %1d %s\n", blank2, ltx+r, rby, gPsCmd[PS_LINETO]);
165       fprintf(FP, "%s%1d %1d %1d %1d %1d %s\n", blank2,
166             ltx, rby, ltx, lty, r, gPsCmd[PS_ARCTO4]);
167       fprintf(FP, "%s%1d %1d %s\n", blank2, ltx, lty+r, gPsCmd[PS_LINETO]);
168       fprintf(FP, "%s%1d %1d %1d %1d %1d %s\n", blank2,
169             ltx, lty, rbx, lty, r, gPsCmd[PS_ARCTO4]);
170    }
171 }
172 
173 static
DumpRCBoxPath(FP,ObjPtr,ltx,lty,rbx,rby,r,width,pen,dash,trans_pat)174 void DumpRCBoxPath(FP, ObjPtr, ltx, lty, rbx, rby, r, width, pen, dash,
175       trans_pat)
176    FILE *FP;
177    struct ObjRec *ObjPtr;
178    int ltx, lty, rbx, rby, r, width, pen, dash, trans_pat;
179 {
180    register int i;
181    int w_is_int=TRUE;
182    char *width_spec=ObjPtr->detail.rcb->width_spec;
183    double dw=GetWidthInDouble(width, width_spec, &w_is_int);
184 
185    fprintf(FP, "   %s\n", gPsCmd[PS_GSAVE]);
186    if (!colorDump && useGray && pen > BACKPAT) {
187       GrayCheck(pen);
188       fprintf(FP, "      %s %s\n", GrayStr(pen), gPsCmd[PS_SETGRAY]);
189    }
190    DumpRCBoxPSPath(FP, ltx, lty, rbx, rby, r, "      ", "         ");
191    fprintf(FP, "      %s\n", gPsCmd[PS_CLOSEPATH]);
192 
193    if (ObjPtr->ctm != NULL) {
194       fprintf(FP, "      %s\n", &(gPsCmd[PS_TGIFSETMATRIX])[1]);
195    }
196    if (dash != 0) {
197       fprintf(FP, "      [");
198       for (i=0; i < dashListLength[dash]-1; i++) {
199          fprintf(FP, "%1d ", (int)(dashList[dash][i]));
200       }
201       fprintf(FP, "%1d] 0 %s\n",
202             (int)(dashList[dash][dashListLength[dash]-1]), gPsCmd[PS_SETDASH]);
203    }
204    if (w_is_int) {
205       if (width != 1) {
206          fprintf(FP, "      %1d %s\n", width, gPsCmd[PS_SETLINEWIDTH]);
207       }
208    } else {
209       fprintf(FP, "      %.3f %s\n", dw, gPsCmd[PS_SETLINEWIDTH]);
210    }
211    switch (pen) {
212    case SOLIDPAT: fprintf(FP, "      %s\n", gPsCmd[PS_STROKE]); break;
213    case BACKPAT:
214       fprintf(FP, "      1 %s %s 0 %s\n",
215             gPsCmd[PS_SETGRAY], gPsCmd[PS_STROKE], gPsCmd[PS_SETGRAY]);
216       break;
217    default:
218       if (colorDump || !useGray) {
219          if (preDumpSetup) PSUseColorPattern();
220          fprintf(FP, "      %s\n", gPsCmd[PS_FLATTENPATH]);
221          DumpPatFill(FP, pen, ObjPtr->bbox, 6, TRUE);
222       } else {
223          fprintf(FP, "      %s\n", gPsCmd[PS_STROKE]);
224       }
225       break;
226    }
227    fprintf(FP, "   %s\n", gPsCmd[PS_GRESTORE]);
228 }
229 
DumpRCBoxObj(FP,ObjPtr)230 void DumpRCBoxObj(FP, ObjPtr)
231    FILE *FP;
232    struct ObjRec *ObjPtr;
233 {
234    register int ltx, lty, rbx, rby;
235    int trans_pat, fill, width, pen, dash, color_index, r;
236 
237    if (ObjPtr->ctm == NULL) {
238       ltx = ObjPtr->obbox.ltx; lty = ObjPtr->obbox.lty;
239       rbx = ObjPtr->obbox.rbx; rby = ObjPtr->obbox.rby;
240    } else {
241       ltx = ObjPtr->orig_obbox.ltx; lty = ObjPtr->orig_obbox.lty;
242       rbx = ObjPtr->orig_obbox.rbx; rby = ObjPtr->orig_obbox.rby;
243    }
244 
245    trans_pat = ObjPtr->trans_pat;
246    fill = ObjPtr->detail.rcb->fill;
247    pen = ObjPtr->detail.rcb->pen;
248    width = ObjPtr->detail.rcb->width;
249    dash = ObjPtr->detail.rcb->dash;
250    r = ObjPtr->detail.rcb->radius;
251 
252    if ((fill == NONEPAT || (trans_pat && fill == BACKPAT)) &&
253          (pen == NONEPAT || (trans_pat && pen == BACKPAT))) {
254       return;
255    }
256    fprintf(FP, "%% RCBOX\n");
257    if (ObjPtr->ctm != NULL) {
258       float m[6];
259 
260       fprintf(FP, "%s\n", gPsCmd[PS_GSAVE]);
261       m[CTM_SX] = ((float)ObjPtr->ctm->m[CTM_SX])/((float)1000.0);
262       m[CTM_SY] = ((float)ObjPtr->ctm->m[CTM_SY])/((float)1000.0);
263       m[CTM_SIN] = ((float)ObjPtr->ctm->m[CTM_SIN])/((float)1000.0);
264       m[CTM_MSIN] = ((float)ObjPtr->ctm->m[CTM_MSIN])/((float)1000.0);
265       fprintf(FP, "   %1d %1d %s\n", ObjPtr->x, ObjPtr->y,
266             gPsCmd[PS_TRANSLATE]);
267       fprintf(FP, "   [%.3f %.3f %.3f %.3f %1d %1d] %s\n",
268             m[CTM_SX], m[CTM_SIN], m[CTM_MSIN], m[CTM_SY],
269             ObjPtr->ctm->t[CTM_TX], ObjPtr->ctm->t[CTM_TY], gPsCmd[PS_CONCAT]);
270       fprintf(FP, "   %1d %s %1d %s %s\n",
271             ObjPtr->x, gPsCmd[PS_NEG], ObjPtr->y, gPsCmd[PS_NEG],
272             gPsCmd[PS_TRANSLATE]);
273    }
274    color_index = ObjPtr->color;
275    DumpRGBColorLine(FP, color_index, 0, TRUE);
276 
277    switch (fill) {
278    case NONEPAT: break;
279    case SOLIDPAT:
280       DumpRCBoxPSPath(FP, ltx, lty, rbx, rby, r, "", "   ");
281       fprintf(FP, "%s %s\n", gPsCmd[PS_CLOSEPATH], gPsCmd[PS_FILL]);
282       break;
283    case BACKPAT:
284       if (!trans_pat) {
285          DumpRCBoxPSPath(FP, ltx, lty, rbx, rby, r, "", "   ");
286          fprintf(FP, "%s 1 %s %s\n",
287                gPsCmd[PS_CLOSEPATH], gPsCmd[PS_SETGRAY], gPsCmd[PS_FILL]);
288          DumpRGBColorLine(FP, color_index, 3, TRUE);
289       }
290       break;
291    default:
292       fprintf(FP, "%s\n", gPsCmd[PS_GSAVE]);
293       if (colorDump || !useGray) {
294          if (!trans_pat) {
295             DumpRCBoxPSPath(FP, ltx, lty, rbx, rby, r, "   ", "      ");
296             fprintf(FP, "   %s 1 %s %s\n", gPsCmd[PS_CLOSEPATH],
297                   gPsCmd[PS_SETGRAY], gPsCmd[PS_FILL]);
298             DumpRGBColorLine(FP, color_index, 3, TRUE);
299          }
300          DumpRCBoxPSPath(FP, ltx, lty, rbx, rby, r, "   ", "      ");
301          if (preDumpSetup) PSUseColorPattern();
302          fprintf(FP, "   %s %s %s\n", gPsCmd[PS_CLOSEPATH],
303                gPsCmd[PS_EOCLIP], gPsCmd[PS_NEWPATH]);
304          DumpPatFill(FP, fill, ObjPtr->bbox, 3, TRUE);
305       } else {
306          GrayCheck(fill);
307          fprintf(FP, "   %s %s\n", GrayStr(fill), gPsCmd[PS_SETGRAY]);
308          DumpRCBoxPSPath(FP, ltx, lty, rbx, rby, r, "   ", "      ");
309          fprintf(FP, "   %s %s\n", gPsCmd[PS_CLOSEPATH], gPsCmd[PS_FILL]);
310       }
311       fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]);
312       break;
313    }
314    if (pen == NONEPAT || (pen == BACKPAT && trans_pat)) {
315       if (ObjPtr->ctm != NULL) fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]);
316       fprintf(FP, "\n");
317       return;
318    }
319    fprintf(FP, "%s\n", gPsCmd[PS_GSAVE]);
320 
321    if ((colorDump || !useGray) && pen > BACKPAT && !trans_pat) {
322       DumpRCBoxPath(FP, ObjPtr, ltx, lty, rbx, rby, r, width, BACKPAT, 0,
323             trans_pat);
324       DumpRGBColorLine(FP, color_index, 3, TRUE);
325    }
326    DumpRCBoxPath(FP, ObjPtr, ltx, lty, rbx, rby, r, width, pen, dash,
327          trans_pat);
328 
329    fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]);
330    if (ObjPtr->ctm != NULL) fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]);
331    fprintf(FP, "\n");
332 }
333 
NeedsToCacheRCBoxObj(ObjPtr)334 int NeedsToCacheRCBoxObj(ObjPtr)
335    struct ObjRec *ObjPtr;
336 {
337    return (ObjPtr->ctm != NULL);
338 }
339 
340 static
MakeCachedRCBox(ObjPtr)341 void MakeCachedRCBox(ObjPtr)
342    struct ObjRec *ObjPtr;
343 {
344    struct RCBoxRec *rcbox_ptr=ObjPtr->detail.rcb;
345    XPoint *sv=NULL;
346    IntPoint *pv;
347    char *smooth=NULL;
348    struct BBRec obbox;
349    int i, w, h, sn;
350    int r=rcbox_ptr->radius, num_vs;
351 
352    if (ObjPtr->ctm == NULL) return;
353 
354    obbox.ltx = ObjPtr->orig_obbox.ltx - ObjPtr->x;
355    obbox.lty = ObjPtr->orig_obbox.lty - ObjPtr->y;
356    obbox.rbx = ObjPtr->orig_obbox.rbx - ObjPtr->x;
357    obbox.rby = ObjPtr->orig_obbox.rby - ObjPtr->y;
358    w = obbox.rbx - obbox.ltx;
359    h = obbox.rby - obbox.lty;
360    num_vs = (w < (r<<1) || h < (r<<1)) ? 5 : 13;
361 
362    if (rcbox_ptr->rotated_vlist != NULL) free(rcbox_ptr->rotated_vlist);
363    rcbox_ptr->rotated_n = 0;
364    rcbox_ptr->rotated_vlist = (XPoint*)malloc((num_vs+1)*sizeof(XPoint));
365    pv = (IntPoint*)malloc((num_vs+1)*sizeof(IntPoint));
366    if (rcbox_ptr->rotated_vlist == NULL || pv == NULL) FailAllocMessage();
367    if (num_vs == 13) {
368       smooth = (char*)malloc((num_vs+1)*sizeof(char));
369       if (smooth == NULL) FailAllocMessage();
370    }
371    if (num_vs == 5) {
372       pv[0].x = obbox.ltx; pv[0].y = obbox.lty;
373       pv[1].x = obbox.rbx; pv[1].y = obbox.lty;
374       pv[2].x = obbox.rbx; pv[2].y = obbox.rby;
375       pv[3].x = obbox.ltx; pv[3].y = obbox.rby;
376       pv[4].x = pv[0].x; pv[4].y = pv[0].y;
377    } else {
378       pv[0].x  = obbox.ltx;   pv[0].y  = obbox.lty;
379       pv[1].x  = obbox.ltx+r; pv[1].y  = obbox.lty;
380       pv[2].x  = obbox.rbx-r; pv[2].y  = obbox.lty;
381       pv[3].x  = obbox.rbx;   pv[3].y  = obbox.lty;
382       pv[4].x  = obbox.rbx;   pv[4].y  = obbox.lty+r;
383       pv[5].x  = obbox.rbx;   pv[5].y  = obbox.rby-r;
384       pv[6].x  = obbox.rbx;   pv[6].y  = obbox.rby;
385       pv[7].x  = obbox.rbx-r; pv[7].y  = obbox.rby;
386       pv[8].x  = obbox.ltx+r; pv[8].y  = obbox.rby;
387       pv[9].x  = obbox.ltx;   pv[9].y  = obbox.rby;
388       pv[10].x = obbox.ltx;   pv[10].y = obbox.rby-r;
389       pv[11].x = obbox.ltx;   pv[11].y = obbox.lty+r;
390       pv[12].x = pv[0].x; pv[12].y = pv[0].y;
391       for (i=0; i < num_vs; i++) smooth[i] = FALSE;
392       smooth[0] = smooth[3] = smooth[6] = smooth[9] = smooth[12] = TRUE;
393    }
394    for (i=0; i < num_vs; i++) {
395       int x, y;
396 
397       TransformPointThroughCTM(pv[i].x, pv[i].y, ObjPtr->ctm, &x, &y);
398       pv[i].x = x + ObjPtr->x;
399       pv[i].y = y + ObjPtr->y;
400       rcbox_ptr->rotated_vlist[i].x = (short)OFFSET_X(pv[i].x);
401       rcbox_ptr->rotated_vlist[i].y = (short)OFFSET_Y(pv[i].y);
402    }
403    if (num_vs == 13) {
404       sv = MakeMultiSplinePolygonVertex(LT_SPLINE, &sn, smooth, drawOrigX,
405             drawOrigY, num_vs, pv);
406       if (sv == NULL) FailAllocMessage();
407       free(rcbox_ptr->rotated_vlist);
408       rcbox_ptr->rotated_n = sn;
409       rcbox_ptr->rotated_vlist = sv;
410    } else {
411       rcbox_ptr->rotated_n = num_vs;
412    }
413    free(pv);
414    if (smooth != NULL) free(smooth);
415 }
416 
DrawRCBoxObj(win,XOff,YOff,ObjPtr)417 void DrawRCBoxObj(win, XOff, YOff, ObjPtr)
418    Window win;
419    int XOff, YOff;
420    struct ObjRec *ObjPtr;
421 {
422    struct RCBoxRec *rcbox_ptr=ObjPtr->detail.rcb;
423    int trans_pat, fill, pen, pixel, ltx, lty, rbx, rby, width, dash;
424    int real_x_off, real_y_off, radius;
425    XGCValues values;
426 
427    trans_pat = ObjPtr->trans_pat;
428    pen = rcbox_ptr->pen;
429    fill = rcbox_ptr->fill;
430    width = rcbox_ptr->width;
431    dash = rcbox_ptr->dash;
432    radius = ZOOMED_SIZE(rcbox_ptr->radius);
433    pixel = colorPixels[ObjPtr->color];
434 
435    if (NeedsToCacheRCBoxObj(ObjPtr) && rcbox_ptr->rotated_vlist==NULL) {
436       MakeCachedRCBox(ObjPtr);
437    }
438    if (userDisableRedraw) return;
439 
440    if ((fill == NONEPAT || (trans_pat && fill == BACKPAT)) &&
441          (pen == NONEPAT || (trans_pat && pen == BACKPAT))) {
442       return;
443    }
444    real_x_off = (zoomedIn ? XOff : (XOff>>zoomScale)<<zoomScale);
445    real_y_off = (zoomedIn ? YOff : (YOff>>zoomScale)<<zoomScale);
446    ltx = ZOOMED_SIZE(ObjPtr->obbox.ltx - real_x_off);
447    lty = ZOOMED_SIZE(ObjPtr->obbox.lty - real_y_off);
448    rbx = ZOOMED_SIZE(ObjPtr->obbox.rbx - real_x_off);
449    rby = ZOOMED_SIZE(ObjPtr->obbox.rby - real_y_off);
450 
451    SetRCBoxVertex(ltx, lty, rbx, rby, radius);
452 
453    if (fill != NONEPAT) {
454       values.foreground = GetDrawingBgPixel(fill, pixel);
455       values.function = GXcopy;
456       values.fill_style = (trans_pat ? FillStippled : FillOpaqueStippled);
457       values.stipple = patPixmap[fill];
458       XChangeGC(mainDisplay, drawGC,
459             GCForeground | GCFunction | GCFillStyle | GCStipple, &values);
460       if (ObjPtr->ctm != NULL) {
461          XFillPolygon(mainDisplay, win, drawGC, rcbox_ptr->rotated_vlist,
462                rcbox_ptr->rotated_n, Convex, CoordModeOrigin);
463       } else {
464          MyFillRCBox(win, drawGC, ltx, lty, rbx, rby, radius);
465       }
466    }
467    if (pen != NONEPAT) {
468       values.foreground = GetDrawingBgPixel(pen, pixel);
469       values.function = GXcopy;
470       values.fill_style = (trans_pat ? FillStippled : FillOpaqueStippled);
471       values.stipple = patPixmap[pen];
472       values.line_width = ZOOMED_SIZE(width);
473 #ifdef NO_THIN_LINE
474       if (values.line_width < 1) values.line_width = 1;
475 #else
476 #ifdef THIN_OVAL_AND_ARC
477       if (values.line_width <= 1) values.line_width = 0;
478 #endif
479 #endif
480       if (dash != 0) {
481          XSetDashes(mainDisplay, drawGC, 0, dashList[dash],
482                dashListLength[dash]);
483          values.line_style = LineOnOffDash;
484       } else {
485          values.line_style = LineSolid;
486       }
487       XChangeGC(mainDisplay, drawGC,
488             GCForeground | GCFunction | GCFillStyle | GCStipple | GCLineWidth |
489             GCLineStyle, &values);
490       if (ObjPtr->ctm != NULL) {
491          XDrawLines(mainDisplay, win, drawGC, rcbox_ptr->rotated_vlist,
492                rcbox_ptr->rotated_n, CoordModeOrigin);
493       } else {
494          MyRCBox(win, drawGC, ltx, lty, rbx, rby, radius);
495       }
496    }
497 }
498 
CreateRCBoxObj(X1,Y1,X2,Y2,CreateAbsolute)499 void CreateRCBoxObj(X1, Y1, X2, Y2, CreateAbsolute)
500    int X1, Y1, X2, Y2, CreateAbsolute;
501 {
502    struct RCBoxRec *rcbox_ptr;
503    struct ObjRec *obj_ptr;
504    int width, w, ltx, lty, rbx, rby;
505 
506    rcbox_ptr = (struct RCBoxRec *)malloc(sizeof(struct RCBoxRec));
507    if (rcbox_ptr == NULL) FailAllocMessage();
508    memset(rcbox_ptr, 0, sizeof(struct RCBoxRec));
509    rcbox_ptr->fill = objFill;
510    rcbox_ptr->width = width = curWidthOfLine[lineWidth];
511    UtilStrCpyN(rcbox_ptr->width_spec, sizeof(rcbox_ptr->width_spec),
512          curWidthOfLineSpec[lineWidth]);
513    rcbox_ptr->pen = penPat;
514    rcbox_ptr->dash = curDash;
515    rcbox_ptr->radius = rcbRadius;
516 
517    rcbox_ptr->rotated_n = 0;
518    rcbox_ptr->rotated_vlist = NULL;
519 
520    obj_ptr = (struct ObjRec *)malloc(sizeof(struct ObjRec));
521    if (obj_ptr == NULL) FailAllocMessage();
522    memset(obj_ptr, 0, sizeof(struct ObjRec));
523 
524    if (X1 < X2) {
525       if (Y1 < Y2) {
526          ltx = X1; lty = Y1; rbx = X2; rby = Y2;
527       } else {
528          ltx = X1; lty = Y2; rbx = X2; rby = Y1;
529       }
530    } else {
531       if (Y1 < Y2) {
532          ltx = X2; lty = Y1; rbx = X1; rby = Y2;
533       } else {
534          ltx = X2; lty = Y2; rbx = X1; rby = Y1;
535       }
536    }
537    if (CreateAbsolute) {
538       obj_ptr->bbox.ltx = obj_ptr->obbox.ltx = obj_ptr->x = ltx;
539       obj_ptr->bbox.lty = obj_ptr->obbox.lty = obj_ptr->y = lty;
540       obj_ptr->bbox.rbx = obj_ptr->obbox.rbx = rbx;
541       obj_ptr->bbox.rby = obj_ptr->obbox.rby = rby;
542    } else {
543       obj_ptr->bbox.ltx = obj_ptr->obbox.ltx = obj_ptr->x = ABS_X(ltx);
544       obj_ptr->bbox.lty = obj_ptr->obbox.lty = obj_ptr->y = ABS_Y(lty);
545       obj_ptr->bbox.rbx = obj_ptr->obbox.rbx = ABS_X(rbx);
546       obj_ptr->bbox.rby = obj_ptr->obbox.rby = ABS_Y(rby);
547    }
548    w = HALF_W(width);
549    obj_ptr->bbox.ltx -= w;
550    obj_ptr->bbox.lty -= w;
551    obj_ptr->bbox.rbx += w;
552    obj_ptr->bbox.rby += w;
553    obj_ptr->type = OBJ_RCBOX;
554    obj_ptr->color = colorIndex;
555    if (mainDisplay != NULL) {
556       UtilStrCpyN(obj_ptr->color_str, sizeof(obj_ptr->color_str),
557             colorMenuItems[colorIndex]);
558    }
559    obj_ptr->id = objId++;
560    obj_ptr->dirty = FALSE;
561    obj_ptr->rotation = 0;
562    obj_ptr->locked = FALSE;
563    obj_ptr->detail.rcb = rcbox_ptr;
564    obj_ptr->fattr = obj_ptr->lattr = NULL;
565    obj_ptr->ctm = NULL;
566    obj_ptr->invisible = FALSE;
567    obj_ptr->trans_pat = transPat;
568 
569    AddObj(NULL, topObj, obj_ptr);
570 }
571 
572 static
ContinueRCBox(OrigX,OrigY)573 void ContinueRCBox(OrigX, OrigY)
574    int OrigX, OrigY;
575 {
576    int end_x, end_y, grid_x, grid_y, saved_x, saved_y;
577    int done=FALSE, abort=FALSE;
578    int radius=ZOOMED_SIZE(rcbRadius);
579    char buf[80], w_buf[80], h_buf[80], x_buf[80], y_buf[80];
580    XEvent input, ev;
581    XMotionEvent *motion_ev;
582 
583    SetXorDrawGC(xorColorPixels[colorIndex]);
584 
585    saved_x = grid_x = OrigX;
586    saved_y = grid_y = OrigY;
587    PixelToMeasurementUnit(w_buf, 0);
588    PixelToMeasurementUnit(h_buf, 0);
589    PixelToMeasurementUnit(x_buf, ABS_X(grid_x));
590    PixelToMeasurementUnit(y_buf, ABS_Y(grid_y));
591    sprintf(buf, "w=%s\nh=%s\nx=%s\ny=%s", w_buf, h_buf, x_buf, y_buf);
592    StartShowMeasureCursor(grid_x, grid_y, buf, TRUE);
593    BeginIntervalRulers(grid_x, grid_y, grid_x, grid_y);
594    if (!debugNoPointerGrab) {
595       XGrabPointer(mainDisplay, drawWindow, FALSE,
596             PointerMotionMask | ButtonReleaseMask,
597             GrabModeAsync, GrabModeAsync, None, handCursor, CurrentTime);
598    }
599    SetRCBoxVertex(OrigX, OrigY, saved_x, saved_y, radius);
600    while (!done) {
601       XNextEvent(mainDisplay, &input);
602 
603       if (input.type == Expose || input.type == VisibilityNotify) {
604          ExposeEventHandler(&input, TRUE);
605          SetXorDrawGC(xorColorPixels[colorIndex]);
606       } else if (input.type == ButtonRelease) {
607          XUngrabPointer(mainDisplay, CurrentTime);
608          MyRCBox(drawWindow,drawGC,OrigX,OrigY,saved_x,saved_y,radius);
609          EndIntervalRulers(grid_x, grid_y);
610          PixelToMeasurementUnit(w_buf, ABS_SIZE(abs(saved_x-OrigX)));
611          PixelToMeasurementUnit(h_buf, ABS_SIZE(abs(saved_y-OrigY)));
612          PixelToMeasurementUnit(x_buf, ABS_X(saved_x));
613          PixelToMeasurementUnit(y_buf, ABS_Y(saved_y));
614          sprintf(buf, "w=%s\nh=%s\nx=%s\ny=%s", w_buf, h_buf, x_buf, y_buf);
615          EndShowMeasureCursor(saved_x, saved_y, buf, TRUE);
616          done = TRUE;
617       } else if (input.type == MotionNotify) {
618          motion_ev = &(input.xmotion);
619          end_x = motion_ev->x;
620          end_y = motion_ev->y;
621          GridXY(end_x, end_y, &grid_x, &grid_y);
622          if (motion_ev->state & (ShiftMask | ControlMask)) {
623             int w, h, pos_w=TRUE, pos_h=TRUE;
624 
625             w = grid_x - OrigX;
626             h = grid_y - OrigY;
627             if (w < 0) {
628                w = (-w);
629                pos_w = FALSE;
630             }
631             if (h < 0) {
632                h = (-h);
633                pos_h = FALSE;
634             }
635             if (w > h) {
636                grid_x = (pos_w ? (OrigX+h) : (OrigX-h));
637             } else {
638                grid_y = (pos_h ? (OrigY+w) : (OrigY-w));
639             }
640          }
641          if (grid_x != saved_x || grid_y != saved_y) {
642             PixelToMeasurementUnit(w_buf, ABS_SIZE(abs(saved_x-OrigX)));
643             PixelToMeasurementUnit(h_buf, ABS_SIZE(abs(saved_y-OrigY)));
644             PixelToMeasurementUnit(x_buf, ABS_X(saved_x));
645             PixelToMeasurementUnit(y_buf, ABS_Y(saved_y));
646             sprintf(buf, "w=%s\nh=%s\nx=%s\ny=%s", w_buf, h_buf, x_buf, y_buf);
647             ShowMeasureCursor(saved_x, saved_y, buf, TRUE);
648             MyRCBox(drawWindow,drawGC,OrigX,OrigY,saved_x,saved_y,radius);
649             saved_x = grid_x;
650             saved_y = grid_y;
651             SetRCBoxVertex(OrigX, OrigY, saved_x, saved_y, radius);
652             MyRCBox(drawWindow,drawGC,OrigX,OrigY,saved_x,saved_y,radius);
653             PixelToMeasurementUnit(w_buf, ABS_SIZE(abs(saved_x-OrigX)));
654             PixelToMeasurementUnit(h_buf, ABS_SIZE(abs(saved_y-OrigY)));
655             PixelToMeasurementUnit(x_buf, ABS_X(saved_x));
656             PixelToMeasurementUnit(y_buf, ABS_Y(saved_y));
657             sprintf(buf, "w=%s\nh=%s\nx=%s\ny=%s", w_buf, h_buf, x_buf, y_buf);
658             ShowMeasureCursor(saved_x, saved_y, buf, TRUE);
659          }
660          DrawIntervalRulers(OrigX, OrigY, grid_x, grid_y, NULL);
661          while (XCheckMaskEvent(mainDisplay, PointerMotionMask, &ev)) ;
662       } else if (input.type == KeyPress) {
663          if (KeyPressEventIsEscape(&input.xkey)) {
664             XUngrabPointer(mainDisplay, CurrentTime);
665             MyRCBox(drawWindow,drawGC,OrigX,OrigY,saved_x,saved_y,radius);
666             EndIntervalRulers(grid_x, grid_y);
667             PixelToMeasurementUnit(w_buf, ABS_SIZE(abs(saved_x-OrigX)));
668             PixelToMeasurementUnit(h_buf, ABS_SIZE(abs(saved_y-OrigY)));
669             PixelToMeasurementUnit(x_buf, ABS_X(saved_x));
670             PixelToMeasurementUnit(y_buf, ABS_Y(saved_y));
671             sprintf(buf, "w=%s\nh=%s\nx=%s\ny=%s", w_buf, h_buf, x_buf, y_buf);
672             EndShowMeasureCursor(saved_x, saved_y, buf, TRUE);
673             abort = TRUE;
674             done = TRUE;
675          }
676       }
677    }
678    if (!abort && OrigX != grid_x && OrigY != grid_y) {
679       CreateRCBoxObj(OrigX, OrigY, grid_x, grid_y, FALSE);
680       RecordNewObjCmd();
681       DrawRCBoxObj(drawWindow, drawOrigX, drawOrigY, topObj);
682       rcBoxDrawn = TRUE;
683       SetFileModified(TRUE);
684    }
685    XSync(mainDisplay, False);
686 }
687 
DrawRCBox(input)688 void DrawRCBox(input)
689    XEvent *input;
690 {
691    XButtonEvent *button_ev;
692    int mouse_x, mouse_y, grid_x, grid_y;
693 
694    if (input->type != ButtonPress) return;
695 
696    button_ev = &(input->xbutton);
697    if (button_ev->button == Button1) {
698       mouse_x = button_ev->x;
699       mouse_y = button_ev->y;
700       GridXY(mouse_x, mouse_y, &grid_x, &grid_y);
701       ContinueRCBox(grid_x, grid_y);
702    }
703 }
704 
MakeRCBoxObjFromBoundingBox()705 void MakeRCBoxObjFromBoundingBox()
706 {
707    if (topSel == NULL) {
708       MsgBox(TgLoadCachedString(CSTID_NO_OBJ_SELECTED), TOOL_NAME, INFO_MB);
709       return;
710    }
711    if (curChoice == VERTEXMODE) SetCurChoice(NOTHING);
712 
713    HighLightReverse();
714    CreateRCBoxObj(selObjLtX, selObjLtY, selObjRbX, selObjRbY, TRUE);
715    SelectTopObj();
716    RecordNewObjCmd();
717    RedrawAnArea(botObj, selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
718          selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
719    HighLightForward();
720    justDupped = FALSE;
721    SetFileModified(TRUE);
722 }
723 
SaveRCBoxObj(FP,ObjPtr)724 void SaveRCBoxObj(FP, ObjPtr)
725    FILE *FP;
726    struct ObjRec *ObjPtr;
727 {
728    struct RCBoxRec *rcbox_ptr=ObjPtr->detail.rcb;
729 
730    if (fprintf(FP, "rcbox('%s','',", colorMenuItems[ObjPtr->color]) == EOF) {
731       writeFileFailed = TRUE;
732    }
733    if (fprintf(FP,
734          "%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,'%s',%1d,",
735          ObjPtr->obbox.ltx, ObjPtr->obbox.lty, ObjPtr->obbox.rbx,
736          ObjPtr->obbox.rby, rcbox_ptr->fill, rcbox_ptr->width, rcbox_ptr->pen,
737          rcbox_ptr->dash, rcbox_ptr->radius, ObjPtr->id, ObjPtr->rotation,
738          ObjPtr->locked, ObjPtr->ctm!=NULL, ObjPtr->invisible,
739          rcbox_ptr->width_spec, ObjPtr->trans_pat) == EOF) {
740       writeFileFailed = TRUE;
741    }
742    if (ObjPtr->ctm != NULL && fprintf(FP,
743          "[\n    %1d,%1d,%1d,%1d,%1d,%1d,%g,%g,%g,%g,%1d,%1d],",
744          ObjPtr->x, ObjPtr->y,
745          ObjPtr->orig_obbox.ltx, ObjPtr->orig_obbox.lty,
746          ObjPtr->orig_obbox.rbx, ObjPtr->orig_obbox.rby,
747          ObjPtr->ctm->m[CTM_SX], ObjPtr->ctm->m[CTM_SIN],
748          ObjPtr->ctm->m[CTM_MSIN], ObjPtr->ctm->m[CTM_SY],
749          ObjPtr->ctm->t[CTM_TX], ObjPtr->ctm->t[CTM_TY]) == EOF) {
750       writeFileFailed = TRUE;
751    }
752    if (serializingFile) SaveCreatorID(FP, ObjPtr, "    ");
753    SaveAttrs(FP, ObjPtr->lattr);
754    if (fprintf(FP, ")") == EOF) writeFileFailed = TRUE;
755 }
756 
ReadRCBoxObj(FP,Inbuf,ObjPtr)757 void ReadRCBoxObj(FP, Inbuf, ObjPtr)
758    FILE *FP;
759    char *Inbuf;
760    struct ObjRec **ObjPtr;
761 {
762    struct RCBoxRec *rcbox_ptr;
763    char color_str[40], bg_color_str[40], *s, msg[MAXSTRING], width_spec[40];
764    int ltx, lty, rbx, rby, trans_pat=FALSE, fill, width, pen, dash, radius;
765    int rotation, new_alloc, id=0, w, locked=FALSE;
766    int transformed=FALSE, invisible=FALSE;
767 
768    *ObjPtr = NULL;
769 
770    s = FindChar((int)'(', Inbuf);
771    s = ParseStr(s, (int)',', color_str, sizeof(color_str));
772    if (fileVersion >= 37) {
773       s = ParseStr(s, (int)',', bg_color_str, sizeof(bg_color_str));
774    }
775    InitScan(s, ", \t\n");
776 
777    rotation = 0;
778    *width_spec = '\0';
779    if (fileVersion <= 8) {
780       sprintf(msg, TgLoadCachedString(CSTID_FILEVER_TOO_LARGE_FOR_RCBOX),
781             fileVersion);
782       if (PRTGIF) {
783          fprintf(stderr, "%s\n", msg);
784       } else {
785          Msg(msg);
786       }
787       return;
788    } else if (fileVersion <= 13) {
789       if (GETINT("rcbox", ltx,      "ltx") == INVALID ||
790           GETINT("rcbox", lty,      "lty") == INVALID ||
791           GETINT("rcbox", rbx,      "rbx") == INVALID ||
792           GETINT("rcbox", rby,      "rby") == INVALID ||
793           GETINT("rcbox", fill,     "fill") == INVALID ||
794           GETINT("rcbox", width,    "width") == INVALID ||
795           GETINT("rcbox", pen,      "pen") == INVALID ||
796           GETINT("rcbox", dash,     "dash") == INVALID ||
797           GETINT("rcbox", radius,   "radius") == INVALID ||
798           GETINT("rcbox", id,       "id") == INVALID) {
799          return;
800       }
801       if (id >= objId) objId = id+1;
802    } else if (fileVersion <= 25) {
803       if (GETINT("rcbox", ltx,      "ltx") == INVALID ||
804           GETINT("rcbox", lty,      "lty") == INVALID ||
805           GETINT("rcbox", rbx,      "rbx") == INVALID ||
806           GETINT("rcbox", rby,      "rby") == INVALID ||
807           GETINT("rcbox", fill,     "fill") == INVALID ||
808           GETINT("rcbox", width,    "width") == INVALID ||
809           GETINT("rcbox", pen,      "pen") == INVALID ||
810           GETINT("rcbox", dash,     "dash") == INVALID ||
811           GETINT("rcbox", radius,   "radius") == INVALID ||
812           GETINT("rcbox", id,       "id") == INVALID ||
813           GETINT("rcbox", rotation, "rotation") == INVALID) {
814          return;
815       }
816       if (id >= objId) objId = id+1;
817    } else if (fileVersion <= 32) {
818       if (GETINT("rcbox", ltx,      "ltx") == INVALID ||
819           GETINT("rcbox", lty,      "lty") == INVALID ||
820           GETINT("rcbox", rbx,      "rbx") == INVALID ||
821           GETINT("rcbox", rby,      "rby") == INVALID ||
822           GETINT("rcbox", fill,     "fill") == INVALID ||
823           GETINT("rcbox", width,    "width") == INVALID ||
824           GETINT("rcbox", pen,      "pen") == INVALID ||
825           GETINT("rcbox", dash,     "dash") == INVALID ||
826           GETINT("rcbox", radius,   "radius") == INVALID ||
827           GETINT("rcbox", id,       "id") == INVALID ||
828           GETINT("rcbox", rotation, "rotation") == INVALID ||
829           GETINT("rcbox", locked,   "locked") == INVALID) {
830          return;
831       }
832       if (id >= objId) objId = id+1;
833    } else if (fileVersion <= 34) {
834       if (GETINT("rcbox", ltx,         "ltx") == INVALID ||
835           GETINT("rcbox", lty,         "lty") == INVALID ||
836           GETINT("rcbox", rbx,         "rbx") == INVALID ||
837           GETINT("rcbox", rby,         "rby") == INVALID ||
838           GETINT("rcbox", fill,        "fill") == INVALID ||
839           GETINT("rcbox", width,       "width") == INVALID ||
840           GETINT("rcbox", pen,         "pen") == INVALID ||
841           GETINT("rcbox", dash,        "dash") == INVALID ||
842           GETINT("rcbox", radius,      "radius") == INVALID ||
843           GETINT("rcbox", id,          "id") == INVALID ||
844           GETINT("rcbox", rotation,    "rotation") == INVALID ||
845           GETINT("rcbox", locked,      "locked") == INVALID ||
846           GETINT("rcbox", transformed, "transformed") == INVALID ||
847           GETINT("rcbox", invisible,   "invisible") == INVALID ||
848           GETSTR("rcbox", width_spec,  "width_spec") == INVALID) {
849          return;
850       }
851       if (id >= objId) objId = id+1;
852       UtilRemoveQuotes(width_spec);
853    } else {
854       if (GETINT("rcbox", ltx,         "ltx") == INVALID ||
855           GETINT("rcbox", lty,         "lty") == INVALID ||
856           GETINT("rcbox", rbx,         "rbx") == INVALID ||
857           GETINT("rcbox", rby,         "rby") == INVALID ||
858           GETINT("rcbox", fill,        "fill") == INVALID ||
859           GETINT("rcbox", width,       "width") == INVALID ||
860           GETINT("rcbox", pen,         "pen") == INVALID ||
861           GETINT("rcbox", dash,        "dash") == INVALID ||
862           GETINT("rcbox", radius,      "radius") == INVALID ||
863           GETINT("rcbox", id,          "id") == INVALID ||
864           GETINT("rcbox", rotation,    "rotation") == INVALID ||
865           GETINT("rcbox", locked,      "locked") == INVALID ||
866           GETINT("rcbox", transformed, "transformed") == INVALID ||
867           GETINT("rcbox", invisible,   "invisible") == INVALID ||
868           GETSTR("rcbox", width_spec,  "width_spec") == INVALID ||
869           GETINT("rcbox", trans_pat,   "trans_pat") == INVALID) {
870          return;
871       }
872       if (id >= objId) objId = id+1;
873       UtilRemoveQuotes(width_spec);
874    }
875    if (ltx > rbx || lty > rby) {
876       int tmp_ltx, tmp_lty, tmp_rbx, tmp_rby;
877 
878       if (!PRTGIF) Msg(TgLoadCachedString(CSTID_BAD_RCBOX_BBOX_ADJUSTED));
879       CalcBBox(ltx, lty, rbx, rby, &tmp_ltx, &tmp_lty, &tmp_rbx, &tmp_rby);
880       ltx = tmp_ltx; lty = tmp_lty; rbx = tmp_rbx; rby = tmp_rby;
881    }
882 
883    if (fileVersion <= 16 && width <= 6) width = origWidthOfLine[width];
884    if (fileVersion <= 32) {
885       sprintf(width_spec, "%1d", width);
886    }
887    fill = UpgradePenFill(fill);
888    pen = UpgradePenFill(pen);
889 
890    *ObjPtr = (struct ObjRec *)malloc(sizeof(struct ObjRec));
891    if (*ObjPtr == NULL) FailAllocMessage();
892    memset(*ObjPtr, 0, sizeof(struct ObjRec));
893    rcbox_ptr = (struct RCBoxRec *)malloc(sizeof(struct RCBoxRec));
894    if (rcbox_ptr == NULL) FailAllocMessage();
895    memset(rcbox_ptr, 0, sizeof(struct RCBoxRec));
896 
897    rcbox_ptr->fill = fill;
898    rcbox_ptr->width = width;
899    UtilStrCpyN(rcbox_ptr->width_spec, sizeof(rcbox_ptr->width_spec),
900          width_spec);
901    rcbox_ptr->pen = pen;
902    rcbox_ptr->dash = dash;
903    rcbox_ptr->radius = radius;
904 
905    rcbox_ptr->rotated_n = 0;
906    rcbox_ptr->rotated_vlist = NULL;
907 
908    (*ObjPtr)->x = ltx;
909    (*ObjPtr)->y = lty;
910    (*ObjPtr)->color = QuickFindColorIndex(*ObjPtr, color_str, &new_alloc, TRUE);
911    UtilStrCpyN((*ObjPtr)->color_str, sizeof((*ObjPtr)->color_str), color_str);
912    (*ObjPtr)->dirty = FALSE;
913    (*ObjPtr)->id = id;
914    (*ObjPtr)->rotation = rotation;
915    (*ObjPtr)->locked = locked;
916    (*ObjPtr)->type = OBJ_RCBOX;
917    (*ObjPtr)->obbox.ltx = ltx;
918    (*ObjPtr)->obbox.lty = lty;
919    (*ObjPtr)->obbox.rbx = rbx;
920    (*ObjPtr)->obbox.rby = rby;
921    w = HALF_W(width);
922    (*ObjPtr)->bbox.ltx = ltx - w;
923    (*ObjPtr)->bbox.lty = lty - w;
924    (*ObjPtr)->bbox.rbx = rbx + w;
925    (*ObjPtr)->bbox.rby = rby + w;
926    (*ObjPtr)->detail.rcb = rcbox_ptr;
927    (*ObjPtr)->ctm = NULL;
928    (*ObjPtr)->invisible = invisible;
929    (*ObjPtr)->trans_pat = trans_pat;
930    if (fileVersion >= 33 && transformed) {
931       int real_x=0, real_y=0;
932       struct BBRec orig_obbox;
933       char inbuf[MAXSTRING+1];
934       struct XfrmMtrxRec *ctm;
935 
936       (void)fgets(inbuf, MAXSTRING, FP);
937       scanLineNum++;
938       InitScan(inbuf, "\t\n, ");
939 
940       ctm = (struct XfrmMtrxRec *)malloc(sizeof(struct XfrmMtrxRec));
941       if (ctm == NULL) FailAllocMessage();
942       if (GETINT("rcbox", real_x,           "real_x") == INVALID ||
943           GETINT("rcbox", real_y,           "real_y") == INVALID ||
944           GETINT("rcbox", orig_obbox.ltx,   "orig_obbox.ltx") == INVALID ||
945           GETINT("rcbox", orig_obbox.lty,   "orig_obbox.lty") == INVALID ||
946           GETINT("rcbox", orig_obbox.rbx,   "orig_obbox.rbx") == INVALID ||
947           GETINT("rcbox", orig_obbox.rby,   "orig_obbox.rby") == INVALID ||
948           GETDBL("rcbox", ctm->m[CTM_SX],   "CTM_SX") == INVALID ||
949           GETDBL("rcbox", ctm->m[CTM_SIN],  "CTM_SIN") == INVALID ||
950           GETDBL("rcbox", ctm->m[CTM_MSIN], "CTM_MSIN") == INVALID ||
951           GETDBL("rcbox", ctm->m[CTM_SY],   "CTM_SY") == INVALID ||
952           GETINT("rcbox", ctm->t[CTM_TX],   "CTM_TX") == INVALID ||
953           GETINT("rcbox", ctm->t[CTM_TY],   "CTM_TY") == INVALID) {
954          return;
955       }
956       (*ObjPtr)->ctm = ctm;
957       if (ctm != NULL) {
958          memcpy(&(*ObjPtr)->orig_obbox, &orig_obbox, sizeof(struct BBRec));
959          (*ObjPtr)->x = real_x;
960          (*ObjPtr)->y = real_y;
961          GetTransformedOBBoxOffsetVs(*ObjPtr, (*ObjPtr)->rotated_obbox);
962       }
963    }
964 }
965 
SetRCBoxPropMask(ObjPtr,plMask,plSkip,pProp)966 void SetRCBoxPropMask(ObjPtr, plMask, plSkip, pProp)
967    struct ObjRec *ObjPtr;
968    long *plMask, *plSkip;
969    struct PropertiesRec *pProp;
970 {
971    struct RCBoxRec *rcbox_ptr=ObjPtr->detail.rcb;
972 
973    SetCTMPropertyMask(ObjPtr->ctm, plMask, plSkip, pProp);
974 
975    SetIntPropertyMask(PROP_MASK_COLOR, ObjPtr->color,
976          colorMenuItems[ObjPtr->color], plMask, plSkip, pProp);
977    SetIntPropertyMask(PROP_MASK_WIDTH, rcbox_ptr->width, rcbox_ptr->width_spec,
978          plMask, plSkip, pProp);
979 
980    SetIntPropertyMask(PROP_MASK_TRANSPAT, ObjPtr->trans_pat, NULL,
981          plMask, plSkip, pProp);
982    SetIntPropertyMask(PROP_MASK_FILL, rcbox_ptr->fill, NULL,
983          plMask, plSkip, pProp);
984    SetIntPropertyMask(PROP_MASK_PEN, rcbox_ptr->pen, NULL,
985          plMask, plSkip, pProp);
986    SetIntPropertyMask(PROP_MASK_DASH, rcbox_ptr->dash, NULL,
987          plMask, plSkip, pProp);
988    SetIntPropertyMask(PROP_MASK_RCB_RADIUS, rcbox_ptr->radius, NULL,
989          plMask, plSkip, pProp);
990 }
991 
FreeRCBoxObj(ObjPtr)992 void FreeRCBoxObj(ObjPtr)
993    struct ObjRec *ObjPtr;
994 {
995    if (ObjPtr->detail.rcb->rotated_vlist != NULL) {
996       free(ObjPtr->detail.rcb->rotated_vlist);
997    }
998    free(ObjPtr->detail.rcb);
999    free(ObjPtr);
1000 }
1001