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/polygon.c,v 1.41 2011/06/09 15:55:15 cvsps Exp $
19 */
20
21 #define _INCLUDE_FROM_POLYGON_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 "color.e"
31 #include "choice.e"
32 #include "cursor.e"
33 #include "cutpaste.e"
34 #include "dialog.e"
35 #include "drawing.e"
36 #include "dup.e"
37 #include "grid.e"
38 #include "file.e"
39 #include "mainloop.e"
40 #include "mark.e"
41 #include "msg.e"
42 #include "obj.e"
43 #include "pattern.e"
44 #include "poly.e"
45 #include "polygon.e"
46 #include "ps.e"
47 #include "raster.e"
48 #include "rect.e"
49 #include "ruler.e"
50 #include "select.e"
51 #include "setup.e"
52 #include "spline.e"
53 #include "strtbl.e"
54 #include "util.e"
55 #include "xpixmap.e"
56
57 int polygonDrawn=FALSE;
58
MakePolygonVertex(XOff,YOff,NumVs,Vs)59 XPoint *MakePolygonVertex(XOff, YOff, NumVs, Vs)
60 int XOff, YOff, NumVs;
61 register IntPoint *Vs;
62 {
63 register XPoint *v;
64 register int i;
65 int real_x_off, real_y_off;
66
67 real_x_off = (zoomedIn ? XOff : (XOff>>zoomScale)<<zoomScale);
68 real_y_off = (zoomedIn ? YOff : (YOff>>zoomScale)<<zoomScale);
69
70 v = (XPoint*)malloc((NumVs+1)*sizeof(XPoint));
71 if (v == NULL) FailAllocMessage();
72 for (i = 0; i < NumVs; i++) {
73 v[i].x = (short)ZOOMED_SIZE(Vs[i].x-real_x_off);
74 v[i].y = (short)ZOOMED_SIZE(Vs[i].y-real_y_off);
75 }
76 return v;
77 }
78
DumpPoints(FP,NumPts,V,Indent)79 void DumpPoints(FP, NumPts, V, Indent)
80 FILE *FP;
81 int NumPts, Indent;
82 IntPoint *V;
83 {
84 register int i, j;
85
86 for (i=1; i < NumPts; i++) {
87 for (j = 0; j < Indent; j++) fprintf(FP, " ");
88 fprintf(FP, "%1d %1d %s\n", V[i].x, V[i].y, gPsCmd[PS_LINETO]);
89 }
90 }
91
92 static
DumpJustPolygonPath(FP,Vs,NumPts,Smooth,Curved)93 void DumpJustPolygonPath(FP, Vs, NumPts, Smooth, Curved)
94 FILE *FP;
95 IntPoint *Vs;
96 char *Smooth;
97 int NumPts, Curved;
98 {
99 fprintf(FP, "%s\n", gPsCmd[PS_NEWPATH]);
100 if (Curved == LT_INTSPLINE) {
101 DumpCurvedPolygonPoints(FP, Curved, NumPts, Vs, 3);
102 } else {
103 DumpMultiCurvedPolygonPoints(FP, Smooth, Curved, NumPts, Vs, 3);
104 }
105 fprintf(FP, "%s\n", gPsCmd[PS_CLOSEPATH]);
106 }
107
108 static
DumpPolygonPath(FP,ObjPtr,Vs,NumPts,Width,Pen,Fill,Dash,TransPat)109 void DumpPolygonPath(FP, ObjPtr, Vs, NumPts, Width, Pen, Fill, Dash, TransPat)
110 FILE *FP;
111 struct ObjRec *ObjPtr;
112 IntPoint *Vs;
113 int NumPts, Width, Pen, Fill, Dash, TransPat;
114 {
115 register int i;
116 int w_is_int=TRUE;
117 char *width_spec=ObjPtr->detail.g->width_spec;
118 double dw=GetWidthInDouble(Width, width_spec, &w_is_int);
119
120 if (Fill != (-1) && Pen == (-1)) {
121 /* dumping the fill */
122 switch (Fill) {
123 case SOLIDPAT: fprintf(FP, " %s\n", gPsCmd[PS_EOFILL]); break;
124 case BACKPAT:
125 if (!TransPat) {
126 fprintf(FP, " 1 %s %s\n", gPsCmd[PS_SETGRAY], gPsCmd[PS_EOFILL]);
127 }
128 break;
129 default:
130 if (colorDump || !useGray) {
131 if (preDumpSetup) PSUseColorPattern();
132 fprintf(FP, " %s %s\n", gPsCmd[PS_EOCLIP], gPsCmd[PS_NEWPATH]);
133 for (i=0; i < 3; i++) fprintf(FP, " ");
134 DumpPatFill(FP, Fill, ObjPtr->bbox, 0, TRUE);
135 } else {
136 GrayCheck(Fill);
137 for (i=0; i < 3; i++) fprintf(FP, " ");
138 fprintf(FP, "%s %s\n", GrayStr(Fill), gPsCmd[PS_SETGRAY]);
139 fprintf(FP, " %s\n", gPsCmd[PS_EOFILL]);
140 }
141 break;
142 }
143 } else if (Fill == (-1) && Pen != (-1)) {
144 /* dumping the pen */
145 if (ObjPtr->ctm != NULL) {
146 fprintf(FP, " %s\n", &(gPsCmd[PS_TGIFSETMATRIX])[1]);
147 }
148 if (w_is_int) {
149 if (Width != 1) {
150 fprintf(FP, " %1d %s\n", Width, gPsCmd[PS_SETLINEWIDTH]);
151 }
152 } else {
153 fprintf(FP, " %.3f %s\n", dw, gPsCmd[PS_SETLINEWIDTH]);
154 }
155 if (Dash != 0) {
156 fprintf(FP, " [");
157 for (i = 0; i < dashListLength[Dash]-1; i++) {
158 fprintf(FP, "%1d ", (int)(dashList[Dash][i]));
159 }
160 fprintf(FP, "%1d] 0 %s\n",
161 (int)(dashList[Dash][dashListLength[Dash]-1]),
162 gPsCmd[PS_SETDASH]);
163 }
164 switch (Pen) {
165 case SOLIDPAT: fprintf(FP, " %s\n", gPsCmd[PS_STROKE]); break;
166 case BACKPAT:
167 if (!TransPat) {
168 fprintf(FP, " 1 %s %s 0 %s\n", gPsCmd[PS_SETGRAY],
169 gPsCmd[PS_STROKE], gPsCmd[PS_SETGRAY]);
170 }
171 break;
172 default:
173 if (colorDump || !useGray) {
174 if (preDumpSetup) PSUseColorPattern();
175 fprintf(FP, " %s\n", gPsCmd[PS_FLATTENPATH]);
176 for (i=0; i < 3; i++) fprintf(FP, " ");
177 DumpPatFill(FP, Pen, ObjPtr->bbox, 0, TRUE);
178 } else {
179 GrayCheck(Pen);
180 fprintf(FP, " %s %s\n", GrayStr(Pen), gPsCmd[PS_SETGRAY]);
181 fprintf(FP, " %s\n", gPsCmd[PS_STROKE]);
182 }
183 break;
184 }
185 }
186 }
187
DumpPolygonObj(FP,ObjPtr)188 void DumpPolygonObj(FP, ObjPtr)
189 FILE *FP;
190 struct ObjRec *ObjPtr;
191 {
192 IntPoint *v=NULL, *intv=NULL;
193 int num_pts=0, trans_pat, fill, width, pen, curved, dash, color_index, intn;
194 char *smooth=NULL;
195
196 trans_pat = ObjPtr->trans_pat;
197 fill = ObjPtr->detail.g->fill;
198 width = ObjPtr->detail.g->width;
199 pen = ObjPtr->detail.g->pen;
200 curved = ObjPtr->detail.g->curved;
201 dash = ObjPtr->detail.g->dash;
202 intv = ObjPtr->detail.g->intvlist;
203 intn = ObjPtr->detail.g->intn;
204 if (curved == LT_STRUCT_SPLINE) {
205 v = ObjPtr->detail.g->ssvlist;
206 num_pts = ObjPtr->detail.g->ssn;
207 smooth = ObjPtr->detail.g->ssmooth;
208 } else {
209 v = ObjPtr->detail.g->vlist;
210 num_pts = ObjPtr->detail.g->n;
211 smooth = ObjPtr->detail.g->smooth;
212 }
213
214 if ((fill == NONEPAT || (trans_pat && fill == BACKPAT)) &&
215 (pen == NONEPAT || (trans_pat && pen == BACKPAT))) {
216 return;
217 }
218 fprintf(FP, "%% POLYGON/CLOSED-SPLINE\n");
219 color_index = ObjPtr->color;
220 DumpRGBColorLine(FP, color_index, 0, TRUE);
221
222 if (ObjPtr->ctm != NULL) {
223 float m[6];
224
225 fprintf(FP, "%s\n", gPsCmd[PS_GSAVE]);
226 m[CTM_SX] = ((float)ObjPtr->ctm->m[CTM_SX])/((float)1000.0);
227 m[CTM_SY] = ((float)ObjPtr->ctm->m[CTM_SY])/((float)1000.0);
228 m[CTM_SIN] = ((float)ObjPtr->ctm->m[CTM_SIN])/((float)1000.0);
229 m[CTM_MSIN] = ((float)ObjPtr->ctm->m[CTM_MSIN])/((float)1000.0);
230 fprintf(FP, " %1d %1d %s\n", ObjPtr->x, ObjPtr->y,
231 gPsCmd[PS_TRANSLATE]);
232 fprintf(FP, " [%.3f %.3f %.3f %.3f %1d %1d] %s\n",
233 m[CTM_SX], m[CTM_SIN], m[CTM_MSIN], m[CTM_SY],
234 ObjPtr->ctm->t[CTM_TX], ObjPtr->ctm->t[CTM_TY], gPsCmd[PS_CONCAT]);
235 fprintf(FP, " %1d %s %1d %s %s\n",
236 ObjPtr->x, gPsCmd[PS_NEG], ObjPtr->y, gPsCmd[PS_NEG],
237 gPsCmd[PS_TRANSLATE]);
238 }
239 if (curved != LT_INTSPLINE) {
240 DumpJustPolygonPath(FP, v, num_pts, smooth, curved);
241 } else {
242 DumpJustPolygonPath(FP, intv, intn, smooth, curved);
243 }
244 fprintf(FP, "%s\n", gPsCmd[PS_GSAVE]);
245
246 if (fill != NONEPAT) {
247 if (curved != LT_INTSPLINE) {
248 if ((colorDump || !useGray) && fill > BACKPAT && !trans_pat) {
249 DumpPolygonPath(FP, ObjPtr, v, num_pts, width, (-1), BACKPAT, 0,
250 trans_pat);
251 fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]);
252 fprintf(FP, "%s\n", gPsCmd[PS_GSAVE]);
253 }
254 DumpPolygonPath(FP, ObjPtr, v, num_pts, width, (-1), fill, 0,
255 trans_pat);
256 } else {
257 if ((colorDump || !useGray) && fill > BACKPAT && !trans_pat) {
258 DumpPolygonPath(FP, ObjPtr, intv, intn, width, (-1), BACKPAT, 0,
259 trans_pat);
260 fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]);
261 fprintf(FP, "%s\n", gPsCmd[PS_GSAVE]);
262 }
263 DumpPolygonPath(FP, ObjPtr, intv, intn, width, (-1), fill, 0,
264 trans_pat);
265 }
266 }
267 if (pen != NONEPAT) {
268 fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]);
269 fprintf(FP, "%s\n", gPsCmd[PS_GSAVE]);
270 if (curved != LT_INTSPLINE) {
271 if ((colorDump || !useGray) && pen > BACKPAT && !trans_pat) {
272 DumpPolygonPath(FP, ObjPtr, v, num_pts, width, BACKPAT, (-1), 0,
273 trans_pat);
274 fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]);
275 fprintf(FP, "%s\n", gPsCmd[PS_GSAVE]);
276 }
277 DumpPolygonPath(FP, ObjPtr, v, num_pts, width, pen, (-1), dash,
278 trans_pat);
279 } else {
280 if ((colorDump || !useGray) && pen > BACKPAT && !trans_pat) {
281 DumpPolygonPath(FP, ObjPtr, intv, intn, width, BACKPAT, (-1), 0,
282 trans_pat);
283 fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]);
284 fprintf(FP, "%s\n", gPsCmd[PS_GSAVE]);
285 }
286 DumpPolygonPath(FP, ObjPtr, intv, intn, width, pen, (-1), dash,
287 trans_pat);
288 }
289 }
290 fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]);
291 if (ObjPtr->ctm != NULL) fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]);
292 fprintf(FP, "\n");
293 }
294
NeedsToCachePolygonObj(ObjPtr)295 int NeedsToCachePolygonObj(ObjPtr)
296 struct ObjRec *ObjPtr;
297 {
298 return (ObjPtr->ctm != NULL);
299 }
300
301 static
MakeCachedPolygon(ObjPtr)302 void MakeCachedPolygon(ObjPtr)
303 struct ObjRec *ObjPtr;
304 {
305 register int i;
306 struct PolygonRec *polygon_ptr=ObjPtr->detail.g;
307 IntPoint *v=polygon_ptr->vlist, *pv=NULL, *pv1=NULL;
308 int num_pts=polygon_ptr->n, num_pts1=0;
309
310 if (ObjPtr->ctm == NULL) return;
311
312 if (polygon_ptr->rotated_vlist != NULL) free(polygon_ptr->rotated_vlist);
313 polygon_ptr->rotated_n = 0;
314 polygon_ptr->rotated_vlist = NULL;
315
316 if (polygon_ptr->curved == LT_STRUCT_SPLINE) {
317 v = polygon_ptr->ssvlist;
318 num_pts = polygon_ptr->ssn;
319 }
320 pv = (IntPoint*)malloc((num_pts+1)*sizeof(IntPoint));
321 if (pv == NULL) {
322 FailAllocMessage();
323 return;
324 }
325 for (i=0; i < num_pts; i++) {
326 int x, y;
327
328 TransformPointThroughCTM(v[i].x-ObjPtr->x, v[i].y-ObjPtr->y,
329 ObjPtr->ctm, &x, &y);
330 pv[i].x = x+ObjPtr->x;
331 pv[i].y = y+ObjPtr->y;
332 }
333 switch (polygon_ptr->curved) {
334 case LT_STRAIGHT:
335 case LT_SPLINE:
336 polygon_ptr->rotated_vlist = MakeMultiSplinePolygonVertex(
337 polygon_ptr->curved, &(polygon_ptr->rotated_n),
338 polygon_ptr->smooth, drawOrigX, drawOrigY, num_pts, pv);
339 break;
340 case LT_STRUCT_SPLINE:
341 polygon_ptr->rotated_vlist = MakeMultiSplinePolygonVertex(
342 polygon_ptr->curved, &(polygon_ptr->rotated_n),
343 polygon_ptr->ssmooth, drawOrigX, drawOrigY, num_pts, pv);
344 break;
345 case LT_INTSPLINE:
346 polygon_ptr->rotated_vlist = MakeIntSplinePolygonVertex(
347 &(polygon_ptr->rotated_n), &(num_pts1), &(pv1),
348 drawOrigX, drawOrigY, num_pts, pv);
349 free(pv1);
350 break;
351 }
352 free(pv);
353 }
354
DrawPolygonObj(Win,XOff,YOff,ObjPtr)355 void DrawPolygonObj(Win, XOff, YOff, ObjPtr)
356 Window Win;
357 int XOff, YOff;
358 struct ObjRec *ObjPtr;
359 {
360 struct PolygonRec *polygon_ptr=ObjPtr->detail.g;
361 XPoint *v;
362 int trans_pat, fill, width, pen, dash, pixel, num_pts;
363 XGCValues values;
364
365 trans_pat = ObjPtr->trans_pat;
366 fill = polygon_ptr->fill;
367 width = polygon_ptr->width;
368 pen = polygon_ptr->pen;
369 dash = polygon_ptr->dash;
370 pixel = colorPixels[ObjPtr->color];
371
372 if (NeedsToCachePolygonObj(ObjPtr) && polygon_ptr->rotated_vlist==NULL) {
373 MakeCachedPolygon(ObjPtr);
374 }
375 if (userDisableRedraw) return;
376
377 if ((fill == NONEPAT || (trans_pat && fill == BACKPAT)) &&
378 (pen == NONEPAT || (trans_pat && pen == BACKPAT))) {
379 return;
380 }
381 v = polygon_ptr->svlist;
382 num_pts = polygon_ptr->sn;
383
384 if (fill != 0) {
385 values.foreground = GetDrawingBgPixel(fill, pixel);
386 values.function = GXcopy;
387 values.fill_style = (trans_pat ? FillStippled : FillOpaqueStippled);
388 values.stipple = patPixmap[fill];
389 XChangeGC(mainDisplay, drawGC,
390 GCForeground | GCFunction | GCFillStyle | GCStipple, &values);
391 if (ObjPtr->ctm == NULL) {
392 XFillPolygon(mainDisplay, Win, drawGC, v, num_pts, Complex,
393 CoordModeOrigin);
394 } else {
395 XFillPolygon(mainDisplay, Win, drawGC, polygon_ptr->rotated_vlist,
396 polygon_ptr->rotated_n, Complex, CoordModeOrigin);
397 }
398 }
399
400 if (pen == NONEPAT) return;
401
402 values.foreground = GetDrawingBgPixel(pen, pixel);
403 values.function = GXcopy;
404 values.fill_style = (trans_pat ? FillStippled : FillOpaqueStippled);
405 values.stipple = patPixmap[pen];
406 values.line_width = ZOOMED_SIZE(width);
407 #ifdef NO_THIN_LINE
408 if (values.line_width < 1) values.line_width = 1;
409 #endif
410 values.join_style = JoinBevel;
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 |
420 GCLineWidth | GCLineStyle | GCJoinStyle, &values);
421
422 if (ObjPtr->ctm == NULL) {
423 XDrawLines(mainDisplay, Win, drawGC, v, num_pts, CoordModeOrigin);
424 } else {
425 XDrawLines(mainDisplay, Win, drawGC, polygon_ptr->rotated_vlist,
426 polygon_ptr->rotated_n, CoordModeOrigin);
427 }
428 values.join_style = JoinMiter;
429 XChangeGC(mainDisplay, drawGC, GCJoinStyle, &values);
430 }
431
432 #define CREATE_RELATIVE (FALSE)
433 #define CREATE_ABSOLUTE (TRUE)
434
CreatePolygonObj(NumPts,CreateAbsolute)435 void CreatePolygonObj(NumPts, CreateAbsolute)
436 int NumPts;
437 int CreateAbsolute;
438 {
439 register int i;
440 struct PtRec *pt_ptr=NULL, *next_pt=NULL;
441 struct PolygonRec *polygon_ptr=NULL;
442 struct ObjRec *obj_ptr=NULL;
443 IntPoint *v=NULL;
444 int width, w, ltx, lty, rbx, rby, num_ss_pts=0;
445 char *smooth=NULL;
446 CVListElem *elem=NULL;
447 IntPointTriplet *pipt=NULL;
448
449 polygon_ptr = (struct PolygonRec *)malloc(sizeof(struct PolygonRec));
450 if (polygon_ptr == NULL) FailAllocMessage();
451 memset(polygon_ptr, 0, sizeof(struct PolygonRec));
452 if (curSpline == LT_STRUCT_SPLINE) {
453 num_ss_pts = ((NumPts-1)*3)+1;
454 polygon_ptr->n = num_ss_pts;
455 v = (IntPoint*)malloc((num_ss_pts+1)*sizeof(IntPoint));
456 if (v == NULL) FailAllocMessage();
457 smooth = (char*)malloc((num_ss_pts+1)*sizeof(char));
458 if (smooth == NULL) FailAllocMessage();
459 elem = ListLast(&gStructSplineList);
460 pipt = (IntPointTriplet*)(elem->obj);
461 ltx = rbx = pipt->hinge_pt.x;
462 lty = rby = pipt->hinge_pt.y;
463
464 for (i=NumPts-1; i >= 0; i--, elem=ListPrev(&gStructSplineList, elem)) {
465 pipt = (IntPointTriplet*)(elem->obj);
466 if (i == 0) {
467 v[0].x = CreateAbsolute ? pipt->hinge_pt.x :
468 ABS_X(pipt->hinge_pt.x);
469 v[0].y = CreateAbsolute ? pipt->hinge_pt.y :
470 ABS_Y(pipt->hinge_pt.y);
471 if (pipt->later_valid) {
472 v[1].x = CreateAbsolute ? pipt->later_smooth_pt.x :
473 ABS_X(pipt->later_smooth_pt.x);
474 v[1].y = CreateAbsolute ? pipt->later_smooth_pt.y :
475 ABS_Y(pipt->later_smooth_pt.y);
476 smooth[1] = TRUE;
477 } else {
478 v[1].x = v[0].x;
479 v[1].y = v[0].y;
480 smooth[1] = FALSE;
481 }
482 smooth[0] = FALSE;
483 } else if (i == NumPts-1) {
484 v[num_ss_pts-1].x = CreateAbsolute ? pipt->hinge_pt.x :
485 ABS_X(pipt->hinge_pt.x);
486 v[num_ss_pts-1].y = CreateAbsolute ? pipt->hinge_pt.y :
487 ABS_Y(pipt->hinge_pt.y);
488 if (pipt->earlier_valid) {
489 v[num_ss_pts-2].x = CreateAbsolute ? pipt->earlier_smooth_pt.x :
490 ABS_X(pipt->earlier_smooth_pt.x);
491 v[num_ss_pts-2].y = CreateAbsolute ? pipt->earlier_smooth_pt.y :
492 ABS_Y(pipt->earlier_smooth_pt.y);
493 smooth[num_ss_pts-2] = TRUE;
494 } else {
495 v[num_ss_pts-2].x = v[num_ss_pts-1].x;
496 v[num_ss_pts-2].y = v[num_ss_pts-1].y;
497 smooth[num_ss_pts-2] = FALSE;
498 }
499 smooth[num_ss_pts-1] = FALSE;
500 } else {
501 int index=3*i;
502
503 v[index-1].x = CreateAbsolute ? pipt->earlier_smooth_pt.x :
504 ABS_X(pipt->earlier_smooth_pt.x);
505 v[index-1].y = CreateAbsolute ? pipt->earlier_smooth_pt.y :
506 ABS_Y(pipt->earlier_smooth_pt.y);
507 v[index].x = CreateAbsolute ? pipt->hinge_pt.x :
508 ABS_X(pipt->hinge_pt.x);
509 v[index].y = CreateAbsolute ? pipt->hinge_pt.y :
510 ABS_Y(pipt->hinge_pt.y);
511 v[index+1].x = CreateAbsolute ? pipt->later_smooth_pt.x :
512 ABS_X(pipt->later_smooth_pt.x);
513 v[index+1].y = CreateAbsolute ? pipt->later_smooth_pt.y :
514 ABS_Y(pipt->later_smooth_pt.y);
515 smooth[index-1] = pipt->earlier_valid;
516 smooth[index] = FALSE;
517 smooth[index+1] = pipt->later_valid;
518 }
519 free(pipt);
520 }
521 for (i=0; i < num_ss_pts; i++) {
522 if (v[i].x < ltx) ltx = v[i].x;
523 if (v[i].y < lty) lty = v[i].y;
524 if (v[i].x > rbx) rbx = v[i].x;
525 if (v[i].y > rby) rby = v[i].y;
526 }
527 numPtsInPoly = 0;
528 ListUnlinkAll(&gStructSplineList);
529 } else {
530 polygon_ptr->n = NumPts;
531 v = (IntPoint*)malloc((NumPts+1)*sizeof(IntPoint));
532 if (v == NULL) FailAllocMessage();
533 if (curSpline != LT_INTSPLINE) {
534 smooth = (char*)malloc((NumPts+1)*sizeof(char));
535 if (smooth == NULL) FailAllocMessage();
536 }
537 pt_ptr = lastPtPtr;
538 ltx = rbx = pt_ptr->x;
539 lty = rby = pt_ptr->y;
540 for (i=NumPts-1; i >= 0; i--, lastPtPtr = next_pt) {
541 next_pt = lastPtPtr->next;
542 v[i].x = CreateAbsolute ? lastPtPtr->x : ABS_X(lastPtPtr->x);
543 v[i].y = CreateAbsolute ? lastPtPtr->y : ABS_Y(lastPtPtr->y);
544 if (curSpline != LT_INTSPLINE) {
545 if (lastPtPtr->x < ltx) ltx = lastPtPtr->x;
546 if (lastPtPtr->y < lty) lty = lastPtPtr->y;
547 if (lastPtPtr->x > rbx) rbx = lastPtPtr->x;
548 if (lastPtPtr->y > rby) rby = lastPtPtr->y;
549 smooth[i] = (curSpline != LT_STRAIGHT);
550 }
551 free(lastPtPtr);
552 }
553 numPtsInPoly = 0;
554 lastPtPtr = NULL;
555 }
556 polygon_ptr->vlist = v;
557 polygon_ptr->smooth = smooth;
558 polygon_ptr->svlist = NULL;
559 polygon_ptr->intvlist = NULL;
560 polygon_ptr->fill = objFill;
561 polygon_ptr->width = width = curWidthOfLine[lineWidth];
562 UtilStrCpyN(polygon_ptr->width_spec, sizeof(polygon_ptr->width_spec),
563 curWidthOfLineSpec[lineWidth]);
564 polygon_ptr->pen = penPat;
565 polygon_ptr->curved = curSpline;
566 polygon_ptr->dash = curDash;
567 /*
568 * polygon_ptr->tighter = (curSpline == LT_STRUCT_SPLINE) ?
569 * tighterStructSplines : FALSE;
570 */
571 polygon_ptr->rotated_n = 0;
572 polygon_ptr->rotated_vlist = NULL;
573
574 obj_ptr = (struct ObjRec *)malloc(sizeof(struct ObjRec));
575 if (obj_ptr == NULL) FailAllocMessage();
576 memset(obj_ptr, 0, sizeof(struct ObjRec));
577 obj_ptr->detail.g = polygon_ptr;
578
579 obj_ptr->color = colorIndex;
580 if (mainDisplay != NULL) {
581 UtilStrCpyN(obj_ptr->color_str, sizeof(obj_ptr->color_str),
582 colorMenuItems[colorIndex]);
583 }
584 obj_ptr->type = OBJ_POLYGON;
585 if (CreateAbsolute) {
586 obj_ptr->bbox.ltx = obj_ptr->obbox.ltx = obj_ptr->x = ltx;
587 obj_ptr->bbox.lty = obj_ptr->obbox.lty = obj_ptr->y = lty;
588 obj_ptr->bbox.rbx = obj_ptr->obbox.rbx = rbx;
589 obj_ptr->bbox.rby = obj_ptr->obbox.rby = rby;
590 } else {
591 obj_ptr->bbox.ltx = obj_ptr->obbox.ltx = obj_ptr->x = ABS_X(ltx);
592 obj_ptr->bbox.lty = obj_ptr->obbox.lty = obj_ptr->y = ABS_Y(lty);
593 obj_ptr->bbox.rbx = obj_ptr->obbox.rbx = ABS_X(rbx);
594 obj_ptr->bbox.rby = obj_ptr->obbox.rby = ABS_Y(rby);
595 }
596 w = HALF_W(width);
597 obj_ptr->bbox.ltx -= w;
598 obj_ptr->bbox.lty -= w;
599 obj_ptr->bbox.rbx += w;
600 obj_ptr->bbox.rby += w;
601 obj_ptr->id = objId++;
602 obj_ptr->dirty = FALSE;
603 obj_ptr->rotation = 0;
604 obj_ptr->locked = FALSE;
605 obj_ptr->fattr = obj_ptr->lattr = NULL;
606 obj_ptr->ctm = NULL;
607 obj_ptr->invisible = FALSE;
608 obj_ptr->trans_pat = transPat;
609
610 AdjObjSplineVs(obj_ptr);
611 if (curSpline != LT_INTSPLINE) {
612 UpdPolyBBox(obj_ptr, polygon_ptr->n, polygon_ptr->vlist);
613 } else {
614 UpdPolyBBox(obj_ptr, polygon_ptr->intn, polygon_ptr->intvlist);
615 }
616 AdjObjBBox(obj_ptr);
617 AddObj(NULL, topObj, obj_ptr);
618 }
619
ResetCreatePolygon()620 void ResetCreatePolygon()
621 {
622 numPtsInPoly = 0;
623 lastPtPtr = NULL;
624 }
625
AddPtToCreatePolygon(AbsX,AbsY)626 void AddPtToCreatePolygon(AbsX, AbsY)
627 int AbsX, AbsY;
628 {
629 struct PtRec *pt_ptr=(struct PtRec *)malloc(sizeof(struct PtRec));
630
631 if (pt_ptr == NULL) FailAllocMessage();
632 memset(pt_ptr, 0, sizeof(struct PtRec));
633 pt_ptr->next = lastPtPtr;
634 numPtsInPoly++;
635 lastPtPtr = pt_ptr;
636 pt_ptr->x = AbsX;
637 pt_ptr->y = AbsY;
638 }
639
640 #define POLYGON_DRAW (FALSE)
641 #define POLYGON_ERASE (TRUE)
642 #define POLYGON_CLICK (FALSE)
643 #define POLYGON_DRAG (TRUE)
644
645 #define POLYGON_STARTSHOW 0
646 #define POLYGON_DOSHOW 1
647 #define POLYGON_ENDSHOW 2
648
649 typedef struct tagPolygonMeasureCursorInfo {
650 IntPoint first_pt;
651 IntPoint prev_prev_pt;
652 IntPoint prev_pt;
653 } PolygonMeasureCursorInfo;
654
655 static
DoPolygonMeasureCursor(ppmci,start,num_pts,x,y,dx,dy,erase,drag,closed)656 void DoPolygonMeasureCursor(ppmci, start, num_pts, x, y, dx, dy, erase, drag,
657 closed)
658 PolygonMeasureCursorInfo *ppmci;
659 int start, num_pts, x, y, dx, dy, erase, drag, closed;
660 {
661 char buf[80], w_buf[80], h_buf[80], x_buf[80], y_buf[80], a_buf[80];
662 int angle2=0;
663
664 if (erase == POLYGON_DRAW && drag == POLYGON_CLICK) {
665 if (num_pts == 1) {
666 ppmci->first_pt.x = ppmci->prev_pt.x = ppmci->prev_prev_pt.x = x;
667 ppmci->first_pt.y = ppmci->prev_pt.y = ppmci->prev_prev_pt.y = y;
668 } else {
669 ppmci->prev_prev_pt.x = ppmci->prev_pt.x;
670 ppmci->prev_prev_pt.y = ppmci->prev_pt.y;
671 ppmci->prev_pt.x = x;
672 ppmci->prev_pt.y = y;
673 }
674 }
675 if (x == ppmci->prev_pt.x && y == ppmci->prev_pt.y) {
676 strcpy(a_buf, "0");
677 } else if (num_pts == 1) {
678 PointsToArc(ppmci->prev_pt.x, ppmci->prev_pt.y, ppmci->prev_pt.x+100,
679 ppmci->prev_pt.y, x, y, ARC_CCW, FALSE, NULL, NULL, NULL, NULL,
680 NULL, &angle2);
681 if (angle2 > 180*64) angle2=(360*64)-angle2;
682 FormatAngle(angle2, a_buf);
683 } else if (closed) {
684 if (x == ppmci->first_pt.x && y == ppmci->first_pt.y) {
685 strcpy(a_buf, "0");
686 } else {
687 PointsToArc(x, y, ppmci->first_pt.x, ppmci->first_pt.y,
688 ppmci->prev_pt.x, ppmci->prev_pt.y, ARC_CCW, FALSE, NULL, NULL,
689 NULL, NULL, NULL, &angle2);
690 if (angle2 > 180*64) angle2=(360*64)-angle2;
691 FormatAngle(angle2, a_buf);
692 }
693 } else {
694 PointsToArc(ppmci->prev_pt.x, ppmci->prev_pt.y, ppmci->prev_prev_pt.x,
695 ppmci->prev_prev_pt.y, x, y, ARC_CCW, FALSE, NULL, NULL, NULL, NULL,
696 NULL, &angle2);
697 if (angle2 > 180*64) angle2=(360*64)-angle2;
698 FormatAngle(angle2, a_buf);
699 }
700 PixelToMeasurementUnit(w_buf, dx);
701 PixelToMeasurementUnit(h_buf, dy);
702 PixelToMeasurementUnit(x_buf, x);
703 PixelToMeasurementUnit(y_buf, y);
704 sprintf(buf, "w=%s\nh=%s\nx=%s\ny=%s\nangle=%s", w_buf, h_buf, x_buf, y_buf,
705 a_buf);
706
707 x = OFFSET_X(x);
708 y = OFFSET_Y(y);
709 switch (start) {
710 case POLYGON_STARTSHOW: StartShowMeasureCursor(x, y, buf, TRUE); break;
711 case POLYGON_DOSHOW: ShowMeasureCursor(x, y, buf, TRUE); break;
712 case POLYGON_ENDSHOW: EndShowMeasureCursor(x, y, buf, TRUE); break;
713 }
714 }
715
716 static
EraseStructSplineLinesForCont(OrigX,OrigY,grid_x,grid_y,sv,sn,sv2,sn2)717 void EraseStructSplineLinesForCont(OrigX, OrigY, grid_x, grid_y, sv, sn, sv2,
718 sn2)
719 int OrigX, OrigY, grid_x, grid_y, sn, sn2;
720 XPoint *sv, *sv2;
721 {
722 if (sv == NULL && sv2 == NULL) {
723 XDrawLine(mainDisplay, drawWindow, drawGC, OrigX, OrigY, grid_x, grid_y);
724 } else {
725 if (sv != NULL) {
726 XDrawLines(mainDisplay, drawWindow, drawGC, sv, sn, CoordModeOrigin);
727 }
728 if (sv2 != NULL) {
729 XDrawLines(mainDisplay, drawWindow, drawGC, sv2, sn2, CoordModeOrigin);
730 }
731 }
732 }
733
734 static
ContinueForStructSplinePolygonControlPoints(OrigX,OrigY,LastX,LastY,psv,psn,psv2,psn2,pipt_first,pipt_prev,pipt,pn_abort)735 void ContinueForStructSplinePolygonControlPoints(OrigX, OrigY, LastX, LastY,
736 psv, psn, psv2, psn2, pipt_first, pipt_prev, pipt, pn_abort)
737 int OrigX, OrigY, LastX, LastY, *psn, *psn2, *pn_abort;
738 XPoint **psv, **psv2;
739 IntPointTriplet *pipt_first, *pipt_prev, *pipt;
740 {
741 int i=0, done=FALSE, grid_x=0, grid_y=0, end_x=0, end_y=0, n=2;
742 int sn=(*psn), orig_sn=(*psn), sn2=(*psn2), orig_sn2=(*psn2);
743 int num_pts=1, first_time=TRUE;
744 IntPoint v[4];
745 XPoint *sv=NULL, *orig_sv=(*psv), *sv2=NULL, *orig_sv2=(*psv2), dash_vs[2];
746 PolygonMeasureCursorInfo pmci;
747 XGCValues values;
748
749 *pn_abort = FALSE;
750
751 if (orig_sv != NULL) {
752 sv = (XPoint*)malloc(orig_sn*sizeof(XPoint));
753 if (sv == NULL) FailAllocMessage();
754 memset(sv, 0, orig_sn*sizeof(XPoint));
755 for (i=0; i < orig_sn; i++) {
756 sv[i].x = orig_sv[i].x;
757 sv[i].y = orig_sv[i].y;
758 }
759 sn = orig_sn;
760 }
761 if (orig_sv2 != NULL) {
762 sv2 = (XPoint*)malloc(orig_sn2*sizeof(XPoint));
763 if (sv2 == NULL) FailAllocMessage();
764 memset(sv2, 0, orig_sn2*sizeof(XPoint));
765 for (i=0; i < orig_sn2; i++) {
766 sv2[i].x = orig_sv2[i].x;
767 sv2[i].y = orig_sv2[i].y;
768 }
769 sn2 = orig_sn2;
770 }
771 memset(pipt, 0, sizeof(IntPointTriplet));
772 pipt->earlier_valid = pipt->later_valid = FALSE;
773 pipt->hinge_pt.x = pipt->earlier_smooth_pt.x = pipt->later_smooth_pt.x =
774 LastX;
775 pipt->hinge_pt.y = pipt->earlier_smooth_pt.y = pipt->later_smooth_pt.y =
776 LastY;
777 pipt->ratio = (double)1;
778
779 XSetDashes(mainDisplay, revDefaultGC, 0, dashList[8], dashListLength[8]);
780
781 grid_x = end_x = dash_vs[0].x = dash_vs[1].x = LastX;
782 grid_y = end_y = dash_vs[0].y = dash_vs[1].y = LastY;
783 v[0].x = ABS_X(OrigX);
784 v[0].y = ABS_Y(OrigY);
785 v[1].x = ABS_X(LastX);
786 v[1].y = ABS_Y(LastY);
787 n = 2;
788 MARKHR(drawWindow, revDefaultGC, LastX, LastY);
789
790 /* the previous curve has already been drawn */
791 /* draw the measure cursor */
792 DoPolygonMeasureCursor(&pmci, POLYGON_DOSHOW, num_pts, ABS_X(grid_x),
793 ABS_Y(grid_y), 0, 0, POLYGON_ERASE, POLYGON_DRAG);
794 while (!done) {
795 XEvent input, ev;
796
797 XNextEvent(mainDisplay, &input);
798
799 if (input.type == Expose || input.type == VisibilityNotify) {
800 ExposeEventHandler(&input, TRUE);
801 SetXorDrawGC(colorIndex);
802 } else if (input.type == MotionNotify) {
803 end_x = input.xmotion.x;
804 end_y = input.xmotion.y;
805
806 /* erase */
807 if (first_time || grid_x != LastX || grid_y != LastY) {
808 EraseStructSplineLinesForCont(OrigX, OrigY, grid_x, grid_y, sv, sn,
809 sv2, sn2);
810 if (!pipt_first->earlier_valid && sv != NULL && sv2 == NULL) {
811 XDrawLine(mainDisplay, drawWindow, drawGC, grid_x, grid_y,
812 pipt_first->earlier_smooth_pt.x,
813 pipt_first->earlier_smooth_pt.y);
814 }
815 first_time = FALSE;
816 } else {
817 if (orig_sv != NULL || orig_sv2 != NULL) {
818 if (orig_sv != NULL) {
819 XDrawLines(mainDisplay, drawWindow, drawGC, orig_sv, orig_sn,
820 CoordModeOrigin);
821 }
822 if (orig_sv2 != NULL) {
823 XDrawLines(mainDisplay, drawWindow, drawGC, orig_sv2,
824 orig_sn2, CoordModeOrigin);
825 }
826 } else {
827 XDrawLine(mainDisplay, drawWindow, drawGC, OrigX, OrigY, LastX,
828 LastY);
829 }
830 }
831 DoPolygonMeasureCursor(&pmci, POLYGON_DOSHOW, num_pts, ABS_X(grid_x),
832 ABS_Y(grid_y), ABS_SIZE(abs(grid_x-LastX)),
833 ABS_SIZE(abs(grid_y-LastY)), POLYGON_ERASE, POLYGON_DRAG);
834 MARKHO(drawWindow, revDefaultGC, dash_vs[0].x, dash_vs[0].y);
835 MARKHO(drawWindow, revDefaultGC, dash_vs[1].x, dash_vs[1].y);
836 values.line_style = LineOnOffDash;
837 XChangeGC(mainDisplay, revDefaultGC, GCLineStyle, &values);
838 MyDashedLine(drawWindow, revDefaultGC, dash_vs, 2);
839 values.line_style = LineSolid;
840 XChangeGC(mainDisplay, revDefaultGC, GCLineStyle, &values);
841
842 /* draw */
843 GridXY(end_x, end_y, &grid_x, &grid_y);
844 MarkRulers(grid_x, grid_y);
845 if (grid_x != LastX || grid_y != LastY) {
846 if (sv != NULL) {
847 free(sv);
848 sv = NULL;
849 }
850 if (sv2 != NULL) {
851 free(sv2);
852 sv2 = NULL;
853 }
854 v[0].x = ABS_X(OrigX);
855 v[0].y = ABS_Y(OrigY);
856 if (pipt_prev->later_valid) {
857 v[1].x = ABS_X(pipt_prev->later_smooth_pt.x);
858 v[1].y = ABS_Y(pipt_prev->later_smooth_pt.y);
859 n = 4;
860 } else {
861 n = 3;
862 }
863 v[n-2].x = ABS_X((LastX<<1)-grid_x);
864 v[n-2].y = ABS_Y((LastY<<1)-grid_y);
865 v[n-1].x = ABS_X(LastX);
866 v[n-1].y = ABS_Y(LastY);
867 sv = MakeSplinePolyVertex(0, curSpline, &sn, drawOrigX, drawOrigY,
868 n, v);
869 XDrawLines(mainDisplay, drawWindow, drawGC, sv, sn,
870 CoordModeOrigin);
871
872 v[0].x = ABS_X(pipt_first->hinge_pt.x);
873 v[0].y = ABS_Y(pipt_first->hinge_pt.y);
874 if (pipt_first->earlier_valid) {
875 v[1].x = ABS_X(pipt_first->earlier_smooth_pt.x);
876 v[1].y = ABS_Y(pipt_first->earlier_smooth_pt.y);
877 n = 4;
878 } else {
879 n = 3;
880 }
881 v[n-2].x = ABS_X(grid_x);
882 v[n-2].y = ABS_Y(grid_y);
883 v[n-1].x = ABS_X(LastX);
884 v[n-1].y = ABS_Y(LastY);
885 sv2 = MakeSplinePolyVertex(0, curSpline, &sn2, drawOrigX, drawOrigY,
886 n, v);
887 XDrawLines(mainDisplay, drawWindow, drawGC, sv2, sn2,
888 CoordModeOrigin);
889 } else {
890 if (orig_sv != NULL || orig_sv2 != NULL) {
891 if (orig_sv != NULL) {
892 XDrawLines(mainDisplay, drawWindow, drawGC, orig_sv, orig_sn,
893 CoordModeOrigin);
894 }
895 if (orig_sv2 != NULL) {
896 XDrawLines(mainDisplay, drawWindow, drawGC, orig_sv2,
897 orig_sn2, CoordModeOrigin);
898 }
899 } else {
900 XDrawLine(mainDisplay, drawWindow, drawGC, OrigX, OrigY, LastX,
901 LastY);
902 }
903 }
904 while (XCheckMaskEvent(mainDisplay, PointerMotionMask, &ev)) ;
905
906 dash_vs[0].x = grid_x;
907 dash_vs[0].y = grid_y;
908 dash_vs[1].x = (LastX<<1)-grid_x;
909 dash_vs[1].y = (LastY<<1)-grid_y;
910 pipt->later_smooth_pt.x = dash_vs[0].x;
911 pipt->later_smooth_pt.y = dash_vs[0].y;
912 pipt->earlier_smooth_pt.x = dash_vs[1].x;
913 pipt->earlier_smooth_pt.y = dash_vs[1].y;
914 if (grid_x == LastX && grid_y == LastY) {
915 pipt->earlier_valid = pipt->later_valid = FALSE;
916 } else {
917 pipt->earlier_valid = pipt->later_valid = TRUE;
918 }
919 MARKHO(drawWindow, revDefaultGC, dash_vs[0].x, dash_vs[0].y);
920 MARKHO(drawWindow, revDefaultGC, dash_vs[1].x, dash_vs[1].y);
921 values.line_style = LineOnOffDash;
922 XChangeGC(mainDisplay, revDefaultGC, GCLineStyle, &values);
923 MyDashedLine(drawWindow, revDefaultGC, dash_vs, 2);
924 values.line_style = LineSolid;
925 XChangeGC(mainDisplay, revDefaultGC, GCLineStyle, &values);
926 DoPolygonMeasureCursor(&pmci, POLYGON_DOSHOW, num_pts, ABS_X(grid_x),
927 ABS_Y(grid_y), ABS_SIZE(abs(grid_x-LastX)),
928 ABS_SIZE(abs(grid_y-LastY)), POLYGON_DRAW, POLYGON_DRAG);
929 } else if (input.type == KeyPress) {
930 if (KeyPressEventIsEscape(&input.xkey)) {
931 /* erase */
932 DoPolygonMeasureCursor(&pmci, POLYGON_ENDSHOW, num_pts,
933 ABS_X(grid_x), ABS_Y(grid_y), ABS_SIZE(abs(grid_x-LastX)),
934 ABS_SIZE(abs(grid_y-LastY)), POLYGON_ERASE, POLYGON_DRAG);
935 MARKHO(drawWindow, revDefaultGC, dash_vs[0].x, dash_vs[0].y);
936 MARKHO(drawWindow, revDefaultGC, dash_vs[1].x, dash_vs[1].y);
937 values.line_style = LineOnOffDash;
938 XChangeGC(mainDisplay, revDefaultGC, GCLineStyle, &values);
939 MyDashedLine(drawWindow, revDefaultGC, dash_vs, 2);
940 values.line_style = LineSolid;
941 XChangeGC(mainDisplay, revDefaultGC, GCLineStyle, &values);
942 Msg("");
943 *pn_abort = TRUE;
944 done = TRUE;
945 }
946 } else if (input.type == ButtonRelease) {
947 /* erase */
948 DoPolygonMeasureCursor(&pmci, POLYGON_ENDSHOW, num_pts, ABS_X(grid_x),
949 ABS_Y(grid_y), ABS_SIZE(abs(grid_x-LastX)),
950 ABS_SIZE(abs(grid_y-LastY)), POLYGON_ERASE, POLYGON_DRAG);
951 MARKHO(drawWindow, revDefaultGC, dash_vs[0].x, dash_vs[0].y);
952 MARKHO(drawWindow, revDefaultGC, dash_vs[1].x, dash_vs[1].y);
953 values.line_style = LineOnOffDash;
954 XChangeGC(mainDisplay, revDefaultGC, GCLineStyle, &values);
955 MyDashedLine(drawWindow, revDefaultGC, dash_vs, 2);
956 values.line_style = LineSolid;
957 XChangeGC(mainDisplay, revDefaultGC, GCLineStyle, &values);
958
959 GridXY(input.xbutton.x, input.xbutton.y, &grid_x, &grid_y);
960 pipt->later_smooth_pt.x = grid_x;
961 pipt->later_smooth_pt.y = grid_y;
962 pipt->earlier_smooth_pt.x = (LastX<<1)-grid_x;
963 pipt->earlier_smooth_pt.y = (LastY<<1)-grid_y;
964 if (grid_x == LastX && grid_y == LastY) {
965 pipt->earlier_valid = pipt->later_valid = FALSE;
966 if (sv2 != NULL) {
967 free(sv2);
968 sv2 = NULL;
969
970 v[0].x = ABS_X(pipt_first->hinge_pt.x);
971 v[0].y = ABS_Y(pipt_first->hinge_pt.y);
972 if (pipt_first->earlier_valid) {
973 v[1].x = ABS_X(pipt_first->earlier_smooth_pt.x);
974 v[1].y = ABS_Y(pipt_first->earlier_smooth_pt.y);
975 n = 3;
976 } else {
977 n = 2;
978 }
979 v[n-1].x = ABS_X(LastX);
980 v[n-1].y = ABS_Y(LastY);
981 if (n > 2) {
982 sv2 = MakeSplinePolyVertex(0, curSpline, &sn2, drawOrigX,
983 drawOrigY, n, v);
984 } else {
985 XDrawLine(mainDisplay, drawWindow, drawGC,
986 pipt_first->hinge_pt.x, pipt_first->hinge_pt.y,
987 LastX, LastY);
988 }
989 }
990 } else {
991 pipt->earlier_valid = pipt->later_valid = TRUE;
992 }
993 done = TRUE;
994 }
995 }
996 MARKHR(drawWindow, revDefaultGC, LastX, LastY);
997
998 *psv = sv;
999 *psn = sn;
1000 *psv2 = sv2;
1001 *psn2 = sn2;
1002
1003 if (orig_sv != NULL) free(orig_sv);
1004 if (orig_sv2 != NULL) free(orig_sv2);
1005 }
1006
1007 static
EraseStructSplineLinesForContAndUpdateSvs(OrigX,OrigY,grid_x,grid_y,pev,num_pts,psv,sn,psv2,sn2,pipt_prev,pipt_first)1008 void EraseStructSplineLinesForContAndUpdateSvs(OrigX, OrigY, grid_x, grid_y,
1009 pev, num_pts, psv, sn, psv2, sn2, pipt_prev, pipt_first)
1010 int OrigX, OrigY, grid_x, grid_y, sn, sn2;
1011 XEvent *pev;
1012 XPoint **psv, **psv2;
1013 IntPointTriplet *pipt_prev, *pipt_first;
1014 {
1015 XPoint *sv=(*psv), *sv2=(*psv2);
1016
1017 /* erase */
1018 if (sv == NULL && sv2 != NULL && !pipt_prev->later_valid) {
1019 /* erase the straight line */
1020 XDrawLine(mainDisplay, drawWindow, drawGC,
1021 pipt_prev->later_smooth_pt.x, pipt_prev->later_smooth_pt.y,
1022 grid_x, grid_y);
1023 }
1024 EraseStructSplineLinesForCont(OrigX, OrigY, grid_x, grid_y, sv, sn, sv2,
1025 sn2);
1026 if ((pev->type == MotionNotify && num_pts > 1) ||
1027 (pev->type == ButtonPress && num_pts > 2)) {
1028 if (pipt_first->earlier_valid) {
1029 /* don't need to do anything here */
1030 } else {
1031 XDrawLine(mainDisplay, drawWindow, drawGC, pipt_first->hinge_pt.x,
1032 pipt_first->hinge_pt.y, grid_x, grid_y);
1033 }
1034 }
1035 if (sv != NULL) free(sv);
1036 if (sv2 != NULL) free(sv2);
1037 *psv = *psv2 = NULL;
1038 }
1039
1040 static
CountStructuredSplinePolygonVs()1041 int CountStructuredSplinePolygonVs()
1042 {
1043 int i=0, len=ListLength(&gStructSplineList), num_vs=0;
1044 CVListElem *elem=NULL;
1045
1046 for (i=0, elem=ListFirst(&gStructSplineList); elem != NULL;
1047 i++, elem=ListNext(&gStructSplineList, elem)) {
1048 IntPointTriplet *ipt=(IntPointTriplet*)(elem->obj);
1049
1050 if (i == 0) {
1051 if (ipt->later_valid) {
1052 num_vs++;
1053 }
1054 } else if (i == len-1) {
1055 if (ipt->earlier_valid) {
1056 num_vs++;
1057 }
1058 } else {
1059 if (ipt->later_valid) {
1060 num_vs++;
1061 }
1062 if (ipt->earlier_valid) {
1063 num_vs++;
1064 }
1065 }
1066 num_vs++;
1067 }
1068 return num_vs;
1069 }
1070
1071 #ifdef _TGIF_DBG
sync()1072 void sync()
1073 {
1074 XSync(mainDisplay,0);
1075 }
1076 #endif /* _TGIF_DBG */
1077
1078 static XComposeStatus c_stat;
1079
1080 static
ContinuePolygon(OrigX,OrigY)1081 void ContinuePolygon(OrigX, OrigY)
1082 int OrigX, OrigY;
1083 /* OrigX and OrigY are screen coordinates (scaled and translated). */
1084 {
1085 register int i;
1086 XEvent input, ev;
1087 XButtonEvent *button_ev;
1088 XMotionEvent *motion_ev;
1089 KeySym key_sym;
1090 int start_polygon_x=OrigX, start_polygon_y=OrigY;
1091 int end_x, end_y, grid_x, grid_y, done=FALSE;
1092 int saved_x, saved_y, closed=FALSE, abort=FALSE;
1093 int num_pts=1, n=2, sn=0, sn2=0, max_n=40, intn=0, tmp_n=0;
1094 int ltx=OrigX, lty=OrigY, rbx=OrigX, rby=OrigY, nothing_is_drawn=TRUE;
1095 XPoint *sv=NULL, *sv2=NULL;
1096 IntPoint *pv=NULL, *cntrlv=NULL, tmp_vs[4];
1097 IntPointTriplet ipt_prev, ipt, first_ipt;
1098 PolygonMeasureCursorInfo pmci;
1099
1100 memset(&ipt, 0, sizeof(IntPointTriplet));
1101 memset(&ipt_prev, 0, sizeof(IntPointTriplet));
1102 memset(&first_ipt, 0, sizeof(IntPointTriplet));
1103 memset(&pmci, 0, sizeof(PolygonMeasureCursorInfo));
1104 SetXorDrawGC(xorColorPixels[colorIndex]);
1105
1106 grid_x = end_x = saved_x = OrigX;
1107 grid_y = end_y = saved_y = OrigY;
1108 if (curSpline != LT_STRAIGHT && curSpline != LT_STRUCT_SPLINE) {
1109 pv = (IntPoint*)malloc((max_n+1)*sizeof(IntPoint));
1110 if (pv == NULL) FailAllocMessage();
1111 pv[0].x = pv[1].x = pv[2].x = ABS_X(OrigX);
1112 pv[0].y = pv[1].y = pv[2].y = ABS_Y(OrigY);
1113 switch (curSpline) {
1114 case LT_SPLINE:
1115 sv = MakeSplinePolygonVertex(0, curSpline, &sn, drawOrigX, drawOrigY,
1116 n+1, pv);
1117 break;
1118 case LT_INTSPLINE:
1119 sv = MakeIntSplinePolygonVertex(&sn, &intn, &cntrlv,
1120 drawOrigX, drawOrigY, n+1, pv);
1121 for (i=0; i < sn; i++) {
1122 if (sv[i].x < ltx) ltx = sv[i].x;
1123 if (sv[i].y < lty) lty = sv[i].y;
1124 if (sv[i].x > rbx) rbx = sv[i].x;
1125 if (sv[i].y > rby) rby = sv[i].y;
1126 }
1127 break;
1128 }
1129 } else if (curSpline == LT_STRUCT_SPLINE) {
1130 ipt_prev.earlier_valid = ipt_prev.later_valid = FALSE;
1131 ipt_prev.earlier_smooth_pt.x = ipt_prev.hinge_pt.x =
1132 ipt_prev.later_smooth_pt.x = OrigX;
1133 ipt_prev.earlier_smooth_pt.y = ipt_prev.hinge_pt.y =
1134 ipt_prev.later_smooth_pt.y = OrigY;
1135 memcpy(&first_ipt, &ipt_prev, sizeof(IntPointTriplet));
1136 pv = (IntPoint*)malloc((max_n+1)*sizeof(IntPoint));
1137 if (pv == NULL) FailAllocMessage();
1138 pv[0].x = pv[1].x = pv[2].x = pv[3].x = ABS_X(OrigX);
1139 pv[0].y = pv[1].y = pv[2].y = pv[3].y = ABS_Y(OrigY);
1140 sv = MakeSplinePolyVertex(0, curSpline, &sn, drawOrigX, drawOrigY, n+1,
1141 pv);
1142 }
1143 SaveStatusStrings();
1144 if (curSpline == LT_STRUCT_SPLINE) {
1145 SetMouseStatus(TgLoadCachedString(CSTID_ADD_A_STRUCT_VERTEX),
1146 TgLoadCachedString(CSTID_CLOSE_POLYGON_SPLINE),
1147 TgLoadCachedString(CSTID_CLOSE_POLYGON_SPLINE));
1148 } else {
1149 SetMouseStatus(TgLoadCachedString(CSTID_ADD_A_VERTEX),
1150 TgLoadCachedString(CSTID_CLOSE_POLYGON_SPLINE),
1151 TgLoadCachedString(CSTID_CLOSE_POLYGON_SPLINE));
1152 }
1153 DoPolygonMeasureCursor(&pmci, POLYGON_STARTSHOW, num_pts, ABS_X(grid_x),
1154 ABS_Y(grid_y), 0, 0, POLYGON_DRAW, POLYGON_CLICK, closed);
1155 if (!debugNoPointerGrab) {
1156 XGrabPointer(mainDisplay, drawWindow, FALSE,
1157 PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
1158 GrabModeAsync, GrabModeAsync, None, handCursor, CurrentTime);
1159 }
1160 if (curSpline == LT_STRUCT_SPLINE) {
1161 DoPolygonMeasureCursor(&pmci, POLYGON_DOSHOW, num_pts, ABS_X(grid_x),
1162 ABS_Y(grid_y), 0, 0, POLYGON_ERASE, POLYGON_DRAG, closed);
1163 ContinueForStructSplinePolygonControlPoints(OrigX, OrigY,
1164 grid_x, grid_y, &sv, &sn, &sv2, &sn2, &first_ipt,
1165 &ipt_prev, &ipt, &abort);
1166 memcpy(&first_ipt, &ipt, sizeof(IntPointTriplet));
1167 memcpy(&ipt_prev, &ipt, sizeof(IntPointTriplet));
1168 if (first_ipt.later_valid) {
1169 grid_x = OFFSET_X(first_ipt.later_smooth_pt.x);
1170 grid_y = OFFSET_Y(first_ipt.later_smooth_pt.y);
1171 }
1172 SetFirstPoint(OrigX, OrigY, &first_ipt);
1173 DoPolygonMeasureCursor(&pmci, POLYGON_STARTSHOW, num_pts, ABS_X(grid_x),
1174 ABS_Y(grid_y), ABS_SIZE(abs(grid_x-OrigX)),
1175 ABS_SIZE(abs(grid_y-OrigY)), POLYGON_DRAW,
1176 POLYGON_CLICK, closed);
1177 } else {
1178 SetFirstPoint(OrigX, OrigY, NULL);
1179 }
1180 while (!done && !abort) {
1181 XNextEvent(mainDisplay, &input);
1182
1183 if (input.type == Expose || input.type == VisibilityNotify) {
1184 ExposeEventHandler(&input, TRUE);
1185 SetXorDrawGC(xorColorPixels[colorIndex]);
1186 } else if ((!(shiftForDiagMouseMove && DiagEventCheck(&input))) &&
1187 (input.type == KeyPress || input.type == KeyRelease)) {
1188 char s[80];
1189 int has_ch=FALSE;
1190
1191 has_ch = XLookupString(&(input.xkey), s, sizeof(s), &key_sym, &c_stat);
1192 if (num_pts > 1 && !(curSpline != LT_STRAIGHT &&
1193 curSpline != LT_STRUCT_SPLINE) &&
1194 (key_sym == XK_Control_L || key_sym == XK_Control_R)) {
1195 XDrawLine(mainDisplay, drawWindow, drawGC, saved_x, saved_y,
1196 grid_x, grid_y);
1197 /* erase */
1198 DoPolygonMeasureCursor(&pmci, POLYGON_DOSHOW, num_pts,
1199 ABS_X(grid_x), ABS_Y(grid_y), ABS_SIZE(abs(grid_x-OrigX)),
1200 ABS_SIZE(abs(grid_y-OrigY)), POLYGON_ERASE, POLYGON_DRAG,
1201 closed);
1202 if (ControlKeyPressedEvent(&input)) {
1203 closed = TRUE;
1204 } else {
1205 closed = FALSE;
1206 }
1207 /* draw */
1208 DoPolygonMeasureCursor(&pmci, POLYGON_DOSHOW, num_pts,
1209 ABS_X(grid_x), ABS_Y(grid_y), ABS_SIZE(abs(grid_x-OrigX)),
1210 ABS_SIZE(abs(grid_y-OrigY)), POLYGON_DRAW, POLYGON_DRAG,
1211 closed);
1212 } else if (CharIsESC(&(input.xkey), s, key_sym, &has_ch)) {
1213 /* erase */
1214 DoPolygonMeasureCursor(&pmci, POLYGON_ENDSHOW, num_pts,
1215 ABS_X(grid_x), ABS_Y(grid_y), ABS_SIZE(abs(grid_x-OrigX)),
1216 ABS_SIZE(abs(grid_y-OrigY)), POLYGON_ERASE, POLYGON_CLICK,
1217 closed);
1218 abort = TRUE;
1219 done = TRUE;
1220 }
1221 } else if ((input.type==MotionNotify && input.xany.window==drawWindow) ||
1222 (shiftForDiagMouseMove && DiagEventCheck(&input) &&
1223 (input.type == KeyPress || input.type == KeyRelease))) {
1224 unsigned int event_state=0;
1225
1226 /* erase */
1227 DoPolygonMeasureCursor(&pmci, POLYGON_DOSHOW, num_pts, ABS_X(grid_x),
1228 ABS_Y(grid_y), ABS_SIZE(abs(grid_x-OrigX)),
1229 ABS_SIZE(abs(grid_y-OrigY)), POLYGON_ERASE, POLYGON_DRAG,
1230 closed);
1231 if (curSpline != LT_STRAIGHT && curSpline != LT_STRUCT_SPLINE) {
1232 XDrawLines(mainDisplay, drawWindow, drawGC, sv, sn,
1233 CoordModeOrigin);
1234 } else if (curSpline == LT_STRUCT_SPLINE) {
1235 if (nothing_is_drawn) {
1236 /* then there is nothing to erase */
1237 nothing_is_drawn = FALSE;
1238 } else {
1239 EraseStructSplineLinesForContAndUpdateSvs(OrigX, OrigY, grid_x,
1240 grid_y, &input, num_pts, &sv, sn, &sv2, sn2, &ipt_prev,
1241 &first_ipt);
1242 }
1243 } else {
1244 XDrawLine(mainDisplay, drawWindow, drawGC, OrigX, OrigY, grid_x,
1245 grid_y);
1246 }
1247 if (num_pts > 1 && closed) {
1248 XDrawLine(mainDisplay, drawWindow, drawGC, saved_x, saved_y,
1249 grid_x, grid_y);
1250 }
1251 if (input.type == KeyPress || input.type == KeyRelease) {
1252 end_x = grid_x;
1253 end_y = grid_y;
1254 event_state = input.xkey.state;
1255 } else {
1256 motion_ev = &(input.xmotion);
1257 end_x = motion_ev->x;
1258 end_y = motion_ev->y;
1259 event_state = motion_ev->state;
1260 }
1261 if (shiftForDiagMouseMove && DiagEventCheck(&input)) {
1262 if (input.type == KeyRelease) {
1263 end_x = input.xkey.x;
1264 end_y = input.xkey.y;
1265 } else {
1266 DiagGridXY(OrigX, OrigY, &end_x, &end_y);
1267 }
1268 }
1269 /* draw */
1270 GridXY(end_x, end_y, &grid_x, &grid_y);
1271 MarkRulers(grid_x, grid_y);
1272 if (curSpline != LT_STRAIGHT && curSpline != LT_STRUCT_SPLINE) {
1273 if (sv != NULL) {
1274 free(sv);
1275 sv = NULL;
1276 }
1277 pv[n-1].x = ABS_X(grid_x);
1278 pv[n-1].y = ABS_Y(grid_y);
1279 switch (curSpline) {
1280 case LT_SPLINE:
1281 sv = MakeSplinePolygonVertex(0, curSpline, &sn, drawOrigX,
1282 drawOrigY, n+1, pv);
1283 break;
1284 case LT_INTSPLINE:
1285 if (cntrlv != NULL) free(cntrlv);
1286 sv = MakeIntSplinePolygonVertex(&sn, &intn, &cntrlv,
1287 drawOrigX, drawOrigY, n+1, pv);
1288 for (i=0; i < sn; i++) {
1289 if (sv[i].x < ltx) ltx = sv[i].x;
1290 if (sv[i].y < lty) lty = sv[i].y;
1291 if (sv[i].x > rbx) rbx = sv[i].x;
1292 if (sv[i].y > rby) rby = sv[i].y;
1293 }
1294 break;
1295 }
1296 XDrawLines(mainDisplay, drawWindow, drawGC, sv, sn,
1297 CoordModeOrigin);
1298 } else if (curSpline == LT_STRUCT_SPLINE) {
1299 if (sv != NULL) {
1300 free(sv);
1301 sv = NULL;
1302 }
1303 if (sv2 != NULL) {
1304 free(sv2);
1305 sv2 = NULL;
1306 }
1307 if (ipt_prev.later_valid) {
1308 pv[0].x = ABS_X(OrigX);
1309 pv[0].y = ABS_Y(OrigY);
1310 pv[1].x = ABS_X(ipt_prev.later_smooth_pt.x);
1311 pv[1].y = ABS_Y(ipt_prev.later_smooth_pt.y);
1312 pv[2].x = pv[3].x = ABS_X(grid_x);
1313 pv[2].y = pv[3].y = ABS_Y(grid_y);
1314 n = 3;
1315 sv = MakeSplinePolyVertex(0, curSpline, &sn, drawOrigX,
1316 drawOrigY, n, pv);
1317 XDrawLines(mainDisplay, drawWindow, drawGC, sv, sn,
1318 CoordModeOrigin);
1319 if (first_ipt.earlier_valid) {
1320 tmp_n = 3;
1321 tmp_vs[0].x = ABS_X(grid_x);
1322 tmp_vs[0].y = ABS_Y(grid_y);
1323 tmp_vs[1].x = ABS_X(first_ipt.earlier_smooth_pt.x);
1324 tmp_vs[1].y = ABS_Y(first_ipt.earlier_smooth_pt.y);
1325 tmp_vs[2].x = ABS_X(first_ipt.hinge_pt.x);
1326 tmp_vs[2].y = ABS_Y(first_ipt.hinge_pt.y);
1327 sv2 = MakeSplinePolyVertex(0, curSpline, &sn2,
1328 drawOrigX, drawOrigY, tmp_n, tmp_vs);
1329 XDrawLines(mainDisplay, drawWindow, drawGC, sv2, sn2,
1330 CoordModeOrigin);
1331 } else {
1332 XDrawLine(mainDisplay, drawWindow, drawGC,
1333 first_ipt.hinge_pt.x, first_ipt.hinge_pt.y,
1334 grid_x, grid_y);
1335 }
1336 } else {
1337 XDrawLine(mainDisplay, drawWindow, drawGC, OrigX, OrigY,
1338 grid_x, grid_y);
1339 if (num_pts > 1) {
1340 if (first_ipt.earlier_valid) {
1341 tmp_n = 3;
1342 tmp_vs[0].x = ABS_X(grid_x);
1343 tmp_vs[0].y = ABS_Y(grid_y);
1344 tmp_vs[1].x = ABS_X(first_ipt.earlier_smooth_pt.x);
1345 tmp_vs[1].y = ABS_Y(first_ipt.earlier_smooth_pt.y);
1346 tmp_vs[2].x = ABS_X(first_ipt.hinge_pt.x);
1347 tmp_vs[2].y = ABS_Y(first_ipt.hinge_pt.y);
1348 sv2 = MakeSplinePolyVertex(0, curSpline, &sn2,
1349 drawOrigX, drawOrigY, tmp_n, tmp_vs);
1350 XDrawLines(mainDisplay, drawWindow, drawGC, sv2, sn2,
1351 CoordModeOrigin);
1352 } else {
1353 XDrawLine(mainDisplay, drawWindow, drawGC,
1354 first_ipt.hinge_pt.x, first_ipt.hinge_pt.y, grid_x,
1355 grid_y);
1356 }
1357 }
1358 }
1359 } else {
1360 if (num_pts > 1) {
1361 if (event_state & ControlMask) {
1362 XDrawLine(mainDisplay, drawWindow, drawGC, saved_x, saved_y,
1363 grid_x, grid_y);
1364 closed = TRUE;
1365 } else {
1366 closed = FALSE;
1367 }
1368 }
1369 XDrawLine(mainDisplay, drawWindow, drawGC, OrigX, OrigY, grid_x,
1370 grid_y);
1371 }
1372 DoPolygonMeasureCursor(&pmci, POLYGON_DOSHOW, num_pts, ABS_X(grid_x),
1373 ABS_Y(grid_y), ABS_SIZE(abs(grid_x-OrigX)),
1374 ABS_SIZE(abs(grid_y-OrigY)), POLYGON_DRAW, POLYGON_DRAG, closed);
1375 while (XCheckMaskEvent(mainDisplay, PointerMotionMask, &ev)) ;
1376 } else if (input.type == ButtonPress) {
1377 /* erase */
1378 DoPolygonMeasureCursor(&pmci, POLYGON_ENDSHOW, num_pts, ABS_X(grid_x),
1379 ABS_Y(grid_y), ABS_SIZE(abs(grid_x-OrigX)),
1380 ABS_SIZE(abs(grid_y-OrigY)), POLYGON_ERASE, POLYGON_DRAG,
1381 closed);
1382 button_ev = &(input.xbutton);
1383
1384 end_x = button_ev->x;
1385 end_y = button_ev->y;
1386
1387 if (shiftForDiagMouseMove && DiagEventCheck(&input)) {
1388 DiagGridXY(OrigX, OrigY, &end_x, &end_y);
1389 }
1390 GridXY(end_x, end_y, &grid_x, &grid_y);
1391
1392 if (grid_x == OrigX && grid_y == OrigY) {
1393 if (curSpline == LT_STRUCT_SPLINE) {
1394 if (num_pts == 1) {
1395 abort = TRUE;
1396 } else {
1397 /* need to overwrite the previous point */
1398
1399 /* erase */
1400
1401 /*
1402 * since we've clicked at the same point, need to pretend
1403 * that num_pts is one more
1404 */
1405 EraseStructSplineLinesForContAndUpdateSvs(OrigX, OrigY,
1406 grid_x, grid_y, &input, num_pts+1, &sv, sn, &sv2, sn2,
1407 &ipt_prev, &first_ipt);
1408 if (ipt_prev.later_valid) {
1409 /* erase whole curve */
1410 DrawAllStructSplinePointsForCont(num_pts);
1411 ipt_prev.earlier_valid = ipt_prev.later_valid = FALSE;
1412 ipt_prev.earlier_smooth_pt.x = ipt_prev.later_smooth_pt.x =
1413 ipt_prev.hinge_pt.x;
1414 ipt_prev.earlier_smooth_pt.y = ipt_prev.later_smooth_pt.y =
1415 ipt_prev.hinge_pt.y;
1416 UpdateLastPointForCont(&ipt_prev);
1417 /* draw whole curve */
1418 DrawAllStructSplinePointsForCont(num_pts);
1419 }
1420 UpdatePrevToLastPointForCont(&ipt_prev);
1421 ipt.earlier_valid = ipt.later_valid = FALSE;
1422 ipt.earlier_smooth_pt.x = ipt.later_smooth_pt.x =
1423 ipt.hinge_pt.x = grid_x;
1424 ipt.earlier_smooth_pt.y = ipt.later_smooth_pt.y =
1425 ipt.hinge_pt.y = grid_y;
1426 OrigX = ipt_prev.hinge_pt.x;
1427 OrigY = ipt_prev.hinge_pt.y;
1428 if (ipt_prev.later_valid) {
1429 pv[0].x = ABS_X(OrigX);
1430 pv[0].y = ABS_Y(OrigY);
1431 pv[1].x = ABS_X(ipt_prev.later_smooth_pt.x);
1432 pv[1].y = ABS_Y(ipt_prev.later_smooth_pt.y);
1433 pv[2].x = pv[3].x = ABS_X(grid_x);
1434 pv[2].y = pv[3].y = ABS_Y(grid_y);
1435 n = 3;
1436 sv = MakeSplinePolyVertex(0, curSpline, &sn, drawOrigX,
1437 drawOrigY, n, pv);
1438 }
1439 if (first_ipt.earlier_valid) {
1440 tmp_n = 3;
1441 tmp_vs[0].x = ABS_X(grid_x);
1442 tmp_vs[0].y = ABS_Y(grid_y);
1443 tmp_vs[1].x = ABS_X(first_ipt.earlier_smooth_pt.x);
1444 tmp_vs[1].y = ABS_Y(first_ipt.earlier_smooth_pt.y);
1445 tmp_vs[2].x = ABS_X(first_ipt.hinge_pt.x);
1446 tmp_vs[2].y = ABS_Y(first_ipt.hinge_pt.y);
1447 sv2 = MakeSplinePolyVertex(0, curSpline, &sn2,
1448 drawOrigX, drawOrigY, tmp_n, tmp_vs);
1449 XDrawLines(mainDisplay, drawWindow, drawGC, sv2, sn2,
1450 CoordModeOrigin);
1451 }
1452 }
1453 }
1454 } else {
1455 num_pts++;
1456 ipt.earlier_valid = ipt.later_valid = FALSE;
1457 ipt.earlier_smooth_pt.x = ipt.later_smooth_pt.x = ipt.hinge_pt.x =
1458 grid_x;
1459 ipt.earlier_smooth_pt.y = ipt.later_smooth_pt.y = ipt.hinge_pt.y =
1460 grid_y;
1461 ipt.ratio = (double)1;
1462 AddPointForCont(grid_x, grid_y, &ipt);
1463 if (curSpline != LT_STRAIGHT && curSpline != LT_STRUCT_SPLINE) {
1464 if (n >= max_n-3) {
1465 max_n += 40;
1466 pv = (IntPoint*)realloc(pv, sizeof(IntPoint)*max_n+1);
1467 if (pv == NULL) FailAllocMessage();
1468 }
1469 /* erase */
1470 XDrawLines(mainDisplay, drawWindow, drawGC, sv, sn,
1471 CoordModeOrigin);
1472 if (sv != NULL) {
1473 free(sv);
1474 sv = NULL;
1475 }
1476 pv[n].x = ABS_X(grid_x);
1477 pv[n].y = ABS_Y(grid_y);
1478 n++;
1479 pv[n].x = pv[0].x;
1480 pv[n].y = pv[0].y;
1481 switch (curSpline) {
1482 case LT_SPLINE:
1483 sv = MakeSplinePolygonVertex(0, curSpline, &sn, drawOrigX,
1484 drawOrigY, n+1, pv);
1485 break;
1486 case LT_INTSPLINE:
1487 if (cntrlv != NULL) free(cntrlv);
1488 sv = MakeIntSplinePolygonVertex(&sn, &intn, &cntrlv,
1489 drawOrigX, drawOrigY, n+1, pv);
1490 for (i=0; i < sn; i++) {
1491 if (sv[i].x < ltx) ltx = sv[i].x;
1492 if (sv[i].y < lty) lty = sv[i].y;
1493 if (sv[i].x > rbx) rbx = sv[i].x;
1494 if (sv[i].y > rby) rby = sv[i].y;
1495 }
1496 break;
1497 }
1498 /* draw */
1499 XDrawLines(mainDisplay, drawWindow, drawGC, sv, sn,
1500 CoordModeOrigin);
1501 } else if (curSpline == LT_STRUCT_SPLINE) {
1502 /* erase */
1503 EraseStructSplineLinesForContAndUpdateSvs(OrigX, OrigY, grid_x,
1504 grid_y, &input, num_pts, &sv, sn, &sv2, sn2, &ipt_prev,
1505 &first_ipt);
1506 /* draw */
1507 if (ipt_prev.later_valid) {
1508 pv[0].x = ABS_X(OrigX);
1509 pv[0].y = ABS_Y(OrigY);
1510 pv[1].x = ABS_X(ipt_prev.later_smooth_pt.x);
1511 pv[1].y = ABS_Y(ipt_prev.later_smooth_pt.y);
1512 pv[2].x = pv[3].x = ABS_X(grid_x);
1513 pv[2].y = pv[3].y = ABS_Y(grid_y);
1514 n = 3;
1515 sv = MakeSplinePolyVertex(0, curSpline, &sn, drawOrigX,
1516 drawOrigY, n, pv);
1517 XDrawLines(mainDisplay, drawWindow, drawGC, sv, sn,
1518 CoordModeOrigin);
1519 if (first_ipt.earlier_valid) {
1520 tmp_n = 3;
1521 tmp_vs[0].x = ABS_X(grid_x);
1522 tmp_vs[0].y = ABS_Y(grid_y);
1523 tmp_vs[1].x = ABS_X(first_ipt.earlier_smooth_pt.x);
1524 tmp_vs[1].y = ABS_Y(first_ipt.earlier_smooth_pt.y);
1525 tmp_vs[2].x = ABS_X(first_ipt.hinge_pt.x);
1526 tmp_vs[2].y = ABS_Y(first_ipt.hinge_pt.y);
1527 sv2 = MakeSplinePolyVertex(0, curSpline, &sn2,
1528 drawOrigX, drawOrigY, tmp_n, tmp_vs);
1529 XDrawLines(mainDisplay, drawWindow, drawGC, sv2, sn2,
1530 CoordModeOrigin);
1531 } else {
1532 XDrawLine(mainDisplay, drawWindow, drawGC,
1533 first_ipt.hinge_pt.x, first_ipt.hinge_pt.y,
1534 grid_x, grid_y);
1535 }
1536 } else {
1537 XDrawLine(mainDisplay, drawWindow, drawGC, OrigX, OrigY,
1538 grid_x, grid_y);
1539 if (sv != NULL) {
1540 free(sv);
1541 sv = NULL;
1542 }
1543 }
1544 }
1545 }
1546 if (abort) {
1547 continue;
1548 }
1549 if (num_pts == 2 && closed && button_ev->button == Button1 &&
1550 curSpline == LT_STRAIGHT) {
1551 XDrawLine(mainDisplay, drawWindow, drawGC, OrigX, OrigY, grid_x,
1552 grid_y);
1553 }
1554 if (grid_x == start_polygon_x && grid_y == start_polygon_y) {
1555 if (curSpline != LT_STRAIGHT && curSpline != LT_STRUCT_SPLINE) {
1556 /* erase the whole thing */
1557 XDrawLines(mainDisplay, drawWindow, drawGC, sv, sn,
1558 CoordModeOrigin);
1559 } else if (curSpline == LT_STRUCT_SPLINE) {
1560 CVListElem *elem=ListFirst(&gStructSplineList);
1561 IntPointTriplet *pipt=(IntPointTriplet*)(elem->obj);
1562
1563 /* erase the last part */
1564 if (nothing_is_drawn) {
1565 /* then there is nothing to erase */
1566 nothing_is_drawn = FALSE;
1567 } else {
1568 EraseStructSplineLinesForContAndUpdateSvs(OrigX, OrigY,
1569 grid_x, grid_y, &input, num_pts, &sv, sn, &sv2, sn2,
1570 &ipt_prev, &first_ipt);
1571 }
1572 /* make the last point identical to the first point */
1573 UpdateLastPointForCont(pipt);
1574 } else {
1575 /* erase the last part */
1576 XDrawLine(mainDisplay, drawWindow, drawGC, OrigX, OrigY,
1577 grid_x, grid_y);
1578 if (num_pts > 1 && closed) {
1579 XDrawLine(mainDisplay, drawWindow, drawGC, saved_x,
1580 saved_y, grid_x, grid_y);
1581 }
1582 if (num_pts < 4) {
1583 XDrawLine(mainDisplay, drawWindow, drawGC, saved_x,
1584 saved_y, OrigX, OrigY);
1585 }
1586 }
1587 done = TRUE;
1588 } else {
1589 switch(button_ev->button) {
1590 case Button1:
1591 if (curSpline == LT_STRUCT_SPLINE) {
1592 /*
1593 * if the first point is curved, both the curve "before"
1594 * and "after have been drawn at this point
1595 * if the first point is *not* curved, only the curve "before"
1596 * has been drawn, the line "after" is open (not drawn)
1597 */
1598 ContinueForStructSplinePolygonControlPoints(OrigX, OrigY,
1599 grid_x, grid_y, &sv, &sn, &sv2, &sn2, &first_ipt,
1600 &ipt_prev, &ipt, &abort);
1601 UpdateLastPointForCont(&ipt);
1602 /* at this point, the curve has been drawn */
1603 if (sv != NULL) {
1604 free(sv);
1605 sv = NULL;
1606 if (sv2 == NULL && !first_ipt.earlier_valid) {
1607 /* erase it */
1608 XDrawLine(mainDisplay, drawWindow, drawGC,
1609 first_ipt.hinge_pt.x, first_ipt.hinge_pt.y,
1610 ipt.hinge_pt.x, ipt.hinge_pt.y);
1611 }
1612 }
1613 if (sv2 != NULL) {
1614 /* erase it */
1615 XDrawLines(mainDisplay, drawWindow, drawGC, sv2, sn2,
1616 CoordModeOrigin);
1617 free(sv2);
1618 sv2 = NULL;
1619 if (ipt.later_valid) {
1620 sn = 2;
1621 sv = (XPoint*)malloc((sn+1)*sizeof(XPoint));
1622 if (sv == NULL) FailAllocMessage();
1623 sv[0].x = ABS_X(ipt.later_smooth_pt.x);
1624 sv[0].y = ABS_Y(ipt.later_smooth_pt.y);
1625 sv[1].x = ABS_X(ipt.hinge_pt.x);
1626 sv[1].y = ABS_Y(ipt.hinge_pt.y);
1627 XDrawLines(mainDisplay, drawWindow, drawGC, sv, sn,
1628 CoordModeOrigin);
1629 if (first_ipt.earlier_valid) {
1630 tmp_n = 3;
1631 tmp_vs[0].x = ABS_X(ipt.later_smooth_pt.x);
1632 tmp_vs[0].y = ABS_Y(ipt.later_smooth_pt.y);
1633 tmp_vs[1].x = ABS_X(first_ipt.earlier_smooth_pt.x);
1634 tmp_vs[1].y = ABS_Y(first_ipt.earlier_smooth_pt.y);
1635 tmp_vs[2].x = ABS_X(first_ipt.hinge_pt.x);
1636 tmp_vs[2].y = ABS_Y(first_ipt.hinge_pt.y);
1637 sv2 = MakeSplinePolyVertex(0, curSpline, &sn2,
1638 drawOrigX, drawOrigY, tmp_n, tmp_vs);
1639 XDrawLines(mainDisplay, drawWindow, drawGC, sv2, sn2,
1640 CoordModeOrigin);
1641 } else {
1642 XDrawLine(mainDisplay, drawWindow, drawGC,
1643 first_ipt.hinge_pt.x, first_ipt.hinge_pt.y,
1644 ipt.later_smooth_pt.x, ipt.later_smooth_pt.y);
1645 }
1646 } else {
1647 nothing_is_drawn = TRUE;
1648 }
1649 } else {
1650 nothing_is_drawn = TRUE;
1651 }
1652 if (!abort) {
1653 CVListElem *elem=ListLast(&gStructSplineList);
1654
1655 if (elem != NULL) {
1656 IntPointTriplet *pipt=(IntPointTriplet*)(elem->obj);
1657
1658 memcpy(pipt, &ipt, sizeof(IntPointTriplet));
1659 }
1660 memcpy(&ipt_prev, &ipt, sizeof(IntPointTriplet));
1661 OrigX = ipt.hinge_pt.x;
1662 OrigY = ipt.hinge_pt.y;
1663 if (ipt.later_valid) {
1664 grid_x = ipt.later_smooth_pt.x;
1665 grid_y = ipt.later_smooth_pt.y;
1666 } else {
1667 grid_x = ipt.hinge_pt.x;
1668 grid_y = ipt.hinge_pt.y;
1669 }
1670 DoPolygonMeasureCursor(&pmci, POLYGON_STARTSHOW, num_pts,
1671 ABS_X(grid_x), ABS_Y(grid_y),
1672 ABS_SIZE(abs(grid_x-OrigX)),
1673 ABS_SIZE(abs(grid_y-OrigY)), POLYGON_DRAW,
1674 POLYGON_CLICK, closed);
1675 }
1676 } else {
1677 OrigX = grid_x; OrigY = grid_y;
1678 /* draw */
1679 DoPolygonMeasureCursor(&pmci, POLYGON_STARTSHOW, num_pts,
1680 ABS_X(grid_x), ABS_Y(grid_y), 0, 0, POLYGON_DRAW,
1681 POLYGON_CLICK, closed);
1682 }
1683 break;
1684 case Button2:
1685 case Button3:
1686 if (curSpline != LT_STRAIGHT && curSpline != LT_STRUCT_SPLINE) {
1687 XDrawLines(mainDisplay, drawWindow, drawGC, sv, sn,
1688 CoordModeOrigin);
1689 if (num_pts == 1) {
1690 done = TRUE;
1691 break;
1692 }
1693 } else if (curSpline == LT_STRUCT_SPLINE) {
1694 /*
1695 * if the first point is curved, both the curve "before"
1696 * and "after have been drawn at this point
1697 * if the first point is *not* curved, only the curve "before"
1698 * has been drawn, the line "after" is open (not drawn)
1699 */
1700 memset(&ipt, 0, sizeof(IntPointTriplet));
1701 ipt.earlier_valid = ipt.later_valid = FALSE;
1702 ipt.hinge_pt.x = ipt.earlier_smooth_pt.x =
1703 ipt.later_smooth_pt.x = grid_x;
1704 ipt.hinge_pt.y = ipt.earlier_smooth_pt.y =
1705 ipt.later_smooth_pt.y = grid_y;
1706 ipt.ratio = (double)1;
1707 ContinueForStructSplinePolygonControlPoints(OrigX, OrigY,
1708 grid_x, grid_y, &sv, &sn, &sv2, &sn2, &first_ipt,
1709 &ipt_prev, &ipt, &abort);
1710 UpdateLastPointForCont(&ipt);
1711 if (num_pts == 1 && !first_ipt.later_valid &&
1712 !ipt.earlier_valid) {
1713 done = TRUE;
1714 break;
1715 }
1716 } else {
1717 XDrawLine(mainDisplay, drawWindow, drawGC, OrigX, OrigY,
1718 grid_x, grid_y);
1719 if (num_pts > 1 && closed) {
1720 XDrawLine(mainDisplay, drawWindow, drawGC, saved_x,
1721 saved_y, grid_x, grid_y);
1722 }
1723 if (num_pts < 3) {
1724 XDrawLine(mainDisplay, drawWindow, drawGC, saved_x,
1725 saved_y, OrigX, OrigY);
1726 }
1727 if (num_pts == 1) {
1728 done = TRUE;
1729 break;
1730 }
1731 }
1732 num_pts++;
1733 AddPointForCont(start_polygon_x, start_polygon_y, &first_ipt);
1734 done = TRUE;
1735 break;
1736 }
1737 }
1738 }
1739 }
1740 XUngrabPointer(mainDisplay, CurrentTime);
1741 RestoreStatusStrings();
1742 SetMouseStatus(NULL, NULL, NULL);
1743 Msg("");
1744
1745 if (pv != NULL) free(pv);
1746 if (sv != NULL) free(sv);
1747 if (cntrlv != NULL) free(cntrlv);
1748
1749 if (!abort) {
1750 if (curSpline == LT_STRUCT_SPLINE) {
1751 int num_actual_vs=CountStructuredSplinePolygonVs();
1752
1753 if (num_actual_vs <= 3) {
1754 abort = TRUE;
1755 }
1756 } else if (num_pts <= 3) {
1757 abort = TRUE;
1758 }
1759 }
1760 if (!abort) {
1761 CreatePolygonObj(num_pts, CREATE_RELATIVE);
1762 RecordNewObjCmd();
1763 RedrawAnArea(botObj, topObj->bbox.ltx-GRID_ABS_SIZE(1),
1764 topObj->bbox.lty-GRID_ABS_SIZE(1),
1765 topObj->bbox.rbx+GRID_ABS_SIZE(1),
1766 topObj->bbox.rby+GRID_ABS_SIZE(1));
1767 polygonDrawn = TRUE;
1768 SetFileModified(TRUE);
1769 } else {
1770 if (curSpline != LT_INTSPLINE) {
1771 ltx = rbx = grid_x;
1772 lty = rby = grid_y;
1773 }
1774 FreePointsForCont(<x, <y, &rbx, &rby);
1775 RedrawAnArea(botObj, ABS_X(ltx)-GRID_ABS_SIZE(1),
1776 ABS_Y(lty)-GRID_ABS_SIZE(1), ABS_X(rbx)+GRID_ABS_SIZE(1),
1777 ABS_Y(rby)+GRID_ABS_SIZE(1));
1778 numPtsInPoly = 0;
1779 lastPtPtr = NULL;
1780 polygonDrawn = FALSE;
1781 }
1782 }
1783
DrawPolygon(input)1784 void DrawPolygon(input)
1785 XEvent *input;
1786 {
1787 XButtonEvent *button_ev;
1788 int mouse_x, mouse_y, grid_x, grid_y;
1789
1790 if (input->type != ButtonPress) return;
1791
1792 button_ev = &(input->xbutton);
1793 if (button_ev->button == Button1) {
1794 mouse_x = button_ev->x;
1795 mouse_y = button_ev->y;
1796 GridXY(mouse_x, mouse_y, &grid_x, &grid_y);
1797 ContinuePolygon(grid_x, grid_y);
1798 }
1799 }
1800
SelectAndHighLightNewObjects(PrevTopObj)1801 void SelectAndHighLightNewObjects(PrevTopObj)
1802 struct ObjRec *PrevTopObj;
1803 {
1804 register struct ObjRec *obj_ptr;
1805 register struct SelRec *sel_ptr;
1806
1807 if (topSel != NULL) {
1808 HighLightReverse();
1809 RemoveAllSel();
1810 }
1811 for (obj_ptr=topObj; obj_ptr != PrevTopObj; obj_ptr=obj_ptr->next) {
1812 sel_ptr = (struct SelRec *)malloc(sizeof(struct SelRec));
1813 if (sel_ptr == NULL) FailAllocMessage();
1814 sel_ptr->obj = obj_ptr;
1815 sel_ptr->prev = sel_ptr->next = NULL;
1816 AddSel(botSel, NULL, sel_ptr);
1817 }
1818 UpdSelBBox();
1819 HighLightForward();
1820 }
1821
InputPolygonPts()1822 void InputPolygonPts()
1823 {
1824 char inbuf[MAXSTRING+1];
1825 int more_polygon=FALSE, num_polygons=0;
1826 int started_composite=FALSE;
1827 struct ObjRec *saved_top_obj=topObj;
1828
1829 MakeQuiescent();
1830 XSync(mainDisplay, False);
1831 do {
1832 int len, ok=TRUE, num_pts=0;
1833 int first_x=0, first_y=0, eof=TRUE;
1834 struct PtRec *pt_ptr;
1835
1836 more_polygon = FALSE;
1837 numPtsInPoly = 0;
1838 lastPtPtr = NULL;
1839 printf("%s\n", TgLoadString(STID_INPUT_PAIRS_OF_POINTS_POLYGON));
1840 printf("> ");
1841 fflush(stdout);
1842 while (ok && fgets(inbuf, MAXSTRING, stdin) != NULL) {
1843 if (strcmp(inbuf, ";\n") == 0) {
1844 eof = FALSE;
1845 more_polygon = TRUE;
1846 break;
1847 }
1848 if (strcmp(inbuf, ".\n") == 0) {
1849 eof = FALSE;
1850 break;
1851 }
1852 len = strlen(inbuf);
1853 if (len > 0) {
1854 char *c_ptr=strtok(inbuf," ,\t\n"), *c_ptr1=NULL;
1855
1856 if (c_ptr != NULL) c_ptr1 = strtok(NULL," ,\t\n");
1857 if (c_ptr1 != NULL) while (strchr(" ,\t\n", *c_ptr1)) c_ptr1++;
1858 while (c_ptr != NULL && c_ptr1 != NULL) {
1859 num_pts++;
1860 pt_ptr = (struct PtRec *)malloc(sizeof(struct PtRec));
1861 if (pt_ptr == NULL) FailAllocMessage();
1862 pt_ptr->next = lastPtPtr;
1863 if (sscanf(c_ptr, "%d", &pt_ptr->x) != 1 ||
1864 sscanf(c_ptr1, "%d", &pt_ptr->y) != 1) {
1865 ok = FALSE;
1866 MsgBox(TgLoadString(STID_READ_INT_ERR_FOR_POLYGON_PTS),
1867 TOOL_NAME, INFO_MB);
1868 XSync(mainDisplay, False);
1869 break;
1870 }
1871 if (lastPtPtr == NULL) {
1872 first_x = pt_ptr->x;
1873 first_y = pt_ptr->y;
1874 }
1875 lastPtPtr = pt_ptr;
1876 c_ptr = strtok(NULL," ,\t\n");
1877 if (c_ptr != NULL) c_ptr1 = strtok(NULL," ,\t\n");
1878 if (c_ptr1 != NULL) while (strchr(" ,\t\n", *c_ptr1)) c_ptr1++;
1879 }
1880 if (c_ptr != NULL) {
1881 ok = FALSE;
1882 MsgBox(TgLoadString(STID_READ_INT_ERR_FOR_POLYGON_PTS),
1883 TOOL_NAME, INFO_MB);
1884 XSync(mainDisplay, False);
1885 }
1886 }
1887 printf("> ");
1888 fflush(stdout);
1889 }
1890 printf("\n");
1891 if (eof) rewind(stdin);
1892 if (ok && num_pts > 2) {
1893 num_polygons++;
1894 if (lastPtPtr->x != first_x || lastPtPtr->y != first_y) {
1895 num_pts++;
1896 pt_ptr = (struct PtRec *)malloc(sizeof(struct PtRec));
1897 if (pt_ptr == NULL) FailAllocMessage();
1898 pt_ptr->next = lastPtPtr;
1899 pt_ptr->x = first_x;
1900 pt_ptr->y = first_y;
1901 lastPtPtr = pt_ptr;
1902 }
1903 CreatePolygonObj(num_pts, CREATE_ABSOLUTE);
1904 if (more_polygon || num_polygons > 1) {
1905 if (num_polygons <= 1) {
1906 StartCompositeCmd();
1907 started_composite = TRUE;
1908 }
1909 RecordNewObjCmd();
1910 numRedrawBBox = 0;
1911 topObj->tmp_parent = NULL;
1912 DrawObj(drawWindow, topObj);
1913 } else {
1914 RecordNewObjCmd();
1915 RedrawAnArea(botObj, topObj->bbox.ltx-GRID_ABS_SIZE(1),
1916 topObj->bbox.lty-GRID_ABS_SIZE(1),
1917 topObj->bbox.rbx+GRID_ABS_SIZE(1),
1918 topObj->bbox.rby+GRID_ABS_SIZE(1));
1919 SelectTopObj();
1920 SetFileModified(TRUE);
1921 justDupped = FALSE;
1922 }
1923 }
1924 if (ok && num_pts <= 2) {
1925 MsgBox(TgLoadString(STID_TOO_FEW_POINTERS_ENTERED), TOOL_NAME,
1926 INFO_MB);
1927 XSync(mainDisplay, False);
1928 }
1929 for ( ; lastPtPtr != NULL; lastPtPtr=pt_ptr) {
1930 pt_ptr = lastPtPtr->next;
1931 free(pt_ptr);
1932 }
1933 } while (more_polygon);
1934 if (num_polygons > 1 || started_composite) {
1935 SelectAndHighLightNewObjects(saved_top_obj);
1936 GroupSelObj(TRUE, TRUE, TRUE);
1937 EndCompositeCmd();
1938
1939 SetFileModified(TRUE);
1940 justDupped = FALSE;
1941 }
1942 }
1943
1944 static
AddToLastPoint(XOff,YOff)1945 void AddToLastPoint(XOff, YOff)
1946 int XOff, YOff;
1947 {
1948 struct PtRec *pt_ptr=(struct PtRec *)malloc(sizeof(struct PtRec));
1949
1950 if (pt_ptr == NULL) FailAllocMessage();
1951 pt_ptr->next = lastPtPtr;
1952 numPtsInPoly++;
1953 lastPtPtr = pt_ptr;
1954 pt_ptr->x = XOff;
1955 pt_ptr->y = YOff;
1956 }
1957
GetBoundingBox()1958 void GetBoundingBox()
1959 {
1960 struct SelRec *sel_ptr, *tmp_top_sel=NULL, *tmp_bot_sel=NULL;
1961 int num_created=0, saved_cur_spline=curSpline;
1962
1963 if (topSel == NULL) {
1964 MsgBox(TgLoadCachedString(CSTID_NO_OBJ_SELECTED), TOOL_NAME, INFO_MB);
1965 return;
1966 }
1967 if (curChoice == VERTEXMODE) SetCurChoice(NOTHING);
1968 curSpline = LT_STRAIGHT;
1969
1970 tmp_top_sel = tmp_bot_sel = NULL;
1971
1972 HighLightReverse();
1973 StartCompositeCmd();
1974 for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
1975 struct ObjRec *obj_ptr=sel_ptr->obj;
1976 struct SelRec *new_sel_ptr;
1977
1978 if (obj_ptr->ctm == NULL) {
1979 struct BBRec *p_obbox=(&obj_ptr->obbox);
1980
1981 AddToLastPoint(p_obbox->ltx, p_obbox->lty);
1982 AddToLastPoint(p_obbox->ltx, p_obbox->rby);
1983 AddToLastPoint(p_obbox->rbx, p_obbox->rby);
1984 AddToLastPoint(p_obbox->rbx, p_obbox->lty);
1985 AddToLastPoint(p_obbox->ltx, p_obbox->lty);
1986 CreatePolygonObj(5, CREATE_ABSOLUTE);
1987 } else {
1988 int i;
1989
1990 numPtsInPoly = 0;
1991 lastPtPtr = NULL;
1992 for (i=0; i < 5; i++) {
1993 AddToLastPoint(obj_ptr->rotated_obbox[i].x,
1994 obj_ptr->rotated_obbox[i].y);
1995 }
1996 CreatePolygonObj(5, CREATE_RELATIVE);
1997 }
1998
1999 new_sel_ptr = (struct SelRec *)malloc(sizeof(struct SelRec));
2000 if (new_sel_ptr == NULL) FailAllocMessage();
2001 new_sel_ptr->obj = topObj;
2002 new_sel_ptr->next = NULL;
2003 new_sel_ptr->prev = NULL;
2004 PrepareToRecord(CMD_NEW, NULL, NULL, 0);
2005 RecordCmd(CMD_NEW, NULL, new_sel_ptr, new_sel_ptr, 1);
2006
2007 new_sel_ptr->next = tmp_top_sel;
2008 if (tmp_top_sel == NULL) {
2009 tmp_bot_sel = new_sel_ptr;
2010 } else {
2011 tmp_top_sel->prev = new_sel_ptr;
2012 }
2013 tmp_top_sel = new_sel_ptr;
2014 num_created++;
2015 }
2016 EndCompositeCmd();
2017 curSpline = saved_cur_spline;
2018
2019 RemoveAllSel();
2020 topSel = tmp_top_sel;
2021 botSel = tmp_bot_sel;
2022 UpdSelBBox();
2023 RedrawAnArea(botObj, selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
2024 selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
2025 HighLightForward();
2026 justDupped = FALSE;
2027 SetFileModified(TRUE);
2028 }
2029
SavePolygonObj(FP,ObjPtr)2030 void SavePolygonObj(FP, ObjPtr)
2031 FILE *FP;
2032 struct ObjRec *ObjPtr;
2033 {
2034 register int i, n;
2035 int count;
2036 struct PolygonRec *polygon_ptr=ObjPtr->detail.g;
2037
2038 n = polygon_ptr->n;
2039 if (fprintf(FP, "polygon('%s','',%1d,[\n\t",
2040 colorMenuItems[ObjPtr->color], polygon_ptr->n) == EOF) {
2041 writeFileFailed = TRUE;
2042 }
2043 for (i=0, count = 0; i < n-1; i++) {
2044 if (fprintf(FP, "%1d,%1d,", polygon_ptr->vlist[i].x,
2045 polygon_ptr->vlist[i].y) == EOF) {
2046 writeFileFailed = TRUE;
2047 }
2048 if (++count == 8) {
2049 count = 0;
2050 if (fprintf(FP, "\n\t") == EOF) writeFileFailed = TRUE;
2051 }
2052 }
2053 if (fprintf(FP, "%1d,%1d],",
2054 polygon_ptr->vlist[n-1].x, polygon_ptr->vlist[n-1].y) == EOF)
2055 writeFileFailed = TRUE;
2056
2057 if (fprintf(FP,
2058 "%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,'%s',%1d,",
2059 polygon_ptr->fill, polygon_ptr->width, polygon_ptr->pen,
2060 polygon_ptr->curved, ObjPtr->id, polygon_ptr->dash, ObjPtr->rotation,
2061 ObjPtr->locked, ObjPtr->ctm!=NULL, ObjPtr->invisible,
2062 polygon_ptr->width_spec, ObjPtr->trans_pat) == EOF) {
2063 writeFileFailed = TRUE;
2064 }
2065 if (fprintf(FP, "\n \"") == EOF) writeFileFailed = TRUE;
2066 SaveSmoothHinge(FP, polygon_ptr->curved, polygon_ptr->n,
2067 polygon_ptr->smooth);
2068 if (fprintf(FP, "\",") == EOF) writeFileFailed = TRUE;
2069 if (ObjPtr->ctm != NULL && fprintf(FP,
2070 "[\n\t%1d,%1d,%1d,%1d,%1d,%1d,%g,%g,%g,%g,%1d,%1d],",
2071 ObjPtr->x, ObjPtr->y,
2072 ObjPtr->orig_obbox.ltx, ObjPtr->orig_obbox.lty,
2073 ObjPtr->orig_obbox.rbx, ObjPtr->orig_obbox.rby,
2074 ObjPtr->ctm->m[CTM_SX], ObjPtr->ctm->m[CTM_SIN],
2075 ObjPtr->ctm->m[CTM_MSIN], ObjPtr->ctm->m[CTM_SY],
2076 ObjPtr->ctm->t[CTM_TX], ObjPtr->ctm->t[CTM_TY]) == EOF) {
2077 writeFileFailed = TRUE;
2078 }
2079 if (serializingFile) SaveCreatorID(FP, ObjPtr, " ");
2080 SaveAttrs(FP, ObjPtr->lattr);
2081 if (fprintf(FP, ")") == EOF) writeFileFailed = TRUE;
2082 }
2083
ReadPolygonObj(FP,Inbuf,ObjPtr)2084 void ReadPolygonObj(FP, Inbuf, ObjPtr)
2085 FILE *FP;
2086 char *Inbuf;
2087 struct ObjRec **ObjPtr;
2088 {
2089 register int i;
2090 struct PolygonRec *polygon_ptr;
2091 IntPoint *v;
2092 char color_str[40], bg_color_str[40], *s, inbuf[MAXSTRING];
2093 int num_pts, ltx=0, lty=0, rbx=0, rby=0, x, y, id=0;
2094 int trans_pat=FALSE, fill, width, pen, w, new_alloc, locked=FALSE;
2095 int curved, dash, initialized, rotation, count;
2096 int real_x=0, real_y=0, transformed=FALSE, invisible=FALSE;
2097 char *smooth=NULL, width_spec[40];
2098 struct XfrmMtrxRec *ctm=NULL;
2099 struct BBRec orig_obbox;
2100
2101 *ObjPtr = NULL;
2102
2103 s = FindChar((int)'(', Inbuf);
2104 s = ParseStr(s, (int)',', color_str, sizeof(color_str));
2105 if (fileVersion >= 37) {
2106 s = ParseStr(s, (int)',', bg_color_str, sizeof(bg_color_str));
2107 }
2108 InitScan(s, "\t\n, []");
2109
2110 if (GETINT("polygon", num_pts, "number of points") == INVALID) {
2111 return;
2112 }
2113 if (num_pts <= 0) {
2114 (void)sprintf(gszMsgBox, TgLoadString(STID_INVALID_NUM_PTS_IN_POLYGON),
2115 scanFileName, scanLineNum);
2116 if (PRTGIF) {
2117 fprintf(stderr, "%s\n", gszMsgBox);
2118 } else {
2119 Msg(gszMsgBox);
2120 }
2121 return;
2122 }
2123
2124 *ObjPtr = (struct ObjRec *)malloc(sizeof(struct ObjRec));
2125 if (*ObjPtr == NULL) FailAllocMessage();
2126 memset(*ObjPtr, 0, sizeof(struct ObjRec));
2127 polygon_ptr = (struct PolygonRec *)malloc(sizeof(struct PolygonRec));
2128 if (polygon_ptr == NULL) FailAllocMessage();
2129 memset(polygon_ptr, 0, sizeof(struct PolygonRec));
2130
2131 if (num_pts < 3) {
2132 v = (IntPoint*)malloc(5*sizeof(IntPoint));
2133 if (v == NULL) FailAllocMessage();
2134 smooth = (char*)malloc(5*sizeof(char));
2135 if (smooth == NULL) FailAllocMessage();
2136 } else {
2137 v = (IntPoint*)malloc((num_pts+1)*sizeof(IntPoint));
2138 if (v == NULL) FailAllocMessage();
2139 smooth = (char*)malloc((num_pts+1)*sizeof(char));
2140 if (smooth == NULL) FailAllocMessage();
2141 }
2142
2143 initialized = FALSE;
2144
2145 *width_spec = '\0';
2146 if (fileVersion <= 13) {
2147 for (i=0; i < num_pts; i++) {
2148 if (GETINT("polygon", x, "x") == INVALID ||
2149 GETINT("polygon", y, "y") == INVALID) {
2150 free(*ObjPtr);
2151 free(polygon_ptr);
2152 free(v);
2153 *ObjPtr = NULL;
2154 return;
2155 }
2156 v[i].x = x; v[i].y = y;
2157 if (!initialized) {
2158 initialized = TRUE;
2159 ltx = rbx = x; lty = rby = y;
2160 } else {
2161 if (x < ltx) ltx = x; if (y < lty) lty = y;
2162 if (x > rbx) rbx = x; if (y > rby) rby = y;
2163 }
2164 }
2165 } else {
2166 (void)fgets(inbuf, MAXSTRING, FP);
2167 scanLineNum++;
2168 s = inbuf;
2169 InitScan(s, "\t\n, []");
2170 for (i=0, count = 0; i < num_pts; i++) {
2171 if (GETINT("polygon", x, "x") == INVALID ||
2172 GETINT("polygon", y, "y") == INVALID) {
2173 free(*ObjPtr);
2174 free(polygon_ptr);
2175 free(v);
2176 *ObjPtr = NULL;
2177 return;
2178 }
2179 v[i].x = x; v[i].y = y;
2180 if (!initialized) {
2181 initialized = TRUE;
2182 ltx = rbx = x; lty = rby = y;
2183 } else {
2184 if (x < ltx) ltx = x; if (y < lty) lty = y;
2185 if (x > rbx) rbx = x; if (y > rby) rby = y;
2186 }
2187 if (++count == 8 && i != num_pts-1) {
2188 count = 0;
2189 (void)fgets(inbuf, MAXSTRING, FP);
2190 scanLineNum++;
2191 s = inbuf;
2192 InitScan(s, "\t\n, []");
2193 }
2194 }
2195 }
2196
2197 switch (num_pts) {
2198 case 1:
2199 sprintf(gszMsgBox, TgLoadCachedString(CSTID_SNGL_PT_POLYGON_CONVERTED),
2200 v[0].x, v[0].y);
2201 if (PRTGIF) {
2202 fprintf(stderr, "%s\n", gszMsgBox);
2203 } else {
2204 Msg(gszMsgBox);
2205 }
2206 v[3].x = v[2].x = v[1].x = v[0].x;
2207 v[3].y = v[2].y = v[1].y = v[0].y;
2208 num_pts = 4;
2209 break;
2210 case 2:
2211 sprintf(gszMsgBox, TgLoadCachedString(CSTID_TWO_PT_POLYGON_CONVERTED),
2212 v[0].x, v[0].y, v[1].x, v[1].y);
2213 if (PRTGIF) {
2214 fprintf(stderr, "%s\n", gszMsgBox);
2215 } else {
2216 Msg(gszMsgBox);
2217 }
2218 v[3].x = v[2].x = v[0].x;
2219 v[3].y = v[2].y = v[0].y;
2220 num_pts = 4;
2221 break;
2222 case 3:
2223 sprintf(gszMsgBox, TgLoadCachedString(CSTID_TWO_PT_POLYGON_CONVERTED),
2224 v[0].x, v[0].y, v[1].x, v[1].y);
2225 if (PRTGIF) {
2226 fprintf(stderr, "%s\n", gszMsgBox);
2227 } else {
2228 Msg(gszMsgBox);
2229 }
2230 v[3].x = v[2].x = v[0].x;
2231 v[3].y = v[2].y = v[0].y;
2232 num_pts = 4;
2233 break;
2234 }
2235
2236 polygon_ptr->n = num_pts;
2237
2238 dash = 0;
2239 rotation = 0;
2240 if (fileVersion <= 3) {
2241 if (GETINT("polygon", fill, "fill") == INVALID ||
2242 GETINT("polygon", width, "width") == INVALID ||
2243 GETINT("polygon", pen, "pen") == INVALID) {
2244 free(*ObjPtr);
2245 free(polygon_ptr);
2246 free(v);
2247 *ObjPtr = NULL;
2248 return;
2249 }
2250 if (width == LINE_CURVED) {
2251 width = 0;
2252 curved = TRUE;
2253 } else {
2254 curved = FALSE;
2255 }
2256 switch (width) {
2257 case 1: width = 3; break;
2258 case 2: width = 6; break;
2259 }
2260 id = objId++;
2261 } else if (fileVersion <= 5) {
2262 if (GETINT("polygon", fill, "fill") == INVALID ||
2263 GETINT("polygon", width, "width") == INVALID ||
2264 GETINT("polygon", pen, "pen") == INVALID ||
2265 GETINT("polygon", curved, "curved") == INVALID) {
2266 free(*ObjPtr);
2267 free(polygon_ptr);
2268 free(v);
2269 *ObjPtr = NULL;
2270 return;
2271 }
2272 switch (width) {
2273 case 1: width = 3; break;
2274 case 2: width = 6; break;
2275 }
2276 id = objId++;
2277 } else if (fileVersion <= 7) {
2278 if (GETINT("polygon", fill, "fill") == INVALID ||
2279 GETINT("polygon", width, "width") == INVALID ||
2280 GETINT("polygon", pen, "pen") == INVALID ||
2281 GETINT("polygon", curved, "curved") == INVALID) {
2282 free(*ObjPtr);
2283 free(polygon_ptr);
2284 free(v);
2285 *ObjPtr = NULL;
2286 return;
2287 }
2288 id = objId++;
2289 } else if (fileVersion <= 8) {
2290 if (GETINT("polygon", fill, "fill") == INVALID ||
2291 GETINT("polygon", width, "width") == INVALID ||
2292 GETINT("polygon", pen, "pen") == INVALID ||
2293 GETINT("polygon", curved, "curved") == INVALID ||
2294 GETINT("polygon", id, "id") == INVALID) {
2295 free(*ObjPtr);
2296 free(polygon_ptr);
2297 free(v);
2298 *ObjPtr = NULL;
2299 return;
2300 }
2301 if (id >= objId) objId = id+1;
2302 } else if (fileVersion <= 13) {
2303 if (GETINT("polygon", fill, "fill") == INVALID ||
2304 GETINT("polygon", width, "width") == INVALID ||
2305 GETINT("polygon", pen, "pen") == INVALID ||
2306 GETINT("polygon", curved, "curved") == INVALID ||
2307 GETINT("polygon", id, "id") == INVALID ||
2308 GETINT("polygon", dash, "dash") == INVALID) {
2309 free(*ObjPtr);
2310 free(polygon_ptr);
2311 free(v);
2312 *ObjPtr = NULL;
2313 return;
2314 }
2315 if (id >= objId) objId = id+1;
2316 } else if (fileVersion <= 25) {
2317 if (GETINT("polygon", fill, "fill") == INVALID ||
2318 GETINT("polygon", width, "width") == INVALID ||
2319 GETINT("polygon", pen, "pen") == INVALID ||
2320 GETINT("polygon", curved, "curved") == INVALID ||
2321 GETINT("polygon", id, "id") == INVALID ||
2322 GETINT("polygon", dash, "dash") == INVALID ||
2323 GETINT("polygon", rotation, "rotation") == INVALID) {
2324 free(*ObjPtr);
2325 free(polygon_ptr);
2326 free(v);
2327 *ObjPtr = NULL;
2328 return;
2329 }
2330 if (id >= objId) objId = id+1;
2331 } else if (fileVersion <= 32) {
2332 if (GETINT("polygon", fill, "fill") == INVALID ||
2333 GETINT("polygon", width, "width") == INVALID ||
2334 GETINT("polygon", pen, "pen") == INVALID ||
2335 GETINT("polygon", curved, "curved") == INVALID ||
2336 GETINT("polygon", id, "id") == INVALID ||
2337 GETINT("polygon", dash, "dash") == INVALID ||
2338 GETINT("polygon", rotation, "rotation") == INVALID ||
2339 GETINT("polygon", locked, "locked") == INVALID) {
2340 free(*ObjPtr);
2341 free(polygon_ptr);
2342 free(v);
2343 *ObjPtr = NULL;
2344 return;
2345 }
2346 if (id >= objId) objId = id+1;
2347 } else if (fileVersion <= 34) {
2348 if (GETINT("polygon", fill, "fill") == INVALID ||
2349 GETINT("polygon", width, "width") == INVALID ||
2350 GETINT("polygon", pen, "pen") == INVALID ||
2351 GETINT("polygon", curved, "curved") == INVALID ||
2352 GETINT("polygon", id, "id") == INVALID ||
2353 GETINT("polygon", dash, "dash") == INVALID ||
2354 GETINT("polygon", rotation, "rotation") == INVALID ||
2355 GETINT("polygon", locked, "locked") == INVALID ||
2356 GETINT("polygon", transformed, "transformed") == INVALID ||
2357 GETINT("polygon", invisible, "invisible") == INVALID ||
2358 GETSTR("polygon", width_spec, "width_spec") == INVALID) {
2359 free(*ObjPtr);
2360 free(polygon_ptr);
2361 free(v);
2362 *ObjPtr = NULL;
2363 return;
2364 }
2365 if (id >= objId) objId = id+1;
2366 UtilRemoveQuotes(width_spec);
2367 } else {
2368 if (GETINT("polygon", fill, "fill") == INVALID ||
2369 GETINT("polygon", width, "width") == INVALID ||
2370 GETINT("polygon", pen, "pen") == INVALID ||
2371 GETINT("polygon", curved, "curved") == INVALID ||
2372 GETINT("polygon", id, "id") == INVALID ||
2373 GETINT("polygon", dash, "dash") == INVALID ||
2374 GETINT("polygon", rotation, "rotation") == INVALID ||
2375 GETINT("polygon", locked, "locked") == INVALID ||
2376 GETINT("polygon", transformed, "transformed") == INVALID ||
2377 GETINT("polygon", invisible, "invisible") == INVALID ||
2378 GETSTR("polygon", width_spec, "width_spec") == INVALID ||
2379 GETINT("polygon", trans_pat, "trans_pat") == INVALID) {
2380 free(*ObjPtr);
2381 free(polygon_ptr);
2382 free(v);
2383 *ObjPtr = NULL;
2384 return;
2385 }
2386 if (id >= objId) objId = id+1;
2387 UtilRemoveQuotes(width_spec);
2388 }
2389
2390 if (fileVersion <= 16 && width <= 6) width = origWidthOfLine[width];
2391
2392 if (fileVersion <= 25 && curved > 1) curved = 0;
2393 if (curved == LT_INTSPLINE && smooth != NULL) {
2394 free(smooth);
2395 smooth = NULL;
2396 }
2397 if (fileVersion <= 30) {
2398 switch (curved) {
2399 case LT_STRAIGHT:
2400 for (i=0; i < num_pts; i++) smooth[i] = FALSE;
2401 break;
2402 case LT_SPLINE:
2403 for (i=0; i < num_pts; i++) smooth[i] = TRUE;
2404 break;
2405 }
2406 } else if (!ReadSmoothHinge(FP, curved, num_pts, smooth)) {
2407 free(*ObjPtr);
2408 free(polygon_ptr);
2409 free(v);
2410 *ObjPtr = NULL;
2411 return;
2412 }
2413 if (fileVersion >= 33 && transformed) {
2414 (void)fgets(inbuf, MAXSTRING, FP);
2415 scanLineNum++;
2416 InitScan(inbuf, "\t\n, ");
2417
2418 ctm = (struct XfrmMtrxRec *)malloc(sizeof(struct XfrmMtrxRec));
2419 if (ctm == NULL) FailAllocMessage();
2420 if (GETINT("polygon", real_x, "real_x") == INVALID ||
2421 GETINT("polygon", real_y, "real_y") == INVALID ||
2422 GETINT("polygon", orig_obbox.ltx, "orig_obbox.ltx") == INVALID ||
2423 GETINT("polygon", orig_obbox.lty, "orig_obbox.lty") == INVALID ||
2424 GETINT("polygon", orig_obbox.rbx, "orig_obbox.rbx") == INVALID ||
2425 GETINT("polygon", orig_obbox.rby, "orig_obbox.rby") == INVALID ||
2426 GETDBL("polygon", ctm->m[CTM_SX], "CTM_SX") == INVALID ||
2427 GETDBL("polygon", ctm->m[CTM_SIN], "CTM_SIN") == INVALID ||
2428 GETDBL("polygon", ctm->m[CTM_MSIN], "CTM_MSIN") == INVALID ||
2429 GETDBL("polygon", ctm->m[CTM_SY], "CTM_SY") == INVALID ||
2430 GETINT("polygon", ctm->t[CTM_TX], "CTM_TX") == INVALID ||
2431 GETINT("polygon", ctm->t[CTM_TY], "CTM_TY") == INVALID) {
2432 free(*ObjPtr);
2433 free(polygon_ptr);
2434 free(v);
2435 *ObjPtr = NULL;
2436 free(ctm);
2437 return;
2438 }
2439 }
2440 if (fileVersion <= 32) {
2441 sprintf(width_spec, "%1d", width);
2442 }
2443
2444 fill = UpgradePenFill(fill);
2445 pen = UpgradePenFill(pen);
2446
2447 polygon_ptr->fill = fill;
2448 polygon_ptr->width = width;
2449 UtilStrCpyN(polygon_ptr->width_spec, sizeof(polygon_ptr->width_spec),
2450 width_spec);
2451 polygon_ptr->pen = pen;
2452 polygon_ptr->curved = curved;
2453 polygon_ptr->dash = dash;
2454
2455 polygon_ptr->vlist = v;
2456 polygon_ptr->smooth = smooth;
2457 polygon_ptr->svlist = NULL;
2458 polygon_ptr->intvlist = NULL;
2459
2460 polygon_ptr->rotated_n = 0;
2461 polygon_ptr->rotated_vlist = NULL;
2462
2463 (*ObjPtr)->x = ltx;
2464 (*ObjPtr)->y = lty;
2465 (*ObjPtr)->color = QuickFindColorIndex(*ObjPtr, color_str, &new_alloc, TRUE);
2466 UtilStrCpyN((*ObjPtr)->color_str, sizeof((*ObjPtr)->color_str), color_str);
2467 (*ObjPtr)->dirty = FALSE;
2468 (*ObjPtr)->id = id;
2469 (*ObjPtr)->rotation = rotation;
2470 (*ObjPtr)->locked = locked;
2471 (*ObjPtr)->type = OBJ_POLYGON;
2472 (*ObjPtr)->obbox.ltx = ltx;
2473 (*ObjPtr)->obbox.lty = lty;
2474 (*ObjPtr)->obbox.rbx = rbx;
2475 (*ObjPtr)->obbox.rby = rby;
2476 w = HALF_W(width);
2477 (*ObjPtr)->bbox.ltx = ltx - w;
2478 (*ObjPtr)->bbox.lty = lty - w;
2479 (*ObjPtr)->bbox.rbx = rbx + w;
2480 (*ObjPtr)->bbox.rby = rby + w;
2481 (*ObjPtr)->detail.g = polygon_ptr;
2482 (*ObjPtr)->ctm = ctm;
2483 (*ObjPtr)->invisible = invisible;
2484 (*ObjPtr)->trans_pat = trans_pat;
2485 if (ctm != NULL) {
2486 memcpy(&(*ObjPtr)->orig_obbox, &orig_obbox, sizeof(struct BBRec));
2487 (*ObjPtr)->x = real_x;
2488 (*ObjPtr)->y = real_y;
2489 GetTransformedOBBoxOffsetVs(*ObjPtr, (*ObjPtr)->rotated_obbox);
2490 }
2491 AdjObjCache(*ObjPtr);
2492 AdjObjSplineVs(*ObjPtr);
2493 if (polygon_ptr->curved != LT_INTSPLINE) {
2494 UpdPolyBBox(*ObjPtr, polygon_ptr->n, polygon_ptr->vlist);
2495 } else {
2496 UpdPolyBBox(*ObjPtr, polygon_ptr->intn, polygon_ptr->intvlist);
2497 }
2498 }
2499
SetPolygonPropMask(ObjPtr,plMask,plSkip,pProp)2500 void SetPolygonPropMask(ObjPtr, plMask, plSkip, pProp)
2501 struct ObjRec *ObjPtr;
2502 long *plMask, *plSkip;
2503 struct PropertiesRec *pProp;
2504 {
2505 struct PolygonRec *polygon_ptr=ObjPtr->detail.g;
2506
2507 SetCTMPropertyMask(ObjPtr->ctm, plMask, plSkip, pProp);
2508
2509 SetIntPropertyMask(PROP_MASK_COLOR, ObjPtr->color,
2510 colorMenuItems[ObjPtr->color], plMask, plSkip, pProp);
2511 SetIntPropertyMask(PROP_MASK_WIDTH, polygon_ptr->width,
2512 polygon_ptr->width_spec, plMask, plSkip, pProp);
2513
2514 SetIntPropertyMask(PROP_MASK_TRANSPAT, ObjPtr->trans_pat, NULL,
2515 plMask, plSkip, pProp);
2516 SetIntPropertyMask(PROP_MASK_FILL, polygon_ptr->fill, NULL,
2517 plMask, plSkip, pProp);
2518 SetIntPropertyMask(PROP_MASK_PEN, polygon_ptr->pen, NULL,
2519 plMask, plSkip, pProp);
2520 SetIntPropertyMask(PROP_MASK_DASH, polygon_ptr->dash, NULL,
2521 plMask, plSkip, pProp);
2522 SetIntPropertyMask(PROP_MASK_CURVED, polygon_ptr->curved, NULL,
2523 plMask, plSkip, pProp);
2524 }
2525
FreePolygonObj(ObjPtr)2526 void FreePolygonObj(ObjPtr)
2527 struct ObjRec *ObjPtr;
2528 {
2529 if (ObjPtr->detail.g->ssvlist != NULL) free(ObjPtr->detail.g->ssvlist);
2530 if (ObjPtr->detail.g->intvlist != NULL) free(ObjPtr->detail.g->intvlist);
2531 if (ObjPtr->detail.g->svlist != NULL) free(ObjPtr->detail.g->svlist);
2532 if (ObjPtr->detail.g->rotated_vlist != NULL) {
2533 free(ObjPtr->detail.g->rotated_vlist);
2534 }
2535 free(ObjPtr->detail.g->vlist);
2536 if (ObjPtr->detail.g->smooth != NULL) free(ObjPtr->detail.g->smooth);
2537 if (ObjPtr->detail.g->ssmooth != NULL) free(ObjPtr->detail.g->ssmooth);
2538 free(ObjPtr->detail.g);
2539 free(ObjPtr);
2540 }
2541