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