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/poly.c,v 1.69 2011/05/16 16:21:59 william Exp $
19 */
20
21 #define _INCLUDE_FROM_POLY_C_
22
23 #include "tgifdefs.h"
24
25 #include "arc.e"
26 #include "attr.e"
27 #include "auxtext.e"
28 #include "choice.e"
29 #include "cmd.e"
30 #include "color.e"
31 #include "cursor.e"
32 #include "cutpaste.e"
33 #include "dialog.e"
34 #include "drawing.e"
35 #include "dup.e"
36 #include "file.e"
37 #include "grid.e"
38 #include "list.e"
39 #include "mainloop.e"
40 #include "mark.e"
41 #include "msg.e"
42 #include "obj.e"
43 #include "page.e"
44 #include "pattern.e"
45 #include "pin.e"
46 #include "poly.e"
47 #include "polygon.e"
48 #include "ps.e"
49 #include "raster.e"
50 #include "rect.e"
51 #include "ruler.e"
52 #include "select.e"
53 #include "setup.e"
54 #include "special.e"
55 #include "spline.e"
56 #include "stretch.e"
57 #include "strtbl.e"
58 #include "util.e"
59 #include "xpixmap.e"
60
61 #define RETREAT (0.8)
62
63 WiringInfo gstWiringInfo;
64
65 int polyDrawn=FALSE;
66 int queryPolyNameOnConnect=TRUE;
67
68 /* short widthOfLine[] = { 0, 3, 6, 0 }; */
69 /* short arrowHeadH[] = { 3, 5, 10, 3 }; */
70 /* short arrowHeadW[] = { 8, 12, 22, 8 }; */
71
72 short origWidthOfLine[] = { 1, 2, 3, 4, 5, 6, 7 };
73 short origArrowHeadH[] = { 3, 4, 5, 6, 7, 8, 9 };
74 short origArrowHeadW[] = { 8, 10, 12, 14, 18, 20, 22 };
75
76 short *curWidthOfLine=NULL;
77 short *curArrowHeadH=NULL;
78 short *curArrowHeadW=NULL;
79
80 char **curWidthOfLineSpec=NULL;
81 char **curArrowHeadHSpec=NULL;
82 char **curArrowHeadWSpec=NULL;
83
84 int numPtsInPoly=0;
85 CVList gStructSplineList;
86
87 struct PtRec *lastPtPtr=NULL;
88 struct ObjRec *drawPolyHighlightedNode=NULL;
89
GetPolyOrPolygonAbsVs(pn_return,pn_allocated,ObjPtr)90 IntPoint *GetPolyOrPolygonAbsVs(pn_return, pn_allocated, ObjPtr)
91 int *pn_return, *pn_allocated;
92 struct ObjRec *ObjPtr;
93 {
94 int i=0, n=0;
95 struct PolyRec *poly_ptr=NULL;
96 struct PolygonRec *polygon_ptr=NULL;
97 IntPoint *vs=NULL, *return_vs=NULL;
98
99 switch (ObjPtr->type) {
100 case OBJ_POLY:
101 poly_ptr = ObjPtr->detail.p;
102 if (poly_ptr->curved == LT_STRUCT_SPLINE) {
103 n = poly_ptr->ssn;
104 vs = poly_ptr->ssvlist;
105 } else {
106 n = poly_ptr->n;
107 vs = poly_ptr->vlist;
108 }
109 break;
110 case OBJ_POLYGON:
111 polygon_ptr = ObjPtr->detail.g;
112 if (polygon_ptr->curved == LT_STRUCT_SPLINE) {
113 n = polygon_ptr->ssn;
114 vs = polygon_ptr->ssvlist;
115 } else {
116 n = polygon_ptr->n;
117 vs = polygon_ptr->vlist;
118 }
119 break;
120 }
121 *pn_return = n;
122 if (ObjPtr->ctm == NULL) {
123 *pn_allocated = FALSE;
124 return vs;
125 }
126 *pn_allocated = TRUE;
127
128 return_vs = (IntPoint*)malloc(n*sizeof(IntPoint));
129 if (return_vs == NULL) FailAllocMessage();
130 memset(return_vs, 0, n*sizeof(IntPoint));
131
132 for (i=0; i < n; i++) {
133 int x_off=0, y_off=0;
134
135 TransformPointThroughCTM(vs[i].x-ObjPtr->x, vs[i].y-ObjPtr->y,
136 ObjPtr->ctm, &x_off, &y_off);
137 return_vs[i].x = ObjPtr->x + x_off;
138 return_vs[i].y = ObjPtr->y + y_off;
139 }
140 return return_vs;
141 }
142
MakePolyVertex(XOff,YOff,NumVs,Vs)143 XPoint *MakePolyVertex(XOff, YOff, NumVs, Vs)
144 int XOff, YOff, NumVs;
145 register IntPoint *Vs;
146 {
147 register XPoint *v;
148 register int i;
149 int real_x_off, real_y_off;
150
151 real_x_off = (zoomedIn ? XOff : (XOff>>zoomScale)<<zoomScale);
152 real_y_off = (zoomedIn ? YOff : (YOff>>zoomScale)<<zoomScale);
153
154 v = (XPoint*)malloc((NumVs+1)*sizeof(XPoint));
155 if (v == NULL) FailAllocMessage();
156 for (i = 0; i < NumVs; i++) {
157 v[i].x = (short)ZOOMED_SIZE(Vs[i].x-real_x_off);
158 v[i].y = (short)ZOOMED_SIZE(Vs[i].y-real_y_off);
159 }
160 return v;
161 }
162
CalcPolyBBox(ObjPtr)163 void CalcPolyBBox(ObjPtr)
164 struct ObjRec *ObjPtr;
165 {
166 register int x, y;
167 struct PolyRec *poly_ptr=ObjPtr->detail.p;
168 int style=poly_ptr->style, width=poly_ptr->width;
169 int aw=poly_ptr->aw, ah=poly_ptr->ah;
170 int ltx=ObjPtr->obbox.ltx, lty=ObjPtr->obbox.lty;
171 int rbx=ObjPtr->obbox.rbx, rby=ObjPtr->obbox.rby;
172 int dx=0, dy=0, tmp_x=0, tmp_y=0, num_pts=0;
173 double len, sin, cos, w, h;
174 IntPoint *v=NULL;
175 int retracted_arrow=(RetractedArrowAttr(ObjPtr) ||
176 AutoRetractedArrowAttr(ObjPtr, TRUE));
177
178 switch (poly_ptr->curved) {
179 case LT_STRAIGHT:
180 case LT_SPLINE:
181 num_pts = poly_ptr->n;
182 v = poly_ptr->vlist;
183 break;
184 case LT_STRUCT_SPLINE:
185 num_pts = poly_ptr->ssn;
186 v = poly_ptr->ssvlist;
187 break;
188 case LT_INTSPLINE:
189 num_pts = poly_ptr->intn;
190 v = poly_ptr->intvlist;
191 break;
192 }
193 dx = v[1].x - v[0].x;
194 dy = v[1].y - v[0].y;
195 if ((style & LS_LEFT) && (dx != 0 || dy != 0)) {
196 len = (double)sqrt((double)(((double)dx)*((double)dx) +
197 ((double)dy)*((double)dy)));
198 sin = ((double)dy) / len;
199 cos = ((double)dx) / len;
200
201 w = (double)aw; h = (double)max(ah,(width>>1));
202
203 x = round(v[0].x + w*cos - h*sin);
204 y = round(v[0].y + w*sin + h*cos);
205 if (ObjPtr->ctm != NULL) {
206 TransformPointThroughCTM(x-ObjPtr->x, y-ObjPtr->y, ObjPtr->ctm,
207 &tmp_x, &tmp_y);
208 x = tmp_x+ObjPtr->x;
209 y = tmp_y+ObjPtr->y;
210 }
211 if (x < ltx) ltx = x; if (y < lty) lty = y;
212 if (x > rbx) rbx = x; if (y > rby) rby = y;
213
214 x = round(v[0].x + w*cos + h*sin);
215 y = round(v[0].y + w*sin - h*cos);
216 if (ObjPtr->ctm != NULL) {
217 TransformPointThroughCTM(x-ObjPtr->x, y-ObjPtr->y, ObjPtr->ctm,
218 &tmp_x, &tmp_y);
219 x = tmp_x+ObjPtr->x;
220 y = tmp_y+ObjPtr->y;
221 }
222 if (x < ltx) ltx = x; if (y < lty) lty = y;
223 if (x > rbx) rbx = x; if (y > rby) rby = y;
224 }
225 dx = v[num_pts-1].x - v[num_pts-2].x;
226 dy = v[num_pts-1].y - v[num_pts-2].y;
227 if ((style & LS_RIGHT) && (dx != 0 || dy != 0)) {
228 len = (double)sqrt((double)(((double)dx)*((double)dx) +
229 ((double)dy)*((double)dy)));
230 sin = ((double)dy) / len;
231 cos = ((double)dx) / len;
232
233 w = (double)aw; h = (double)max(ah,(width>>1));
234
235 x = round(v[num_pts-1].x - w*cos + h*sin);
236 y = round(v[num_pts-1].y - w*sin - h*cos);
237 if (ObjPtr->ctm != NULL) {
238 TransformPointThroughCTM(x-ObjPtr->x, y-ObjPtr->y, ObjPtr->ctm,
239 &tmp_x, &tmp_y);
240 x = tmp_x+ObjPtr->x;
241 y = tmp_y+ObjPtr->y;
242 }
243 if (x < ltx) ltx = x; if (y < lty) lty = y;
244 if (x > rbx) rbx = x; if (y > rby) rby = y;
245
246 x = round(v[num_pts-1].x - w*cos - h*sin);
247 y = round(v[num_pts-1].y - w*sin + h*cos);
248 if (ObjPtr->ctm != NULL) {
249 TransformPointThroughCTM(x-ObjPtr->x, y-ObjPtr->y, ObjPtr->ctm,
250 &tmp_x, &tmp_y);
251 x = tmp_x+ObjPtr->x;
252 y = tmp_y+ObjPtr->y;
253 }
254 if (x < ltx) ltx = x; if (y < lty) lty = y;
255 if (x > rbx) rbx = x; if (y > rby) rby = y;
256 }
257 if (retracted_arrow) {
258 int i;
259
260 for (i=1; i < num_pts; i++) {
261 x = v[i].x; y = v[i].y;
262 if (x-ah < ltx) ltx = x-ah; if (y-ah < lty) lty = y-ah;
263 if (x+ah > rbx) rbx = x+ah; if (y+ah > rby) rby = y+ah;
264 }
265 }
266 ObjPtr->bbox.ltx = min(ltx, ObjPtr->obbox.ltx-(width>>1));
267 ObjPtr->bbox.lty = min(lty, ObjPtr->obbox.lty-(width>>1));
268 ObjPtr->bbox.rbx = max(rbx, ObjPtr->obbox.rbx+(width>>1));
269 ObjPtr->bbox.rby = max(rby, ObjPtr->obbox.rby+(width>>1));
270 }
271
UpdPolyBBox(ObjPtr,NumPts,V)272 void UpdPolyBBox(ObjPtr, NumPts, V)
273 struct ObjRec *ObjPtr;
274 int NumPts;
275 IntPoint *V;
276 {
277 register int i;
278 int ltx, lty, rbx, rby;
279
280 ltx = rbx = V[0].x;
281 lty = rby = V[0].y;
282
283 for (i = 1; i < NumPts; i++) {
284 if (V[i].x < ltx) ltx = V[i].x; if (V[i].y < lty) lty = V[i].y;
285 if (V[i].x > rbx) rbx = V[i].x; if (V[i].y > rby) rby = V[i].y;
286 }
287 if (ObjPtr->ctm == NULL) {
288 ObjPtr->x = ltx;
289 ObjPtr->y = lty;
290 ObjPtr->obbox.ltx = ltx;
291 ObjPtr->obbox.lty = lty;
292 ObjPtr->obbox.rbx = rbx;
293 ObjPtr->obbox.rby = rby;
294 } else {
295 IntPoint abs_obj_obbox_vs[5];
296
297 ObjPtr->orig_obbox.ltx = ltx;
298 ObjPtr->orig_obbox.lty = lty;
299 ObjPtr->orig_obbox.rbx = rbx;
300 ObjPtr->orig_obbox.rby = rby;
301 GetTransformedOBBoxAbsVs(ObjPtr, abs_obj_obbox_vs);
302 ObjPtr->obbox.ltx = min(min(abs_obj_obbox_vs[0].x,abs_obj_obbox_vs[1].x),
303 min(abs_obj_obbox_vs[2].x,abs_obj_obbox_vs[3].x));
304 ObjPtr->obbox.rbx = max(max(abs_obj_obbox_vs[0].x,abs_obj_obbox_vs[1].x),
305 max(abs_obj_obbox_vs[2].x,abs_obj_obbox_vs[3].x));
306 ObjPtr->obbox.lty = min(min(abs_obj_obbox_vs[0].y,abs_obj_obbox_vs[1].y),
307 min(abs_obj_obbox_vs[2].y,abs_obj_obbox_vs[3].y));
308 ObjPtr->obbox.rby = max(max(abs_obj_obbox_vs[0].y,abs_obj_obbox_vs[1].y),
309 max(abs_obj_obbox_vs[2].y,abs_obj_obbox_vs[3].y));
310 }
311 AdjObjBBox(ObjPtr);
312 }
313
UpdNonIntSplinePolyBBox(obj_ptr,num_pts,v)314 void UpdNonIntSplinePolyBBox(obj_ptr, num_pts, v)
315 struct ObjRec *obj_ptr;
316 int num_pts;
317 IntPoint *v;
318 {
319 switch (obj_ptr->type) {
320 case OBJ_POLY:
321 switch (obj_ptr->detail.p->curved) {
322 case LT_STRAIGHT:
323 case LT_SPLINE:
324 case LT_STRUCT_SPLINE:
325 UpdPolyBBox(obj_ptr, num_pts, v);
326 break;
327 case LT_INTSPLINE:
328 UpdPolyBBox(obj_ptr, obj_ptr->detail.p->intn,
329 obj_ptr->detail.p->intvlist);
330 break;
331 }
332 break;
333 case OBJ_POLYGON:
334 switch (obj_ptr->detail.g->curved) {
335 case LT_STRAIGHT:
336 case LT_SPLINE:
337 case LT_STRUCT_SPLINE:
338 UpdPolyBBox(obj_ptr, num_pts, v);
339 break;
340 case LT_INTSPLINE:
341 UpdPolyBBox(obj_ptr, obj_ptr->detail.g->intn,
342 obj_ptr->detail.g->intvlist);
343 break;
344 }
345 break;
346 }
347 }
348
UpdPolyOrPolygonBBox(obj_ptr)349 void UpdPolyOrPolygonBBox(obj_ptr)
350 struct ObjRec *obj_ptr;
351 {
352 switch (obj_ptr->type) {
353 case OBJ_POLY:
354 switch (obj_ptr->detail.p->curved) {
355 case LT_STRAIGHT:
356 case LT_SPLINE:
357 case LT_STRUCT_SPLINE:
358 UpdPolyBBox(obj_ptr, obj_ptr->detail.p->n, obj_ptr->detail.p->vlist);
359 break;
360 case LT_INTSPLINE:
361 UpdPolyBBox(obj_ptr, obj_ptr->detail.p->intn,
362 obj_ptr->detail.p->intvlist);
363 break;
364 }
365 break;
366 case OBJ_POLYGON:
367 switch (obj_ptr->detail.g->curved) {
368 case LT_STRAIGHT:
369 case LT_SPLINE:
370 case LT_STRUCT_SPLINE:
371 UpdPolyBBox(obj_ptr, obj_ptr->detail.g->n, obj_ptr->detail.g->vlist);
372 break;
373 case LT_INTSPLINE:
374 UpdPolyBBox(obj_ptr, obj_ptr->detail.g->intn,
375 obj_ptr->detail.g->intvlist);
376 break;
377 }
378 break;
379 }
380 }
381
382 #define CREATE_RELATIVE (FALSE)
383 #define CREATE_ABSOLUTE (TRUE)
384
CreatePolyObj(NumPts,CreateAbsolute)385 void CreatePolyObj(NumPts, CreateAbsolute)
386 int NumPts;
387 int CreateAbsolute;
388 {
389 struct PtRec *pt_ptr=NULL, *next_pt=NULL;
390 struct PolyRec *poly_ptr=NULL;
391 struct ObjRec *obj_ptr=NULL;
392 register int i;
393 IntPoint *v=NULL;
394 int ltx, lty, rbx, rby, num_ss_pts=0;
395 char *smooth=NULL;
396 CVListElem *elem=NULL;
397 IntPointTriplet *pipt=NULL;
398
399 poly_ptr = (struct PolyRec *)malloc(sizeof(struct PolyRec));
400 if (poly_ptr == NULL) FailAllocMessage();
401 memset(poly_ptr, 0, sizeof(struct PolyRec));
402 if (curSpline == LT_STRUCT_SPLINE) {
403 num_ss_pts = (NumPts*3)-2;
404 poly_ptr->n = num_ss_pts;
405 v = (IntPoint*)malloc((num_ss_pts+1)*sizeof(IntPoint));
406 if (v == NULL) FailAllocMessage();
407 smooth = (char*)malloc((num_ss_pts+1)*sizeof(char));
408 if (smooth == NULL) FailAllocMessage();
409 elem = ListLast(&gStructSplineList);
410 pipt = (IntPointTriplet*)(elem->obj);
411 ltx = rbx = pipt->hinge_pt.x;
412 lty = rby = pipt->hinge_pt.y;
413
414 for (i=NumPts-1; i >= 0; i--, elem=ListPrev(&gStructSplineList, elem)) {
415 pipt = (IntPointTriplet*)(elem->obj);
416 if (i == 0) {
417 v[0].x = CreateAbsolute ? pipt->hinge_pt.x :
418 ABS_X(pipt->hinge_pt.x);
419 v[0].y = CreateAbsolute ? pipt->hinge_pt.y :
420 ABS_Y(pipt->hinge_pt.y);
421 if (pipt->later_valid) {
422 v[1].x = CreateAbsolute ? pipt->later_smooth_pt.x :
423 ABS_X(pipt->later_smooth_pt.x);
424 v[1].y = CreateAbsolute ? pipt->later_smooth_pt.y :
425 ABS_Y(pipt->later_smooth_pt.y);
426 smooth[1] = TRUE;
427 } else {
428 v[1].x = v[0].x;
429 v[1].y = v[0].y;
430 smooth[1] = FALSE;
431 }
432 smooth[0] = FALSE;
433 } else if (i == NumPts-1) {
434 v[num_ss_pts-1].x = CreateAbsolute ? pipt->hinge_pt.x :
435 ABS_X(pipt->hinge_pt.x);
436 v[num_ss_pts-1].y = CreateAbsolute ? pipt->hinge_pt.y :
437 ABS_Y(pipt->hinge_pt.y);
438 if (pipt->earlier_valid) {
439 v[num_ss_pts-2].x = CreateAbsolute ? pipt->earlier_smooth_pt.x :
440 ABS_X(pipt->earlier_smooth_pt.x);
441 v[num_ss_pts-2].y = CreateAbsolute ? pipt->earlier_smooth_pt.y :
442 ABS_Y(pipt->earlier_smooth_pt.y);
443 smooth[num_ss_pts-2] = TRUE;
444 } else {
445 v[num_ss_pts-2].x = v[num_ss_pts-1].x;
446 v[num_ss_pts-2].y = v[num_ss_pts-1].y;
447 smooth[num_ss_pts-2] = FALSE;
448 }
449 smooth[num_ss_pts-1] = FALSE;
450 } else {
451 int index=3*i;
452
453 v[index-1].x = CreateAbsolute ? pipt->earlier_smooth_pt.x :
454 ABS_X(pipt->earlier_smooth_pt.x);
455 v[index-1].y = CreateAbsolute ? pipt->earlier_smooth_pt.y :
456 ABS_Y(pipt->earlier_smooth_pt.y);
457 v[index].x = CreateAbsolute ? pipt->hinge_pt.x :
458 ABS_X(pipt->hinge_pt.x);
459 v[index].y = CreateAbsolute ? pipt->hinge_pt.y :
460 ABS_Y(pipt->hinge_pt.y);
461 v[index+1].x = CreateAbsolute ? pipt->later_smooth_pt.x :
462 ABS_X(pipt->later_smooth_pt.x);
463 v[index+1].y = CreateAbsolute ? pipt->later_smooth_pt.y :
464 ABS_Y(pipt->later_smooth_pt.y);
465 smooth[index-1] = pipt->earlier_valid;
466 smooth[index] = FALSE;
467 smooth[index+1] = pipt->later_valid;
468 }
469 free(pipt);
470 }
471 for (i=0; i < num_ss_pts; i++) {
472 if (v[i].x < ltx) ltx = v[i].x;
473 if (v[i].y < lty) lty = v[i].y;
474 if (v[i].x > rbx) rbx = v[i].x;
475 if (v[i].y > rby) rby = v[i].y;
476 }
477 numPtsInPoly = 0;
478 ListUnlinkAll(&gStructSplineList);
479 } else {
480 poly_ptr->n = NumPts;
481 v = (IntPoint*)malloc((NumPts+1)*sizeof(IntPoint));
482 if (v == NULL) FailAllocMessage();
483 if (curSpline != LT_INTSPLINE) {
484 smooth = (char*)malloc((NumPts+1)*sizeof(char));
485 if (smooth == NULL) FailAllocMessage();
486 }
487 pt_ptr = lastPtPtr;
488 ltx = rbx = pt_ptr->x;
489 lty = rby = pt_ptr->y;
490
491 for (i=NumPts-1; i >= 0; i--, lastPtPtr=next_pt) {
492 next_pt = lastPtPtr->next;
493 v[i].x = CreateAbsolute ? lastPtPtr->x : ABS_X(lastPtPtr->x);
494 v[i].y = CreateAbsolute ? lastPtPtr->y : ABS_Y(lastPtPtr->y);
495 if (curSpline != LT_INTSPLINE) {
496 if (lastPtPtr->x < ltx) ltx = lastPtPtr->x;
497 if (lastPtPtr->y < lty) lty = lastPtPtr->y;
498 if (lastPtPtr->x > rbx) rbx = lastPtPtr->x;
499 if (lastPtPtr->y > rby) rby = lastPtPtr->y;
500 if (curSpline == LT_STRAIGHT) {
501 smooth[i] = FALSE;
502 } else {
503 smooth[i] = (i != 0 && i != NumPts-1);
504 }
505 }
506 free(lastPtPtr);
507 }
508 numPtsInPoly = 0;
509 lastPtPtr = NULL;
510 }
511 poly_ptr->vlist = v;
512 poly_ptr->smooth = smooth;
513 poly_ptr->svlist = poly_ptr->asvlist = NULL;
514 poly_ptr->intvlist = NULL;
515 poly_ptr->style = lineStyle;
516 poly_ptr->width = curWidthOfLine[lineWidth];
517 poly_ptr->aw = curArrowHeadW[lineWidth];
518 poly_ptr->ah = curArrowHeadH[lineWidth];
519 UtilStrCpyN(poly_ptr->width_spec, sizeof(poly_ptr->width_spec),
520 curWidthOfLineSpec[lineWidth]);
521 UtilStrCpyN(poly_ptr->aw_spec, sizeof(poly_ptr->aw_spec),
522 curArrowHeadWSpec[lineWidth]);
523 UtilStrCpyN(poly_ptr->ah_spec, sizeof(poly_ptr->ah_spec),
524 curArrowHeadHSpec[lineWidth]);
525 poly_ptr->pen = penPat;
526 poly_ptr->curved = curSpline;
527 poly_ptr->fill = objFill;
528 poly_ptr->dash = curDash;
529 /*
530 * poly_ptr->tighter = (curSpline == LT_STRUCT_SPLINE) ?
531 * tighterStructSplines : FALSE;
532 */
533 poly_ptr->rotated_n = 0;
534 poly_ptr->rotated_vlist = NULL;
535 poly_ptr->rotated_asn = 0;
536 poly_ptr->rotated_asvlist = NULL;
537
538 obj_ptr = (struct ObjRec *)malloc(sizeof(struct ObjRec));
539 if (obj_ptr == NULL) FailAllocMessage();
540 memset(obj_ptr, 0, sizeof(struct ObjRec));
541 obj_ptr->detail.p = poly_ptr;
542
543 obj_ptr->color = colorIndex;
544 if (mainDisplay != NULL) {
545 UtilStrCpyN(obj_ptr->color_str, sizeof(obj_ptr->color_str),
546 colorMenuItems[colorIndex]);
547 }
548 obj_ptr->type = OBJ_POLY;
549 if (CreateAbsolute) {
550 obj_ptr->obbox.ltx = obj_ptr->x = ltx;
551 obj_ptr->obbox.lty = obj_ptr->y = lty;
552 obj_ptr->obbox.rbx = rbx;
553 obj_ptr->obbox.rby = rby;
554 } else {
555 obj_ptr->obbox.ltx = obj_ptr->x = ABS_X(ltx);
556 obj_ptr->obbox.lty = obj_ptr->y = ABS_Y(lty);
557 obj_ptr->obbox.rbx = ABS_X(rbx);
558 obj_ptr->obbox.rby = ABS_Y(rby);
559 }
560 obj_ptr->id = objId++;
561 obj_ptr->dirty = FALSE;
562 obj_ptr->rotation = 0;
563 obj_ptr->locked = FALSE;
564 obj_ptr->fattr = obj_ptr->lattr = NULL;
565 obj_ptr->ctm = NULL;
566 obj_ptr->invisible = FALSE;
567 obj_ptr->trans_pat = transPat;
568
569 AdjObjSplineVs(obj_ptr);
570 if (curSpline != LT_INTSPLINE) {
571 UpdPolyBBox(obj_ptr, poly_ptr->n, poly_ptr->vlist);
572 } else {
573 UpdPolyBBox(obj_ptr, poly_ptr->intn, poly_ptr->intvlist);
574 }
575 AdjObjBBox(obj_ptr);
576 AddObj(NULL, topObj, obj_ptr);
577 }
578
ResetCreatePoly()579 void ResetCreatePoly()
580 {
581 numPtsInPoly = 0;
582 lastPtPtr = NULL;
583 CVListInit(&gStructSplineList);
584 }
585
AddPtToCreatePoly(AbsX,AbsY)586 void AddPtToCreatePoly(AbsX, AbsY)
587 int AbsX, AbsY;
588 {
589 struct PtRec *pt_ptr=(struct PtRec *)malloc(sizeof(struct PtRec));
590
591 if (pt_ptr == NULL) FailAllocMessage();
592 memset(pt_ptr, 0, sizeof(struct PtRec));
593 pt_ptr->next = lastPtPtr;
594 numPtsInPoly++;
595 lastPtPtr = pt_ptr;
596 pt_ptr->x = AbsX;
597 pt_ptr->y = AbsY;
598 }
599
600 #ifdef HP_LINE_BUG
601 static
MyDrawLines(dpy,win,gc,sv,sn)602 void MyDrawLines(dpy, win, gc, sv, sn)
603 Display *dpy;
604 Window win;
605 GC gc;
606 XPoint *sv;
607 int sn;
608 {
609 if (sn == 2) {
610 XPoint hp_sv[3];
611
612 hp_sv[0].x = sv[0].x; hp_sv[0].y = sv[0].y;
613 hp_sv[1].x = sv[0].x; hp_sv[1].y = sv[0].y;
614 hp_sv[2].x = sv[1].x; hp_sv[2].y = sv[1].y;
615 XDrawLines(dpy, win, gc, hp_sv, 3, CoordModeOrigin);
616 } else {
617 XDrawLines(dpy, win, gc, sv, sn, CoordModeOrigin);
618 }
619 }
620 #else /* ~HP_LINE_BUG */
621 #define MyDrawLines(dpy,win,gc,sv,sn) \
622 XDrawLines((dpy),(win),(gc),(sv),(sn),CoordModeOrigin)
623 #endif /* HP_LINE_BUG */
624
625 static
SetXorDrawGCForPoly(color_index,line_width_index)626 void SetXorDrawGCForPoly(color_index, line_width_index)
627 int color_index, line_width_index;
628 {
629 XGCValues values;
630
631 values.fill_style = FillSolid;
632 #ifdef NO_THIN_LINE
633 values.line_width = 1;
634 #else /* ~NO_THIN_LINE */
635 values.line_width = 0;
636 #endif /* NO_THIN_LINE */
637 if (curChoice == FREEHAND) {
638 values.foreground = colorPixels[color_index];
639 values.function = GXcopy;
640 values.line_width = curWidthOfLine[line_width_index];
641 #ifdef NO_THIN_LINE
642 if (curWidthOfLine[lineWidth] < 1) values.line_width = 1;
643 #endif /* NO_THIN_LINE */
644 } else {
645 values.foreground = xorColorPixels[color_index];
646 values.function = GXxor;
647 }
648 values.line_style = LineSolid;
649 values.join_style = JoinBevel;
650
651 XChangeGC(mainDisplay, drawGC,
652 GCForeground | GCFunction | GCFillStyle | GCLineWidth | GCLineStyle |
653 GCJoinStyle, &values);
654 }
655
656 #define POLY_DRAW (FALSE)
657 #define POLY_ERASE (TRUE)
658 #define POLY_CLICK (FALSE)
659 #define POLY_DRAG (TRUE)
660
661 #define POLY_STARTSHOW 0
662 #define POLY_DOSHOW 1
663 #define POLY_ENDSHOW 2
664
665 typedef struct tagPolyMeasureCursorInfo {
666 IntPoint first_pt;
667 IntPoint prev_prev_pt;
668 IntPoint prev_pt;
669 } PolyMeasureCursorInfo;
670
671 static
DoPolyMeasureCursor(ppmci,start,num_pts,x,y,dx,dy,erase,drag)672 void DoPolyMeasureCursor(ppmci, start, num_pts, x, y, dx, dy, erase, drag)
673 PolyMeasureCursorInfo *ppmci;
674 int start, num_pts, x, y, dx, dy, erase, drag;
675 {
676 char buf[80], w_buf[80], h_buf[80], x_buf[80], y_buf[80], a_buf[80];
677 int angle2=0;
678
679 if (erase == POLY_DRAW && drag == POLY_CLICK) {
680 if (num_pts == 1) {
681 ppmci->first_pt.x = ppmci->prev_pt.x = ppmci->prev_prev_pt.x = x;
682 ppmci->first_pt.y = ppmci->prev_pt.y = ppmci->prev_prev_pt.y = y;
683 } else {
684 ppmci->prev_prev_pt.x = ppmci->prev_pt.x;
685 ppmci->prev_prev_pt.y = ppmci->prev_pt.y;
686 ppmci->prev_pt.x = x;
687 ppmci->prev_pt.y = y;
688 }
689 }
690 if (x == ppmci->prev_pt.x && y == ppmci->prev_pt.y) {
691 strcpy(a_buf, "0");
692 } else if (num_pts == 1) {
693 PointsToArc(ppmci->prev_pt.x, ppmci->prev_pt.y, ppmci->prev_pt.x+100,
694 ppmci->prev_pt.y, x, y, ARC_CCW, FALSE, NULL, NULL, NULL, NULL,
695 NULL, &angle2);
696 if (angle2 > 180*64) angle2=(360*64)-angle2;
697 FormatAngle(angle2, a_buf);
698 } else {
699 PointsToArc(ppmci->prev_pt.x, ppmci->prev_pt.y, ppmci->prev_prev_pt.x,
700 ppmci->prev_prev_pt.y, x, y, ARC_CCW, FALSE, NULL, NULL, NULL, NULL,
701 NULL, &angle2);
702 if (angle2 > 180*64) angle2=(360*64)-angle2;
703 FormatAngle(angle2, a_buf);
704 }
705 PixelToMeasurementUnit(w_buf, dx);
706 PixelToMeasurementUnit(h_buf, dy);
707 PixelToMeasurementUnit(x_buf, x);
708 PixelToMeasurementUnit(y_buf, y);
709 if (curChoice == FREEHAND) {
710 sprintf(buf, "x=%s\ny=%s", x_buf, y_buf);
711 } else {
712 sprintf(buf, "w=%s\nh=%s\nx=%s\ny=%s\nangle=%s", w_buf, h_buf, x_buf,
713 y_buf, a_buf);
714 }
715 x = OFFSET_X(x);
716 y = OFFSET_Y(y);
717 switch (start) {
718 case POLY_STARTSHOW: StartShowMeasureCursor(x, y, buf, TRUE); break;
719 case POLY_DOSHOW: ShowMeasureCursor(x, y, buf, TRUE); break;
720 case POLY_ENDSHOW: EndShowMeasureCursor(x, y, buf, TRUE); break;
721 }
722 }
723
FreePointsForCont(pn_ltx,pn_lty,pn_rbx,pn_rby)724 void FreePointsForCont(pn_ltx, pn_lty, pn_rbx, pn_rby)
725 int *pn_ltx, *pn_lty, *pn_rbx, *pn_rby;
726 {
727 int ltx=(*pn_ltx), lty=(*pn_lty), rbx=(*pn_rbx), rby=(*pn_rby);
728
729 if (curSpline == LT_STRUCT_SPLINE) {
730 CVListElem *elem=NULL;
731
732 for (elem=ListFirst(&gStructSplineList); elem != NULL;
733 elem=ListNext(&gStructSplineList, elem)) {
734 IntPointTriplet *ipt=(IntPointTriplet*)(elem->obj);
735
736 if (ipt != NULL) {
737 if (ipt->hinge_pt.x < ltx) ltx = ipt->hinge_pt.x;
738 if (ipt->hinge_pt.y < lty) lty = ipt->hinge_pt.y;
739 if (ipt->hinge_pt.x > rbx) rbx = ipt->hinge_pt.x;
740 if (ipt->hinge_pt.y > rby) rby = ipt->hinge_pt.y;
741 if (ipt->earlier_valid) {
742 if (ipt->earlier_smooth_pt.x < ltx) {
743 ltx = ipt->earlier_smooth_pt.x;
744 }
745 if (ipt->earlier_smooth_pt.y < lty) {
746 lty = ipt->earlier_smooth_pt.y;
747 }
748 if (ipt->earlier_smooth_pt.x > rbx) {
749 rbx = ipt->earlier_smooth_pt.x;
750 }
751 if (ipt->earlier_smooth_pt.y > rby) {
752 rby = ipt->hinge_pt.y;
753 }
754 }
755 if (ipt->later_valid) {
756 if (ipt->later_smooth_pt.x < ltx) ltx = ipt->later_smooth_pt.x;
757 if (ipt->later_smooth_pt.y < lty) lty = ipt->later_smooth_pt.y;
758 if (ipt->later_smooth_pt.x > rbx) rbx = ipt->later_smooth_pt.x;
759 if (ipt->later_smooth_pt.y > rby) rby = ipt->later_smooth_pt.y;
760 }
761 free(ipt);
762 }
763 }
764 ListUnlinkAll(&gStructSplineList);
765 } else {
766 struct PtRec *pt_ptr=NULL, *next_pt=NULL;
767
768 for (pt_ptr=lastPtPtr; pt_ptr != NULL; pt_ptr=next_pt) {
769 if (curSpline != LT_INTSPLINE) {
770 if (pt_ptr->x < ltx) ltx = pt_ptr->x;
771 if (pt_ptr->y < lty) lty = pt_ptr->y;
772 if (pt_ptr->x > rbx) rbx = pt_ptr->x;
773 if (pt_ptr->y > rby) rby = pt_ptr->y;
774 }
775 next_pt = pt_ptr->next;
776 free(pt_ptr);
777 }
778 }
779 *pn_ltx = ltx;
780 *pn_lty = lty;
781 *pn_rbx = rbx;
782 *pn_rby = rby;
783 }
784
SetFirstPoint(grid_x,grid_y,pipt_first)785 int SetFirstPoint(grid_x, grid_y, pipt_first)
786 int grid_x, grid_y;
787 IntPointTriplet *pipt_first;
788 {
789 if (curSpline == LT_STRUCT_SPLINE) {
790 IntPointTriplet *ipt=(IntPointTriplet*)malloc(sizeof(IntPointTriplet));
791
792 if (ipt == NULL) return FailAllocMessage();
793 memset(ipt, 0, sizeof(IntPointTriplet));
794 if (pipt_first == NULL) {
795 ipt->earlier_smooth_pt.x = ipt->hinge_pt.x = ipt->later_smooth_pt.x =
796 grid_x; /* offset */
797 ipt->earlier_smooth_pt.y = ipt->hinge_pt.y = ipt->later_smooth_pt.y =
798 grid_y; /* offset */
799 ipt->ratio = (double)1;
800 } else {
801 memcpy(ipt, pipt_first, sizeof(IntPointTriplet));
802 }
803 ListAppend(&gStructSplineList, ipt);
804 } else {
805 numPtsInPoly = 1;
806 lastPtPtr = (struct PtRec *)malloc(sizeof(struct PtRec));
807 if (lastPtPtr == NULL) return FailAllocMessage();
808 lastPtPtr->x = grid_x; /* offset */
809 lastPtPtr->y = grid_y; /* offset */
810 lastPtPtr->next = NULL;
811 }
812 return TRUE;
813 }
814
AddPointForCont(grid_x,grid_y,pipt)815 int AddPointForCont(grid_x, grid_y, pipt)
816 int grid_x, grid_y;
817 IntPointTriplet *pipt;
818 {
819 if (curSpline == LT_STRUCT_SPLINE) {
820 IntPointTriplet *ipt=(IntPointTriplet*)malloc(sizeof(IntPointTriplet));
821
822 if (ipt == NULL) return FailAllocMessage();
823 memcpy(ipt, pipt, sizeof(IntPointTriplet));
824 ListAppend(&gStructSplineList, ipt);
825 } else {
826 struct PtRec *pt_ptr=NULL;
827
828 pt_ptr = (struct PtRec *)malloc(sizeof(struct PtRec));
829 if (pt_ptr == NULL) FailAllocMessage();
830 pt_ptr->next = lastPtPtr;
831 lastPtPtr = pt_ptr;
832 pt_ptr->x = grid_x;
833 pt_ptr->y = grid_y;
834 }
835 return TRUE;
836 }
837
UpdateLastPointForCont(pipt)838 void UpdateLastPointForCont(pipt)
839 IntPointTriplet *pipt;
840 {
841 CVListElem *elem=ListLast(&gStructSplineList);
842 IntPointTriplet *ipt=(IntPointTriplet*)(elem->obj);
843
844 memcpy(ipt, pipt, sizeof(IntPointTriplet));
845 }
846
DrawAllStructSplinePointsForCont(num_pts)847 void DrawAllStructSplinePointsForCont(num_pts)
848 int num_pts;
849 {
850 int i=0;
851 CVListElem *elem=ListFirst(&gStructSplineList);
852 IntPointTriplet *pipt=(IntPointTriplet*)(elem->obj);
853
854 for (i=0; i < num_pts-1; i++) {
855 CVListElem *next_elem=ListNext(&gStructSplineList, elem);
856 IntPointTriplet *pipt_next=(IntPointTriplet*)(next_elem->obj);
857 int tmp_n=0;
858 IntPoint tmp_vs[4];
859
860 tmp_vs[0].x = ABS_X(pipt->hinge_pt.x);
861 tmp_vs[0].y = ABS_Y(pipt->hinge_pt.y);
862 if (pipt->later_valid) {
863 if (pipt_next->earlier_valid) {
864 tmp_n = 4;
865 tmp_vs[1].x = ABS_X(pipt->later_smooth_pt.x);
866 tmp_vs[1].y = ABS_Y(pipt->later_smooth_pt.y);
867 tmp_vs[2].x = ABS_X(pipt_next->earlier_smooth_pt.x);
868 tmp_vs[2].y = ABS_Y(pipt_next->earlier_smooth_pt.y);
869 } else {
870 tmp_n = 3;
871 tmp_vs[1].x = ABS_X(pipt->later_smooth_pt.x);
872 tmp_vs[1].y = ABS_Y(pipt->later_smooth_pt.y);
873 }
874 } else {
875 if (pipt_next->earlier_valid) {
876 tmp_n = 3;
877 tmp_vs[1].x = ABS_X(pipt_next->earlier_smooth_pt.x);
878 tmp_vs[1].y = ABS_Y(pipt_next->earlier_smooth_pt.y);
879 } else {
880 tmp_n = 2;
881 XDrawLine(mainDisplay, drawWindow, drawGC, pipt->hinge_pt.x,
882 pipt->hinge_pt.y, pipt_next->hinge_pt.x,
883 pipt_next->hinge_pt.y);
884 }
885 }
886 tmp_vs[tmp_n-1].x = ABS_X(pipt_next->hinge_pt.x);
887 tmp_vs[tmp_n-1].y = ABS_Y(pipt_next->hinge_pt.y);
888
889 if (tmp_n > 2) {
890 int sn=0;
891 XPoint *sv=MakeSplinePolyVertex(0, curSpline, &sn, drawOrigX,
892 drawOrigY, tmp_n, tmp_vs);
893
894 XDrawLines(mainDisplay, drawWindow, drawGC, sv, sn, CoordModeOrigin);
895 free(sv);
896 }
897 }
898 }
899
UpdatePrevToLastPointForCont(pipt_prev)900 void UpdatePrevToLastPointForCont(pipt_prev)
901 IntPointTriplet *pipt_prev;
902 {
903 CVListElem *elem=ListLast(&gStructSplineList);
904 IntPointTriplet *pipt=(IntPointTriplet*)(elem->obj);
905
906 elem = ListPrev(&gStructSplineList, elem);
907 pipt = (IntPointTriplet*)(elem->obj);
908 memcpy(pipt_prev, pipt, sizeof(IntPointTriplet));
909 }
910
911 static
ContinueForStructSplinePolyControlPoints(OrigX,OrigY,LastX,LastY,psv,psn,pipt_prev,pipt,pn_abort)912 void ContinueForStructSplinePolyControlPoints(OrigX, OrigY, LastX, LastY, psv,
913 psn, pipt_prev, pipt, pn_abort)
914 int OrigX, OrigY, LastX, LastY, *psn, *pn_abort;
915 XPoint **psv;
916 IntPointTriplet *pipt_prev, *pipt;
917 {
918 int i=0, done=FALSE, grid_x=0, grid_y=0, end_x=0, end_y=0, n=2;
919 int sn=(*psn), orig_sn=(*psn), num_pts=1, first_time=TRUE;
920 IntPoint v[4];
921 XPoint *sv=NULL, *orig_sv=(*psv), dash_vs[2];
922 PolyMeasureCursorInfo pmci;
923 XGCValues values;
924
925 *pn_abort = FALSE;
926
927 if (orig_sv != NULL) {
928 sv = (XPoint*)malloc(orig_sn*sizeof(XPoint));
929 if (sv == NULL) FailAllocMessage();
930 memset(sv, 0, orig_sn*sizeof(XPoint));
931 for (i=0; i < orig_sn; i++) {
932 sv[i].x = orig_sv[i].x;
933 sv[i].y = orig_sv[i].y;
934 }
935 sn = orig_sn;
936 }
937 memset(pipt, 0, sizeof(IntPointTriplet));
938 pipt->earlier_valid = pipt->later_valid = FALSE;
939 pipt->hinge_pt.x = pipt->earlier_smooth_pt.x = pipt->later_smooth_pt.x =
940 LastX;
941 pipt->hinge_pt.y = pipt->earlier_smooth_pt.y = pipt->later_smooth_pt.y =
942 LastY;
943 pipt->ratio = (double)1;
944
945 XSetDashes(mainDisplay, revDefaultGC, 0, dashList[8], dashListLength[8]);
946
947 grid_x = end_x = dash_vs[0].x = dash_vs[1].x = LastX;
948 grid_y = end_y = dash_vs[0].y = dash_vs[1].y = LastY;
949 v[0].x = ABS_X(OrigX);
950 v[0].y = ABS_Y(OrigY);
951 v[1].x = ABS_X(LastX);
952 v[1].y = ABS_Y(LastY);
953 n = 2;
954 MARKHR(drawWindow, revDefaultGC, LastX, LastY);
955
956 /* the previous curve has already been drawn */
957 /* draw the measure cursor */
958 DoPolyMeasureCursor(&pmci, POLY_DOSHOW, num_pts, ABS_X(grid_x),
959 ABS_Y(grid_y), 0, 0, POLY_ERASE, POLY_DRAG);
960 while (!done) {
961 XEvent input, ev;
962
963 XNextEvent(mainDisplay, &input);
964
965 if (input.type == Expose || input.type == VisibilityNotify) {
966 ExposeEventHandler(&input, TRUE);
967 SetXorDrawGCForPoly(colorIndex, lineWidth);
968 } else if (input.type == MotionNotify) {
969 end_x = input.xmotion.x;
970 end_y = input.xmotion.y;
971
972 /* erase */
973 if (first_time || grid_x != LastX || grid_y != LastY) {
974 if (sv != NULL) {
975 MyDrawLines(mainDisplay, drawWindow, drawGC, sv, sn);
976 } else {
977 XDrawLine(mainDisplay, drawWindow, drawGC, OrigX, OrigY, grid_x,
978 grid_y);
979 }
980 first_time = FALSE;
981 } else {
982 if (orig_sv != NULL) {
983 MyDrawLines(mainDisplay, drawWindow, drawGC, orig_sv, orig_sn);
984 } else {
985 XDrawLine(mainDisplay, drawWindow, drawGC, OrigX, OrigY, LastX,
986 LastY);
987 }
988 }
989 DoPolyMeasureCursor(&pmci, POLY_DOSHOW, num_pts, ABS_X(grid_x),
990 ABS_Y(grid_y), ABS_SIZE(abs(grid_x-LastX)),
991 ABS_SIZE(abs(grid_y-LastY)), POLY_ERASE, POLY_DRAG);
992 MARKHO(drawWindow, revDefaultGC, dash_vs[0].x, dash_vs[0].y);
993 MARKHO(drawWindow, revDefaultGC, dash_vs[1].x, dash_vs[1].y);
994 values.line_style = LineOnOffDash;
995 XChangeGC(mainDisplay, revDefaultGC, GCLineStyle, &values);
996 MyDashedLine(drawWindow, revDefaultGC, dash_vs, 2);
997 values.line_style = LineSolid;
998 XChangeGC(mainDisplay, revDefaultGC, GCLineStyle, &values);
999
1000 /* draw */
1001 GridXY(end_x, end_y, &grid_x, &grid_y);
1002 MarkRulers(grid_x, grid_y);
1003 if (grid_x != LastX || grid_y != LastY) {
1004 if (sv != NULL) {
1005 free(sv);
1006 sv = NULL;
1007 }
1008 if (pipt_prev->later_valid) {
1009 v[1].x = ABS_X(pipt_prev->later_smooth_pt.x);
1010 v[1].y = ABS_Y(pipt_prev->later_smooth_pt.y);
1011 n = 4;
1012 } else {
1013 n = 3;
1014 }
1015 v[n-2].x = ABS_X((LastX<<1)-grid_x);
1016 v[n-2].y = ABS_Y((LastY<<1)-grid_y);
1017 v[n-1].x = ABS_X(LastX);
1018 v[n-1].y = ABS_Y(LastY);
1019 sv = MakeSplinePolyVertex(0, curSpline, &sn, drawOrigX, drawOrigY,
1020 n, v);
1021 MyDrawLines(mainDisplay, drawWindow, drawGC, sv, sn);
1022 } else {
1023 if (orig_sv != NULL) {
1024 MyDrawLines(mainDisplay, drawWindow, drawGC, orig_sv, orig_sn);
1025 } else {
1026 XDrawLine(mainDisplay, drawWindow, drawGC, OrigX, OrigY, LastX,
1027 LastY);
1028 }
1029 }
1030 while (XCheckMaskEvent(mainDisplay, PointerMotionMask, &ev)) ;
1031
1032 dash_vs[0].x = grid_x;
1033 dash_vs[0].y = grid_y;
1034 dash_vs[1].x = (LastX<<1)-grid_x;
1035 dash_vs[1].y = (LastY<<1)-grid_y;
1036 pipt->later_smooth_pt.x = dash_vs[0].x;
1037 pipt->later_smooth_pt.y = dash_vs[0].y;
1038 pipt->earlier_smooth_pt.x = dash_vs[1].x;
1039 pipt->earlier_smooth_pt.y = dash_vs[1].y;
1040 if (grid_x == LastX && grid_y == LastY) {
1041 pipt->earlier_valid = pipt->later_valid = FALSE;
1042 } else {
1043 pipt->earlier_valid = pipt->later_valid = TRUE;
1044 }
1045 MARKHO(drawWindow, revDefaultGC, dash_vs[0].x, dash_vs[0].y);
1046 MARKHO(drawWindow, revDefaultGC, dash_vs[1].x, dash_vs[1].y);
1047 values.line_style = LineOnOffDash;
1048 XChangeGC(mainDisplay, revDefaultGC, GCLineStyle, &values);
1049 MyDashedLine(drawWindow, revDefaultGC, dash_vs, 2);
1050 values.line_style = LineSolid;
1051 XChangeGC(mainDisplay, revDefaultGC, GCLineStyle, &values);
1052 DoPolyMeasureCursor(&pmci, POLY_DOSHOW, num_pts, ABS_X(grid_x),
1053 ABS_Y(grid_y), ABS_SIZE(abs(grid_x-LastX)),
1054 ABS_SIZE(abs(grid_y-LastY)), POLY_DRAW, POLY_DRAG);
1055 } else if (input.type == KeyPress) {
1056 if (KeyPressEventIsEscape(&input.xkey)) {
1057 /* erase */
1058 DoPolyMeasureCursor(&pmci, POLY_ENDSHOW, num_pts, ABS_X(grid_x),
1059 ABS_Y(grid_y), ABS_SIZE(abs(grid_x-LastX)),
1060 ABS_SIZE(abs(grid_y-LastY)), POLY_ERASE, POLY_DRAG);
1061 MARKHO(drawWindow, revDefaultGC, dash_vs[0].x, dash_vs[0].y);
1062 MARKHO(drawWindow, revDefaultGC, dash_vs[1].x, dash_vs[1].y);
1063 values.line_style = LineOnOffDash;
1064 XChangeGC(mainDisplay, revDefaultGC, GCLineStyle, &values);
1065 MyDashedLine(drawWindow, revDefaultGC, dash_vs, 2);
1066 values.line_style = LineSolid;
1067 XChangeGC(mainDisplay, revDefaultGC, GCLineStyle, &values);
1068 Msg("");
1069 *pn_abort = TRUE;
1070 done = TRUE;
1071 }
1072 } else if (input.type == ButtonRelease) {
1073 /* erase */
1074 DoPolyMeasureCursor(&pmci, POLY_ENDSHOW, num_pts, ABS_X(grid_x),
1075 ABS_Y(grid_y), ABS_SIZE(abs(grid_x-LastX)),
1076 ABS_SIZE(abs(grid_y-LastY)), POLY_ERASE, POLY_DRAG);
1077 MARKHO(drawWindow, revDefaultGC, dash_vs[0].x, dash_vs[0].y);
1078 MARKHO(drawWindow, revDefaultGC, dash_vs[1].x, dash_vs[1].y);
1079 values.line_style = LineOnOffDash;
1080 XChangeGC(mainDisplay, revDefaultGC, GCLineStyle, &values);
1081 MyDashedLine(drawWindow, revDefaultGC, dash_vs, 2);
1082 values.line_style = LineSolid;
1083 XChangeGC(mainDisplay, revDefaultGC, GCLineStyle, &values);
1084
1085 GridXY(input.xbutton.x, input.xbutton.y, &grid_x, &grid_y);
1086 pipt->later_smooth_pt.x = grid_x;
1087 pipt->later_smooth_pt.y = grid_y;
1088 pipt->earlier_smooth_pt.x = (LastX<<1)-grid_x;
1089 pipt->earlier_smooth_pt.y = (LastY<<1)-grid_y;
1090 if (grid_x == LastX && grid_y == LastY) {
1091 pipt->earlier_valid = pipt->later_valid = FALSE;
1092 } else {
1093 pipt->earlier_valid = pipt->later_valid = TRUE;
1094 }
1095 done = TRUE;
1096 }
1097 }
1098 MARKHR(drawWindow, revDefaultGC, LastX, LastY);
1099
1100 *psv = sv;
1101 *psn = sn;
1102
1103 if (orig_sv != NULL) free(orig_sv);
1104 }
1105
1106 static
ContinuePoly(OrigX,OrigY)1107 void ContinuePoly(OrigX, OrigY)
1108 int OrigX, OrigY;
1109 /* OrigX and OrigY are screen coordinates (scaled and translated). */
1110 /* OrigX and OrigY are also on grid. */
1111 {
1112 int i;
1113 XGCValues values;
1114 XEvent input, ev;
1115 XButtonEvent *button_ev;
1116 int abort=FALSE;
1117 int end_x, end_y, grid_x, grid_y, done=FALSE, num_pts=1;
1118 int last_x=OrigX, last_y=OrigY, n=2, sn=0, max_n=40, intn=0;
1119 int ltx=OrigX, lty=OrigY, rbx=OrigX, rby=OrigY;
1120 int one_line_status=FALSE, freehand_n=0, nothing_is_drawn=FALSE;
1121 char status_buf[MAX_STATUS_BTNS+1][MAXSTRING+1];
1122 IntPointTriplet ipt_prev, ipt, first_ipt;
1123 XPoint *sv=NULL, *freehand_vs=NULL;
1124 IntPoint *v=NULL, *cntrlv=NULL;
1125 PolyMeasureCursorInfo pmci;
1126
1127 memset(&ipt, 0, sizeof(IntPointTriplet));
1128 memset(&ipt_prev, 0, sizeof(IntPointTriplet));
1129 memset(&first_ipt, 0, sizeof(IntPointTriplet));
1130 memset(&pmci, 0, sizeof(PolyMeasureCursorInfo));
1131 SetXorDrawGCForPoly(colorIndex, lineWidth);
1132
1133 grid_x = end_x = OrigX;
1134 grid_y = end_y = OrigY;
1135 if (curChoice == FREEHAND) {
1136 freehand_vs = (XPoint*)malloc((max_n+1)*sizeof(XPoint));
1137 if (freehand_vs == NULL) FailAllocMessage();
1138 freehand_vs[0].x = freehand_vs[1].x = OrigX;
1139 freehand_vs[0].y = freehand_vs[1].y = OrigY;
1140 freehand_n = 1;
1141 } else if (curSpline != LT_STRAIGHT && curSpline != LT_STRUCT_SPLINE) {
1142 v = (IntPoint*)malloc((max_n+1)*sizeof(IntPoint));
1143 if (v == NULL) FailAllocMessage();
1144 v[0].x = v[1].x = v[2].x = ABS_X(OrigX);
1145 v[0].y = v[1].y = v[2].y = ABS_Y(OrigY);
1146 switch (curSpline) {
1147 case LT_SPLINE:
1148 sv = MakeSplinePolyVertex(0, curSpline, &sn, drawOrigX, drawOrigY, n,
1149 v);
1150 break;
1151 case LT_INTSPLINE:
1152 sv = MakeIntSplinePolyVertex(&sn, &intn, &cntrlv,
1153 drawOrigX, drawOrigY, n, v);
1154 for (i=0; i < sn; i++) {
1155 if (sv[i].x < ltx) ltx = sv[i].x;
1156 if (sv[i].y < lty) lty = sv[i].y;
1157 if (sv[i].x > rbx) rbx = sv[i].x;
1158 if (sv[i].y > rby) rby = sv[i].y;
1159 }
1160 break;
1161 }
1162 } else if (curSpline == LT_STRUCT_SPLINE) {
1163 ipt_prev.earlier_valid = ipt_prev.later_valid = FALSE;
1164 ipt_prev.earlier_smooth_pt.x = ipt_prev.hinge_pt.x =
1165 ipt_prev.later_smooth_pt.x = OrigX;
1166 ipt_prev.earlier_smooth_pt.y = ipt_prev.hinge_pt.y =
1167 ipt_prev.later_smooth_pt.y = OrigY;
1168 memcpy(&first_ipt, &ipt_prev, sizeof(IntPointTriplet));
1169 v = (IntPoint*)malloc((max_n+1)*sizeof(IntPoint));
1170 if (v == NULL) FailAllocMessage();
1171 v[0].x = v[1].x = v[2].x = v[3].x = ABS_X(OrigX);
1172 v[0].y = v[1].y = v[2].y = v[3].y = ABS_Y(OrigY);
1173 sv = MakeSplinePolyVertex(0, curSpline, &sn, drawOrigX, drawOrigY, n+1,
1174 v);
1175 }
1176 SaveStatusStrings();
1177 if (curChoice == FREEHAND) {
1178 DoPolyMeasureCursor(&pmci, POLY_STARTSHOW, num_pts, ABS_X(grid_x),
1179 ABS_Y(grid_y), 0, 0, POLY_DRAW, POLY_CLICK);
1180 if (!debugNoPointerGrab) {
1181 XGrabPointer(mainDisplay, drawWindow, FALSE,
1182 PointerMotionMask | ButtonReleaseMask,
1183 GrabModeAsync, GrabModeAsync, None, handCursor, CurrentTime);
1184 }
1185 SetFirstPoint(OrigX, OrigY, NULL);
1186 } else {
1187 if (curSpline == LT_STRUCT_SPLINE) {
1188 SetMouseStatus(TgLoadCachedString(CSTID_ADD_A_STRUCT_VERTEX),
1189 TgLoadCachedString(CSTID_ADD_LAST_VERTEX),
1190 TgLoadCachedString(CSTID_ADD_LAST_VERTEX));
1191 } else {
1192 SetMouseStatus(TgLoadCachedString(CSTID_ADD_A_VERTEX),
1193 TgLoadCachedString(CSTID_ADD_LAST_VERTEX),
1194 TgLoadCachedString(CSTID_ADD_LAST_VERTEX));
1195 }
1196 DoPolyMeasureCursor(&pmci, POLY_STARTSHOW, num_pts, ABS_X(grid_x),
1197 ABS_Y(grid_y), 0, 0, POLY_DRAW, POLY_CLICK);
1198 if (!debugNoPointerGrab) {
1199 XGrabPointer(mainDisplay, drawWindow, FALSE,
1200 PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
1201 GrabModeAsync, GrabModeAsync, None, handCursor, CurrentTime);
1202 }
1203 if (curSpline == LT_STRUCT_SPLINE) {
1204 DoPolyMeasureCursor(&pmci, POLY_DOSHOW, num_pts, ABS_X(grid_x),
1205 ABS_Y(grid_y), 0, 0, POLY_ERASE, POLY_DRAG);
1206 ContinueForStructSplinePolyControlPoints(OrigX, OrigY,
1207 grid_x, grid_y, &sv, &sn, &ipt_prev, &ipt, &abort);
1208 memcpy(&first_ipt, &ipt, sizeof(IntPointTriplet));
1209 memcpy(&ipt_prev, &ipt, sizeof(IntPointTriplet));
1210 if (first_ipt.later_valid) {
1211 grid_x = OFFSET_X(first_ipt.later_smooth_pt.x);
1212 grid_y = OFFSET_Y(first_ipt.later_smooth_pt.y);
1213 }
1214 SetFirstPoint(OrigX, OrigY, &first_ipt);
1215 DoPolyMeasureCursor(&pmci, POLY_STARTSHOW, num_pts, ABS_X(grid_x),
1216 ABS_Y(grid_y), ABS_SIZE(abs(grid_x-OrigX)),
1217 ABS_SIZE(abs(grid_y-OrigY)), POLY_DRAW, POLY_CLICK);
1218 } else {
1219 SetFirstPoint(OrigX, OrigY, NULL);
1220 }
1221 }
1222 if (gstWiringInfo.num_ports_to_connect > 0 || drawPolyToConnectPins > 0) {
1223 *gstWiringInfo.last_port_name = '\0';
1224 drawPolyHighlightedNode = NULL;
1225 SaveStatusStringsIntoBuf(status_buf, &one_line_status);
1226 values.line_width = 3;
1227 XChangeGC(mainDisplay, revGrayGC, GCLineWidth, &values);
1228 }
1229 while (!done) {
1230 XNextEvent(mainDisplay, &input);
1231
1232 if (input.type == Expose || input.type == VisibilityNotify) {
1233 ExposeEventHandler(&input, TRUE);
1234 SetXorDrawGCForPoly(colorIndex, lineWidth);
1235 } else if ((input.type==MotionNotify && input.xany.window==drawWindow) ||
1236 input.type == KeyPress || input.type == KeyRelease) {
1237 if (input.type == KeyPress) {
1238 if (KeyPressEventIsEscape(&input.xkey)) {
1239 /* erase */
1240 DoPolyMeasureCursor(&pmci, POLY_ENDSHOW, num_pts, ABS_X(grid_x),
1241 ABS_Y(grid_y), ABS_SIZE(abs(grid_x-OrigX)),
1242 ABS_SIZE(abs(grid_y-OrigY)), POLY_ERASE, POLY_CLICK);
1243 Msg("");
1244 abort = TRUE;
1245 done = TRUE;
1246 }
1247 }
1248 if (done) {
1249 break;
1250 }
1251 /* erase */
1252 if (curChoice == FREEHAND) {
1253 if (freehand_n > 1) {
1254 MyDrawLines(mainDisplay, drawWindow, drawGC,
1255 freehand_vs, freehand_n);
1256 }
1257 } else {
1258 if (curSpline != LT_STRAIGHT && curSpline != LT_STRUCT_SPLINE) {
1259 MyDrawLines(mainDisplay, drawWindow, drawGC, sv, sn);
1260 } else if (curSpline == LT_STRUCT_SPLINE) {
1261 if (nothing_is_drawn) {
1262 /* then there is nothing to erase */
1263 nothing_is_drawn = FALSE;
1264 } else {
1265 if (sv == NULL) {
1266 XDrawLine(mainDisplay, drawWindow, drawGC, OrigX, OrigY,
1267 grid_x, grid_y);
1268 } else {
1269 MyDrawLines(mainDisplay, drawWindow, drawGC, sv, sn);
1270 }
1271 }
1272 } else {
1273 XDrawLine(mainDisplay, drawWindow, drawGC, OrigX, OrigY, grid_x,
1274 grid_y);
1275 }
1276 }
1277 DoPolyMeasureCursor(&pmci, POLY_DOSHOW, num_pts, ABS_X(grid_x),
1278 ABS_Y(grid_y), ABS_SIZE(abs(grid_x-OrigX)),
1279 ABS_SIZE(abs(grid_y-OrigY)), POLY_ERASE, POLY_DRAG);
1280
1281 if (input.type == KeyPress || input.type == KeyRelease) {
1282 end_x = grid_x;
1283 end_y = grid_y;
1284 } else {
1285 end_x = input.xmotion.x;
1286 end_y = input.xmotion.y;
1287 }
1288 if (shiftForDiagMouseMove && DiagEventCheck(&input)) {
1289 if (input.type == KeyRelease) {
1290 end_x = input.xkey.x;
1291 end_y = input.xkey.y;
1292 } else {
1293 DiagGridXY(OrigX, OrigY, &end_x, &end_y);
1294 }
1295 }
1296 /* draw */
1297 if (curChoice == FREEHAND) {
1298 grid_x = end_x;
1299 grid_y = end_y;
1300 MarkRulers(grid_x, grid_y);
1301 if (curSpline != LT_STRAIGHT && curSpline != LT_STRUCT_SPLINE) {
1302 if (sv != NULL) {
1303 free(sv);
1304 sv = NULL;
1305 }
1306 v[n-1].x = v[n].x = ABS_X(grid_x);
1307 v[n-1].y = v[n].y = ABS_Y(grid_y);
1308 switch (curSpline) {
1309 case LT_SPLINE:
1310 sv = MakeSplinePolyVertex(0, curSpline, &sn, drawOrigX,
1311 drawOrigY, n, v);
1312 break;
1313 case LT_INTSPLINE:
1314 if (cntrlv != NULL) free(cntrlv);
1315 sv = MakeIntSplinePolyVertex(&sn, &intn, &cntrlv,
1316 drawOrigX, drawOrigY, n, v);
1317 for (i=0; i < sn; i++) {
1318 if (sv[i].x < ltx) ltx = sv[i].x;
1319 if (sv[i].y < lty) lty = sv[i].y;
1320 if (sv[i].x > rbx) rbx = sv[i].x;
1321 if (sv[i].y > rby) rby = sv[i].y;
1322 }
1323 break;
1324 }
1325 MyDrawLines(mainDisplay, drawWindow, drawGC, sv, sn);
1326 } else {
1327 XDrawLine(mainDisplay, drawWindow, drawGC, OrigX, OrigY, grid_x,
1328 grid_y);
1329 if (sv != NULL) {
1330 free(sv);
1331 sv = NULL;
1332 }
1333 }
1334 while (XCheckMaskEvent(mainDisplay, PointerMotionMask, &ev)) ;
1335
1336 if (grid_x != last_x || grid_y != last_y) {
1337 num_pts++;
1338 AddPointForCont(grid_x, grid_y, &ipt);
1339 last_x = grid_x;
1340 last_y = grid_y;
1341 if (curSpline != LT_STRAIGHT && curSpline != LT_STRUCT_SPLINE) {
1342 if (n >= max_n-2) {
1343 max_n += 40;
1344 v = (IntPoint*)realloc(v, sizeof(IntPoint)*max_n+1);
1345 if (v == NULL) FailAllocMessage();
1346 }
1347 MyDrawLines(mainDisplay, drawWindow, drawGC, sv, sn);
1348 if (sv != NULL) {
1349 free(sv);
1350 sv = NULL;
1351 }
1352 v[n].x = v[n+1].x = ABS_X(grid_x);
1353 v[n].y = v[n+1].y = ABS_Y(grid_y);
1354 n++;
1355 switch (curSpline) {
1356 case LT_SPLINE:
1357 sv = MakeSplinePolyVertex(0, curSpline, &sn, drawOrigX,
1358 drawOrigY, n, v);
1359 break;
1360 case LT_INTSPLINE:
1361 if (cntrlv != NULL) free(cntrlv);
1362 sv = MakeIntSplinePolyVertex(&sn, &intn, &cntrlv,
1363 drawOrigX, drawOrigY, n, v);
1364 for (i=0; i < sn; i++) {
1365 if (sv[i].x < ltx) ltx = sv[i].x;
1366 if (sv[i].y < lty) lty = sv[i].y;
1367 if (sv[i].x > rbx) rbx = sv[i].x;
1368 if (sv[i].y > rby) rby = sv[i].y;
1369 }
1370 break;
1371 }
1372 MyDrawLines(mainDisplay, drawWindow, drawGC, sv, sn);
1373 } else {
1374 if (freehand_n >= max_n-2) {
1375 max_n += 40;
1376 freehand_vs = (XPoint*)realloc(freehand_vs,
1377 sizeof(XPoint)*max_n+1);
1378 if (freehand_vs == NULL) FailAllocMessage();
1379 }
1380 freehand_vs[freehand_n].x = grid_x;
1381 freehand_vs[freehand_n].y = grid_y;
1382 freehand_n++;
1383 }
1384 }
1385 OrigX = grid_x; OrigY = grid_y;
1386 } else {
1387 if (gstWiringInfo.num_ports_to_connect > 0) {
1388 int need_to_highlight=FALSE, something_changed=FALSE;
1389 struct ObjRec *owner_obj=NULL, *obj_ptr, *obj_under_cursor=NULL;
1390 char port_name[MAXSTRING];
1391
1392 obj_ptr = FindAnObj(end_x, end_y, &owner_obj, &obj_under_cursor,
1393 port_name);
1394 if (drawPolyHighlightedNode != NULL) {
1395 if (obj_under_cursor != drawPolyHighlightedNode) {
1396 /* un-highlight */
1397 SelBox(drawWindow, revGrayGC,
1398 OFFSET_X(drawPolyHighlightedNode->bbox.ltx)-2,
1399 OFFSET_Y(drawPolyHighlightedNode->bbox.lty)-2,
1400 OFFSET_X(drawPolyHighlightedNode->bbox.rbx)+2,
1401 OFFSET_Y(drawPolyHighlightedNode->bbox.rby)+2);
1402 if (obj_under_cursor != NULL &&
1403 ObjIsAPort(obj_under_cursor)) {
1404 drawPolyHighlightedNode = obj_under_cursor;
1405 SetWiringNodeInfo(obj_under_cursor, owner_obj,
1406 port_name, FALSE);
1407 } else {
1408 drawPolyHighlightedNode = NULL;
1409 SetWiringNodeInfo(NULL, NULL, NULL, FALSE);
1410 }
1411 if (drawPolyHighlightedNode != NULL) {
1412 need_to_highlight = TRUE;
1413 }
1414 something_changed = TRUE;
1415 }
1416 } else {
1417 if (obj_under_cursor != NULL) {
1418 if (ObjIsAPort(obj_under_cursor)) {
1419 drawPolyHighlightedNode = obj_under_cursor;
1420 SetWiringNodeInfo(obj_under_cursor, owner_obj,
1421 port_name, FALSE);
1422 } else {
1423 drawPolyHighlightedNode = NULL;
1424 SetWiringNodeInfo(NULL, NULL, NULL, FALSE);
1425 }
1426 if (drawPolyHighlightedNode != NULL) {
1427 need_to_highlight = TRUE;
1428 something_changed = TRUE;
1429 }
1430 }
1431 }
1432 if (need_to_highlight) {
1433 SelBox(drawWindow, revGrayGC,
1434 OFFSET_X(drawPolyHighlightedNode->bbox.ltx)-2,
1435 OFFSET_Y(drawPolyHighlightedNode->bbox.lty)-2,
1436 OFFSET_X(drawPolyHighlightedNode->bbox.rbx)+2,
1437 OFFSET_Y(drawPolyHighlightedNode->bbox.rby)+2);
1438 }
1439 if (something_changed) {
1440 if (*gstWiringInfo.last_port_name != '\0') {
1441 sprintf(gszMsgBox,
1442 TgLoadCachedString(CSTID_END_A_WIRE_AT_NAMED_PORT),
1443 gstWiringInfo.last_port_name);
1444 SetStringStatus(gszMsgBox);
1445 } else {
1446 RestoreStatusStringsFromBuf(status_buf, one_line_status);
1447 SetMouseStatus(TgLoadCachedString(CSTID_ADD_A_VERTEX),
1448 TgLoadCachedString(CSTID_ADD_LAST_VERTEX),
1449 TgLoadCachedString(CSTID_ADD_LAST_VERTEX));
1450 }
1451 }
1452 if (drawPolyHighlightedNode != NULL) {
1453 grid_x = OFFSET_X((drawPolyHighlightedNode->obbox.ltx +
1454 drawPolyHighlightedNode->obbox.rbx)>>1);
1455 grid_y = OFFSET_Y((drawPolyHighlightedNode->obbox.lty +
1456 drawPolyHighlightedNode->obbox.rby)>>1);
1457 } else {
1458 GridXY(end_x, end_y, &grid_x, &grid_y);
1459 }
1460 #ifdef _NOT_DEFINED
1461 /*
1462 * drawPolyToConnectPins is only set to > 0 in "pin.c"
1463 * what's in "pin.c" is not used at this time
1464 */
1465 } else if (drawPolyToConnectPins > 0) {
1466 HandlePinHighlights(end_x, end_y);
1467 if (drawPolyHighlightedNode != NULL) {
1468 grid_x = OFFSET_X((drawPolyHighlightedNode->obbox.ltx +
1469 drawPolyHighlightedNode->obbox.rbx)>>1);
1470 grid_y = OFFSET_Y((drawPolyHighlightedNode->obbox.lty +
1471 drawPolyHighlightedNode->obbox.rby)>>1);
1472 } else {
1473 GridXY(end_x, end_y, &grid_x, &grid_y);
1474 }
1475 #endif /* _NOT_DEFINED */
1476 } else {
1477 GridXY(end_x, end_y, &grid_x, &grid_y);
1478 }
1479 MarkRulers(grid_x, grid_y);
1480 if (curSpline != LT_STRAIGHT && curSpline != LT_STRUCT_SPLINE) {
1481 if (sv != NULL) {
1482 free(sv);
1483 sv = NULL;
1484 }
1485 v[n-1].x = v[n].x = ABS_X(grid_x);
1486 v[n-1].y = v[n].y = ABS_Y(grid_y);
1487 switch (curSpline) {
1488 case LT_SPLINE:
1489 sv = MakeSplinePolyVertex(0, curSpline, &sn, drawOrigX,
1490 drawOrigY, n, v);
1491 break;
1492 case LT_INTSPLINE:
1493 free(cntrlv);
1494 sv = MakeIntSplinePolyVertex(&sn, &intn, &cntrlv,
1495 drawOrigX, drawOrigY, n, v);
1496 for (i=0; i < sn; i++) {
1497 if (sv[i].x < ltx) ltx = sv[i].x;
1498 if (sv[i].y < lty) lty = sv[i].y;
1499 if (sv[i].x > rbx) rbx = sv[i].x;
1500 if (sv[i].y > rby) rby = sv[i].y;
1501 }
1502 break;
1503 }
1504 MyDrawLines(mainDisplay, drawWindow, drawGC, sv, sn);
1505 } else if (curSpline == LT_STRUCT_SPLINE) {
1506 if (sv != NULL) {
1507 free(sv);
1508 sv = NULL;
1509 }
1510 if (ipt_prev.later_valid) {
1511 v[0].x = ABS_X(OrigX);
1512 v[0].y = ABS_Y(OrigY);
1513 v[1].x = ABS_X(ipt_prev.later_smooth_pt.x);
1514 v[1].y = ABS_Y(ipt_prev.later_smooth_pt.y);
1515 v[2].x = v[3].x = ABS_X(grid_x);
1516 v[2].y = v[3].y = ABS_Y(grid_y);
1517 n = 3;
1518 sv = MakeSplinePolyVertex(0, curSpline, &sn, drawOrigX,
1519 drawOrigY, n, v);
1520 MyDrawLines(mainDisplay, drawWindow, drawGC, sv, sn);
1521 } else {
1522 XDrawLine(mainDisplay, drawWindow, drawGC, OrigX, OrigY,
1523 grid_x, grid_y);
1524 if (sv != NULL) {
1525 free(sv);
1526 sv = NULL;
1527 }
1528 }
1529 } else {
1530 XDrawLine(mainDisplay, drawWindow, drawGC, OrigX, OrigY,
1531 grid_x, grid_y);
1532 }
1533 }
1534 DoPolyMeasureCursor(&pmci, POLY_DOSHOW, num_pts, ABS_X(grid_x),
1535 ABS_Y(grid_y), ABS_SIZE(abs(grid_x-OrigX)),
1536 ABS_SIZE(abs(grid_y-OrigY)), POLY_DRAW, POLY_DRAG);
1537 while (XCheckMaskEvent(mainDisplay, PointerMotionMask, &ev)) ;
1538 } else if (input.type == ButtonPress && curChoice != FREEHAND) {
1539 /* erase */
1540 DoPolyMeasureCursor(&pmci, POLY_ENDSHOW, num_pts, ABS_X(grid_x),
1541 ABS_Y(grid_y), ABS_SIZE(abs(grid_x-OrigX)),
1542 ABS_SIZE(abs(grid_y-OrigY)), POLY_ERASE, POLY_DRAG);
1543
1544 button_ev = &(input.xbutton);
1545
1546 end_x = button_ev->x;
1547 end_y = button_ev->y;
1548 if (shiftForDiagMouseMove && DiagEventCheck(&input)) {
1549 DiagGridXY(OrigX, OrigY, &end_x, &end_y);
1550 }
1551 if (drawPolyHighlightedNode != NULL) {
1552 grid_x = OFFSET_X((drawPolyHighlightedNode->obbox.ltx +
1553 drawPolyHighlightedNode->obbox.rbx)>>1);
1554 grid_y = OFFSET_Y((drawPolyHighlightedNode->obbox.lty +
1555 drawPolyHighlightedNode->obbox.rby)>>1);
1556 } else {
1557 GridXY(end_x, end_y, &grid_x, &grid_y);
1558 }
1559 if (grid_x == last_x && grid_y == last_y) {
1560 if (curSpline == LT_STRUCT_SPLINE) {
1561 if (num_pts == 1) {
1562 abort = TRUE;
1563 } else {
1564 /* need to overwrite the previous point */
1565
1566 /* erase */
1567 if (sv != NULL) {
1568 MyDrawLines(mainDisplay, drawWindow, drawGC, sv, sn);
1569 free(sv);
1570 sv = NULL;
1571 } else {
1572 XDrawLine(mainDisplay, drawWindow, drawGC, OrigX, OrigY,
1573 grid_x, grid_y);
1574 }
1575 if (ipt_prev.later_valid) {
1576 /* erase whole curve */
1577 DrawAllStructSplinePointsForCont(num_pts);
1578 ipt_prev.earlier_valid = ipt_prev.later_valid = FALSE;
1579 ipt_prev.earlier_smooth_pt.x = ipt_prev.later_smooth_pt.x =
1580 ipt_prev.hinge_pt.x;
1581 ipt_prev.earlier_smooth_pt.y = ipt_prev.later_smooth_pt.y =
1582 ipt_prev.hinge_pt.y;
1583 UpdateLastPointForCont(&ipt_prev);
1584 /* draw whole curve */
1585 DrawAllStructSplinePointsForCont(num_pts);
1586 }
1587 UpdatePrevToLastPointForCont(&ipt_prev);
1588 ipt.earlier_valid = ipt.later_valid = FALSE;
1589 ipt.earlier_smooth_pt.x = ipt.later_smooth_pt.x =
1590 ipt.hinge_pt.x = grid_x;
1591 ipt.earlier_smooth_pt.y = ipt.later_smooth_pt.y =
1592 ipt.hinge_pt.y = grid_y;
1593 OrigX = ipt_prev.hinge_pt.x;
1594 OrigY = ipt_prev.hinge_pt.y;
1595 if (ipt_prev.later_valid) {
1596 v[0].x = ABS_X(OrigX);
1597 v[0].y = ABS_Y(OrigY);
1598 v[1].x = ABS_X(ipt_prev.later_smooth_pt.x);
1599 v[1].y = ABS_Y(ipt_prev.later_smooth_pt.y);
1600 v[2].x = v[3].x = ABS_X(grid_x);
1601 v[2].y = v[3].y = ABS_Y(grid_y);
1602 n = 3;
1603 sv = MakeSplinePolyVertex(0, curSpline, &sn, drawOrigX,
1604 drawOrigY, n, v);
1605 }
1606 }
1607 }
1608 } else {
1609 num_pts++;
1610 AddPointForCont(grid_x, grid_y, &ipt);
1611 last_x = grid_x;
1612 last_y = grid_y;
1613 if (curSpline != LT_STRAIGHT && curSpline != LT_STRUCT_SPLINE) {
1614 if (n >= max_n-2) {
1615 max_n += 40;
1616 v = (IntPoint*)realloc(v, sizeof(IntPoint)*max_n+1);
1617 if (v == NULL) FailAllocMessage();
1618 }
1619 /* erase */
1620 MyDrawLines(mainDisplay, drawWindow, drawGC, sv, sn);
1621 if (sv != NULL) {
1622 free(sv);
1623 sv = NULL;
1624 }
1625 v[n].x = v[n+1].x = ABS_X(grid_x);
1626 v[n].y = v[n+1].y = ABS_Y(grid_y);
1627 n++;
1628 switch (curSpline) {
1629 case LT_SPLINE:
1630 sv = MakeSplinePolyVertex(0, curSpline, &sn, drawOrigX,
1631 drawOrigY, n, v);
1632 break;
1633 case LT_INTSPLINE:
1634 if (cntrlv != NULL) free(cntrlv);
1635 sv = MakeIntSplinePolyVertex(&sn, &intn, &cntrlv,
1636 drawOrigX, drawOrigY, n, v);
1637 for (i=0; i < sn; i++) {
1638 if (sv[i].x < ltx) ltx = sv[i].x;
1639 if (sv[i].y < lty) lty = sv[i].y;
1640 if (sv[i].x > rbx) rbx = sv[i].x;
1641 if (sv[i].y > rby) rby = sv[i].y;
1642 }
1643 break;
1644 }
1645 /* draw */
1646 MyDrawLines(mainDisplay, drawWindow, drawGC, sv, sn);
1647 } else if (curSpline == LT_STRUCT_SPLINE) {
1648 /* erase */
1649 if (sv != NULL) {
1650 MyDrawLines(mainDisplay, drawWindow, drawGC, sv, sn);
1651 free(sv);
1652 sv = NULL;
1653 } else {
1654 XDrawLine(mainDisplay, drawWindow, drawGC, OrigX, OrigY,
1655 grid_x, grid_y);
1656 }
1657 /* draw */
1658 if (ipt_prev.later_valid) {
1659 v[0].x = ABS_X(OrigX);
1660 v[0].y = ABS_Y(OrigY);
1661 v[1].x = ABS_X(ipt_prev.later_smooth_pt.x);
1662 v[1].y = ABS_Y(ipt_prev.later_smooth_pt.y);
1663 v[2].x = v[3].x = ABS_X(grid_x);
1664 v[2].y = v[3].y = ABS_Y(grid_y);
1665 n = 3;
1666 sv = MakeSplinePolyVertex(0, curSpline, &sn, drawOrigX,
1667 drawOrigY, n, v);
1668 MyDrawLines(mainDisplay, drawWindow, drawGC, sv, sn);
1669 } else {
1670 XDrawLine(mainDisplay, drawWindow, drawGC, OrigX, OrigY,
1671 grid_x, grid_y);
1672 if (sv != NULL) {
1673 free(sv);
1674 sv = NULL;
1675 }
1676 }
1677 }
1678 }
1679
1680 switch (button_ev->button) {
1681 case Button1:
1682 if ((drawPolyToConnectPins > 0 &&
1683 drawPolyHighlightedNode != NULL) ||
1684 (gstWiringInfo.num_ports_to_connect > 0 &&
1685 drawPolyHighlightedNode != NULL)) {
1686 gpEndPin = drawPolyHighlightedNode;
1687 done = TRUE;
1688 } else {
1689 if (curSpline == LT_STRUCT_SPLINE) {
1690 ContinueForStructSplinePolyControlPoints(OrigX, OrigY, grid_x,
1691 grid_y, &sv, &sn, &ipt_prev, &ipt, &abort);
1692 UpdateLastPointForCont(&ipt);
1693 /* at this point, the curve has been drawn */
1694 if (sv != NULL) {
1695 free(sv);
1696 sv = NULL;
1697 }
1698 nothing_is_drawn = TRUE;
1699 if (!abort) {
1700 CVListElem *elem=ListLast(&gStructSplineList);
1701
1702 if (elem != NULL) {
1703 IntPointTriplet *pipt=(IntPointTriplet*)(elem->obj);
1704
1705 memcpy(pipt, &ipt, sizeof(IntPointTriplet));
1706 }
1707 memcpy(&ipt_prev, &ipt, sizeof(IntPointTriplet));
1708 OrigX = ipt.hinge_pt.x;
1709 OrigY = ipt.hinge_pt.y;
1710 if (ipt.later_valid) {
1711 grid_x = ipt.later_smooth_pt.x;
1712 grid_y = ipt.later_smooth_pt.y;
1713 } else {
1714 grid_x = ipt.hinge_pt.x;
1715 grid_y = ipt.hinge_pt.y;
1716 }
1717 DoPolyMeasureCursor(&pmci, POLY_STARTSHOW, num_pts,
1718 ABS_X(grid_x), ABS_Y(grid_y),
1719 ABS_SIZE(abs(grid_x-OrigX)),
1720 ABS_SIZE(abs(grid_y-OrigY)), POLY_DRAW, POLY_CLICK);
1721 }
1722 } else {
1723 OrigX = grid_x;
1724 OrigY = grid_y;
1725 /* draw */
1726 DoPolyMeasureCursor(&pmci, POLY_STARTSHOW, num_pts,
1727 ABS_X(grid_x), ABS_Y(grid_y), 0, 0, POLY_DRAW,
1728 POLY_CLICK);
1729 XDrawLine(mainDisplay, drawWindow, drawGC, OrigX, OrigY,
1730 grid_x, grid_y);
1731 }
1732 }
1733 break;
1734 case Button2:
1735 case Button3:
1736 #ifdef _NOT_DEFINED
1737 /*
1738 * drawPolyToConnectPins is only set to > 0 in "pin.c"
1739 * what's in "pin.c" is not used at this time
1740 */
1741 if (drawPolyToConnectPins > 0) {
1742 if (drawPolyHighlightedNode == NULL) {
1743 abort = TRUE;
1744 } else {
1745 gpEndPin = drawPolyHighlightedNode;
1746 }
1747 }
1748 #endif /* _NOT_DEFINED */
1749 if (curSpline == LT_STRUCT_SPLINE) {
1750 memset(&ipt, 0, sizeof(IntPointTriplet));
1751 ipt.earlier_valid = ipt.later_valid = FALSE;
1752 ipt.hinge_pt.x = ipt.earlier_smooth_pt.x =
1753 ipt.later_smooth_pt.x = grid_x;
1754 ipt.hinge_pt.y = ipt.earlier_smooth_pt.y =
1755 ipt.later_smooth_pt.y = grid_y;
1756 ipt.ratio = (double)1;
1757 ContinueForStructSplinePolyControlPoints(OrigX, OrigY, grid_x,
1758 grid_y, &sv, &sn, &ipt_prev, &ipt, &abort);
1759 UpdateLastPointForCont(&ipt);
1760 }
1761 done = TRUE;
1762 break;
1763 }
1764 } else if (input.type == ButtonRelease && curChoice == FREEHAND) {
1765 DoPolyMeasureCursor(&pmci, POLY_ENDSHOW, num_pts, ABS_X(grid_x),
1766 ABS_Y(grid_y), ABS_SIZE(abs(grid_x-OrigX)),
1767 ABS_SIZE(abs(grid_y-OrigY)), POLY_ERASE, POLY_CLICK);
1768
1769 button_ev = &(input.xbutton);
1770
1771 if (grid_x != last_x || grid_y != last_y) {
1772 num_pts++;
1773 AddPointForCont(grid_x, grid_y, &ipt);
1774 last_x = grid_x;
1775 last_y = grid_y;
1776 }
1777 done = TRUE;
1778 }
1779 }
1780 if (drawPolyHighlightedNode != NULL) {
1781 if (gstWiringInfo.num_ports_to_connect > 0) {
1782 SelBox(drawWindow, revGrayGC,
1783 OFFSET_X(drawPolyHighlightedNode->bbox.ltx)-2,
1784 OFFSET_Y(drawPolyHighlightedNode->bbox.lty)-2,
1785 OFFSET_X(drawPolyHighlightedNode->bbox.rbx)+2,
1786 OFFSET_Y(drawPolyHighlightedNode->bbox.rby)+2);
1787 #ifdef _NOT_DEFINED
1788 /*
1789 * drawPolyToConnectPins is only set to > 0 in "pin.c"
1790 * what's in "pin.c" is not used at this time
1791 */
1792 } else if (drawPolyToConnectPins > 0) {
1793 HighLightAPin(FALSE);
1794 #endif /* _NOT_DEFINED */
1795 }
1796 drawPolyHighlightedNode = NULL;
1797 } else if (!abort && gstWiringInfo.num_ports_to_connect > 0) {
1798 XBell(mainDisplay, 0);
1799 Msg("");
1800 Msg(TgLoadString(STID_TRY_AGAIN_AND_END_IN_A_PORT));
1801 abort = TRUE;
1802 }
1803 XUngrabPointer(mainDisplay, CurrentTime);
1804 if (gstWiringInfo.num_ports_to_connect > 0 || drawPolyToConnectPins > 0) {
1805 values.line_width = 1;
1806 XChangeGC(mainDisplay, revGrayGC, GCLineWidth, &values);
1807 RestoreStatusStringsFromBuf(status_buf, one_line_status);
1808 }
1809 RestoreStatusStrings();
1810 SetMouseStatus(NULL, NULL, NULL);
1811 if (!abort) Msg("");
1812
1813 values.join_style = JoinMiter;
1814 XChangeGC(mainDisplay, drawGC, GCJoinStyle, &values);
1815
1816 if (v != NULL) free(v);
1817 if (sv != NULL) free(sv);
1818 if (cntrlv != NULL) free(cntrlv);
1819 if (curChoice == FREEHAND && freehand_vs != NULL) {
1820 free(freehand_vs);
1821 }
1822 if (!abort && num_pts > 1) {
1823 CreatePolyObj(num_pts, CREATE_RELATIVE);
1824 RecordNewObjCmd();
1825 RedrawAnArea(botObj, topObj->bbox.ltx-GRID_ABS_SIZE(1),
1826 topObj->bbox.lty-GRID_ABS_SIZE(1),
1827 topObj->bbox.rbx+GRID_ABS_SIZE(1),
1828 topObj->bbox.rby+GRID_ABS_SIZE(1));
1829 polyDrawn = TRUE;
1830 SetFileModified(TRUE);
1831 } else {
1832 if (curSpline != LT_INTSPLINE) {
1833 ltx = rbx = grid_x;
1834 lty = rby = grid_y;
1835 }
1836 FreePointsForCont(<x, <y, &rbx, &rby);
1837 RedrawAnArea(botObj, ABS_X(ltx)-GRID_ABS_SIZE(1),
1838 ABS_Y(lty)-GRID_ABS_SIZE(1), ABS_X(rbx)+GRID_ABS_SIZE(1),
1839 ABS_Y(rby)+GRID_ABS_SIZE(1));
1840 numPtsInPoly = 0;
1841 lastPtPtr = NULL;
1842 polyDrawn = FALSE;
1843 }
1844 if (gstWiringInfo.num_ports_to_connect == 2 && !polyDrawn) {
1845 gstWiringInfo.num_ports_to_connect = (-1);
1846 }
1847 #ifdef _NOT_DEFINED
1848 /*
1849 * drawPolyToConnectPins is only set to > 0 in "pin.c"
1850 * what's in "pin.c" is not used at this time
1851 */
1852 if (drawPolyToConnectPins == 2 && !polyDrawn) {
1853 drawPolyToConnectPins = (-1);
1854 }
1855 #endif /* _NOT_DEFINED */
1856 }
1857
DrawPoly(input)1858 void DrawPoly(input)
1859 XEvent *input;
1860 {
1861 int mouse_x, mouse_y, grid_x, grid_y;
1862 XButtonEvent *button_ev;
1863
1864 if (input->type == KeyPress && curChoice == DRAWPOLY &&
1865 gstWiringInfo.num_ports_to_connect > 0) {
1866 if (KeyPressEventIsEscape(&input->xkey)) {
1867 HandlePressForPortInDrawWindow(TRUE);
1868 }
1869 return;
1870 }
1871 if (input->type != ButtonPress) return;
1872
1873 button_ev = &(input->xbutton);
1874 if (button_ev->button == Button1) {
1875 int saved_cur_spline=curSpline;
1876
1877 mouse_x = input->xbutton.x;
1878 mouse_y = input->xbutton.y;
1879 if (gstWiringInfo.num_ports_to_connect > 0 || drawPolyToConnectPins > 0 ||
1880 curChoice == FREEHAND) {
1881 if (drawPolyHighlightedNode != NULL) {
1882 grid_x = OFFSET_X((drawPolyHighlightedNode->obbox.ltx +
1883 drawPolyHighlightedNode->obbox.rbx)>>1);
1884 grid_y = OFFSET_Y((drawPolyHighlightedNode->obbox.lty +
1885 drawPolyHighlightedNode->obbox.rby)>>1);
1886 if (gstWiringInfo.num_ports_to_connect > 0 ||
1887 curChoice == FREEHAND) {
1888 HandlePressForPortInDrawWindow(FALSE);
1889 #ifdef _NOT_DEFINED
1890 /*
1891 * drawPolyToConnectPins is only set to > 0 in "pin.c"
1892 * what's in "pin.c" is not used at this time
1893 */
1894 } else if (drawPolyToConnectPins > 0) {
1895 HighLightAPin(TRUE);
1896 #endif /* _NOT_DEFINED */
1897 }
1898 drawPolyHighlightedNode = NULL;
1899 } else if (gstWiringInfo.num_ports_to_connect > 0 ||
1900 drawPolyToConnectPins > 0) {
1901 XBell(mainDisplay, 0);
1902 SetStringStatus(TgLoadString(STID_TRY_AGAIN_AND_CLICK_IN_A_PORT));
1903 return;
1904 } else {
1905 grid_x = mouse_x;
1906 grid_y = mouse_y;
1907 }
1908 } else {
1909 GridXY(mouse_x, mouse_y, &grid_x, &grid_y);
1910 }
1911 if (curChoice == FREEHAND) curSpline = LT_STRAIGHT;
1912
1913 ContinuePoly(grid_x, grid_y);
1914
1915 if (curChoice == FREEHAND) curSpline = saved_cur_spline;
1916 }
1917 }
1918
SetWiringNodeInfo(port_obj,port_owner_obj,port_name,first)1919 void SetWiringNodeInfo(port_obj, port_owner_obj, port_name, first)
1920 struct ObjRec *port_obj, *port_owner_obj;
1921 char *port_name;
1922 int first;
1923 {
1924 if (first) {
1925 gstWiringInfo.first_port_obj = port_obj;
1926 gstWiringInfo.first_port_owner_obj = port_owner_obj;
1927 if (port_name == NULL) {
1928 *gstWiringInfo.first_port_name = '\0';
1929 } else {
1930 UtilStrCpyN(gstWiringInfo.first_port_name,
1931 sizeof(gstWiringInfo.first_port_name), port_name);
1932 }
1933 } else {
1934 gstWiringInfo.last_port_obj = port_obj;
1935 gstWiringInfo.last_port_owner_obj = port_owner_obj;
1936 if (port_name == NULL) {
1937 *gstWiringInfo.last_port_name = '\0';
1938 } else {
1939 UtilStrCpyN(gstWiringInfo.last_port_name,
1940 sizeof(gstWiringInfo.last_port_name), port_name);
1941 }
1942 }
1943 }
1944
ResetWiringNodeInfo()1945 void ResetWiringNodeInfo()
1946 {
1947 memset(&gstWiringInfo, 0, sizeof(WiringInfo));
1948 }
1949
InputPolyPts()1950 void InputPolyPts()
1951 {
1952 char inbuf[MAXSTRING+1];
1953 int more_poly=FALSE, num_polys=0;
1954 int started_composite=FALSE;
1955 struct ObjRec *saved_top_obj=topObj;
1956
1957 MakeQuiescent();
1958 XSync(mainDisplay, False);
1959 do {
1960 int len, ok=TRUE, num_pts=0, eof=TRUE;
1961 struct PtRec *pt_ptr;
1962
1963 more_poly = FALSE;
1964 numPtsInPoly = 0;
1965 lastPtPtr = NULL;
1966 printf("%s\n", TgLoadString(STID_INPUT_PAIRS_OF_POINTS_POLY));
1967 printf("> ");
1968 fflush(stdout);
1969 while (ok && fgets(inbuf, MAXSTRING, stdin) != NULL) {
1970 if (strcmp(inbuf, ";\n") == 0) {
1971 more_poly = TRUE;
1972 eof = FALSE;
1973 break;
1974 }
1975 if (strcmp(inbuf, ".\n") == 0) {
1976 eof = FALSE;
1977 break;
1978 }
1979 len = strlen(inbuf);
1980 if (len > 0) {
1981 char *c_ptr=strtok(inbuf," ,\t\n"), *c_ptr1=NULL;
1982
1983 if (c_ptr != NULL) {
1984 c_ptr1 = strtok(NULL," ,\t\n");
1985 }
1986 if (c_ptr1 != NULL) {
1987 while (strchr(" ,\t\n", *c_ptr1)) c_ptr1++;
1988 }
1989 while (c_ptr != NULL && c_ptr1 != NULL) {
1990 num_pts++;
1991 pt_ptr = (struct PtRec *)malloc(sizeof(struct PtRec));
1992 if (pt_ptr == NULL) FailAllocMessage();
1993 pt_ptr->next = lastPtPtr;
1994 if (sscanf(c_ptr, "%d", &pt_ptr->x) != 1 ||
1995 sscanf(c_ptr1, "%d", &pt_ptr->y) != 1) {
1996 ok = FALSE;
1997 MsgBox(TgLoadString(STID_READ_INT_ERROR_FOR_POLY_PTS),
1998 TOOL_NAME, INFO_MB);
1999 XSync(mainDisplay, False);
2000 break;
2001 }
2002 lastPtPtr = pt_ptr;
2003 c_ptr = strtok(NULL," ,\t\n");
2004 if (c_ptr != NULL) {
2005 c_ptr1 = strtok(NULL," ,\t\n");
2006 }
2007 if (c_ptr1 != NULL) {
2008 while (strchr(" ,\t\n", *c_ptr1)) c_ptr1++;
2009 }
2010 }
2011 if (c_ptr != NULL) {
2012 ok = FALSE;
2013 MsgBox(TgLoadString(STID_READ_INT_ERROR_FOR_POLY_PTS), TOOL_NAME,
2014 INFO_MB);
2015 XSync(mainDisplay, False);
2016 }
2017 }
2018 printf("> ");
2019 fflush(stdout);
2020 }
2021 printf("\n");
2022 if (eof) rewind(stdin);
2023 if (ok && num_pts > 1) {
2024 num_polys++;
2025 CreatePolyObj(num_pts, CREATE_ABSOLUTE);
2026 if (more_poly || num_polys > 1) {
2027 if (num_polys <= 1) {
2028 StartCompositeCmd();
2029 started_composite = TRUE;
2030 }
2031 RecordNewObjCmd();
2032 numRedrawBBox = 0;
2033 topObj->tmp_parent = NULL;
2034 DrawObj(drawWindow, topObj);
2035 } else {
2036 RecordNewObjCmd();
2037 RedrawAnArea(botObj, topObj->bbox.ltx-GRID_ABS_SIZE(1),
2038 topObj->bbox.lty-GRID_ABS_SIZE(1),
2039 topObj->bbox.rbx+GRID_ABS_SIZE(1),
2040 topObj->bbox.rby+GRID_ABS_SIZE(1));
2041 SelectTopObj();
2042 SetFileModified(TRUE);
2043 justDupped = FALSE;
2044 }
2045 }
2046 if (ok && num_pts <= 1) {
2047 MsgBox(TgLoadString(STID_TOO_FEW_POINTERS_ENTERED), TOOL_NAME,
2048 INFO_MB);
2049 XSync(mainDisplay, False);
2050 }
2051 for ( ; lastPtPtr != NULL; lastPtPtr=pt_ptr) {
2052 pt_ptr = lastPtPtr->next;
2053 free(pt_ptr);
2054 }
2055 } while (more_poly);
2056 if (num_polys > 1 || started_composite) {
2057 SelectAndHighLightNewObjects(saved_top_obj);
2058 GroupSelObj(TRUE, TRUE, TRUE);
2059 EndCompositeCmd();
2060
2061 SetFileModified(TRUE);
2062 justDupped = FALSE;
2063 }
2064 }
2065
2066 /* --------------------- JoinPoly() --------------------- */
2067
2068 static
FinishJoinPoly(obj_ptr1,obj_ptr2,poly_ptr1,vs,smooth,num_pts)2069 void FinishJoinPoly(obj_ptr1, obj_ptr2, poly_ptr1, vs, smooth, num_pts)
2070 struct ObjRec *obj_ptr1, *obj_ptr2;
2071 struct PolyRec *poly_ptr1;
2072 IntPoint *vs;
2073 char *smooth;
2074 int num_pts;
2075 {
2076 struct SelRec *sel_ptr, *top_sel=NULL, *bot_sel=NULL;
2077 int x0=0, y0=0, index0=0;
2078
2079 if (curChoice == VERTEXMODE) {
2080 if (topVSel->obj == obj_ptr1) {
2081 index0 = topVSel->v_index[0];
2082 x0 = topVSel->x[0];
2083 y0 = topVSel->y[0];
2084 } else {
2085 index0 = botVSel->v_index[0];
2086 x0 = botVSel->x[0];
2087 y0 = botVSel->y[0];
2088 }
2089 }
2090 RemoveAllSel();
2091 if (obj_ptr2->fattr != NULL) {
2092 int count=0;
2093 struct SelRec *next_sel;
2094
2095 PrepareToReplaceAnObj(obj_ptr2);
2096 DetachAllObjAttrs(obj_ptr2, &top_sel, &bot_sel);
2097 /* obj_ptr2 is pointed to by bot_sel now */
2098 AdjObjBBox(obj_ptr2);
2099 for (sel_ptr=top_sel; sel_ptr != NULL; sel_ptr=sel_ptr->next) count++;
2100 RecordCmd(CMD_ONE_TO_MANY, NULL, top_sel, bot_sel, count);
2101 sel_ptr = bot_sel;
2102 bot_sel = bot_sel->prev;
2103 bot_sel->next = NULL;
2104 free(sel_ptr);
2105 if (curChoice == VERTEXMODE) {
2106 for (sel_ptr=top_sel; sel_ptr != NULL; sel_ptr=next_sel) {
2107 next_sel = sel_ptr->next;
2108 free(sel_ptr);
2109 }
2110 top_sel = bot_sel = NULL;
2111 }
2112 }
2113 sel_ptr = (struct SelRec *)malloc(sizeof(struct SelRec));
2114 if (sel_ptr == NULL) FailAllocMessage();
2115 sel_ptr->next = sel_ptr->prev = NULL;
2116 sel_ptr->obj = obj_ptr2;
2117 PrepareToRecord(CMD_DELETE, sel_ptr, sel_ptr, 1);
2118 UnlinkObj(obj_ptr2);
2119 FreeObj(obj_ptr2);
2120 RecordCmd(CMD_DELETE, NULL, NULL, NULL, 0);
2121 free(sel_ptr);
2122
2123 PrepareToReplaceAnObj(obj_ptr1);
2124
2125 if (poly_ptr1->vlist != NULL) free(poly_ptr1->vlist);
2126 if (poly_ptr1->svlist != NULL) free(poly_ptr1->svlist);
2127 if (poly_ptr1->asvlist != NULL) free(poly_ptr1->asvlist);
2128 if (poly_ptr1->smooth != NULL) free(poly_ptr1->smooth);
2129 if (poly_ptr1->intvlist != NULL) free(poly_ptr1->intvlist);
2130 if (poly_ptr1->rotated_vlist != NULL) free(poly_ptr1->rotated_vlist);
2131 if (poly_ptr1->rotated_asvlist != NULL) free(poly_ptr1->rotated_asvlist);
2132 poly_ptr1->smooth = smooth;
2133 poly_ptr1->vlist = poly_ptr1->intvlist = NULL;
2134 poly_ptr1->n = poly_ptr1->intn = 0;
2135 poly_ptr1->svlist = poly_ptr1->asvlist = poly_ptr1->rotated_vlist =
2136 poly_ptr1->rotated_asvlist = NULL;
2137 poly_ptr1->sn = poly_ptr1->asn = poly_ptr1->rotated_n =
2138 poly_ptr1->rotated_asn = 0;
2139 if (obj_ptr1->ctm != NULL) free(obj_ptr1->ctm);
2140 obj_ptr1->ctm = NULL;
2141
2142 poly_ptr1->vlist = vs;
2143 poly_ptr1->n = num_pts;
2144
2145 AdjObjSplineVs(obj_ptr1);
2146 if (poly_ptr1->curved != LT_INTSPLINE) {
2147 UpdPolyBBox(obj_ptr1, poly_ptr1->n, poly_ptr1->vlist);
2148 } else {
2149 UpdPolyBBox(obj_ptr1, poly_ptr1->intn, poly_ptr1->intvlist);
2150 }
2151 AdjObjBBox(obj_ptr1);
2152 RecordReplaceAnObj(obj_ptr1);
2153
2154 topSel = (struct SelRec *)malloc(sizeof(struct SelRec));
2155 if (topSel == NULL) FailAllocMessage();
2156 topSel->obj = obj_ptr1;
2157 topSel->prev = NULL;
2158 topSel->next = top_sel;
2159 if (top_sel != NULL) {
2160 top_sel->prev = topSel;
2161 botSel = bot_sel;
2162 } else {
2163 botSel = topSel;
2164 }
2165 if (curChoice == VERTEXMODE) {
2166 topVSel = botVSel = (struct VSelRec *)malloc(sizeof(struct VSelRec));
2167 if (topVSel == NULL) FailAllocMessage();
2168 memset(topVSel, 0, sizeof(struct VSelRec));
2169 topVSel->obj = obj_ptr1;
2170 topVSel->max_v = 10;
2171 topVSel->v_index = (int*)malloc(10*sizeof(int));
2172 topVSel->x = (int*)malloc(10*sizeof(int));
2173 topVSel->y = (int*)malloc(10*sizeof(int));
2174 if (topVSel->v_index==NULL || topVSel->x==NULL || topVSel->y==NULL) {
2175 FailAllocMessage();
2176 }
2177 topVSel->v_index[0] = index0;
2178 topVSel->x[0] = x0;
2179 topVSel->y[0] = y0;
2180 topVSel->n = 1;
2181 topVSel->next = topVSel->prev = NULL;
2182 }
2183 }
2184
2185 typedef struct tagJoinStructSplineInfo {
2186 StretchStructuredSplineInfo sssi1, sssi2;
2187 } JoinStructSplineInfo;
2188
2189 static
DoJoinPoly(obj_ptr1,obj_ptr2,poly_ptr1,poly_ptr2,min_index,coincide,pjssi)2190 void DoJoinPoly(obj_ptr1, obj_ptr2, poly_ptr1, poly_ptr2, min_index, coincide,
2191 pjssi)
2192 struct ObjRec *obj_ptr1, *obj_ptr2;
2193 struct PolyRec *poly_ptr1, *poly_ptr2;
2194 int min_index, coincide;
2195 JoinStructSplineInfo *pjssi;
2196 /*
2197 * min_index==0: join point 0 of poly_ptr1 and point 0 of poly_ptr2
2198 * min_index==1: join point 0 of poly_ptr1 and point n-1 of poly_ptr2
2199 * min_index==2: join point n-1 of poly_ptr1 and point 0 of poly_ptr2
2200 * min_index==3: join point n-1 of poly_ptr1 and point n-1 of poly_ptr2
2201 */
2202 {
2203 int i, n, n1=poly_ptr1->n, n2=poly_ptr2->n, num_pts, ltx, lty, rbx, rby;
2204 int min_val=0, max_val=0, inc=0, curved=poly_ptr1->curved;
2205 IntPoint *vlist1=poly_ptr1->vlist, *vlist2=poly_ptr2->vlist;
2206 IntPoint *new_vs=NULL, tmp_p;
2207 char *new_smooth=NULL;
2208
2209 if (pjssi != NULL) {
2210 if (coincide) {
2211 num_pts = n1+n2-1;
2212 } else {
2213 num_pts = n1+n2+2;
2214 }
2215 } else {
2216 num_pts = n1+n2;
2217 if (coincide) {
2218 num_pts = n1+n2-1;
2219 } else {
2220 num_pts = n1+n2;
2221 }
2222 }
2223 new_vs = (IntPoint*)malloc((num_pts+1)*sizeof(IntPoint));
2224 if (new_vs == NULL) FailAllocMessage();
2225 if (curved == LT_STRUCT_SPLINE) {
2226 IntPoint tmp_p1, tmp_p2;
2227 int fix_v1_of_vlist2=FALSE, fix_vn2_minus_2_of_vlist2=FALSE;
2228
2229 switch (min_index) {
2230 case 0: min_val=n1-1; max_val=0; inc=(-1); break;
2231 case 1: min_val=n1-1; max_val=0; inc=(-1); break;
2232 case 2: min_val=0; max_val=n1; inc=1; break;
2233 case 3: min_val=0; max_val=n1; inc=1; break;
2234 }
2235 n = 0;
2236 i = min_val;
2237 while (inc > 0 ? i < max_val : i >= max_val) {
2238 if (obj_ptr1->ctm == NULL) {
2239 memcpy(&new_vs[n], &vlist1[i], sizeof(IntPoint));
2240 } else {
2241 TransformObjectV(obj_ptr1, &vlist1[i], &tmp_p);
2242 memcpy(&new_vs[n], &tmp_p, sizeof(IntPoint));
2243 }
2244 n++;
2245 i += inc;
2246 }
2247 if (coincide) {
2248 int has_smooth_1=FALSE, has_smooth_2=FALSE;
2249
2250 switch (min_index) {
2251 case 0: /* join pt 0 of poly1 and pt 0 of poly2 */
2252 has_smooth_1 = pjssi->sssi1.ipt.later_valid;
2253 has_smooth_2 = pjssi->sssi2.ipt.later_valid;
2254 break;
2255 case 1: /* join pt 0 of poly1 and pt n-1 of poly2 */
2256 has_smooth_1 = pjssi->sssi1.ipt.later_valid;
2257 has_smooth_2 = pjssi->sssi2.ipt.earlier_valid;
2258 break;
2259 case 2: /* join pt n-1 of poly1 and pt 0 of poly2 */
2260 has_smooth_1 = pjssi->sssi1.ipt.earlier_valid;
2261 has_smooth_2 = pjssi->sssi2.ipt.later_valid;
2262 break;
2263 case 3: /* join pt n-1 of poly1 and pt n-1 of poly2 */
2264 has_smooth_1 = pjssi->sssi1.ipt.earlier_valid;
2265 has_smooth_2 = pjssi->sssi2.ipt.earlier_valid;
2266 break;
2267 }
2268 if (has_smooth_1) {
2269 /* first point has a corresponding smooth point */
2270 if (has_smooth_2) {
2271 /* last point has a corresponding smooth point */
2272 switch (min_index) {
2273 case 0: /* join pt 0 of poly1 and pt 0 of poly2 */
2274 case 2: /* join pt n-1 of poly1 and pt 0 of poly2 */
2275 if (obj_ptr2->ctm == NULL) {
2276 new_vs[n-2].x = (vlist2[0].x<<1) - vlist2[1].x;
2277 new_vs[n-2].y = (vlist2[0].y<<1) - vlist2[1].y;
2278 } else {
2279 TransformObjectV(obj_ptr2, &vlist2[0], &tmp_p1);
2280 TransformObjectV(obj_ptr2, &vlist2[1], &tmp_p2);
2281 new_vs[n-2].x = (tmp_p1.x<<1) - tmp_p2.x;
2282 new_vs[n-2].y = (tmp_p1.y<<1) - tmp_p2.y;
2283 }
2284 break;
2285 case 1: /* join pt 0 of poly1 and pt n-1 of poly2 */
2286 case 3: /* join pt n-1 of poly1 and pt n-1 of poly2 */
2287 if (obj_ptr2->ctm == NULL) {
2288 new_vs[n-2].x = (vlist2[n2-1].x<<1) - vlist2[n2-2].x;
2289 new_vs[n-2].y = (vlist2[n2-1].y<<1) - vlist2[n2-2].y;
2290 } else {
2291 TransformObjectV(obj_ptr2, &vlist2[n2-1], &tmp_p1);
2292 TransformObjectV(obj_ptr2, &vlist2[n2-2], &tmp_p2);
2293 new_vs[n-2].x = (tmp_p1.x<<1) - tmp_p2.x;
2294 new_vs[n-2].y = (tmp_p1.y<<1) - tmp_p2.y;
2295 }
2296 break;
2297 }
2298 } else {
2299 /* last point does not have a corresponding smooth point */
2300 new_vs[n-2].x = new_vs[n-1].x;
2301 new_vs[n-2].y = new_vs[n-1].y;
2302 }
2303 } else {
2304 /* first point does not have a corresponding smooth point */
2305 if (has_smooth_2) {
2306 /* last point has a corresponding smooth point */
2307 switch (min_index) {
2308 case 0: /* join pt 0 of poly1 and pt 0 of poly2 */
2309 case 2: /* join pt n-1 of poly1 and pt 0 of poly2 */
2310 /*
2311 * Cannot really do the following here because it will
2312 * mess up undo. So, delay the fixing till the end.
2313 *
2314 * vlist2[1].x = vlist2[0].x;
2315 * vlist2[1].y = vlist2[0].y;
2316 */
2317 fix_v1_of_vlist2 = TRUE;
2318 break;
2319 case 1: /* join pt 0 of poly1 and pt n-1 of poly2 */
2320 case 3: /* join pt n-1 of poly1 and pt n-1 of poly2 */
2321 /*
2322 * Cannot really do the following here because it will
2323 * mess up undo. So, delay the fixing till the end.
2324 *
2325 * vlist2[n2-2].x = vlist2[n2-1].x;
2326 * vlist2[n2-2].y = vlist2[n2-1].y;
2327 */
2328 fix_vn2_minus_2_of_vlist2 = TRUE;
2329 break;
2330 }
2331 } else {
2332 /* last point does not have a corresponding smooth point */
2333 }
2334 }
2335 } else {
2336 switch (min_index) {
2337 case 0: /* join point 0 of poly_ptr1 and point 0 of poly_ptr2 */
2338 case 1: /* join point 0 of poly_ptr1 and point n-1 of poly_ptr2 */
2339 if (pjssi->sssi1.ipt.later_valid) {
2340 /* first point has a corresponding smooth point */
2341 new_vs[n].x = (new_vs[n-1].x<<1) - new_vs[n-2].x;
2342 new_vs[n].y = (new_vs[n-1].y<<1) - new_vs[n-2].y;
2343 } else {
2344 /* first point does not have a corresponding smooth point */
2345 new_vs[n].x = new_vs[n-1].x;
2346 new_vs[n].y = new_vs[n-1].y;
2347 }
2348 n++;
2349 break;
2350 case 2: /* join point n-1 of poly_ptr1 and point 0 of poly_ptr2 */
2351 case 3: /* join point n-1 of poly_ptr1 and point n-1 of poly_ptr2 */
2352 if (pjssi->sssi1.ipt.earlier_valid) {
2353 /* first point has a corresponding smooth point */
2354 new_vs[n].x = (new_vs[n-1].x<<1) - new_vs[n-2].x;
2355 new_vs[n].y = (new_vs[n-1].y<<1) - new_vs[n-2].y;
2356 } else {
2357 /* first point does not have a corresponding smooth point */
2358 new_vs[n].x = new_vs[n-1].x;
2359 new_vs[n].y = new_vs[n-1].y;
2360 }
2361 n++;
2362 break;
2363 }
2364 switch (min_index) {
2365 case 0: /* join point 0 of poly_ptr1 and point 0 of poly_ptr2 */
2366 case 2: /* join point n-1 of poly_ptr1 and point 0 of poly_ptr2 */
2367 if (pjssi->sssi2.ipt.later_valid) {
2368 /* last point has a corresponding smooth point */
2369 if (obj_ptr2->ctm == NULL) {
2370 new_vs[n].x = (vlist2[0].x<<1) - vlist2[1].x;
2371 new_vs[n].y = (vlist2[0].y<<1) - vlist2[1].y;
2372 } else {
2373 TransformObjectV(obj_ptr2, &vlist2[0], &tmp_p1);
2374 TransformObjectV(obj_ptr2, &vlist2[1], &tmp_p2);
2375 new_vs[n].x = (tmp_p1.x<<1) - tmp_p2.x;
2376 new_vs[n].y = (tmp_p1.y<<1) - tmp_p2.y;
2377 }
2378 } else {
2379 /* last point does not have a corresponding smooth point */
2380 if (obj_ptr2->ctm == NULL) {
2381 new_vs[n].x = vlist2[0].x;
2382 new_vs[n].y = vlist2[0].y;
2383 } else {
2384 TransformObjectV(obj_ptr2, &vlist2[0], &tmp_p);
2385 new_vs[n].x = tmp_p.x;
2386 new_vs[n].y = tmp_p.y;
2387 }
2388 }
2389 n++;
2390 break;
2391 case 1: /* join point 0 of poly_ptr1 and point n-1 of poly_ptr2 */
2392 case 3: /* join point n-1 of poly_ptr1 and point n-1 of poly_ptr2 */
2393 if (pjssi->sssi2.ipt.earlier_valid) {
2394 /* last point has a corresponding smooth point */
2395 if (obj_ptr2->ctm == NULL) {
2396 new_vs[n].x = (vlist2[n2-1].x<<1) - vlist2[n2-2].x;
2397 new_vs[n].y = (vlist2[n2-1].y<<1) - vlist2[n2-2].y;
2398 } else {
2399 TransformObjectV(obj_ptr2, &vlist2[n2-1], &tmp_p1);
2400 TransformObjectV(obj_ptr2, &vlist2[n2-2], &tmp_p2);
2401 new_vs[n].x = (tmp_p1.x<<1) - tmp_p2.x;
2402 new_vs[n].y = (tmp_p1.y<<1) - tmp_p2.y;
2403 }
2404 } else {
2405 /* last point does not have a corresponding smooth point */
2406 if (obj_ptr2->ctm == NULL) {
2407 new_vs[n].x = vlist2[n2-1].x;
2408 new_vs[n].y = vlist2[n2-1].y;
2409 } else {
2410 TransformObjectV(obj_ptr2, &vlist2[n2-1], &tmp_p);
2411 new_vs[n].x = tmp_p.x;
2412 new_vs[n].y = tmp_p.y;
2413 }
2414 }
2415 n++;
2416 break;
2417 }
2418 }
2419 if (coincide) {
2420 switch (min_index) {
2421 case 0: min_val=1; max_val=n2; inc=1; break;
2422 case 1: min_val=n2-2; max_val=0; inc=(-1); break;
2423 case 2: min_val=1; max_val=n2; inc=1; break;
2424 case 3: min_val=n2-2; max_val=0; inc=(-1); break;
2425 }
2426 } else {
2427 switch (min_index) {
2428 case 0: min_val=0; max_val=n2; inc=1; break;
2429 case 1: min_val=n2-1; max_val=0; inc=(-1); break;
2430 case 2: min_val=0; max_val=n2; inc=1; break;
2431 case 3: min_val=n2-1; max_val=0; inc=(-1); break;
2432 }
2433 }
2434 i = min_val;
2435 while (inc > 0 ? i < max_val : i >= max_val) {
2436 if (obj_ptr2->ctm == NULL) {
2437 memcpy(&new_vs[n], &vlist2[i], sizeof(IntPoint));
2438 } else {
2439 TransformObjectV(obj_ptr2, &vlist2[i], &tmp_p);
2440 memcpy(&new_vs[n], &tmp_p, sizeof(IntPoint));
2441 }
2442 n++;
2443 i += inc;
2444 }
2445 if (fix_v1_of_vlist2 || fix_vn2_minus_2_of_vlist2) {
2446 new_vs[n1].x = new_vs[n1-1].x;
2447 new_vs[n1].y = new_vs[n1-1].y;
2448 }
2449 } else {
2450 if (curved != LT_INTSPLINE) {
2451 new_smooth = (char*)malloc((num_pts+1)*sizeof(char));
2452 if (new_smooth == NULL) FailAllocMessage();
2453 }
2454 switch (min_index) {
2455 case 0: min_val=n1-1; max_val=0; inc=(-1); break;
2456 case 1: min_val=n1-1; max_val=0; inc=(-1); break;
2457 case 2: min_val=0; max_val=n1; inc=1; break;
2458 case 3: min_val=0; max_val=n1; inc=1; break;
2459 }
2460 n = 0;
2461 i = min_val;
2462 while (inc > 0 ? i < max_val : i >= max_val) {
2463 if (obj_ptr1->ctm == NULL) {
2464 memcpy(&new_vs[n], &vlist1[i], sizeof(IntPoint));
2465 } else {
2466 TransformObjectV(obj_ptr1, &vlist1[i], &tmp_p);
2467 memcpy(&new_vs[n], &tmp_p, sizeof(IntPoint));
2468 }
2469 if (new_smooth != NULL) {
2470 new_smooth[n] = poly_ptr1->smooth[i];
2471 }
2472 n++;
2473 i += inc;
2474 }
2475 if (coincide) {
2476 switch (min_index) {
2477 case 0: min_val=1; max_val=n2; inc=1; break;
2478 case 1: min_val=n2-2; max_val=0; inc=(-1); break;
2479 case 2: min_val=1; max_val=n2; inc=1; break;
2480 case 3: min_val=n2-2; max_val=0; inc=(-1); break;
2481 }
2482 } else {
2483 switch (min_index) {
2484 case 0: min_val=0; max_val=n2; inc=1; break;
2485 case 1: min_val=n2-1; max_val=0; inc=(-1); break;
2486 case 2: min_val=0; max_val=n2; inc=1; break;
2487 case 3: min_val=n2-1; max_val=0; inc=(-1); break;
2488 }
2489 }
2490 i = min_val;
2491 while (inc > 0 ? i < max_val : i >= max_val) {
2492 if (obj_ptr2->ctm == NULL) {
2493 memcpy(&new_vs[n], &vlist2[i], sizeof(IntPoint));
2494 } else {
2495 TransformObjectV(obj_ptr2, &vlist2[i], &tmp_p);
2496 memcpy(&new_vs[n], &tmp_p, sizeof(IntPoint));
2497 }
2498 if (new_smooth != NULL) {
2499 new_smooth[n] = poly_ptr2->smooth[i];
2500 }
2501 n++;
2502 i += inc;
2503 }
2504 }
2505 ltx = selLtX; lty = selLtY; rbx = selRbX; rby = selRbY;
2506 HighLightReverse();
2507 StartCompositeCmd();
2508 FinishJoinPoly(obj_ptr1, obj_ptr2, poly_ptr1, new_vs, new_smooth, num_pts);
2509 EndCompositeCmd();
2510 UpdSelBBox();
2511 RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
2512 rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1),
2513 selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
2514 selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
2515 SetFileModified(TRUE);
2516 justDupped = FALSE;
2517 HighLightForward();
2518 }
2519
2520 static
FinishCloseOnePoly(obj_ptr,poly_ptr,vs,smooth,num_pts)2521 void FinishCloseOnePoly(obj_ptr, poly_ptr, vs, smooth, num_pts)
2522 struct ObjRec *obj_ptr;
2523 struct PolyRec *poly_ptr;
2524 IntPoint *vs;
2525 char *smooth;
2526 int num_pts;
2527 {
2528 struct PolygonRec *polygon_ptr=(struct PolygonRec *)malloc(
2529 sizeof(struct PolygonRec));
2530
2531 if (polygon_ptr == NULL) FailAllocMessage();
2532
2533 memset(polygon_ptr, 0, sizeof(struct PolygonRec));
2534 polygon_ptr->n = num_pts;
2535 polygon_ptr->vlist = vs;
2536 polygon_ptr->smooth = smooth;
2537 polygon_ptr->sn = 0;
2538 polygon_ptr->svlist = NULL;
2539 polygon_ptr->intn = 0;
2540 polygon_ptr->intvlist = NULL;
2541 polygon_ptr->fill = poly_ptr->fill;
2542 polygon_ptr->width = poly_ptr->width;
2543 UtilStrCpyN(polygon_ptr->width_spec, sizeof(polygon_ptr->width_spec),
2544 poly_ptr->width_spec);
2545 polygon_ptr->pen = poly_ptr->pen;
2546 polygon_ptr->curved = poly_ptr->curved;
2547 polygon_ptr->dash = poly_ptr->dash;
2548 polygon_ptr->rotated_n = 0;
2549 polygon_ptr->rotated_vlist = NULL;
2550
2551 PrepareToReplaceAnObj(obj_ptr);
2552
2553 if (poly_ptr->vlist != NULL) free(poly_ptr->vlist);
2554 if (poly_ptr->svlist != NULL) free(poly_ptr->svlist);
2555 if (poly_ptr->asvlist != NULL) free(poly_ptr->asvlist);
2556 if (poly_ptr->smooth != NULL) free(poly_ptr->smooth);
2557 if (poly_ptr->intvlist != NULL) free(poly_ptr->intvlist);
2558 if (poly_ptr->rotated_vlist != NULL) free(poly_ptr->rotated_vlist);
2559 if (poly_ptr->rotated_asvlist != NULL) free(poly_ptr->rotated_asvlist);
2560 free(poly_ptr);
2561
2562 obj_ptr->type = OBJ_POLYGON;
2563 obj_ptr->detail.g = polygon_ptr;
2564
2565 AdjObjSplineVs(obj_ptr);
2566 if (polygon_ptr->curved != LT_INTSPLINE) {
2567 UpdPolyBBox(obj_ptr, polygon_ptr->n, polygon_ptr->vlist);
2568 } else {
2569 UpdPolyBBox(obj_ptr, polygon_ptr->intn, polygon_ptr->intvlist);
2570 }
2571 AdjObjBBox(obj_ptr);
2572 RecordReplaceAnObj(obj_ptr);
2573 }
2574
2575 static
CloseOnePoly(obj_ptr)2576 void CloseOnePoly(obj_ptr)
2577 struct ObjRec *obj_ptr;
2578 {
2579 struct PolyRec *poly_ptr=obj_ptr->detail.p;
2580 int i, n=0, num_pts=0, ltx, lty, rbx, rby, coincide=FALSE;
2581 int curved=poly_ptr->curved;
2582 IntPoint *new_vs=NULL, *vs=NULL;
2583 char *new_smooth=NULL, *smooth=NULL;
2584 StretchStructuredSplineInfo sssi_first, sssi_last;
2585
2586 memset(&sssi_first, 0, sizeof(StretchStructuredSplineInfo));
2587 memset(&sssi_last, 0, sizeof(StretchStructuredSplineInfo));
2588
2589 if (curved == LT_STRUCT_SPLINE) {
2590 vs = poly_ptr->ssvlist;
2591 n = poly_ptr->ssn;
2592 smooth = poly_ptr->ssmooth;
2593 if (n < 3) {
2594 MsgBox(TgLoadString(STID_TOO_FEW_VER_TO_CLOSE_POLY), TOOL_NAME,
2595 INFO_MB);
2596 return;
2597 }
2598 } else {
2599 vs = poly_ptr->vlist;
2600 n = poly_ptr->n;
2601 smooth = poly_ptr->smooth;
2602 if (n <= 2) {
2603 MsgBox(TgLoadString(STID_TOO_FEW_VER_TO_CLOSE_POLY), TOOL_NAME,
2604 INFO_MB);
2605 return;
2606 }
2607 }
2608 if (vs[0].x == vs[n-1].x && vs[0].y == vs[n-1].y) {
2609 coincide = TRUE;
2610 if (curved == LT_STRUCT_SPLINE) {
2611 if (n <= 4) {
2612 MsgBox(TgLoadString(STID_TOO_FEW_VER_TO_CLOSE_POLY), TOOL_NAME,
2613 INFO_MB);
2614 return;
2615 }
2616 SetIPTInfoForStretchPoly(0, poly_ptr->n, poly_ptr->vlist, &sssi_first);
2617 SetIPTInfoForStretchPoly(n-1, poly_ptr->n, poly_ptr->vlist,
2618 &sssi_last);
2619 num_pts = poly_ptr->n;
2620 } else {
2621 num_pts = n;
2622 }
2623 } else {
2624 if (curved == LT_STRUCT_SPLINE) {
2625 SetIPTInfoForStretchPoly(0, poly_ptr->n, poly_ptr->vlist, &sssi_first);
2626 SetIPTInfoForStretchPoly(n-1, poly_ptr->n, poly_ptr->vlist,
2627 &sssi_last);
2628 num_pts = poly_ptr->n+3;
2629 } else {
2630 num_pts = n+1;
2631 }
2632 }
2633 new_vs = (IntPoint*)malloc((num_pts+1)*sizeof(IntPoint));
2634 if (new_vs == NULL) FailAllocMessage();
2635 memset(new_vs, 0, (num_pts+1)*sizeof(IntPoint));
2636
2637 if (curved == LT_STRUCT_SPLINE) {
2638 for (i=0; i < poly_ptr->n; i++) {
2639 memcpy(&new_vs[i], &poly_ptr->vlist[i], sizeof(IntPoint));
2640 }
2641 if (coincide) {
2642 if (sssi_first.ipt.later_valid) {
2643 /* first point has a corresponding smooth point */
2644 if (sssi_last.ipt.earlier_valid) {
2645 /* last point has a corresponding smooth point */
2646 /*
2647 * in this case, move the last smooth point
2648 */
2649 new_vs[poly_ptr->n-2].x = (new_vs[0].x<<1) - new_vs[1].x;
2650 new_vs[poly_ptr->n-2].y = (new_vs[0].y<<1) - new_vs[1].y;
2651 } else {
2652 /* last point does not have a corresponding smooth point */
2653 /*
2654 * in this case, remove the first smooth point
2655 */
2656 new_vs[1].x = new_vs[0].x;
2657 new_vs[1].y = new_vs[0].y;
2658 }
2659 } else {
2660 /* first point does not have a corresponding smooth point */
2661 if (sssi_last.ipt.earlier_valid) {
2662 /* last point has a corresponding smooth point */
2663 /*
2664 * in this case, remove the last smooth point
2665 */
2666 new_vs[poly_ptr->n-2].x = new_vs[poly_ptr->n-1].x;
2667 new_vs[poly_ptr->n-2].y = new_vs[poly_ptr->n-1].y;
2668 } else {
2669 /* last point does not have a corresponding smooth point */
2670 /*
2671 * in this case, there is nothing to do
2672 */
2673 }
2674 }
2675 } else {
2676 new_vs[poly_ptr->n+2].x = new_vs[0].x;
2677 new_vs[poly_ptr->n+2].y = new_vs[0].y;
2678
2679 if (sssi_first.ipt.later_valid) {
2680 /* first point has a corresponding smooth point */
2681 if (sssi_last.ipt.earlier_valid) {
2682 /* last point has a corresponding smooth point */
2683 /*
2684 * in this case, create 2 new smooth points
2685 */
2686 new_vs[poly_ptr->n+1].x = (new_vs[0].x<<1) - new_vs[1].x;
2687 new_vs[poly_ptr->n+1].y = (new_vs[0].y<<1) - new_vs[1].y;
2688 new_vs[poly_ptr->n].x = (new_vs[poly_ptr->n-1].x<<1) -
2689 new_vs[poly_ptr->n-2].x;
2690 new_vs[poly_ptr->n].y = (new_vs[poly_ptr->n-1].y<<1) -
2691 new_vs[poly_ptr->n-2].y;
2692 } else {
2693 /* last point does not have a corresponding smooth point */
2694 /*
2695 * in this case, create one new smooth point near the 1st point
2696 */
2697 new_vs[poly_ptr->n+1].x = (new_vs[0].x<<1) - new_vs[1].x;
2698 new_vs[poly_ptr->n+1].y = (new_vs[0].y<<1) - new_vs[1].y;
2699 new_vs[poly_ptr->n].x = new_vs[poly_ptr->n-1].x;
2700 new_vs[poly_ptr->n].y = new_vs[poly_ptr->n-1].y;
2701 }
2702 } else {
2703 /* first point does not have a corresponding smooth point */
2704 if (sssi_last.ipt.earlier_valid) {
2705 /* last point has a corresponding smooth point */
2706 /*
2707 * in this case, create one new smooth point near the last point
2708 */
2709 new_vs[poly_ptr->n+1].x = new_vs[0].x;
2710 new_vs[poly_ptr->n+1].y = new_vs[0].y;
2711 new_vs[poly_ptr->n].x = (new_vs[poly_ptr->n-1].x<<1) -
2712 new_vs[poly_ptr->n-2].x;
2713 new_vs[poly_ptr->n].y = (new_vs[poly_ptr->n-1].y<<1) -
2714 new_vs[poly_ptr->n-2].y;
2715 } else {
2716 /* last point does not have a corresponding smooth point */
2717 /*
2718 * in this case, create 2 hinge points
2719 */
2720 new_vs[poly_ptr->n+1].x = new_vs[0].x;
2721 new_vs[poly_ptr->n+1].y = new_vs[0].y;
2722 new_vs[poly_ptr->n].x = new_vs[poly_ptr->n-1].x;
2723 new_vs[poly_ptr->n].y = new_vs[poly_ptr->n-1].y;
2724 }
2725 }
2726 }
2727 } else {
2728 for (i=0; i < n; i++) memcpy(&new_vs[i], &vs[i], sizeof(IntPoint));
2729 memcpy(&new_vs[n], &vs[0], sizeof(IntPoint));
2730 if (poly_ptr->curved != LT_INTSPLINE) {
2731 new_smooth = (char*)malloc((num_pts+1)*sizeof(char));
2732 if (new_smooth == NULL) FailAllocMessage();
2733 for (i=0; i < n; i++) new_smooth[i] = smooth[i];
2734 new_smooth[0] = new_smooth[n] = FALSE;
2735 }
2736 }
2737 ltx = selLtX; lty = selLtY; rbx = selRbX; rby = selRbY;
2738 HighLightReverse();
2739 FinishCloseOnePoly(obj_ptr, poly_ptr, new_vs, new_smooth, num_pts);
2740 if (curChoice == VERTEXMODE) {
2741 if (topVSel == botVSel) {
2742 int x0=0, y0=0, first_index=(-1), last_index=(-1);
2743
2744 for (i=0; i < topVSel->n; i++) {
2745 if (topVSel->v_index[i] == 0) {
2746 x0 = topVSel->x[i];
2747 y0 = topVSel->y[i];
2748 first_index = i;
2749 } else if (topVSel->v_index[i] ==
2750 (coincide ? num_pts-1 : num_pts-2)) {
2751 if (!coincide) {
2752 topVSel->v_index[i]++;
2753 }
2754 last_index = i;
2755 }
2756 }
2757 if (last_index != (-1) && first_index != (-1)) {
2758 topVSel->n = 2;
2759 topVSel->x[first_index] = topVSel->x[last_index] = x0;
2760 topVSel->y[first_index] = topVSel->y[last_index] = y0;
2761 } else {
2762 fprintf(stderr, "%s\n",
2763 TgLoadString(STID_HUH_WHERE_ARE_THE_VERTICES));
2764 }
2765 } else {
2766 fprintf(stderr, "%s\n", TgLoadString(STID_HUH_TOPVSEL_NE_BOTVSEL));
2767 }
2768 }
2769 UpdSelBBox();
2770 RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
2771 rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1),
2772 selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
2773 selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
2774 SetFileModified(TRUE);
2775 justDupped = FALSE;
2776 HighLightForward();
2777 }
2778
2779 static
JoinPolyCompatCheck(poly_ptr1,poly_ptr2)2780 int JoinPolyCompatCheck(poly_ptr1, poly_ptr2)
2781 struct PolyRec *poly_ptr1, *poly_ptr2;
2782 {
2783 int rc=TRUE;
2784
2785 switch (poly_ptr1->curved) {
2786 case LT_STRAIGHT:
2787 case LT_SPLINE:
2788 if (poly_ptr2->curved == LT_STRAIGHT ||
2789 poly_ptr2->curved == LT_SPLINE) {
2790 /* compatible */
2791 } else {
2792 rc = FALSE;
2793 }
2794 break;
2795 case LT_INTSPLINE:
2796 if (poly_ptr2->curved == LT_INTSPLINE) {
2797 /* compatible */
2798 } else {
2799 rc = FALSE;
2800 }
2801 break;
2802 case LT_STRUCT_SPLINE:
2803 if (poly_ptr2->curved == LT_STRUCT_SPLINE) {
2804 /* compatible */
2805 } else {
2806 rc = FALSE;
2807 }
2808 break;
2809 }
2810 if (!rc) {
2811 MsgBox(TgLoadString(STID_SEL_2_COMPAT_END_PTS_TO_JOIN), TOOL_NAME,
2812 INFO_MB);
2813 return FALSE;
2814 }
2815 return TRUE;
2816 }
2817
JoinPoly()2818 void JoinPoly()
2819 {
2820 struct ObjRec *obj_ptr1=NULL, *obj_ptr2=NULL;
2821 struct PolyRec *poly_ptr1=NULL, *poly_ptr2=NULL;
2822 long dx=0L, dy=0L, min_lval=0L;
2823 int i=0, min_index=(-1);
2824
2825 if (curChoice != VERTEXMODE && curChoice != NOTHING) {
2826 MsgBox(TgLoadString(STID_CMD_ONLY_AVAIL_IN_VERSEL_MODE), TOOL_NAME,
2827 INFO_MB);
2828 return;
2829 }
2830 if (curChoice == VERTEXMODE) {
2831 if (CountSelectedVertices() != 2) {
2832 MsgBox(TgLoadString(STID_SEL_2_ENDPOINT_VER_TO_JOIN), TOOL_NAME,
2833 INFO_MB);
2834 return;
2835 }
2836 obj_ptr1 = topVSel->obj;
2837 obj_ptr2 = botVSel->obj;
2838 if (obj_ptr1->type != OBJ_POLY || obj_ptr2->type != OBJ_POLY) {
2839 MsgBox(TgLoadString(STID_SEL_VER_FROM_POLY_OPEN_ONLY), TOOL_NAME,
2840 INFO_MB);
2841 return;
2842 }
2843 poly_ptr1 = obj_ptr1->detail.p;
2844 for (i=0; i < topVSel->n; i++) {
2845 int index=topVSel->v_index[i];
2846
2847 if (index != 0 && index != poly_ptr1->n-1) {
2848 MsgBox(TgLoadString(STID_SEL_2_ENDPOINT_VER_TO_JOIN), TOOL_NAME,
2849 INFO_MB);
2850 return;
2851 }
2852 }
2853 if (obj_ptr1 == obj_ptr2) {
2854 CloseOnePoly(obj_ptr1);
2855 return;
2856 }
2857 poly_ptr2 = obj_ptr2->detail.p;
2858 for (i=0; i < botVSel->n; i++) {
2859 int index=botVSel->v_index[i];
2860
2861 if (index != 0 && index != poly_ptr2->n-1) {
2862 MsgBox(TgLoadString(STID_SEL_2_ENDPOINT_VER_TO_JOIN), TOOL_NAME,
2863 INFO_MB);
2864 return;
2865 }
2866 }
2867 if (!JoinPolyCompatCheck(poly_ptr1, poly_ptr2)) {
2868 return;
2869 }
2870 if (topVSel->v_index[0] == 0) {
2871 if (botVSel->v_index[0] == 0) {
2872 min_index = 0;
2873 } else {
2874 min_index = 1;
2875 }
2876 } else {
2877 if (botVSel->v_index[0] == 0) {
2878 min_index = 2;
2879 } else {
2880 min_index = 3;
2881 }
2882 }
2883 dx = topVSel->x[0] - botVSel->x[0];
2884 dy = topVSel->y[0] - botVSel->y[0];
2885 min_lval = (dx*dx)+(dy*dy);
2886 } else {
2887 IntPoint p[4], tmp_p;
2888 long d[4];
2889
2890 if (numObjSelected == 1 && topSel->obj->type == OBJ_POLY) {
2891 CloseOnePoly(topSel->obj);
2892 return;
2893 } else if (numObjSelected != 2 || topSel == NULL ||
2894 topSel->obj->type != OBJ_POLY || botSel->obj->type != OBJ_POLY) {
2895 MsgBox(TgLoadString(STID_SEL_2_POLYLINES_OPEN_SPLINES), TOOL_NAME,
2896 INFO_MB);
2897 return;
2898 }
2899 obj_ptr1 = topSel->obj;
2900 obj_ptr2 = botSel->obj;
2901 poly_ptr1 = obj_ptr1->detail.p;
2902 poly_ptr2 = obj_ptr2->detail.p;
2903
2904 if (!JoinPolyCompatCheck(poly_ptr1, poly_ptr2)) {
2905 return;
2906 }
2907 memcpy(&p[0], &poly_ptr1->vlist[0], sizeof(IntPoint));
2908 memcpy(&p[1], &poly_ptr1->vlist[poly_ptr1->n-1], sizeof(IntPoint));
2909 memcpy(&p[2], &poly_ptr2->vlist[0], sizeof(IntPoint));
2910 memcpy(&p[3], &poly_ptr2->vlist[poly_ptr2->n-1], sizeof(IntPoint));
2911 if (obj_ptr1->ctm != NULL) {
2912 TransformObjectV(obj_ptr1, &p[0], &tmp_p);
2913 memcpy(&p[0], &tmp_p, sizeof(IntPoint));
2914 TransformObjectV(obj_ptr1, &p[1], &tmp_p);
2915 memcpy(&p[1], &tmp_p, sizeof(IntPoint));
2916 }
2917 if (obj_ptr2->ctm != NULL) {
2918 TransformObjectV(obj_ptr2, &p[2], &tmp_p);
2919 memcpy(&p[2], &tmp_p, sizeof(IntPoint));
2920 TransformObjectV(obj_ptr2, &p[3], &tmp_p);
2921 memcpy(&p[3], &tmp_p, sizeof(IntPoint));
2922 }
2923 dx=(long)(p[0].x-p[2].x); dy=(long)(p[0].y-p[2].y); d[0]=dx*dx+dy*dy;
2924 dx=(long)(p[0].x-p[3].x); dy=(long)(p[0].y-p[3].y); d[1]=dx*dx+dy*dy;
2925 dx=(long)(p[1].x-p[2].x); dy=(long)(p[1].y-p[2].y); d[2]=dx*dx+dy*dy;
2926 dx=(long)(p[1].x-p[3].x); dy=(long)(p[1].y-p[3].y); d[3]=dx*dx+dy*dy;
2927 min_index = 0;
2928 min_lval = d[0];
2929 for (i=1; i < 4; i++) {
2930 if (d[i] < min_lval) {
2931 min_index = i;
2932 min_lval = d[i];
2933 }
2934 }
2935 }
2936 if (poly_ptr1->curved == LT_STRUCT_SPLINE &&
2937 poly_ptr2->curved == LT_STRUCT_SPLINE) {
2938 JoinStructSplineInfo jssi;
2939
2940 memset(&jssi, 0, sizeof(JoinStructSplineInfo));
2941 switch (min_index) {
2942 case 0:
2943 SetIPTInfoForStretchPoly(0, poly_ptr1->n, poly_ptr1->vlist,
2944 &jssi.sssi1);
2945 SetIPTInfoForStretchPoly(0, poly_ptr2->n, poly_ptr2->vlist,
2946 &jssi.sssi2);
2947 break;
2948 case 1:
2949 SetIPTInfoForStretchPoly(0, poly_ptr1->n, poly_ptr1->vlist,
2950 &jssi.sssi1);
2951 SetIPTInfoForStretchPoly(poly_ptr2->ssn-1, poly_ptr2->n,
2952 poly_ptr2->vlist, &jssi.sssi2);
2953 break;
2954 case 2:
2955 SetIPTInfoForStretchPoly(poly_ptr1->ssn-1, poly_ptr1->n,
2956 poly_ptr1->vlist, &jssi.sssi1);
2957 SetIPTInfoForStretchPoly(0, poly_ptr2->n, poly_ptr2->vlist,
2958 &jssi.sssi2);
2959 break;
2960 case 3:
2961 SetIPTInfoForStretchPoly(poly_ptr1->ssn-1, poly_ptr1->n,
2962 poly_ptr1->vlist, &jssi.sssi1);
2963 SetIPTInfoForStretchPoly(poly_ptr2->ssn-1, poly_ptr2->n,
2964 poly_ptr2->vlist, &jssi.sssi2);
2965 break;
2966 }
2967 DoJoinPoly(obj_ptr1, obj_ptr2, poly_ptr1, poly_ptr2, min_index,
2968 (min_lval==0L), &jssi);
2969 } else {
2970 DoJoinPoly(obj_ptr1, obj_ptr2, poly_ptr1, poly_ptr2, min_index,
2971 (min_lval==0L), NULL);
2972 }
2973 }
2974
2975 /* --------------------- CutPoly() --------------------- */
2976
2977 static
FinishCutPoly(obj_ptr1,poly_ptr1,vs1,smooth1,vs2,smooth2,num_pts1,num_pts2)2978 void FinishCutPoly(obj_ptr1, poly_ptr1, vs1, smooth1, vs2, smooth2,
2979 num_pts1, num_pts2)
2980 struct ObjRec *obj_ptr1;
2981 struct PolyRec *poly_ptr1;
2982 IntPoint *vs1, *vs2;
2983 char *smooth1, *smooth2;
2984 int num_pts1, num_pts2;
2985 {
2986 struct ObjRec *obj_ptr2;
2987 struct PolyRec *poly_ptr2;
2988 int x0, y0;
2989
2990 x0 = topVSel->x[0];
2991 y0 = topVSel->y[0];
2992
2993 RemoveAllSel();
2994 PrepareToReplaceAnObj(obj_ptr1);
2995
2996 obj_ptr2 = DupObj(obj_ptr1);
2997 poly_ptr2 = obj_ptr2->detail.p;
2998 DelAllAttrs(obj_ptr2->fattr);
2999 obj_ptr2->fattr = obj_ptr2->lattr = NULL;
3000
3001 if (poly_ptr1->vlist != NULL) free(poly_ptr1->vlist);
3002 if (poly_ptr1->svlist != NULL) free(poly_ptr1->svlist);
3003 if (poly_ptr1->asvlist != NULL) free(poly_ptr1->asvlist);
3004 if (poly_ptr1->smooth != NULL) free(poly_ptr1->smooth);
3005 if (poly_ptr1->intvlist != NULL) free(poly_ptr1->intvlist);
3006 if (poly_ptr1->rotated_vlist != NULL) free(poly_ptr1->rotated_vlist);
3007 if (poly_ptr1->rotated_asvlist != NULL) free(poly_ptr1->rotated_asvlist);
3008 poly_ptr1->smooth = smooth1;
3009 poly_ptr1->vlist = poly_ptr1->intvlist = NULL;
3010 poly_ptr1->n = poly_ptr1->intn = 0;
3011 poly_ptr1->svlist = poly_ptr1->asvlist = poly_ptr1->rotated_vlist =
3012 poly_ptr1->rotated_asvlist = NULL;
3013 poly_ptr1->sn = poly_ptr1->asn = poly_ptr1->rotated_n =
3014 poly_ptr1->rotated_asn = 0;
3015 if (obj_ptr1->ctm != NULL) free(obj_ptr1->ctm);
3016 obj_ptr1->ctm = NULL;
3017
3018 poly_ptr1->vlist = vs1;
3019 poly_ptr1->n = num_pts1;
3020
3021 if (poly_ptr2->vlist != NULL) free(poly_ptr2->vlist);
3022 if (poly_ptr2->svlist != NULL) free(poly_ptr2->svlist);
3023 if (poly_ptr2->asvlist != NULL) free(poly_ptr2->asvlist);
3024 if (poly_ptr2->smooth != NULL) free(poly_ptr2->smooth);
3025 if (poly_ptr2->intvlist != NULL) free(poly_ptr2->intvlist);
3026 if (poly_ptr2->rotated_vlist != NULL) free(poly_ptr2->rotated_vlist);
3027 if (poly_ptr2->rotated_asvlist != NULL) free(poly_ptr2->rotated_asvlist);
3028 poly_ptr2->smooth = smooth2;
3029 poly_ptr2->vlist = poly_ptr2->intvlist = NULL;
3030 poly_ptr2->n = poly_ptr2->intn = 0;
3031 poly_ptr2->svlist = poly_ptr2->asvlist = poly_ptr2->rotated_vlist =
3032 poly_ptr2->rotated_asvlist = NULL;
3033 poly_ptr2->sn = poly_ptr2->asn = poly_ptr2->rotated_n =
3034 poly_ptr2->rotated_asn = 0;
3035 if (obj_ptr2->ctm != NULL) free(obj_ptr2->ctm);
3036 obj_ptr2->ctm = NULL;
3037
3038 poly_ptr2->vlist = vs2;
3039 poly_ptr2->n = num_pts2;
3040
3041 AdjObjSplineVs(obj_ptr1);
3042 if (poly_ptr1->curved != LT_INTSPLINE) {
3043 UpdPolyBBox(obj_ptr1, poly_ptr1->n, poly_ptr1->vlist);
3044 } else {
3045 UpdPolyBBox(obj_ptr1, poly_ptr1->intn, poly_ptr1->intvlist);
3046 }
3047 AdjObjBBox(obj_ptr1);
3048
3049 AdjObjSplineVs(obj_ptr2);
3050 if (poly_ptr2->curved != LT_INTSPLINE) {
3051 UpdPolyBBox(obj_ptr2, poly_ptr2->n, poly_ptr2->vlist);
3052 } else {
3053 UpdPolyBBox(obj_ptr2, poly_ptr2->intn, poly_ptr2->intvlist);
3054 }
3055 AdjObjBBox(obj_ptr2);
3056 AddObj(obj_ptr1->prev, obj_ptr1, obj_ptr2);
3057
3058 topSel = (struct SelRec *)malloc(sizeof(struct SelRec));
3059 botSel = (struct SelRec *)malloc(sizeof(struct SelRec));
3060 if (topSel==NULL || botSel==NULL) FailAllocMessage();
3061 topSel->obj = obj_ptr2;
3062 botSel->obj = obj_ptr1;
3063 topSel->prev = botSel->next = NULL;
3064 topSel->next = botSel;
3065 botSel->prev = topSel;
3066
3067 RecordCmd(CMD_ONE_TO_MANY, NULL, topSel, botSel, 2);
3068
3069 topVSel = botVSel = (struct VSelRec *)malloc(sizeof(struct VSelRec));
3070 if (topVSel==NULL) FailAllocMessage();
3071 memset(topVSel, 0, sizeof(struct VSelRec));
3072 topVSel->obj = obj_ptr2;
3073 topVSel->max_v = 10;
3074 topVSel->v_index = (int*)malloc(10*sizeof(int));
3075 topVSel->x = (int*)malloc(10*sizeof(int));
3076 topVSel->y = (int*)malloc(10*sizeof(int));
3077 if (topVSel->v_index==NULL || topVSel->x==NULL || topVSel->y==NULL) {
3078 FailAllocMessage();
3079 }
3080 topVSel->v_index[0] = 0;
3081 topVSel->x[0] = x0;
3082 topVSel->y[0] = y0;
3083 topVSel->n = 1;
3084 topVSel->next = topVSel->prev = NULL;
3085 }
3086
3087 static
DoCutPoly(obj_ptr,index,poly_ptr)3088 void DoCutPoly(obj_ptr, index, poly_ptr)
3089 struct ObjRec *obj_ptr;
3090 int index;
3091 struct PolyRec *poly_ptr;
3092 {
3093 int i=0, n=poly_ptr->n, n1=0, n2=0, ltx, lty, rbx, rby;
3094 int curved=poly_ptr->curved;
3095 IntPoint *vs1=NULL, *vs2=NULL;
3096 char *smooth1=NULL, *smooth2=NULL;
3097
3098 if (curved == LT_STRUCT_SPLINE) {
3099 StretchStructuredSplineInfo sssi;
3100
3101 memset(&sssi, 0, sizeof(StretchStructuredSplineInfo));
3102 if (index == poly_ptr->ssn-1) {
3103 return;
3104 }
3105 SetIPTInfoForStretchPoly(index, poly_ptr->n, poly_ptr->vlist, &sssi);
3106 if (!sssi.hinge) {
3107 MsgBox(TgLoadString(STID_CANNOT_CUT_AT_SMOOTH_PT), TOOL_NAME, INFO_MB);
3108 return;
3109 }
3110 n1 = sssi.orig_hinge_index + 1;
3111 n2 = n - sssi.orig_hinge_index;
3112 vs1 = (IntPoint*)malloc((n1+1)*sizeof(IntPoint));
3113 vs2 = (IntPoint*)malloc((n2+1)*sizeof(IntPoint));
3114 if (vs1==NULL || vs2==NULL) FailAllocMessage();
3115
3116 for (i=0; i <= sssi.orig_hinge_index; i++) {
3117 if (obj_ptr->ctm == NULL) {
3118 memcpy(&vs1[i], &poly_ptr->vlist[i], sizeof(IntPoint));
3119 } else {
3120 IntPoint tmp_p;
3121
3122 TransformObjectV(obj_ptr, &poly_ptr->vlist[i], &tmp_p);
3123 memcpy(&vs1[i], &tmp_p, sizeof(IntPoint));
3124 }
3125 }
3126 for (i=sssi.orig_hinge_index; i < n; i++) {
3127 if (obj_ptr->ctm == NULL) {
3128 memcpy(&vs2[i-sssi.orig_hinge_index], &poly_ptr->vlist[i],
3129 sizeof(IntPoint));
3130 } else {
3131 IntPoint tmp_p;
3132
3133 TransformObjectV(obj_ptr, &poly_ptr->vlist[i], &tmp_p);
3134 memcpy(&vs2[i-sssi.orig_hinge_index], &tmp_p, sizeof(IntPoint));
3135 }
3136 }
3137 } else {
3138 n1 = index+1;
3139 n2 = n-index;
3140 vs1 = (IntPoint*)malloc((n1+1)*sizeof(IntPoint));
3141 vs2 = (IntPoint*)malloc((n2+1)*sizeof(IntPoint));
3142 if (vs1==NULL || vs2==NULL) FailAllocMessage();
3143 if (poly_ptr->curved != LT_INTSPLINE) {
3144 smooth1 = (char*)malloc((n1+1)*sizeof(char));
3145 smooth2 = (char*)malloc((n2+1)*sizeof(char));
3146 if (smooth1==NULL || smooth2==NULL) FailAllocMessage();
3147 }
3148 for (i=0; i <= index; i++) {
3149 if (obj_ptr->ctm == NULL) {
3150 memcpy(&vs1[i], &poly_ptr->vlist[i], sizeof(IntPoint));
3151 } else {
3152 IntPoint tmp_p;
3153
3154 TransformObjectV(obj_ptr, &poly_ptr->vlist[i], &tmp_p);
3155 memcpy(&vs1[i], &tmp_p, sizeof(IntPoint));
3156 }
3157 if (smooth1 != NULL) {
3158 smooth1[i] = poly_ptr->smooth[i];
3159 }
3160 }
3161 if (smooth1 != NULL) smooth1[0] = smooth1[index] = FALSE;
3162
3163 for (i=index; i < n; i++) {
3164 if (obj_ptr->ctm == NULL) {
3165 memcpy(&vs2[i-index], &poly_ptr->vlist[i], sizeof(IntPoint));
3166 } else {
3167 IntPoint tmp_p;
3168
3169 TransformObjectV(obj_ptr, &poly_ptr->vlist[i], &tmp_p);
3170 memcpy(&vs2[i-index], &tmp_p, sizeof(IntPoint));
3171 }
3172 if (smooth2 != NULL) {
3173 smooth2[i-index] = poly_ptr->smooth[i];
3174 }
3175 }
3176 if (smooth2 != NULL) smooth2[0] = smooth2[n-1-index] = FALSE;
3177 }
3178 ltx = selLtX; lty = selLtY; rbx = selRbX; rby = selRbY;
3179 HighLightReverse();
3180 FinishCutPoly(obj_ptr, poly_ptr, vs1, smooth1, vs2, smooth2, n1, n2);
3181 UpdSelBBox();
3182 RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
3183 rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1),
3184 selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
3185 selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
3186 SetFileModified(TRUE);
3187 justDupped = FALSE;
3188 HighLightForward();
3189 }
3190
3191 static
FinishCutPolygon(obj_ptr1,polygon_ptr1,vs,smooth,num_pts)3192 void FinishCutPolygon(obj_ptr1, polygon_ptr1, vs, smooth, num_pts)
3193 struct ObjRec *obj_ptr1;
3194 struct PolygonRec *polygon_ptr1;
3195 IntPoint *vs;
3196 char *smooth;
3197 int num_pts;
3198 {
3199 struct ObjRec *obj_ptr2;
3200 struct PolyRec *poly_ptr;
3201 struct PolygonRec *polygon_ptr2;
3202 int x0, y0;
3203
3204 x0 = topVSel->x[0];
3205 y0 = topVSel->y[0];
3206
3207 poly_ptr = (struct PolyRec *)malloc(sizeof(struct PolyRec));
3208 if (poly_ptr == NULL) FailAllocMessage();
3209
3210 memset(poly_ptr, 0, sizeof(struct PolyRec));
3211 poly_ptr->n = num_pts;
3212 poly_ptr->vlist = vs;
3213 poly_ptr->smooth = smooth;
3214 poly_ptr->asn = 0;
3215 poly_ptr->asvlist = NULL;
3216 poly_ptr->sn = 0;
3217 poly_ptr->svlist = NULL;
3218 poly_ptr->intn = 0;
3219 poly_ptr->intvlist = NULL;
3220 poly_ptr->style = LS_PLAIN;
3221 poly_ptr->width = polygon_ptr1->width;
3222 UtilStrCpyN(poly_ptr->width_spec, sizeof(poly_ptr->width_spec),
3223 polygon_ptr1->width_spec);
3224 poly_ptr->pen = polygon_ptr1->pen;
3225 poly_ptr->curved = polygon_ptr1->curved;
3226 poly_ptr->fill = polygon_ptr1->fill;
3227 poly_ptr->dash = polygon_ptr1->dash;
3228 if (poly_ptr->width == curWidthOfLine[lineWidth]) {
3229 poly_ptr->aw = curArrowHeadW[lineWidth];
3230 poly_ptr->ah = curArrowHeadH[lineWidth];
3231 UtilStrCpyN(poly_ptr->aw_spec, sizeof(poly_ptr->aw_spec),
3232 curArrowHeadWSpec[lineWidth]);
3233 UtilStrCpyN(poly_ptr->ah_spec, sizeof(poly_ptr->ah_spec),
3234 curArrowHeadHSpec[lineWidth]);
3235 } else if (maxLineWidths > 0) {
3236 int i, width=poly_ptr->width;
3237 int min_diff=abs(curWidthOfLine[0]-width), min_index=0;
3238
3239 for (i=1; min_diff > 0 && i < maxLineWidths; i++) {
3240 int diff=abs(curWidthOfLine[i]-width);
3241
3242 if (diff < min_diff) {
3243 min_diff = diff;
3244 min_index = i;
3245 }
3246 }
3247 poly_ptr->aw = curArrowHeadW[min_index];
3248 poly_ptr->ah = curArrowHeadH[min_index];
3249 UtilStrCpyN(poly_ptr->aw_spec, sizeof(poly_ptr->aw_spec),
3250 curArrowHeadWSpec[min_index]);
3251 UtilStrCpyN(poly_ptr->ah_spec, sizeof(poly_ptr->ah_spec),
3252 curArrowHeadHSpec[min_index]);
3253 }
3254 poly_ptr->rotated_n = poly_ptr->rotated_asn = 0;
3255 poly_ptr->rotated_vlist = poly_ptr->rotated_asvlist = NULL;
3256
3257 JustRemoveAllVSel();
3258 PrepareToReplaceAnObj(obj_ptr1);
3259
3260 obj_ptr2 = DupObj(obj_ptr1);
3261 obj_ptr2->fattr = obj_ptr1->fattr;
3262 obj_ptr2->lattr = obj_ptr1->lattr;
3263 obj_ptr1->fattr = obj_ptr1->lattr = NULL;
3264 polygon_ptr2 = obj_ptr2->detail.g;
3265
3266 if (polygon_ptr2->vlist != NULL) free(polygon_ptr2->vlist);
3267 if (polygon_ptr2->svlist != NULL) free(polygon_ptr2->svlist);
3268 if (polygon_ptr2->smooth != NULL) free(polygon_ptr2->smooth);
3269 if (polygon_ptr2->intvlist != NULL) free(polygon_ptr2->intvlist);
3270 if (polygon_ptr2->rotated_vlist != NULL) free(polygon_ptr2->rotated_vlist);
3271 free(polygon_ptr2);
3272 if (obj_ptr2->ctm != NULL) free(obj_ptr2->ctm);
3273 obj_ptr2->ctm = NULL;
3274
3275 obj_ptr2->type = OBJ_POLY;
3276 obj_ptr2->detail.p = poly_ptr;
3277
3278 AdjObjSplineVs(obj_ptr2);
3279 if (poly_ptr->curved != LT_INTSPLINE) {
3280 UpdPolyBBox(obj_ptr2, poly_ptr->n, poly_ptr->vlist);
3281 } else {
3282 UpdPolyBBox(obj_ptr2, poly_ptr->intn, poly_ptr->intvlist);
3283 }
3284 AdjObjBBox(obj_ptr2);
3285
3286 AddObj(obj_ptr1->prev, obj_ptr1, obj_ptr2);
3287 UnlinkObj(obj_ptr1);
3288 FreeObj(obj_ptr1);
3289
3290 topSel->obj = obj_ptr2;
3291 topSel->prev = topSel->next = NULL;
3292 botSel = topSel;
3293
3294 RecordReplaceAnObj(obj_ptr2);
3295
3296 topVSel = botVSel = (struct VSelRec *)malloc(sizeof(struct VSelRec));
3297 if (topVSel == NULL) FailAllocMessage();
3298 memset(topVSel, 0, sizeof(struct VSelRec));
3299 topVSel->obj = obj_ptr2;
3300 topVSel->max_v = 10;
3301 topVSel->v_index = (int*)malloc(10*sizeof(int));
3302 topVSel->x = (int*)malloc(10*sizeof(int));
3303 topVSel->y = (int*)malloc(10*sizeof(int));
3304 if (topVSel->v_index==NULL || topVSel->x==NULL || topVSel->y==NULL) {
3305 FailAllocMessage();
3306 }
3307 topVSel->v_index[0] = 0;
3308 topVSel->x[0] = x0;
3309 topVSel->y[0] = y0;
3310 topVSel->n = 1;
3311 topVSel->next = topVSel->prev = NULL;
3312 }
3313
3314 static
DoCutPolygon(obj_ptr,index,polygon_ptr)3315 void DoCutPolygon(obj_ptr, index, polygon_ptr)
3316 struct ObjRec *obj_ptr;
3317 int index;
3318 struct PolygonRec *polygon_ptr;
3319 {
3320 int i, n=polygon_ptr->n, num_pts, ltx, lty, rbx, rby;
3321 int curved=polygon_ptr->curved;
3322 IntPoint *vs=NULL;
3323 char *smooth=NULL;
3324
3325 if (curved == LT_STRUCT_SPLINE) {
3326 StretchStructuredSplineInfo sssi;
3327
3328 memset(&sssi, 0, sizeof(StretchStructuredSplineInfo));
3329 SetIPTInfoForStretchPolygon(index, polygon_ptr->n, polygon_ptr->vlist,
3330 &sssi);
3331 if (!sssi.hinge) {
3332 MsgBox(TgLoadString(STID_CANNOT_CUT_AT_SMOOTH_PT), TOOL_NAME, INFO_MB);
3333 return;
3334 }
3335 num_pts = n;
3336 vs = (IntPoint*)malloc((num_pts+1)*sizeof(IntPoint));
3337 if (vs == NULL) FailAllocMessage();
3338 for (i=sssi.orig_hinge_index; i < num_pts; i++) {
3339 if (obj_ptr->ctm == NULL) {
3340 memcpy(&vs[i-sssi.orig_hinge_index], &polygon_ptr->vlist[i],
3341 sizeof(IntPoint));
3342 } else {
3343 IntPoint tmp_p;
3344
3345 TransformObjectV(obj_ptr, &polygon_ptr->vlist[i], &tmp_p);
3346 memcpy(&vs[i-sssi.orig_hinge_index], &tmp_p, sizeof(IntPoint));
3347 }
3348 }
3349 for (i=1; i <= sssi.orig_hinge_index; i++) {
3350 if (obj_ptr->ctm == NULL) {
3351 memcpy(&vs[i+num_pts-sssi.orig_hinge_index-1],
3352 &polygon_ptr->vlist[i], sizeof(IntPoint));
3353 } else {
3354 IntPoint tmp_p;
3355
3356 TransformObjectV(obj_ptr, &polygon_ptr->vlist[i], &tmp_p);
3357 memcpy(&vs[i+num_pts-sssi.orig_hinge_index-1], &tmp_p,
3358 sizeof(IntPoint));
3359 }
3360 }
3361 } else {
3362 num_pts = n;
3363 vs = (IntPoint*)malloc((num_pts+1)*sizeof(IntPoint));
3364 if (vs == NULL) FailAllocMessage();
3365 if (polygon_ptr->curved != LT_INTSPLINE) {
3366 smooth = (char*)malloc((num_pts+1)*sizeof(char));
3367 if (smooth == NULL) FailAllocMessage();
3368 }
3369 for (i=index; i < num_pts; i++) {
3370 if (obj_ptr->ctm == NULL) {
3371 memcpy(&vs[i-index], &polygon_ptr->vlist[i], sizeof(IntPoint));
3372 } else {
3373 IntPoint tmp_p;
3374
3375 TransformObjectV(obj_ptr, &polygon_ptr->vlist[i], &tmp_p);
3376 memcpy(&vs[i-index], &tmp_p, sizeof(IntPoint));
3377 }
3378 if (smooth != NULL) {
3379 smooth[i-index] = polygon_ptr->smooth[i];
3380 }
3381 }
3382 for (i=1; i <= index; i++) {
3383 if (obj_ptr->ctm == NULL) {
3384 memcpy(&vs[i+num_pts-index-1], &polygon_ptr->vlist[i],
3385 sizeof(IntPoint));
3386 } else {
3387 IntPoint tmp_p;
3388
3389 TransformObjectV(obj_ptr, &polygon_ptr->vlist[i], &tmp_p);
3390 memcpy(&vs[i+num_pts-index-1], &tmp_p, sizeof(IntPoint));
3391 }
3392 if (smooth != NULL) {
3393 smooth[i+num_pts-index-1] = polygon_ptr->smooth[i];
3394 }
3395 }
3396 if (smooth != NULL) smooth[0] = smooth[num_pts-1] = FALSE;
3397 }
3398 ltx = selLtX; lty = selLtY; rbx = selRbX; rby = selRbY;
3399 HighLightReverse();
3400 FinishCutPolygon(obj_ptr, polygon_ptr, vs, smooth, num_pts);
3401 UpdSelBBox();
3402 RedrawAreas(botObj, ltx-GRID_ABS_SIZE(1), lty-GRID_ABS_SIZE(1),
3403 rbx+GRID_ABS_SIZE(1), rby+GRID_ABS_SIZE(1),
3404 selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
3405 selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
3406 SetFileModified(TRUE);
3407 justDupped = FALSE;
3408 HighLightForward();
3409 }
3410
3411 static
CopyPolySegmentProperties(obj_ptr,poly_ptr,curved)3412 void CopyPolySegmentProperties(obj_ptr, poly_ptr, curved)
3413 struct ObjRec *obj_ptr;
3414 struct PolyRec *poly_ptr;
3415 int curved;
3416 {
3417 struct PolyRec *new_poly_ptr=topObj->detail.p;
3418
3419 new_poly_ptr->style = LS_PLAIN;
3420 new_poly_ptr->width = poly_ptr->width;
3421 new_poly_ptr->aw = poly_ptr->aw;
3422 new_poly_ptr->ah = poly_ptr->ah;
3423 strcpy(new_poly_ptr->width_spec, poly_ptr->width_spec);
3424 strcpy(new_poly_ptr->aw_spec, poly_ptr->aw_spec);
3425 strcpy(new_poly_ptr->ah_spec, poly_ptr->ah_spec);
3426 new_poly_ptr->pen = poly_ptr->pen;
3427 new_poly_ptr->fill = poly_ptr->fill;
3428 new_poly_ptr->curved = curved;
3429 new_poly_ptr->dash = poly_ptr->dash;
3430
3431 topObj->color = obj_ptr->color;
3432 topObj->bg_color = obj_ptr->bg_color;
3433 memcpy(topObj->color_str, obj_ptr->color_str, sizeof(obj_ptr->color_str));
3434 memcpy(topObj->bg_color_str, obj_ptr->bg_color_str,
3435 sizeof(obj_ptr->bg_color_str));
3436 topObj->trans_pat = obj_ptr->trans_pat;
3437
3438 AdjObjSplineVs(topObj);
3439 AdjObjBBox(topObj);
3440 }
3441
3442 static
CopyPolygonSegmentProperties(obj_ptr,polygon_ptr,curved)3443 void CopyPolygonSegmentProperties(obj_ptr, polygon_ptr, curved)
3444 struct ObjRec *obj_ptr;
3445 struct PolygonRec *polygon_ptr;
3446 int curved;
3447 {
3448 struct PolyRec *new_poly_ptr=topObj->detail.p;
3449 int index=0;
3450
3451 new_poly_ptr->style = LS_PLAIN;
3452 new_poly_ptr->width = polygon_ptr->width;
3453 strcpy(new_poly_ptr->width_spec, polygon_ptr->width_spec);
3454 index = GetBestLineWidthIndex(new_poly_ptr->width, INVALID, INVALID);
3455 new_poly_ptr->aw = curArrowHeadW[index];
3456 new_poly_ptr->ah = curArrowHeadH[index];
3457 strcpy(new_poly_ptr->aw_spec, curArrowHeadWSpec[index]);
3458 strcpy(new_poly_ptr->ah_spec, curArrowHeadHSpec[index]);
3459 new_poly_ptr->pen = polygon_ptr->pen;
3460 new_poly_ptr->fill = polygon_ptr->fill;
3461 new_poly_ptr->curved = curved;
3462 new_poly_ptr->dash = polygon_ptr->dash;
3463
3464 topObj->color = obj_ptr->color;
3465 topObj->bg_color = obj_ptr->bg_color;
3466 memcpy(topObj->color_str, obj_ptr->color_str, sizeof(obj_ptr->color_str));
3467 memcpy(topObj->bg_color_str, obj_ptr->bg_color_str,
3468 sizeof(obj_ptr->bg_color_str));
3469 topObj->trans_pat = obj_ptr->trans_pat;
3470
3471 AdjObjSplineVs(topObj);
3472 AdjObjBBox(topObj);
3473 }
3474
3475 static
CreateSegmentsFromObject(obj_ptr,pp_top_obj,pp_bot_obj)3476 int CreateSegmentsFromObject(obj_ptr, pp_top_obj, pp_bot_obj)
3477 struct ObjRec *obj_ptr, **pp_top_obj, **pp_bot_obj;
3478 {
3479 int i=0, n=0, ssn=0, saved_line_style=0, saved_spline=0, curved=(-1);
3480 IntPoint *vlist=NULL, *ssvlist=NULL, tmp_p;
3481 struct PolyRec *poly_ptr=NULL;
3482 struct PolygonRec *polygon_ptr=NULL;
3483 struct ObjRec *saved_top_obj=topObj, *saved_bot_obj=botObj;
3484 char *ssmooth=NULL;
3485
3486 switch (obj_ptr->type) {
3487 case OBJ_POLY:
3488 poly_ptr = obj_ptr->detail.p;
3489 curved = poly_ptr->curved;
3490 n = poly_ptr->n;
3491 if (n <= 2) return FALSE;
3492 vlist = poly_ptr->vlist;
3493 if (curved == LT_STRUCT_SPLINE) {
3494 ssn = poly_ptr->ssn;
3495 if (ssn <= 2) return FALSE;
3496 ssvlist = poly_ptr->ssvlist;
3497 ssmooth = poly_ptr->ssmooth;
3498 }
3499 break;
3500 case OBJ_POLYGON:
3501 polygon_ptr = obj_ptr->detail.g;
3502 curved = polygon_ptr->curved;
3503 n = polygon_ptr->n;
3504 if (n <= 2) return FALSE;
3505 vlist = polygon_ptr->vlist;
3506 if (curved == LT_STRUCT_SPLINE) {
3507 ssn = polygon_ptr->ssn;
3508 if (ssn <= 2) return FALSE;
3509 ssvlist = polygon_ptr->ssvlist;
3510 ssmooth = polygon_ptr->ssmooth;
3511 }
3512 break;
3513 }
3514 curPage->top = topObj = (*pp_top_obj);
3515 curPage->bot = botObj = (*pp_bot_obj);
3516 saved_line_style = lineStyle;
3517 saved_spline = curSpline;
3518 lineStyle = LS_PLAIN;
3519 if (curved == LT_STRUCT_SPLINE) {
3520 IntPoint tmp_vs[4];
3521 int num_vs=0;
3522
3523 curSpline = LT_STRUCT_SPLINE;
3524 ResetCreatePoly();
3525 if (obj_ptr->ctm == NULL) {
3526 memcpy(&tmp_vs[0], &ssvlist[0], sizeof(IntPoint));
3527 } else {
3528 TransformObjectV(obj_ptr, &ssvlist[0], &tmp_p);
3529 memcpy(&tmp_vs[0], &tmp_p, sizeof(IntPoint));
3530 }
3531 num_vs = 1;
3532 for (i=1; i < ssn; i++) {
3533 if (obj_ptr->ctm == NULL) {
3534 memcpy(&tmp_vs[num_vs], &ssvlist[i], sizeof(IntPoint));
3535 } else {
3536 TransformObjectV(obj_ptr, &ssvlist[i], &tmp_p);
3537 memcpy(&tmp_vs[num_vs], &tmp_p, sizeof(IntPoint));
3538 }
3539 num_vs++;
3540 if (!ssmooth[i]) {
3541 IntPointTriplet ipt_first, ipt_last;
3542
3543 memset(&ipt_first, 0, sizeof(IntPointTriplet));
3544 memset(&ipt_last, 0, sizeof(IntPointTriplet));
3545
3546 memcpy(&ipt_first.hinge_pt, &tmp_vs[0], sizeof(IntPoint));
3547 ipt_first.earlier_valid = ipt_first.later_valid = FALSE;
3548 ipt_first.ratio = (double)1;
3549
3550 memcpy(&ipt_last.hinge_pt, &tmp_vs[num_vs-1], sizeof(IntPoint));
3551 ipt_last.earlier_valid = ipt_last.later_valid = FALSE;
3552 ipt_last.ratio = (double)1;
3553
3554 switch (num_vs) {
3555 case 2: break;
3556 case 3:
3557 memcpy(&ipt_first.later_smooth_pt, &tmp_vs[1], sizeof(IntPoint));
3558 ipt_first.later_valid = TRUE;
3559 break;
3560 case 4:
3561 memcpy(&ipt_first.later_smooth_pt, &tmp_vs[1], sizeof(IntPoint));
3562 ipt_first.later_valid = TRUE;
3563 memcpy(&ipt_last.earlier_smooth_pt, &tmp_vs[2],
3564 sizeof(IntPoint));
3565 ipt_last.earlier_valid = TRUE;
3566 break;
3567 }
3568 AddPointForCont(0, 0, &ipt_first);
3569 AddPointForCont(0, 0, &ipt_last);
3570 CreatePolyObj(2, TRUE);
3571 switch (obj_ptr->type) {
3572 case OBJ_POLY:
3573 CopyPolySegmentProperties(obj_ptr, poly_ptr, LT_STRUCT_SPLINE);
3574 break;
3575 case OBJ_POLYGON:
3576 CopyPolygonSegmentProperties(obj_ptr, polygon_ptr,
3577 LT_STRUCT_SPLINE);
3578 break;
3579 }
3580 ResetCreatePoly();
3581 memcpy(&tmp_vs[0], &tmp_vs[num_vs-1], sizeof(IntPoint));
3582 num_vs = 1;
3583 }
3584 }
3585 } else {
3586 IntPoint *tmp_vs=NULL;
3587
3588 tmp_vs = (IntPoint*)malloc(n*sizeof(IntPoint));
3589 if (tmp_vs == NULL) FailAllocMessage();
3590 memset(tmp_vs, 0, n*sizeof(IntPoint));
3591 for (i=0; i < n; i++) {
3592 if (obj_ptr->ctm == NULL) {
3593 memcpy(&tmp_vs[i], &vlist[i], sizeof(IntPoint));
3594 } else {
3595 TransformObjectV(obj_ptr, &vlist[i], &tmp_p);
3596 memcpy(&tmp_vs[i], &tmp_p, sizeof(IntPoint));
3597 }
3598 }
3599 curSpline = LT_STRAIGHT;
3600 for (i=0; i < n-1; i++) {
3601 ResetCreatePoly();
3602 AddPtToCreatePoly(tmp_vs[i].x, tmp_vs[i].y);
3603 AddPtToCreatePoly(tmp_vs[i+1].x, tmp_vs[i+1].y);
3604 CreatePolyObj(2, TRUE);
3605 switch (obj_ptr->type) {
3606 case OBJ_POLY:
3607 CopyPolySegmentProperties(obj_ptr, poly_ptr, LT_STRAIGHT);
3608 break;
3609 case OBJ_POLYGON:
3610 CopyPolygonSegmentProperties(obj_ptr, polygon_ptr, LT_STRAIGHT);
3611 break;
3612 }
3613 }
3614 free(tmp_vs);
3615 }
3616 lineStyle = saved_line_style;
3617 curSpline = saved_spline;
3618 (*pp_top_obj) = topObj;
3619 (*pp_bot_obj) = botObj;
3620 curPage->top = topObj = saved_top_obj;
3621 curPage->bot = botObj = saved_bot_obj;
3622
3623 return TRUE;
3624 }
3625
3626 static
CutPolyIntoSegments()3627 void CutPolyIntoSegments()
3628 {
3629 struct SelRec *sel_ptr=NULL, *new_top_sel=NULL, *new_bot_sel=NULL;
3630 int something_changed=FALSE;
3631
3632 UnSelNonVertexObjs(TRUE, FALSE); /* with highlight */
3633 UpdSelBBox();
3634 if (topSel == NULL) {
3635 MsgBox(TgLoadString(STID_NO_POLY_OBJ_SELECTED), TOOL_NAME, INFO_MB);
3636 return;
3637 }
3638 HighLightReverse();
3639 StartCompositeCmd();
3640
3641 for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
3642 struct ObjRec *new_top_obj=NULL, *new_bot_obj=NULL;
3643
3644 PrepareToReplaceAnObj(sel_ptr->obj);
3645 if (CreateSegmentsFromObject(sel_ptr->obj, &new_top_obj, &new_bot_obj)) {
3646 struct ObjRec *obj_ptr=NULL;
3647 struct SelRec *saved_top_sel=topSel, *saved_bot_sel=botSel;
3648 int count=0;
3649
3650 something_changed = TRUE;
3651 UnlinkObj(sel_ptr->obj);
3652 FreeObj(sel_ptr->obj);
3653
3654 /* add newly created line segments to the top of the object chain */
3655 new_bot_obj->next = topObj;
3656 if (topObj == NULL) {
3657 curPage->bot = botObj = new_bot_obj;
3658 } else {
3659 topObj->prev = new_bot_obj;
3660 }
3661 curPage->top = topObj = new_top_obj;
3662
3663 topSel = botSel = NULL;
3664 for (obj_ptr=new_bot_obj; obj_ptr != NULL; obj_ptr=obj_ptr->prev,
3665 count++) {
3666 AddSel(NULL, topSel, SelectThisObject(obj_ptr));
3667 }
3668 UpdSelBBox();
3669 RecordCmd(CMD_ONE_TO_MANY, NULL, topSel, botSel, numObjSelected);
3670
3671 botSel->next = new_top_sel;
3672 if (new_top_sel == NULL) {
3673 new_bot_sel = botSel;
3674 } else {
3675 new_top_sel->prev = botSel;
3676 }
3677 new_top_sel = topSel;
3678
3679 topSel = saved_top_sel;
3680 botSel = saved_bot_sel;
3681 } else {
3682 AbortPrepareCmd(CMD_REPLACE);
3683 }
3684 }
3685 EndCompositeCmd();
3686
3687 if (something_changed) {
3688 RemoveAllSel();
3689 topSel = new_top_sel;
3690 botSel = new_bot_sel;
3691 UpdSelBBox();
3692
3693 RedrawAnArea(botObj, selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
3694 selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
3695 SetFileModified(TRUE);
3696 justDupped = FALSE;
3697 }
3698 HighLightForward();
3699 }
3700
CutPoly()3701 void CutPoly()
3702 {
3703 struct ObjRec *obj_ptr;
3704 struct PolyRec *poly_ptr=NULL;
3705 struct PolygonRec *polygon_ptr=NULL;
3706 int index;
3707
3708 if (curChoice == NOTHING) {
3709 if (topSel == NULL) {
3710 MsgBox(TgLoadCachedString(CSTID_NO_OBJ_SELECTED), TOOL_NAME, INFO_MB);
3711 return;
3712 }
3713 if (MsgBox(TgLoadString(STID_Q_OK_TO_CUT_INTO_SEGMENTS), TOOL_NAME,
3714 YNC_MB) != MB_ID_YES) {
3715 return;
3716 }
3717 CutPolyIntoSegments();
3718 return;
3719 } else if (curChoice != VERTEXMODE) {
3720 MsgBox(TgLoadString(STID_CMD_ONLY_AVAIL_IN_VERTEX_MODE), TOOL_NAME,
3721 INFO_MB);
3722 return;
3723 } else if (CountSelectedVertices() != 1) {
3724 MsgBox(TgLoadString(STID_SEL_1_VERTEX_TO_CUT), TOOL_NAME, INFO_MB);
3725 return;
3726 }
3727 obj_ptr = topVSel->obj;
3728 index = topVSel->v_index[0];
3729 switch (obj_ptr->type) {
3730 case OBJ_POLY:
3731 poly_ptr = obj_ptr->detail.p;
3732 if (index==0 || index==poly_ptr->n-1) return;
3733 DoCutPoly(obj_ptr, index, poly_ptr);
3734 break;
3735 case OBJ_POLYGON:
3736 polygon_ptr = obj_ptr->detail.g;
3737 DoCutPolygon(obj_ptr, index, polygon_ptr);
3738 break;
3739 default:
3740 MsgBox(TgLoadString(STID_SEL_A_VERTEX_FROM_POLY_OR_GON), TOOL_NAME,
3741 INFO_MB);
3742 return;
3743 }
3744 }
3745
3746 /* --------------------- GetWidthInDouble() --------------------- */
3747
GetWidthInDouble(nVal,pszSpec,pnIsInt)3748 double GetWidthInDouble(nVal, pszSpec, pnIsInt)
3749 int nVal, *pnIsInt;
3750 char *pszSpec;
3751 {
3752 float fval;
3753
3754 if (pnIsInt != NULL) *pnIsInt = TRUE;
3755 if (pszSpec == NULL || *pszSpec == '\0') return (double)nVal;
3756 if (sscanf(pszSpec, "%f", &fval) != 1) return (double)nVal;
3757 if (pnIsInt != NULL) {
3758 if (fabs(((float)nVal)-fval) > INT_TOL) {
3759 *pnIsInt = FALSE;
3760 }
3761 }
3762 return ((double)fval);
3763 }
3764
3765 /* --------------------- SetWidthAndSpec() --------------------- */
3766
SetWidthAndSpec(dWidth,pnWidth,pszWidthSpec)3767 void SetWidthAndSpec(dWidth, pnWidth, pszWidthSpec)
3768 double dWidth;
3769 int *pnWidth;
3770 char *pszWidthSpec;
3771 {
3772 float fval=(float)dWidth;
3773
3774 FormatFloat(&fval, pszWidthSpec);
3775 *pnWidth = round(dWidth);
3776 }
3777
3778 /* --------------------- ScaleWidthAndSpec() --------------------- */
3779
ScaleWidthAndSpec(dScale,pnWidth,pszWidthSpec)3780 void ScaleWidthAndSpec(dScale, pnWidth, pszWidthSpec)
3781 double dScale;
3782 int *pnWidth;
3783 char *pszWidthSpec; /* char[40] */
3784 {
3785 double dw=GetWidthInDouble(*pnWidth, pszWidthSpec, NULL);
3786
3787 dw = dw*dScale;
3788 SetWidthAndSpec(dw, pnWidth, pszWidthSpec);
3789 }
3790
3791 /* --------------------- DumpArrow() --------------------- */
3792
DumpArrow(FP,TailV,HeadV,ArrowW,ArrowH,aw_spec,ah_spec,Pen,TransPat,ColorIndex)3793 void DumpArrow(FP, TailV, HeadV, ArrowW, ArrowH, aw_spec, ah_spec, Pen,
3794 TransPat, ColorIndex)
3795 FILE *FP;
3796 IntPoint *TailV, *HeadV;
3797 int ArrowW, ArrowH, Pen, TransPat, ColorIndex;
3798 char *aw_spec, *ah_spec;
3799 /* HeadV is where the arrow tip is */
3800 /* Make sure this function is not called with (Pen==BACKPAT && TransPat) */
3801 {
3802 int i, dx, dy;
3803 struct BBRec bbox;
3804 IntPoint v[2];
3805 double len, sin, cos, daw, dah;
3806
3807 memset(&bbox, 0, sizeof(struct BBRec));
3808 dx = HeadV->x - TailV->x;
3809 dy = HeadV->y - TailV->y;
3810
3811 if (dx == 0 && dy == 0) return;
3812
3813 fprintf(FP, "%s\n", gPsCmd[PS_GSAVE]);
3814 fprintf(FP, " %s\n", &(gPsCmd[PS_TGIFSETMATRIX])[1]);
3815
3816 daw = GetWidthInDouble(ArrowW, aw_spec, NULL);
3817 dah = GetWidthInDouble(ArrowH, ah_spec, NULL);
3818 if (colorDump || !useGray) {
3819 len = (double)sqrt((double)(((double)dx)*((double)dx) +
3820 ((double)dy)*((double)dy)));
3821 sin = ((double)dy) / len;
3822 cos = ((double)dx) / len;
3823
3824 v[0].x = round(HeadV->x - daw*cos + dah*sin);
3825 v[0].y = round(HeadV->y - daw*sin - dah*cos);
3826 v[1].x = round(HeadV->x - daw*cos - dah*sin);
3827 v[1].y = round(HeadV->y - daw*sin + dah*cos);
3828
3829 bbox.ltx = bbox.rbx = HeadV->x;
3830 bbox.lty = bbox.rby = HeadV->y;
3831
3832 for (i = 0; i < 2; i++) {
3833 if (v[i].x < bbox.ltx) bbox.ltx = v[i].x;
3834 if (v[i].y < bbox.lty) bbox.lty = v[i].y;
3835 if (v[i].x > bbox.rbx) bbox.rbx = v[i].x;
3836 if (v[i].y > bbox.rby) bbox.rby = v[i].y;
3837 }
3838 if (preDumpSetup) PSUseArrow();
3839 if (!TransPat) {
3840 fprintf(FP, " %s\n", gPsCmd[PS_NEWPATH]);
3841 fprintf(FP, " %1d %1d %.3f %.3f %1d %1d TGAT\n",
3842 HeadV->x, HeadV->y, daw, dah, dx, dy);
3843 fprintf(FP, " 1 %s %s %s\n", gPsCmd[PS_SETGRAY],
3844 gPsCmd[PS_CLOSEPATH], gPsCmd[PS_FILL]);
3845 DumpRGBColorLine(FP, ColorIndex, 3, TRUE);
3846 }
3847 } else {
3848 switch (Pen) {
3849 case SOLIDPAT: break;
3850 case BACKPAT: break;
3851 default:
3852 GrayCheck(Pen);
3853 fprintf(FP, " %s %s\n", GrayStr(Pen), gPsCmd[PS_SETGRAY]);
3854 break;
3855 }
3856 }
3857 if (!((colorDump || !useGray) && Pen==BACKPAT)) {
3858 if (preDumpSetup) PSUseArrow();
3859 fprintf(FP, " %s\n", gPsCmd[PS_NEWPATH]);
3860 fprintf(FP, " %1d %1d %.3f %.3f %1d %1d TGAT\n",
3861 HeadV->x, HeadV->y, daw, dah, dx, dy);
3862 }
3863 if (colorDump || !useGray) {
3864 switch (Pen) {
3865 case SOLIDPAT:
3866 fprintf(FP, " %s %s\n", gPsCmd[PS_CLOSEPATH], gPsCmd[PS_FILL]);
3867 break;
3868 case BACKPAT: break;
3869 default:
3870 if (preDumpSetup) PSUseColorPattern();
3871 fprintf(FP, " %s %s %s\n", gPsCmd[PS_CLOSEPATH],
3872 gPsCmd[PS_EOCLIP], gPsCmd[PS_NEWPATH]);
3873 DumpPatFill(FP, Pen, bbox, 3, TRUE);
3874 break;
3875 }
3876 } else {
3877 switch (Pen) {
3878 case SOLIDPAT:
3879 fprintf(FP, " %s %s\n", gPsCmd[PS_CLOSEPATH], gPsCmd[PS_FILL]);
3880 break;
3881 case BACKPAT:
3882 if (!TransPat) {
3883 fprintf(FP, " %s 1 %s %s\n", gPsCmd[PS_CLOSEPATH],
3884 gPsCmd[PS_SETGRAY], gPsCmd[PS_FILL]);
3885 }
3886 break;
3887 default:
3888 fprintf(FP, " %s %s\n", gPsCmd[PS_CLOSEPATH], gPsCmd[PS_FILL]);
3889 break;
3890 }
3891 }
3892 fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]);
3893 }
3894
3895 /* --------------------- DumpPolyObj() --------------------- */
3896
3897 static
CalcArrowRetreatPoint(TailV,HeadV,ArrowW,aw_spec,ReturnV)3898 int CalcArrowRetreatPoint(TailV, HeadV, ArrowW, aw_spec, ReturnV)
3899 IntPoint *TailV, *HeadV, *ReturnV;
3900 int ArrowW;
3901 char *aw_spec;
3902 /* HeadV is where the arrow tip is */
3903 {
3904 int dx, dy;
3905 double len, sin, cos, daw;
3906
3907 dx = HeadV->x - TailV->x;
3908 dy = HeadV->y - TailV->y;
3909
3910 if (dx == 0 && dy == 0) return FALSE;
3911
3912 len = (double)sqrt((double)(((double)dx)*((double)dx) +
3913 ((double)dy)*((double)dy)));
3914 sin = ((double)dy) / len;
3915 cos = ((double)dx) / len;
3916
3917 daw = GetWidthInDouble(ArrowW, aw_spec, NULL);
3918 ReturnV->x = round(HeadV->x-RETREAT*daw*cos);
3919 ReturnV->y = round(HeadV->y-RETREAT*daw*sin);
3920 return TRUE;
3921 }
3922
3923 static
DumpPolyPath(FP,ObjPtr,Vs,NumPts,Smooth,Style,Width,ArrowW,ArrowH,width_spec,aw_spec,ah_spec,Pen,Fill,Curved,Dash,Indent,TransPat)3924 void DumpPolyPath(FP, ObjPtr, Vs, NumPts, Smooth, Style, Width, ArrowW, ArrowH,
3925 width_spec, aw_spec, ah_spec, Pen, Fill, Curved, Dash, Indent, TransPat)
3926 FILE *FP;
3927 register struct ObjRec *ObjPtr;
3928 IntPoint *Vs;
3929 int NumPts, Style, Width, ArrowW, ArrowH;
3930 char *width_spec, *aw_spec, *ah_spec;
3931 int Pen, Fill, Curved, Dash, Indent, TransPat;
3932 char *Smooth;
3933 {
3934 register int i, dx, dy;
3935 int retracted_arrow, color_index=ObjPtr->color, w_is_int=TRUE;
3936 double daw, dw;
3937
3938 retracted_arrow = (RetractedArrowAttr(ObjPtr) ||
3939 AutoRetractedArrowAttr(ObjPtr, TRUE));
3940
3941 daw = GetWidthInDouble(ArrowW, aw_spec, NULL);
3942 dw = GetWidthInDouble(Width, width_spec, &w_is_int);
3943 if (Fill == (-1) && Pen != (-1)) {
3944 /* dumping the pen */
3945 if (Dash != 0) {
3946 for (i=0; i < Indent+3; i++) fprintf(FP, " ");
3947 fprintf(FP, "[");
3948 for (i = 0; i < dashListLength[Dash]-1; i++) {
3949 fprintf(FP, "%1d ", (int)(dashList[Dash][i]));
3950 }
3951 fprintf(FP, "%1d] 0 %s\n",
3952 (int)(dashList[Dash][dashListLength[Dash]-1]),
3953 gPsCmd[PS_SETDASH]);
3954 }
3955 } else if (Fill != (-1) && Pen == (-1)) {
3956 /* dumping the fill */
3957 if (Fill > BACKPAT) {
3958 if (colorDump || !useGray) {
3959 for (i=0; i < Indent; i++) fprintf(FP, " ");
3960 fprintf(FP, "%s\n", gPsCmd[PS_GSAVE]);
3961 if (preDumpSetup) PSUseColorPattern();
3962 if (!TransPat) {
3963 DumpPolyPath(FP, ObjPtr, Vs, NumPts, Smooth, LS_PLAIN, Width,
3964 ArrowW, ArrowH, width_spec, aw_spec, ah_spec,
3965 (-1), BACKPAT, Curved, Dash, Indent, TransPat);
3966 }
3967 } else {
3968 for (i=0; i < Indent; i++) fprintf(FP, " ");
3969 fprintf(FP, "%s\n", gPsCmd[PS_GSAVE]);
3970 GrayCheck(Fill);
3971 for (i=0; i < Indent+3; i++) fprintf(FP, " ");
3972 fprintf(FP, "%s %s\n", GrayStr(Fill), gPsCmd[PS_SETGRAY]);
3973 }
3974 }
3975 }
3976 #ifndef DONT_DRAW_ZERO_LENGTH_POLY_AS_DOT
3977 if (NumPts == 2 && Vs[0].x == Vs[1].x && Vs[0].y == Vs[1].y) {
3978 for (i=0; i < Indent+3; i++) fprintf(FP, " ");
3979 fprintf(FP, "1 %s\n", gPsCmd[PS_SETLINECAP]);
3980 }
3981 #endif /* ~DONT_DRAW_ZERO_LENGTH_POLY_AS_DOT */
3982 for (i=0; i < Indent+3; i++) fprintf(FP, " ");
3983 fprintf(FP, "%s\n", gPsCmd[PS_NEWPATH]);
3984 for (i=0; i < Indent+3; i++) fprintf(FP, " ");
3985 fprintf(FP, " %1d %1d %s\n", Vs[0].x, Vs[0].y, gPsCmd[PS_MOVETO]);
3986 if (Style & LS_LEFT) {
3987 dx = Vs[1].x - Vs[0].x;
3988 dy = Vs[1].y - Vs[0].y;
3989 if (dx != 0 || dy != 0) {
3990 if (!retracted_arrow) {
3991 if (ObjPtr->ctm == NULL) {
3992 for (i=0; i < Indent+6; i++) fprintf(FP, " ");
3993 fprintf(FP, "%1d %1d atan %s cos %.3f %s exch sin %.3f %s %s\n",
3994 dy, dx, gPsCmd[PS_DUP], daw, gPsCmd[PS_MUL], daw,
3995 gPsCmd[PS_MUL], gPsCmd[PS_RMOVETO]);
3996 } else {
3997 IntPoint ip0, ip1, ip2, ip3;
3998
3999 TransformObjectV(ObjPtr, &Vs[1], &ip0);
4000 TransformObjectV(ObjPtr, &Vs[0], &ip1);
4001 if (CalcArrowRetreatPoint(&ip0, &ip1, ArrowW, aw_spec, &ip2)) {
4002 ReversedTransformObjectV(ObjPtr, &ip2, &ip3);
4003 for (i=0; i < Indent+6; i++) fprintf(FP, " ");
4004 fprintf(FP, "%1d %1d %s\n", ip3.x, ip3.y, gPsCmd[PS_MOVETO]);
4005 }
4006 }
4007 }
4008 }
4009 }
4010 if (Style & LS_RIGHT) {
4011 if (Curved == LT_INTSPLINE) {
4012 DumpCurvedPolyPoints(FP, Curved, NumPts, Vs, Indent+6);
4013 } else {
4014 DumpMultiCurvedPolyPoints(FP, Smooth, Style, Curved, NumPts, Vs,
4015 Indent+6);
4016 }
4017 dx = Vs[NumPts-1].x - Vs[NumPts-2].x;
4018 dy = Vs[NumPts-1].y - Vs[NumPts-2].y;
4019 if (dx != 0 || dy != 0) {
4020 if (retracted_arrow) {
4021 for (i=0; i < Indent+6; i++) fprintf(FP, " ");
4022 fprintf(FP, "%1d %1d", Vs[NumPts-1].x, Vs[NumPts-1].y);
4023 } else {
4024 if (ObjPtr->ctm == NULL) {
4025 for (i=0; i < Indent+6; i++) fprintf(FP, " ");
4026 fprintf(FP, "%1d %1d atan %s cos %.3f %s %1d exch %s\n",
4027 dy, dx, gPsCmd[PS_DUP], daw, gPsCmd[PS_MUL],
4028 Vs[NumPts-1].x, gPsCmd[PS_SUB]);
4029 for (i=0; i < Indent+6; i++) fprintf(FP, " ");
4030 fprintf(FP, "exch sin %.3f %s %1d exch %s",
4031 daw, gPsCmd[PS_MUL], Vs[NumPts-1].y, gPsCmd[PS_SUB]);
4032 } else {
4033 IntPoint ip0, ip1, ip2, ip3;
4034
4035 TransformObjectV(ObjPtr, &Vs[NumPts-2], &ip0);
4036 TransformObjectV(ObjPtr, &Vs[NumPts-1], &ip1);
4037 if (CalcArrowRetreatPoint(&ip0, &ip1, ArrowW, aw_spec, &ip2)) {
4038 ReversedTransformObjectV(ObjPtr, &ip2, &ip3);
4039 for (i=0; i < Indent+6; i++) fprintf(FP, " ");
4040 fprintf(FP, "%1d %1d", ip3.x, ip3.y);
4041 }
4042 }
4043 }
4044 switch (Curved) {
4045 case LT_STRAIGHT:
4046 case LT_SPLINE:
4047 case LT_STRUCT_SPLINE:
4048 if (NumPts <= 2 || (Smooth != NULL && !Smooth[NumPts-2])) {
4049 fprintf(FP, " %s", gPsCmd[PS_LINETO]);
4050 } else {
4051 fprintf(FP, " %s", gPsCmd[PS_CURVETO]);
4052 }
4053 break;
4054 case LT_INTSPLINE:
4055 if (NumPts <= 2) {
4056 fprintf(FP, " %s", gPsCmd[PS_LINETO]);
4057 } else {
4058 fprintf(FP, " %s", gPsCmd[PS_CURVETO]);
4059 }
4060 break;
4061 }
4062 }
4063 fprintf(FP, "\n");
4064 } else if (Curved == LT_INTSPLINE) {
4065 DumpCurvedPolyPoints(FP, Curved, NumPts, Vs, Indent+6);
4066 if (NumPts <= 2) {
4067 for (i=0; i < Indent+6; i++) fprintf(FP, " ");
4068 fprintf(FP, "%1d %1d %s\n",Vs[NumPts-1].x,Vs[NumPts-1].y,
4069 gPsCmd[PS_LINETO]);
4070 } else {
4071 for (i=0; i < Indent+6; i++) fprintf(FP, " ");
4072 fprintf(FP, "%1d %1d %s\n",Vs[NumPts-1].x,Vs[NumPts-1].y,
4073 gPsCmd[PS_CURVETO]);
4074 }
4075 } else {
4076 DumpMultiCurvedPolyPoints(FP, Smooth, Style, Curved, NumPts, Vs,
4077 Indent+6);
4078 }
4079 if (Fill == (-1) && Pen != (-1)) {
4080 /* dumping the pen */
4081 for (i=0; i < Indent+3; i++) fprintf(FP, " ");
4082 fprintf(FP, "%s\n", &(gPsCmd[PS_TGIFSETMATRIX])[1]);
4083 for (i=0; i < Indent+3; i++) fprintf(FP, " ");
4084 if (w_is_int) {
4085 fprintf(FP, "%1d %s\n", Width, gPsCmd[PS_SETLINEWIDTH]);
4086 } else {
4087 fprintf(FP, "%.3f %s\n", dw, gPsCmd[PS_SETLINEWIDTH]);
4088 }
4089 for (i=0; i < Indent+3; i++) fprintf(FP, " ");
4090 switch (Pen) {
4091 case SOLIDPAT: fprintf(FP, "%s\n", gPsCmd[PS_STROKE]); break;
4092 case BACKPAT:
4093 if (!TransPat) {
4094 fprintf(FP, "1 %s %s\n", gPsCmd[PS_SETGRAY], gPsCmd[PS_STROKE]);
4095 }
4096 break;
4097 default:
4098 if (colorDump || !useGray) {
4099 if (preDumpSetup) PSUseColorPattern();
4100 fprintf(FP, "%s\n", gPsCmd[PS_FLATTENPATH]);
4101 for (i=0; i < Indent+3; i++) fprintf(FP, " ");
4102 DumpPatFill(FP, Pen, ObjPtr->bbox, 0, TRUE);
4103 } else {
4104 GrayCheck(Pen);
4105 fprintf(FP, "%s %s\n", GrayStr(Pen), gPsCmd[PS_SETGRAY]);
4106 for (i=0; i < Indent+3; i++) fprintf(FP, " ");
4107 fprintf(FP, "%s\n", gPsCmd[PS_STROKE]);
4108 }
4109 break;
4110 }
4111 if (Dash != 0) {
4112 for (i=0; i < Indent+3; i++) fprintf(FP, " ");
4113 fprintf(FP, "[] 0 %s\n", gPsCmd[PS_SETDASH]);
4114 }
4115 if (Width != 1) {
4116 for (i=0; i < Indent+3; i++) fprintf(FP, " ");
4117 fprintf(FP, "1 %s\n", gPsCmd[PS_SETLINEWIDTH]);
4118 }
4119 } else if (Fill != (-1) && Pen == (-1)) {
4120 /* dumping the fill */
4121 for (i=0; i < Indent+3; i++) fprintf(FP, " ");
4122 switch (Fill) {
4123 case SOLIDPAT:
4124 fprintf(FP, "%s %s\n", gPsCmd[PS_CLOSEPATH], gPsCmd[PS_EOFILL]);
4125 break;
4126 case BACKPAT:
4127 if (!TransPat) {
4128 fprintf(FP, "%s 1 %s %s\n", gPsCmd[PS_CLOSEPATH],
4129 gPsCmd[PS_SETGRAY], gPsCmd[PS_EOFILL]);
4130 for (i=0; i < Indent+3; i++) fprintf(FP, " ");
4131 DumpRGBColorLine(FP, color_index, 0, TRUE);
4132 }
4133 break;
4134 default:
4135 if (colorDump || !useGray) {
4136 if (preDumpSetup) PSUseColorPattern();
4137 fprintf(FP, "%s %s %s\n", gPsCmd[PS_CLOSEPATH],
4138 gPsCmd[PS_EOCLIP], gPsCmd[PS_NEWPATH]);
4139 for (i=0; i < Indent+3; i++) fprintf(FP, " ");
4140 DumpPatFill(FP, Fill, ObjPtr->bbox, 0, TRUE);
4141 } else {
4142 fprintf(FP, "%s %s\n", gPsCmd[PS_CLOSEPATH], gPsCmd[PS_EOFILL]);
4143 }
4144 for (i=0; i < Indent; i++) fprintf(FP, " ");
4145 fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]);
4146 break;
4147 }
4148 }
4149 }
4150
DumpPolyObj(FP,ObjPtr)4151 void DumpPolyObj(FP, ObjPtr)
4152 FILE *FP;
4153 register struct ObjRec *ObjPtr;
4154 {
4155 IntPoint *intv=NULL, *v=NULL;
4156 int num_pts, trans_pat, fill, pen, width, curved, dash, color_index;
4157 int style, aw, ah, rotation, intn, retracted_arrow;
4158 char *smooth=NULL, *width_spec=NULL, *aw_spec=NULL, *ah_spec=NULL;
4159
4160 trans_pat = ObjPtr->trans_pat;
4161 fill = ObjPtr->detail.p->fill;
4162 width = ObjPtr->detail.p->width;
4163 aw = ObjPtr->detail.p->aw;
4164 ah = ObjPtr->detail.p->ah;
4165 width_spec = ObjPtr->detail.p->width_spec;
4166 aw_spec = ObjPtr->detail.p->aw_spec;
4167 ah_spec = ObjPtr->detail.p->ah_spec;
4168 pen = ObjPtr->detail.p->pen;
4169 style = ObjPtr->detail.p->style;
4170 curved = ObjPtr->detail.p->curved;
4171 dash = ObjPtr->detail.p->dash;
4172 rotation = ObjPtr->rotation;
4173 if (curved == LT_STRUCT_SPLINE) {
4174 v = ObjPtr->detail.p->ssvlist;
4175 num_pts = ObjPtr->detail.p->ssn;
4176 smooth = ObjPtr->detail.p->ssmooth;
4177 } else {
4178 v = ObjPtr->detail.p->vlist;
4179 num_pts = ObjPtr->detail.p->n;
4180 smooth = ObjPtr->detail.p->smooth;
4181 }
4182 intv = ObjPtr->detail.p->intvlist;
4183 intn = ObjPtr->detail.p->intn;
4184
4185 if ((fill == NONEPAT || (trans_pat && fill == BACKPAT)) &&
4186 (pen == NONEPAT || (trans_pat && pen == BACKPAT))) {
4187 return;
4188 }
4189 fprintf(FP, "%% POLY/OPEN-SPLINE\n");
4190 color_index = ObjPtr->color;
4191 DumpRGBColorLine(FP, color_index, 0, TRUE);
4192
4193 if (ObjPtr->ctm != NULL) {
4194 float m[6];
4195
4196 fprintf(FP, "%s\n", gPsCmd[PS_GSAVE]);
4197 m[CTM_SX] = ((float)ObjPtr->ctm->m[CTM_SX])/((float)1000.0);
4198 m[CTM_SY] = ((float)ObjPtr->ctm->m[CTM_SY])/((float)1000.0);
4199 m[CTM_SIN] = ((float)ObjPtr->ctm->m[CTM_SIN])/((float)1000.0);
4200 m[CTM_MSIN] = ((float)ObjPtr->ctm->m[CTM_MSIN])/((float)1000.0);
4201 fprintf(FP, " %1d %1d %s\n", ObjPtr->x, ObjPtr->y,
4202 gPsCmd[PS_TRANSLATE]);
4203 fprintf(FP, " [%.3f %.3f %.3f %.3f %1d %1d] %s\n",
4204 m[CTM_SX], m[CTM_SIN], m[CTM_MSIN], m[CTM_SY],
4205 ObjPtr->ctm->t[CTM_TX], ObjPtr->ctm->t[CTM_TY], gPsCmd[PS_CONCAT]);
4206 fprintf(FP, " %1d %s %1d %s %s\n",
4207 ObjPtr->x, gPsCmd[PS_NEG], ObjPtr->y, gPsCmd[PS_NEG],
4208 gPsCmd[PS_TRANSLATE]);
4209 }
4210 if (fill != NONEPAT && num_pts > 2 && !(fill == BACKPAT && trans_pat)) {
4211 if (curved != LT_INTSPLINE) {
4212 DumpPolyPath(FP, ObjPtr, v, num_pts, smooth, LS_PLAIN, width, aw, ah,
4213 width_spec, aw_spec, ah_spec, (-1), fill, curved, dash,
4214 (fill > BACKPAT ? 0 : (-3)), trans_pat);
4215 } else {
4216 DumpPolyPath(FP, ObjPtr, intv, intn, smooth, LS_PLAIN, width, aw, ah,
4217 width_spec, aw_spec, ah_spec, (-1), fill, curved, dash,
4218 (fill > BACKPAT ? 0 : (-3)), trans_pat);
4219 }
4220 }
4221 if (pen == NONEPAT || (pen == BACKPAT && trans_pat)) {
4222 if (ObjPtr->ctm != NULL) fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]);
4223 fprintf(FP, "\n");
4224 return;
4225 }
4226
4227 fprintf(FP, "%s\n", gPsCmd[PS_GSAVE]);
4228
4229 if ((colorDump || !useGray) && pen > BACKPAT && !trans_pat) {
4230 fprintf(FP, " %s\n", gPsCmd[PS_GSAVE]);
4231 if (curved != LT_INTSPLINE) {
4232 DumpPolyPath(FP, ObjPtr, v, num_pts, smooth, style, width, aw, ah,
4233 width_spec, aw_spec, ah_spec, BACKPAT, (-1), curved, 0, 3,
4234 trans_pat);
4235 } else {
4236 DumpPolyPath(FP, ObjPtr, intv, intn, smooth, style, width, aw, ah,
4237 width_spec, aw_spec, ah_spec, BACKPAT, (-1), curved, 0, 3,
4238 trans_pat);
4239 }
4240 fprintf(FP, " %s\n", gPsCmd[PS_GRESTORE]);
4241 }
4242 if (curved != LT_INTSPLINE) {
4243 DumpPolyPath(FP, ObjPtr, v, num_pts, smooth, style, width, aw, ah,
4244 width_spec, aw_spec, ah_spec, pen, (-1), curved, dash, 0,
4245 trans_pat);
4246 } else {
4247 DumpPolyPath(FP, ObjPtr, intv, intn, smooth, style, width, aw, ah,
4248 width_spec, aw_spec, ah_spec, pen, (-1), curved, dash, 0,
4249 trans_pat);
4250 }
4251 fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]);
4252
4253 retracted_arrow = (RetractedArrowAttr(ObjPtr) ||
4254 AutoRetractedArrowAttr(ObjPtr, TRUE));
4255
4256 if (ObjPtr->ctm == NULL) {
4257 if (curved != LT_INTSPLINE) {
4258 switch (style) {
4259 case LS_PLAIN: break;
4260 case LS_LEFT:
4261 if (retracted_arrow) {
4262 DumpArrow(FP, &v[2], &v[1], aw, ah, aw_spec, ah_spec,
4263 pen, trans_pat, color_index);
4264 } else {
4265 DumpArrow(FP, &v[1], &v[0], aw, ah, aw_spec, ah_spec,
4266 pen, trans_pat, color_index);
4267 }
4268 break;
4269 case LS_RIGHT:
4270 if (retracted_arrow) {
4271 DumpArrow(FP, &v[num_pts-3], &v[num_pts-2], aw, ah,
4272 aw_spec, ah_spec, pen, trans_pat, color_index);
4273 } else {
4274 DumpArrow(FP, &v[num_pts-2], &v[num_pts-1], aw, ah,
4275 aw_spec, ah_spec, pen, trans_pat, color_index);
4276 }
4277 break;
4278 case LS_DOUBLE:
4279 if (retracted_arrow) {
4280 DumpArrow(FP, &v[2], &v[1], aw, ah, aw_spec, ah_spec,
4281 pen, trans_pat, color_index);
4282 DumpArrow(FP, &v[num_pts-3], &v[num_pts-2], aw, ah,
4283 aw_spec, ah_spec, pen, trans_pat, color_index);
4284 } else {
4285 DumpArrow(FP, &v[1], &v[0], aw, ah, aw_spec, ah_spec,
4286 pen, trans_pat, color_index);
4287 DumpArrow(FP, &v[num_pts-2], &v[num_pts-1], aw, ah,
4288 aw_spec, ah_spec, pen, trans_pat, color_index);
4289 }
4290 break;
4291 }
4292 } else {
4293 switch (style) {
4294 case LS_PLAIN: break;
4295 case LS_LEFT:
4296 if (retracted_arrow) {
4297 DumpArrow(FP, &intv[2], &v[1], aw, ah, aw_spec, ah_spec,
4298 pen, trans_pat, color_index);
4299 } else {
4300 DumpArrow(FP, &intv[1], &intv[0], aw, ah, aw_spec, ah_spec,
4301 pen, trans_pat, color_index);
4302 }
4303 break;
4304 case LS_RIGHT:
4305 if (retracted_arrow) {
4306 DumpArrow(FP, &intv[intn-3], &v[num_pts-2], aw, ah,
4307 aw_spec, ah_spec, pen, trans_pat, color_index);
4308 } else {
4309 DumpArrow(FP, &intv[intn-2], &intv[intn-1], aw, ah,
4310 aw_spec, ah_spec, pen, trans_pat, color_index);
4311 }
4312 break;
4313 case LS_DOUBLE:
4314 if (retracted_arrow) {
4315 DumpArrow(FP, &intv[2], &v[1], aw, ah, aw_spec, ah_spec,
4316 pen, trans_pat, color_index);
4317 DumpArrow(FP, &intv[intn-3], &v[num_pts-2], aw, ah,
4318 aw_spec, ah_spec, pen, trans_pat, color_index);
4319 } else {
4320 DumpArrow(FP, &intv[1], &intv[0], aw, ah, aw_spec, ah_spec,
4321 pen, trans_pat, color_index);
4322 DumpArrow(FP, &intv[intn-2], &intv[intn-1], aw, ah,
4323 aw_spec, ah_spec, pen, trans_pat, color_index);
4324 }
4325 break;
4326 }
4327 }
4328 } else {
4329 IntPoint ip0, ip1;
4330
4331 if (curved != LT_INTSPLINE) {
4332 switch (style) {
4333 case LS_PLAIN: break;
4334 case LS_LEFT:
4335 if (retracted_arrow) {
4336 TransformObjectV(ObjPtr, &v[2], &ip0);
4337 TransformObjectV(ObjPtr, &v[1], &ip1);
4338 DumpArrow(FP, &ip0, &ip1, aw, ah, aw_spec, ah_spec,
4339 pen, trans_pat, color_index);
4340 } else {
4341 TransformObjectV(ObjPtr, &v[1], &ip0);
4342 TransformObjectV(ObjPtr, &v[0], &ip1);
4343 DumpArrow(FP, &ip0, &ip1, aw, ah, aw_spec, ah_spec,
4344 pen, trans_pat, color_index);
4345 }
4346 break;
4347 case LS_RIGHT:
4348 if (retracted_arrow) {
4349 TransformObjectV(ObjPtr, &v[num_pts-3], &ip0);
4350 TransformObjectV(ObjPtr, &v[num_pts-2], &ip1);
4351 DumpArrow(FP, &ip0, &ip1, aw, ah, aw_spec, ah_spec,
4352 pen, trans_pat, color_index);
4353 } else {
4354 TransformObjectV(ObjPtr, &v[num_pts-2], &ip0);
4355 TransformObjectV(ObjPtr, &v[num_pts-1], &ip1);
4356 DumpArrow(FP, &ip0, &ip1, aw, ah, aw_spec, ah_spec,
4357 pen, trans_pat, color_index);
4358 }
4359 break;
4360 case LS_DOUBLE:
4361 if (retracted_arrow) {
4362 TransformObjectV(ObjPtr, &v[2], &ip0);
4363 TransformObjectV(ObjPtr, &v[1], &ip1);
4364 DumpArrow(FP, &ip0, &ip1, aw, ah, aw_spec, ah_spec,
4365 pen, trans_pat, color_index);
4366 TransformObjectV(ObjPtr, &v[num_pts-3], &ip0);
4367 TransformObjectV(ObjPtr, &v[num_pts-2], &ip1);
4368 DumpArrow(FP, &ip0, &ip1, aw, ah, aw_spec, ah_spec,
4369 pen, trans_pat, color_index);
4370 } else {
4371 TransformObjectV(ObjPtr, &v[1], &ip0);
4372 TransformObjectV(ObjPtr, &v[0], &ip1);
4373 DumpArrow(FP, &ip0, &ip1, aw, ah, aw_spec, ah_spec,
4374 pen, trans_pat, color_index);
4375 TransformObjectV(ObjPtr, &v[num_pts-2], &ip0);
4376 TransformObjectV(ObjPtr, &v[num_pts-1], &ip1);
4377 DumpArrow(FP, &ip0, &ip1,aw, ah, aw_spec, ah_spec,
4378 pen, trans_pat, color_index);
4379 }
4380 break;
4381 }
4382 } else {
4383 switch (style) {
4384 case LS_PLAIN: break;
4385 case LS_LEFT:
4386 if (retracted_arrow) {
4387 TransformObjectV(ObjPtr, &intv[2], &ip0);
4388 TransformObjectV(ObjPtr, &v[1], &ip1);
4389 DumpArrow(FP, &ip0, &ip1, aw, ah, aw_spec, ah_spec,
4390 pen, trans_pat, color_index);
4391 } else {
4392 TransformObjectV(ObjPtr, &intv[1], &ip0);
4393 TransformObjectV(ObjPtr, &intv[0], &ip1);
4394 DumpArrow(FP, &ip0, &ip1, aw, ah, aw_spec, ah_spec,
4395 pen, trans_pat, color_index);
4396 }
4397 break;
4398 case LS_RIGHT:
4399 if (retracted_arrow) {
4400 TransformObjectV(ObjPtr, &intv[intn-3], &ip0);
4401 TransformObjectV(ObjPtr, &v[num_pts-2], &ip1);
4402 DumpArrow(FP, &ip0, &ip1, aw, ah, aw_spec, ah_spec,
4403 pen, trans_pat, color_index);
4404 } else {
4405 TransformObjectV(ObjPtr, &intv[intn-2], &ip0);
4406 TransformObjectV(ObjPtr, &intv[intn-1], &ip1);
4407 DumpArrow(FP, &ip0, &ip1, aw, ah, aw_spec, ah_spec,
4408 pen, trans_pat, color_index);
4409 }
4410 break;
4411 case LS_DOUBLE:
4412 if (retracted_arrow) {
4413 TransformObjectV(ObjPtr, &intv[2], &ip0);
4414 TransformObjectV(ObjPtr, &v[1], &ip1);
4415 DumpArrow(FP, &ip0, &ip1, aw, ah, aw_spec, ah_spec,
4416 pen, trans_pat, color_index);
4417 TransformObjectV(ObjPtr, &intv[intn-3], &ip0);
4418 TransformObjectV(ObjPtr, &v[num_pts-2], &ip1);
4419 DumpArrow(FP, &ip0, &ip1, aw, ah, aw_spec, ah_spec,
4420 pen, trans_pat, color_index);
4421 } else {
4422 TransformObjectV(ObjPtr, &intv[1], &ip0);
4423 TransformObjectV(ObjPtr, &intv[0], &ip1);
4424 DumpArrow(FP, &ip0, &ip1, aw, ah, aw_spec, ah_spec,
4425 pen, trans_pat, color_index);
4426 TransformObjectV(ObjPtr, &intv[intn-2], &ip0);
4427 TransformObjectV(ObjPtr, &intv[intn-1], &ip1);
4428 DumpArrow(FP, &ip0, &ip1, aw, ah, aw_spec, ah_spec,
4429 pen, trans_pat, color_index);
4430 }
4431 break;
4432 }
4433 }
4434 }
4435 if (ObjPtr->ctm != NULL) fprintf(FP, "%s\n", gPsCmd[PS_GRESTORE]);
4436 fprintf(FP, "\n");
4437 }
4438
4439 /* --------------------- NeedsToCachePolyObj() --------------------- */
4440
NeedsToCachePolyObj(ObjPtr)4441 int NeedsToCachePolyObj(ObjPtr)
4442 struct ObjRec *ObjPtr;
4443 {
4444 return (ObjPtr->ctm != NULL);
4445 }
4446
4447 /* --------------------- DrawPolyObj() --------------------- */
4448
4449 static
MakeCachedPoly(ObjPtr)4450 void MakeCachedPoly(ObjPtr)
4451 struct ObjRec *ObjPtr;
4452 {
4453 int i;
4454 struct PolyRec *poly_ptr=ObjPtr->detail.p;
4455 IntPoint *pv=poly_ptr->vlist, *intvs=NULL, *vs=NULL;
4456 int n=poly_ptr->n, intn=0;
4457
4458 if (ObjPtr->ctm == NULL) return;
4459 if (poly_ptr->rotated_vlist != NULL) free(poly_ptr->rotated_vlist);
4460 if (poly_ptr->rotated_asvlist != NULL) free(poly_ptr->rotated_asvlist);
4461 poly_ptr->rotated_n = poly_ptr->rotated_asn = 0;
4462 poly_ptr->rotated_vlist = poly_ptr->rotated_asvlist = NULL;
4463
4464 if (poly_ptr->curved == LT_STRUCT_SPLINE) {
4465 pv = poly_ptr->ssvlist;
4466 n = poly_ptr->ssn;
4467 }
4468 vs = (IntPoint*)malloc((n+1)*sizeof(IntPoint));
4469 if (vs == NULL) FailAllocMessage();
4470 for (i=0; i < n; i++) {
4471 int x, y;
4472
4473 TransformPointThroughCTM(pv[i].x-ObjPtr->x, pv[i].y-ObjPtr->y,
4474 ObjPtr->ctm, &x, &y);
4475 vs[i].x = x+ObjPtr->x;
4476 vs[i].y = y+ObjPtr->y;
4477 }
4478 vs[n].x = vs[0].x;
4479 vs[n].y = vs[0].y;
4480
4481 switch (poly_ptr->curved) {
4482 case LT_STRAIGHT:
4483 case LT_SPLINE:
4484 poly_ptr->rotated_vlist = MakeMultiSplinePolyVertex(
4485 poly_ptr->curved, &(poly_ptr->rotated_n), poly_ptr->smooth,
4486 drawOrigX, drawOrigY, n, vs);
4487 break;
4488 case LT_STRUCT_SPLINE:
4489 poly_ptr->rotated_vlist = MakeMultiSplinePolyVertex(
4490 poly_ptr->curved, &(poly_ptr->rotated_n), poly_ptr->ssmooth,
4491 drawOrigX, drawOrigY, n, vs);
4492 break;
4493 case LT_INTSPLINE:
4494 poly_ptr->rotated_vlist = MakeIntSplinePolyVertex(
4495 &(poly_ptr->rotated_n), &(intn), &(intvs),
4496 drawOrigX, drawOrigY, n, vs);
4497 break;
4498 }
4499 poly_ptr->rotated_vlist[poly_ptr->rotated_n].x =
4500 poly_ptr->rotated_vlist[0].x;
4501 poly_ptr->rotated_vlist[poly_ptr->rotated_n].y =
4502 poly_ptr->rotated_vlist[0].y;
4503
4504 if (poly_ptr->style != LS_PLAIN && !RetractedArrowAttr(ObjPtr) &&
4505 !AutoRetractedArrowAttr(ObjPtr,TRUE)) {
4506 int aw=poly_ptr->aw, dx, dy;
4507 double len, sin, cos;
4508
4509 if (aw == 0) aw = 1;
4510
4511 switch (poly_ptr->curved) {
4512 case LT_STRAIGHT:
4513 case LT_SPLINE:
4514 case LT_STRUCT_SPLINE:
4515 dx = vs[1].x - vs[0].x;
4516 dy = vs[1].y - vs[0].y;
4517 if ((poly_ptr->style & LS_LEFT) && (dx != 0 || dy != 0)) {
4518 len = (double)sqrt((double)(((double)dx)*((double)dx) +
4519 ((double)dy)*((double)dy)));
4520 sin = ((double)dy)/len;
4521 cos = ((double)dx)/len;
4522 vs[0].x = round(vs[0].x+RETREAT*aw*cos);
4523 vs[0].y = round(vs[0].y+RETREAT*aw*sin);
4524 }
4525 dx = vs[n-1].x - vs[n-2].x;
4526 dy = vs[n-1].y - vs[n-2].y;
4527 if ((poly_ptr->style & LS_RIGHT) && (dx != 0 || dy != 0)) {
4528 len = (double)sqrt((double)(((double)dx)*((double)dx) +
4529 ((double)dy)*((double)dy)));
4530 sin = ((double)dy)/len;
4531 cos = ((double)dx)/len;
4532 vs[n-1].x = round(vs[n-1].x-(RETREAT*aw*cos));
4533 vs[n-1].y = round(vs[n-1].y-(RETREAT*aw*sin));
4534 }
4535 break;
4536 case LT_INTSPLINE:
4537 dx = intvs[1].x - intvs[0].x;
4538 dy = intvs[1].y - intvs[0].y;
4539 if ((poly_ptr->style & LS_LEFT) && (dx != 0 || dy != 0)) {
4540 len = (double)sqrt((double)(((double)dx)*((double)dx) +
4541 ((double)dy)*((double)dy)));
4542 sin = ((double)dy)/len;
4543 cos = ((double)dx)/len;
4544 intvs[0].x = round(intvs[0].x+RETREAT*aw*cos);
4545 intvs[0].y = round(intvs[0].y+RETREAT*aw*sin);
4546 }
4547 dx = intvs[intn-1].x - intvs[intn-2].x;
4548 dy = intvs[intn-1].y - intvs[intn-2].y;
4549 if ((poly_ptr->style & LS_RIGHT) && (dx != 0 || dy != 0)) {
4550 len = (double)sqrt((double)(((double)dx)*((double)dx) +
4551 ((double)dy)*((double)dy)));
4552 sin = ((double)dy)/len;
4553 cos = ((double)dx)/len;
4554 intvs[intn-1].x = round(intvs[intn-1].x-(RETREAT*aw*cos));
4555 intvs[intn-1].y = round(intvs[intn-1].y-(RETREAT*aw*sin));
4556 }
4557 break;
4558 }
4559 }
4560 if (poly_ptr->style != LS_PLAIN) {
4561 switch (poly_ptr->curved) {
4562 case LT_STRAIGHT:
4563 case LT_SPLINE:
4564 poly_ptr->rotated_asvlist = MakeMultiSplinePolyVertex(
4565 poly_ptr->curved, &(poly_ptr->rotated_asn), poly_ptr->smooth,
4566 drawOrigX, drawOrigY, n, vs);
4567 break;
4568 case LT_STRUCT_SPLINE:
4569 poly_ptr->rotated_asvlist = MakeMultiSplinePolyVertex(
4570 poly_ptr->curved, &(poly_ptr->rotated_asn), poly_ptr->ssmooth,
4571 drawOrigX, drawOrigY, n, vs);
4572 break;
4573 case LT_INTSPLINE:
4574 poly_ptr->rotated_asvlist = MakeSplinePolyVertex(
4575 0, poly_ptr->curved, &(poly_ptr->rotated_asn),
4576 drawOrigX, drawOrigY, intn, intvs);
4577 break;
4578 }
4579 }
4580 free(vs);
4581 if (intvs != NULL) free(intvs);
4582 }
4583
4584 static
SetArrowVsForDraw(obj_ptr,retracted_arrow,real_x_off,real_y_off,v0,v1,vnminus2,vnminus1)4585 void SetArrowVsForDraw(obj_ptr, retracted_arrow, real_x_off, real_y_off,
4586 v0, v1, vnminus2, vnminus1)
4587 struct ObjRec *obj_ptr;
4588 int retracted_arrow, real_x_off, real_y_off;
4589 XPoint *v0, *v1, *vnminus2, *vnminus1;
4590 {
4591 struct PolyRec *poly_ptr=obj_ptr->detail.p;
4592 int n=poly_ptr->n;
4593
4594 if (obj_ptr->ctm == NULL) {
4595 if (poly_ptr->curved != LT_INTSPLINE) {
4596 IntPoint *vs=poly_ptr->vlist;
4597
4598 if (poly_ptr->curved == LT_STRUCT_SPLINE) {
4599 n = poly_ptr->ssn;
4600 vs = poly_ptr->ssvlist;
4601 }
4602 if (retracted_arrow) {
4603 v0->x = ZOOMED_SIZE(vs[1].x-real_x_off);
4604 v0->y = ZOOMED_SIZE(vs[1].y-real_y_off);
4605 v1->x = ZOOMED_SIZE(vs[2].x-real_x_off);
4606 v1->y = ZOOMED_SIZE(vs[2].y-real_y_off);
4607 vnminus2->x = ZOOMED_SIZE(vs[n-3].x-real_x_off);
4608 vnminus2->y = ZOOMED_SIZE(vs[n-3].y-real_y_off);
4609 vnminus1->x = ZOOMED_SIZE(vs[n-2].x-real_x_off);
4610 vnminus1->y = ZOOMED_SIZE(vs[n-2].y-real_y_off);
4611 } else {
4612 v0->x = ZOOMED_SIZE(vs[0].x-real_x_off);
4613 v0->y = ZOOMED_SIZE(vs[0].y-real_y_off);
4614 v1->x = ZOOMED_SIZE(vs[1].x-real_x_off);
4615 v1->y = ZOOMED_SIZE(vs[1].y-real_y_off);
4616 vnminus2->x = ZOOMED_SIZE(vs[n-2].x-real_x_off);
4617 vnminus2->y = ZOOMED_SIZE(vs[n-2].y-real_y_off);
4618 vnminus1->x = ZOOMED_SIZE(vs[n-1].x-real_x_off);
4619 vnminus1->y = ZOOMED_SIZE(vs[n-1].y-real_y_off);
4620 }
4621 } else {
4622 int intn=poly_ptr->intn;
4623 IntPoint *intvlist=poly_ptr->intvlist;
4624
4625 if (retracted_arrow) {
4626 int n=poly_ptr->n;
4627 IntPoint *vs=poly_ptr->vlist;
4628
4629 v0->x = ZOOMED_SIZE(vs[1].x-real_x_off);
4630 v0->y = ZOOMED_SIZE(vs[1].y-real_y_off);
4631 v1->x = ZOOMED_SIZE(intvlist[2].x-real_x_off);
4632 v1->y = ZOOMED_SIZE(intvlist[2].y-real_y_off);
4633 vnminus2->x = ZOOMED_SIZE(intvlist[intn-3].x-real_x_off);
4634 vnminus2->y = ZOOMED_SIZE(intvlist[intn-3].y-real_y_off);
4635 vnminus1->x = ZOOMED_SIZE(vs[n-2].x-real_x_off);
4636 vnminus1->y = ZOOMED_SIZE(vs[n-2].y-real_y_off);
4637 } else {
4638 v0->x = ZOOMED_SIZE(intvlist[0].x-real_x_off);
4639 v0->y = ZOOMED_SIZE(intvlist[0].y-real_y_off);
4640 v1->x = ZOOMED_SIZE(intvlist[1].x-real_x_off);
4641 v1->y = ZOOMED_SIZE(intvlist[1].y-real_y_off);
4642 vnminus2->x = ZOOMED_SIZE(intvlist[intn-2].x-real_x_off);
4643 vnminus2->y = ZOOMED_SIZE(intvlist[intn-2].y-real_y_off);
4644 vnminus1->x = ZOOMED_SIZE(intvlist[intn-1].x-real_x_off);
4645 vnminus1->y = ZOOMED_SIZE(intvlist[intn-1].y-real_y_off);
4646 }
4647 }
4648 } else {
4649 int x, y;
4650
4651 if (poly_ptr->curved != LT_INTSPLINE) {
4652 IntPoint *vs=poly_ptr->vlist;
4653
4654 if (poly_ptr->curved == LT_STRUCT_SPLINE) {
4655 n = poly_ptr->ssn;
4656 vs = poly_ptr->ssvlist;
4657 }
4658 if (retracted_arrow) {
4659 TransformPointThroughCTM(vs[1].x-obj_ptr->x, vs[1].y-obj_ptr->y,
4660 obj_ptr->ctm, &x, &y);
4661 v0->x = ZOOMED_SIZE(x+obj_ptr->x-real_x_off);
4662 v0->y = ZOOMED_SIZE(y+obj_ptr->y-real_y_off);
4663 TransformPointThroughCTM(vs[2].x-obj_ptr->x, vs[2].y-obj_ptr->y,
4664 obj_ptr->ctm, &x, &y);
4665 v1->x = ZOOMED_SIZE(x+obj_ptr->x-real_x_off);
4666 v1->y = ZOOMED_SIZE(y+obj_ptr->y-real_y_off);
4667 TransformPointThroughCTM(vs[n-3].x-obj_ptr->x, vs[n-3].y-obj_ptr->y,
4668 obj_ptr->ctm, &x, &y);
4669 vnminus2->x = ZOOMED_SIZE(x+obj_ptr->x-real_x_off);
4670 vnminus2->y = ZOOMED_SIZE(y+obj_ptr->y-real_y_off);
4671 TransformPointThroughCTM(vs[n-2].x-obj_ptr->x, vs[n-2].y-obj_ptr->y,
4672 obj_ptr->ctm, &x, &y);
4673 vnminus1->x = ZOOMED_SIZE(x+obj_ptr->x-real_x_off);
4674 vnminus1->y = ZOOMED_SIZE(y+obj_ptr->y-real_y_off);
4675 } else {
4676 TransformPointThroughCTM(vs[0].x-obj_ptr->x, vs[0].y-obj_ptr->y,
4677 obj_ptr->ctm, &x, &y);
4678 v0->x = ZOOMED_SIZE(x+obj_ptr->x-real_x_off);
4679 v0->y = ZOOMED_SIZE(y+obj_ptr->y-real_y_off);
4680 TransformPointThroughCTM(vs[1].x-obj_ptr->x, vs[1].y-obj_ptr->y,
4681 obj_ptr->ctm, &x, &y);
4682 v1->x = ZOOMED_SIZE(x+obj_ptr->x-real_x_off);
4683 v1->y = ZOOMED_SIZE(y+obj_ptr->y-real_y_off);
4684 TransformPointThroughCTM(vs[n-2].x-obj_ptr->x, vs[n-2].y-obj_ptr->y,
4685 obj_ptr->ctm, &x, &y);
4686 vnminus2->x = ZOOMED_SIZE(x+obj_ptr->x-real_x_off);
4687 vnminus2->y = ZOOMED_SIZE(y+obj_ptr->y-real_y_off);
4688 TransformPointThroughCTM(vs[n-1].x-obj_ptr->x, vs[n-1].y-obj_ptr->y,
4689 obj_ptr->ctm, &x, &y);
4690 vnminus1->x = ZOOMED_SIZE(x+obj_ptr->x-real_x_off);
4691 vnminus1->y = ZOOMED_SIZE(y+obj_ptr->y-real_y_off);
4692 }
4693 } else {
4694 int intn=poly_ptr->intn;
4695 IntPoint *intvlist=poly_ptr->intvlist;
4696
4697 if (retracted_arrow) {
4698 int n=poly_ptr->n;
4699 IntPoint *vs=poly_ptr->vlist;
4700
4701 TransformPointThroughCTM(vs[1].x-obj_ptr->x, vs[1].y-obj_ptr->y,
4702 obj_ptr->ctm, &x, &y);
4703 v0->x = ZOOMED_SIZE(x+obj_ptr->x-real_x_off);
4704 v0->y = ZOOMED_SIZE(y+obj_ptr->y-real_y_off);
4705 TransformPointThroughCTM(intvlist[2].x-obj_ptr->x,
4706 intvlist[2].y-obj_ptr->y, obj_ptr->ctm, &x, &y);
4707 v1->x = ZOOMED_SIZE(x+obj_ptr->x-real_x_off);
4708 v1->y = ZOOMED_SIZE(y+obj_ptr->y-real_y_off);
4709 TransformPointThroughCTM(intvlist[intn-3].x-obj_ptr->x,
4710 intvlist[intn-3].y-obj_ptr->y, obj_ptr->ctm, &x, &y);
4711 vnminus2->x = ZOOMED_SIZE(x+obj_ptr->x-real_x_off);
4712 vnminus2->y = ZOOMED_SIZE(y+obj_ptr->y-real_y_off);
4713 TransformPointThroughCTM(vs[n-2].x-obj_ptr->x, vs[n-2].y-obj_ptr->y,
4714 obj_ptr->ctm, &x, &y);
4715 vnminus1->x = ZOOMED_SIZE(x+obj_ptr->x-real_x_off);
4716 vnminus1->y = ZOOMED_SIZE(y+obj_ptr->y-real_y_off);
4717 } else {
4718 TransformPointThroughCTM(intvlist[0].x-obj_ptr->x,
4719 intvlist[0].y-obj_ptr->y, obj_ptr->ctm, &x, &y);
4720 v0->x = ZOOMED_SIZE(x+obj_ptr->x-real_x_off);
4721 v0->y = ZOOMED_SIZE(y+obj_ptr->y-real_y_off);
4722 TransformPointThroughCTM(intvlist[1].x-obj_ptr->x,
4723 intvlist[1].y-obj_ptr->y, obj_ptr->ctm, &x, &y);
4724 v1->x = ZOOMED_SIZE(x+obj_ptr->x-real_x_off);
4725 v1->y = ZOOMED_SIZE(y+obj_ptr->y-real_y_off);
4726 TransformPointThroughCTM(intvlist[intn-2].x-obj_ptr->x,
4727 intvlist[intn-2].y-obj_ptr->y, obj_ptr->ctm, &x, &y);
4728 vnminus2->x = ZOOMED_SIZE(x+obj_ptr->x-real_x_off);
4729 vnminus2->y = ZOOMED_SIZE(y+obj_ptr->y-real_y_off);
4730 TransformPointThroughCTM(intvlist[intn-1].x-obj_ptr->x,
4731 intvlist[intn-1].y-obj_ptr->y, obj_ptr->ctm, &x, &y);
4732 vnminus1->x = ZOOMED_SIZE(x+obj_ptr->x-real_x_off);
4733 vnminus1->y = ZOOMED_SIZE(y+obj_ptr->y-real_y_off);
4734 }
4735 }
4736 }
4737 }
4738
DrawPolyObj(Win,XOff,YOff,ObjPtr)4739 void DrawPolyObj(Win, XOff, YOff, ObjPtr)
4740 Window Win;
4741 int XOff, YOff;
4742 struct ObjRec *ObjPtr;
4743 {
4744 struct PolyRec *poly_ptr=ObjPtr->detail.p;
4745 XPoint *v, tmp_v[4];
4746 XPoint v0, v1, vnminus2, vnminus1;
4747 int trans_pat, pen, width, pixel, fill, n, dash, real_x_off, real_y_off;
4748 int style, aw, ah, num_pts, left_dx, left_dy, right_dx, right_dy;
4749 int retracted_arrow=FALSE;
4750 short tmps;
4751 double len, sin, cos;
4752 XGCValues values;
4753
4754 trans_pat = ObjPtr->trans_pat;
4755 n = poly_ptr->n;
4756 fill = poly_ptr->fill;
4757 width = poly_ptr->width;
4758 aw = poly_ptr->aw;
4759 ah = poly_ptr->ah;
4760 pen = poly_ptr->pen;
4761 style = poly_ptr->style;
4762 dash = poly_ptr->dash;
4763 pixel = colorPixels[ObjPtr->color];
4764
4765 if (NeedsToCachePolyObj(ObjPtr) && poly_ptr->rotated_vlist==NULL) {
4766 MakeCachedPoly(ObjPtr);
4767 }
4768 if (userDisableRedraw) return;
4769
4770 if ((fill == NONEPAT || (trans_pat && fill == BACKPAT)) &&
4771 (pen == NONEPAT || (trans_pat && pen == BACKPAT))) {
4772 return;
4773 }
4774 real_x_off = (zoomedIn ? XOff : (XOff>>zoomScale)<<zoomScale);
4775 real_y_off = (zoomedIn ? YOff : (YOff>>zoomScale)<<zoomScale);
4776
4777 v = poly_ptr->svlist;
4778 num_pts = poly_ptr->sn;
4779
4780 if (v != NULL) {
4781 v[num_pts].x = v[0].x;
4782 v[num_pts].y = v[0].y;
4783 }
4784 if (fill != NONEPAT) {
4785 values.foreground = GetDrawingBgPixel(fill, pixel);
4786 values.function = GXcopy;
4787 values.fill_style = (trans_pat ? FillStippled : FillOpaqueStippled);
4788 values.stipple = patPixmap[fill];
4789 XChangeGC(mainDisplay, drawGC,
4790 GCForeground | GCFunction | GCFillStyle | GCStipple, &values);
4791 if (ObjPtr->ctm == NULL) {
4792 XFillPolygon(mainDisplay, Win, drawGC, v, num_pts+1, Complex,
4793 CoordModeOrigin);
4794 } else {
4795 XFillPolygon(mainDisplay, Win, drawGC, poly_ptr->rotated_vlist,
4796 poly_ptr->rotated_n+1, Complex, CoordModeOrigin);
4797 }
4798 }
4799
4800 if (pen == NONEPAT || (pen == BACKPAT && trans_pat)) return;
4801
4802 retracted_arrow = (RetractedArrowAttr(ObjPtr) ||
4803 AutoRetractedArrowAttr(ObjPtr, TRUE));
4804
4805 SetArrowVsForDraw(ObjPtr, retracted_arrow, real_x_off, real_y_off,
4806 &v0, &v1, &vnminus2, &vnminus1);
4807
4808 aw = ZOOMED_SIZE(aw); if (aw == 0) aw = 1;
4809 ah = ZOOMED_SIZE(ah); if (ah == 0) ah = 1;
4810
4811 values.foreground = GetDrawingBgPixel(pen, pixel);
4812 values.function = GXcopy;
4813 values.fill_style = (trans_pat ? FillStippled : FillOpaqueStippled);
4814 values.stipple = patPixmap[pen];
4815 values.line_width = ZOOMED_SIZE(width);
4816 #ifdef NO_THIN_LINE
4817 if (values.line_width < 1) values.line_width = 1;
4818 #endif
4819 values.join_style = JoinBevel;
4820 if (dash != 0) {
4821 XSetDashes(mainDisplay, drawGC, 0, dashList[dash],
4822 dashListLength[dash]);
4823 values.line_style = LineOnOffDash;
4824 } else {
4825 values.line_style = LineSolid;
4826 }
4827 XChangeGC(mainDisplay, drawGC,
4828 GCForeground | GCFunction | GCFillStyle | GCStipple | GCLineWidth |
4829 GCLineStyle | GCJoinStyle, &values);
4830
4831 left_dx = v1.x - v0.x;
4832 left_dy = v1.y - v0.y;
4833
4834 if ((style & LS_LEFT) && (left_dx != 0 || left_dy != 0)) {
4835 /* adjust the first point */
4836 len = (double)sqrt((double)(((double)left_dx)*((double)left_dx) +
4837 ((double)left_dy)*((double)left_dy)));
4838 sin = ((double)left_dy)/len;
4839 cos = ((double)left_dx)/len;
4840
4841 tmp_v[0].x = tmp_v[3].x = v0.x;
4842 tmp_v[0].y = tmp_v[3].y = v0.y;
4843 tmps = round(v0.x + aw*cos - ah*sin); tmp_v[1].x = tmps;
4844 tmps = round(v0.y + aw*sin + ah*cos); tmp_v[1].y = tmps;
4845 tmps = round(v0.x + aw*cos + ah*sin); tmp_v[2].x = tmps;
4846 tmps = round(v0.y + aw*sin - ah*cos); tmp_v[2].y = tmps;
4847
4848 XFillPolygon(mainDisplay, Win, drawGC, tmp_v, 4, Convex,
4849 CoordModeOrigin);
4850 }
4851 right_dx = vnminus1.x - vnminus2.x;
4852 right_dy = vnminus1.y - vnminus2.y;
4853
4854 if ((style & LS_RIGHT) && (right_dx != 0 || right_dy != 0)) {
4855 /* adjust the last point */
4856 len = (double)sqrt((double)(((double)right_dx)*((double)right_dx) +
4857 ((double)right_dy)*((double)right_dy)));
4858 sin = ((double)right_dy)/len;
4859 cos = ((double)right_dx)/len;
4860
4861 tmp_v[0].x = tmp_v[3].x = vnminus1.x;
4862 tmp_v[0].y = tmp_v[3].y = vnminus1.y;
4863 tmps = round(vnminus1.x - aw*cos + ah*sin); tmp_v[1].x = tmps;
4864 tmps = round(vnminus1.y - aw*sin - ah*cos); tmp_v[1].y = tmps;
4865 tmps = round(vnminus1.x - aw*cos - ah*sin); tmp_v[2].x = tmps;
4866 tmps = round(vnminus1.y - aw*sin + ah*cos); tmp_v[2].y = tmps;
4867
4868 XFillPolygon(mainDisplay, Win, drawGC, tmp_v, 4, Convex,
4869 CoordModeOrigin);
4870 }
4871 if (style != LS_PLAIN) {
4872 if (ObjPtr->ctm == NULL) {
4873 MyDrawLines(mainDisplay, Win, drawGC, poly_ptr->asvlist,
4874 poly_ptr->asn);
4875 } else {
4876 MyDrawLines(mainDisplay, Win, drawGC, poly_ptr->rotated_asvlist,
4877 poly_ptr->rotated_asn);
4878 }
4879 } else {
4880 int draw_zero_length_poly=FALSE;
4881
4882 #ifndef DONT_DRAW_ZERO_LENGTH_POLY_AS_DOT
4883 if (ObjPtr->ctm == NULL) {
4884 if (num_pts == 2 && v[0].x == v[1].x && v[0].y == v[1].y) {
4885 draw_zero_length_poly = TRUE;
4886 }
4887 } else {
4888 if (poly_ptr->rotated_n == 2 &&
4889 poly_ptr->rotated_vlist[0].x == poly_ptr->rotated_vlist[1].x &&
4890 poly_ptr->rotated_vlist[0].y == poly_ptr->rotated_vlist[1].y) {
4891 draw_zero_length_poly = TRUE;
4892 }
4893 }
4894 #endif /* ~DONT_DRAW_ZERO_LENGTH_POLY_AS_DOT */
4895 if (ObjPtr->ctm == NULL) {
4896 if (draw_zero_length_poly) {
4897 values.cap_style = CapRound;
4898 XChangeGC(mainDisplay, drawGC, GCCapStyle, &values);
4899 }
4900 MyDrawLines(mainDisplay, Win, drawGC, v, num_pts);
4901 if (draw_zero_length_poly) {
4902 values.cap_style = CapButt;
4903 XChangeGC(mainDisplay, drawGC, GCCapStyle, &values);
4904 }
4905 } else {
4906 if (draw_zero_length_poly) {
4907 values.cap_style = CapRound;
4908 XChangeGC(mainDisplay, drawGC, GCCapStyle, &values);
4909 }
4910 MyDrawLines(mainDisplay, Win, drawGC, poly_ptr->rotated_vlist,
4911 poly_ptr->rotated_n);
4912 if (draw_zero_length_poly) {
4913 values.cap_style = CapButt;
4914 XChangeGC(mainDisplay, drawGC, GCCapStyle, &values);
4915 }
4916 }
4917 }
4918 values.join_style = JoinMiter;
4919 XChangeGC(mainDisplay, drawGC, GCJoinStyle, &values);
4920 }
4921
4922 /* --------------------- SaveSmoothHinge() --------------------- */
4923
4924 static char hexValue[]="0123456789abcdef";
4925
SaveSmoothHinge(FP,Curved,NumPts,Smooth)4926 void SaveSmoothHinge(FP, Curved, NumPts, Smooth)
4927 FILE *FP;
4928 int Curved, NumPts;
4929 char *Smooth;
4930 {
4931 register int nibble_count=0, bit_count=0, data=0, j;
4932
4933 if (Curved == LT_INTSPLINE || Smooth == NULL) return;
4934
4935 for (j=0; j < NumPts; j++) {
4936 data = (Smooth[j] ? (data<<1) | 1 : (data<<1));
4937
4938 if (++bit_count == 4) {
4939 if (nibble_count++ == 64) {
4940 nibble_count = 1;
4941 if (fprintf(FP, "\n ") == EOF) writeFileFailed = TRUE;
4942 }
4943 if (fprintf(FP, "%c", hexValue[data]) == EOF) {
4944 writeFileFailed = TRUE;
4945 }
4946 bit_count = 0;
4947 data = 0;
4948 }
4949 }
4950 if ((NumPts & 0x3) != 0) {
4951 data <<= (4 - (NumPts & 0x3));
4952 if (nibble_count++ == 64) {
4953 nibble_count = 1;
4954 if (fprintf(FP, "\n ") == EOF) writeFileFailed = TRUE;
4955 }
4956 if (fprintf(FP, "%c", hexValue[data]) == EOF) writeFileFailed = TRUE;
4957 }
4958 }
4959
4960 /* --------------------- SavePolyObj() --------------------- */
4961
4962 static
SaveArrowSpec(FP,arrow_style,aw,ah,aindent,aw_spec,ah_spec,aindent_spec)4963 void SaveArrowSpec(FP, arrow_style, aw, ah, aindent, aw_spec, ah_spec,
4964 aindent_spec)
4965 FILE *FP;
4966 int arrow_style, aw, ah, aindent;
4967 char *aw_spec, *ah_spec, *aindent_spec;
4968 {
4969 if (fprintf(FP, "%1d,%1d,%1d,%1d,'%s','%s','%s'",
4970 arrow_style, aw, ah, aindent, aw_spec, ah_spec, aindent_spec) == EOF) {
4971 writeFileFailed = TRUE;
4972 }
4973 }
4974
SavePolyObj(FP,ObjPtr)4975 void SavePolyObj(FP, ObjPtr)
4976 FILE *FP;
4977 struct ObjRec *ObjPtr;
4978 {
4979 register int i, n;
4980 int count, line_cap=LCAP_BUTT;
4981 struct PolyRec *poly_ptr=ObjPtr->detail.p;
4982
4983 n = poly_ptr->n;
4984 if (fprintf(FP, "poly('%s','',%1d,[\n\t",
4985 colorMenuItems[ObjPtr->color], poly_ptr->n) == EOF) {
4986 writeFileFailed = TRUE;
4987 }
4988 for (i=0, count = 0; i < n-1; i++) {
4989 if (fprintf(FP, "%1d,%1d,", poly_ptr->vlist[i].x,
4990 poly_ptr->vlist[i].y) == EOF) {
4991 writeFileFailed = TRUE;
4992 }
4993 if (++count == 8) {
4994 count = 0;
4995 if (fprintf(FP, "\n\t") == EOF) writeFileFailed = TRUE;
4996 }
4997 }
4998 if (fprintf(FP, "%1d,%1d],", poly_ptr->vlist[n-1].x,
4999 poly_ptr->vlist[n-1].y) == EOF) {
5000 writeFileFailed = TRUE;
5001 }
5002 if (fprintf(FP,
5003 "%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,'%s',%1d,%1d,",
5004 poly_ptr->style, poly_ptr->width, poly_ptr->pen, ObjPtr->id,
5005 poly_ptr->curved, poly_ptr->fill, poly_ptr->dash, ObjPtr->rotation,
5006 ObjPtr->locked, ObjPtr->ctm!=NULL, ObjPtr->invisible,
5007 poly_ptr->width_spec, ObjPtr->trans_pat, line_cap) == EOF) {
5008 writeFileFailed = TRUE;
5009 }
5010 if (fprintf(FP, "\n \"") == EOF) writeFileFailed = TRUE;
5011 SaveSmoothHinge(FP, poly_ptr->curved, poly_ptr->n, poly_ptr->smooth);
5012 if (fprintf(FP, "\",") == EOF) writeFileFailed = TRUE;
5013
5014 /* save an empty spline tension spec */
5015 if (fprintf(FP, "\"\",") == EOF) writeFileFailed = TRUE;
5016 /* save the left arrow spec */
5017 if (fprintf(FP, "[\n ") == EOF) writeFileFailed = TRUE;
5018 SaveArrowSpec(FP, ASTY_COMPAT, poly_ptr->aw, poly_ptr->ah, 0,
5019 poly_ptr->aw_spec, poly_ptr->ah_spec, "0");
5020 if (fprintf(FP, "],[") == EOF) writeFileFailed = TRUE;
5021 /* save the right arrow spec */
5022 SaveArrowSpec(FP, ASTY_COMPAT, poly_ptr->aw, poly_ptr->ah, 0,
5023 poly_ptr->aw_spec, poly_ptr->ah_spec, "0");
5024 if (fprintf(FP, "],") == EOF) writeFileFailed = TRUE;
5025
5026 if (ObjPtr->ctm != NULL && fprintf(FP,
5027 "[\n\t%1d,%1d,%1d,%1d,%1d,%1d,%g,%g,%g,%g,%1d,%1d],",
5028 ObjPtr->x, ObjPtr->y,
5029 ObjPtr->orig_obbox.ltx, ObjPtr->orig_obbox.lty,
5030 ObjPtr->orig_obbox.rbx, ObjPtr->orig_obbox.rby,
5031 ObjPtr->ctm->m[CTM_SX], ObjPtr->ctm->m[CTM_SIN],
5032 ObjPtr->ctm->m[CTM_MSIN], ObjPtr->ctm->m[CTM_SY],
5033 ObjPtr->ctm->t[CTM_TX], ObjPtr->ctm->t[CTM_TY]) == EOF) {
5034 writeFileFailed = TRUE;
5035 }
5036 if (serializingFile) SaveCreatorID(FP, ObjPtr, " ");
5037 SaveAttrs(FP, ObjPtr->lattr);
5038 if (fprintf(FP, ")") == EOF) writeFileFailed = TRUE;
5039 }
5040
5041 /* --------------------- ReadSmoothHinge() --------------------- */
5042
ReadSmoothHinge(FP,Curved,NumPts,Smooth)5043 int ReadSmoothHinge(FP, Curved, NumPts, Smooth)
5044 FILE *FP;
5045 int Curved, NumPts;
5046 char *Smooth;
5047 {
5048 int num_nibbles=NumPts>>2, nibble_count=0, bit_count=0, j, k;
5049 char *c_ptr, inbuf[MAXSTRING+1];
5050
5051 if ((NumPts & 0x3) != 0) num_nibbles++;
5052 (void)fgets(inbuf, MAXSTRING, FP);
5053 scanLineNum++;
5054 if (Curved == LT_INTSPLINE || Smooth == NULL) return TRUE;
5055 if ((c_ptr=strchr(inbuf, '"')) == NULL) {
5056 (void)sprintf(gszMsgBox, TgLoadString(STID_INVALID_SMOOTHHINGE_SPEC_POLY),
5057 scanFileName, scanLineNum);
5058 if (PRTGIF) {
5059 fprintf(stderr, "%s\n", gszMsgBox);
5060 } else {
5061 Msg(gszMsgBox);
5062 }
5063 return FALSE;
5064 }
5065 c_ptr++;
5066 for (j=0; *c_ptr != '"' && j < num_nibbles; j++) {
5067 int data=0;
5068
5069 if (nibble_count++ == 64) {
5070 (void)fgets(inbuf, MAXSTRING, FP);
5071 scanLineNum++;
5072 for (c_ptr=inbuf; *c_ptr == ' '; c_ptr++) ;
5073 nibble_count = 1;
5074 }
5075 if (*c_ptr >= '0' && *c_ptr <= '9') {
5076 data = (int)(*c_ptr++) - (int)('0');
5077 } else if (*c_ptr >= 'a' && *c_ptr <= 'f') {
5078 data = (int)(*c_ptr++) - (int)('a') + 10;
5079 }
5080 for (k = 0; k < 4; k++) {
5081 if (bit_count++ == NumPts) break;
5082
5083 Smooth[(j<<2)+k] = (data & (1<<(3-k)) ? TRUE : FALSE);
5084 }
5085 }
5086 /*
5087 * Should be reading spline tension here. But this is not implemented, yet.
5088 */
5089 return TRUE;
5090 }
5091
5092 /* --------------------- ReadPolyObj() --------------------- */
5093
ReadPolyObj(FP,Inbuf,ObjPtr)5094 void ReadPolyObj(FP, Inbuf, ObjPtr)
5095 FILE *FP;
5096 char *Inbuf;
5097 struct ObjRec **ObjPtr;
5098 {
5099 register int i;
5100 struct PolyRec *poly_ptr;
5101 IntPoint *v;
5102 char color_str[40], bg_color_str[40], *s, inbuf[MAXSTRING+1];
5103 char width_spec[40], aw_spec[40], ah_spec[40];
5104 int num_pts, ltx=0, lty=0, rbx=0, rby=0, x, y, id=0;
5105 int initialized, rotation, count, new_alloc, line_cap=LCAP_BUTT;
5106 int style, width=0, pen, curved, fill, dash, locked=FALSE, trans_pat=FALSE;
5107 int aw=origArrowHeadW[6], ah=origArrowHeadH[6], arrow_style=ASTY_COMPAT;
5108 char *smooth=NULL;
5109 int real_x=0, real_y=0, transformed=FALSE, invisible=FALSE;
5110 struct XfrmMtrxRec *ctm=NULL;
5111 struct BBRec orig_obbox;
5112
5113 *ObjPtr = NULL;
5114
5115 s = FindChar((int)'(', Inbuf);
5116 s = ParseStr(s, (int)',', color_str, sizeof(color_str));
5117 if (fileVersion >= 37) {
5118 s = ParseStr(s, (int)',', bg_color_str, sizeof(bg_color_str));
5119 }
5120 InitScan(s, "\t\n, []");
5121
5122 if (GETINT("poly", num_pts, "number of points") == INVALID) {
5123 return;
5124 }
5125 if (num_pts <= 0) {
5126 (void)sprintf(gszMsgBox, TgLoadString(STID_INVALID_NUM_PTS_IN_POLY),
5127 scanFileName, scanLineNum);
5128 if (PRTGIF) {
5129 fprintf(stderr, "%s\n", gszMsgBox);
5130 } else {
5131 Msg(gszMsgBox);
5132 }
5133 return;
5134 }
5135
5136 *ObjPtr = (struct ObjRec *)malloc(sizeof(struct ObjRec));
5137 if (*ObjPtr == NULL) FailAllocMessage();
5138 memset(*ObjPtr, 0, sizeof(struct ObjRec));
5139 poly_ptr = (struct PolyRec *)malloc(sizeof(struct PolyRec));
5140 if (poly_ptr == NULL) FailAllocMessage();
5141 memset(poly_ptr, 0, sizeof(struct PolyRec));
5142
5143 if (num_pts == 1) {
5144 v = (IntPoint*)malloc(4*sizeof(IntPoint));
5145 if (v == NULL) FailAllocMessage();
5146 memset(v, 0, 4*sizeof(IntPoint));
5147 smooth = (char*)malloc(4*sizeof(char));
5148 if (smooth == NULL) FailAllocMessage();
5149 memset(smooth, 0, 4*sizeof(char));
5150 } else {
5151 v = (IntPoint*)malloc((num_pts+1)*sizeof(IntPoint));
5152 if (v == NULL) FailAllocMessage();
5153 memset(v, 0, (num_pts+1)*sizeof(IntPoint));
5154 smooth = (char*)malloc((num_pts+1)*sizeof(char));
5155 if (smooth == NULL) FailAllocMessage();
5156 memset(smooth, 0, (num_pts+1)*sizeof(char));
5157 }
5158
5159 initialized = FALSE;
5160
5161 *width_spec = *aw_spec = *ah_spec = '\0';
5162 if (fileVersion <= 13) {
5163 for (i=0; i < num_pts; i++) {
5164 if (GETINT("poly", x, "x") == INVALID ||
5165 GETINT("poly", y, "y") == INVALID) {
5166 free(*ObjPtr);
5167 free(poly_ptr);
5168 free(v);
5169 *ObjPtr = NULL;
5170 return;
5171 }
5172 v[i].x = x; v[i].y = y;
5173 if (!initialized) {
5174 initialized = TRUE;
5175 ltx = rbx = x; lty = rby = y;
5176 } else {
5177 if (x < ltx) ltx = x; if (y < lty) lty = y;
5178 if (x > rbx) rbx = x; if (y > rby) rby = y;
5179 }
5180 }
5181 } else {
5182 (void)fgets(inbuf, MAXSTRING, FP);
5183 scanLineNum++;
5184 s = inbuf;
5185 InitScan(s, "\t\n, []");
5186 for (i=0, count = 0; i < num_pts; i++) {
5187 if (GETINT("poly", x, "x") == INVALID ||
5188 GETINT("poly", y, "y") == INVALID) {
5189 free(*ObjPtr);
5190 free(poly_ptr);
5191 free(v);
5192 *ObjPtr = NULL;
5193 return;
5194 }
5195 v[i].x = x; v[i].y = y;
5196 if (!initialized) {
5197 initialized = TRUE;
5198 ltx = rbx = x; lty = rby = y;
5199 } else {
5200 if (x < ltx) ltx = x; if (y < lty) lty = y;
5201 if (x > rbx) rbx = x; if (y > rby) rby = y;
5202 }
5203 if (++count == 8 && i != num_pts-1) {
5204 count = 0;
5205 (void)fgets(inbuf, MAXSTRING, FP);
5206 scanLineNum++;
5207 s = inbuf;
5208 InitScan(s, "\t\n, []");
5209 }
5210 }
5211 }
5212
5213 if (num_pts == 1) {
5214 sprintf(gszMsgBox, TgLoadCachedString(CSTID_SINGLE_PT_POLY_CONVERTED),
5215 v[0].x, v[0].y);
5216 if (PRTGIF) {
5217 fprintf(stderr, "%s\n", gszMsgBox);
5218 } else {
5219 Msg(gszMsgBox);
5220 }
5221 v[1].x = v[0].x;
5222 v[1].y = v[0].y;
5223 num_pts = 2;
5224 }
5225
5226 poly_ptr->n = num_pts;
5227
5228 dash = 0;
5229 rotation = 0;
5230 if (fileVersion == INVALID) {
5231 if (GETINT("poly", style, "style") == INVALID ||
5232 GETINT("poly", width, "width") == INVALID ||
5233 GETINT("poly", pen, "pen") == INVALID) {
5234 free(*ObjPtr);
5235 free(poly_ptr);
5236 free(v);
5237 *ObjPtr = NULL;
5238 return;
5239 }
5240 id = objId++;
5241 fill = NONEPAT;
5242 if (width == LINE_CURVED) {
5243 width = 0;
5244 curved = TRUE;
5245 } else {
5246 curved = FALSE;
5247 }
5248 switch (width) {
5249 case 1: width = 3; break;
5250 case 2: width = 6; break;
5251 }
5252 } else if (fileVersion <= 3) {
5253 if (GETINT("poly", style, "style") == INVALID ||
5254 GETINT("poly", width, "width") == INVALID ||
5255 GETINT("poly", pen, "pen") == INVALID ||
5256 GETINT("poly", id, "id") == INVALID) {
5257 free(*ObjPtr);
5258 free(poly_ptr);
5259 free(v);
5260 *ObjPtr = NULL;
5261 return;
5262 }
5263 if (id >= objId) objId = id+1;
5264 fill = NONEPAT;
5265 if (width == LINE_CURVED) {
5266 width = 0;
5267 curved = TRUE;
5268 } else {
5269 curved = FALSE;
5270 }
5271 switch (width) {
5272 case 1: width = 3; break;
5273 case 2: width = 6; break;
5274 }
5275 } else if (fileVersion <= 4) {
5276 if (GETINT("poly", style, "style") == INVALID ||
5277 GETINT("poly", width, "width") == INVALID ||
5278 GETINT("poly", pen, "pen") == INVALID ||
5279 GETINT("poly", id, "id") == INVALID ||
5280 GETINT("poly", curved, "curved") == INVALID) {
5281 free(*ObjPtr);
5282 free(poly_ptr);
5283 free(v);
5284 *ObjPtr = NULL;
5285 return;
5286 }
5287 if (id >= objId) objId = id+1;
5288 fill = NONEPAT;
5289 switch (width) {
5290 case 1: width = 3; break;
5291 case 2: width = 6; break;
5292 }
5293 } else if (fileVersion <= 5) {
5294 if (GETINT("poly", style, "style") == INVALID ||
5295 GETINT("poly", width, "width") == INVALID ||
5296 GETINT("poly", pen, "pen") == INVALID ||
5297 GETINT("poly", id, "id") == INVALID ||
5298 GETINT("poly", curved, "curved") == INVALID ||
5299 GETINT("poly", fill, "fill") == INVALID) {
5300 free(*ObjPtr);
5301 free(poly_ptr);
5302 free(v);
5303 *ObjPtr = NULL;
5304 return;
5305 }
5306 if (id >= objId) objId = id+1;
5307 switch (width) {
5308 case 1: width = 3; break;
5309 case 2: width = 6; break;
5310 }
5311 } else if (fileVersion <= 8) {
5312 if (GETINT("poly", style, "style") == INVALID ||
5313 GETINT("poly", width, "width") == INVALID ||
5314 GETINT("poly", pen, "pen") == INVALID ||
5315 GETINT("poly", id, "id") == INVALID ||
5316 GETINT("poly", curved, "curved") == INVALID ||
5317 GETINT("poly", fill, "fill") == INVALID) {
5318 free(*ObjPtr);
5319 free(poly_ptr);
5320 free(v);
5321 *ObjPtr = NULL;
5322 return;
5323 }
5324 if (id >= objId) objId = id+1;
5325 } else if (fileVersion <= 13) {
5326 if (GETINT("poly", style, "style") == INVALID ||
5327 GETINT("poly", width, "width") == INVALID ||
5328 GETINT("poly", pen, "pen") == INVALID ||
5329 GETINT("poly", id, "id") == INVALID ||
5330 GETINT("poly", curved, "curved") == INVALID ||
5331 GETINT("poly", fill, "fill") == INVALID ||
5332 GETINT("poly", dash, "dash") == INVALID) {
5333 free(*ObjPtr);
5334 free(poly_ptr);
5335 free(v);
5336 *ObjPtr = NULL;
5337 return;
5338 }
5339 if (id >= objId) objId = id+1;
5340 } else if (fileVersion <= 16) {
5341 if (GETINT("poly", style, "style") == INVALID ||
5342 GETINT("poly", width, "width") == INVALID ||
5343 GETINT("poly", pen, "pen") == INVALID ||
5344 GETINT("poly", id, "id") == INVALID ||
5345 GETINT("poly", curved, "curved") == INVALID ||
5346 GETINT("poly", fill, "fill") == INVALID ||
5347 GETINT("poly", dash, "dash") == INVALID ||
5348 GETINT("poly", rotation, "rotation") == INVALID) {
5349 free(*ObjPtr);
5350 free(poly_ptr);
5351 free(v);
5352 *ObjPtr = NULL;
5353 return;
5354 }
5355 if (id >= objId) objId = id+1;
5356 } else if (fileVersion <= 25) {
5357 if (GETINT("poly", style, "style") == INVALID ||
5358 GETINT("poly", width, "width") == INVALID ||
5359 GETINT("poly", pen, "pen") == INVALID ||
5360 GETINT("poly", id, "id") == INVALID ||
5361 GETINT("poly", curved, "curved") == INVALID ||
5362 GETINT("poly", fill, "fill") == INVALID ||
5363 GETINT("poly", dash, "dash") == INVALID ||
5364 GETINT("poly", rotation, "rotation") == INVALID ||
5365 GETINT("poly", aw, "arrow head width") == INVALID ||
5366 GETINT("poly", ah, "arrow head height") == INVALID) {
5367 free(*ObjPtr);
5368 free(poly_ptr);
5369 free(v);
5370 *ObjPtr = NULL;
5371 return;
5372 }
5373 if (id >= objId) objId = id+1;
5374 } else if (fileVersion <= 32) {
5375 if (GETINT("poly", style, "style") == INVALID ||
5376 GETINT("poly", width, "width") == INVALID ||
5377 GETINT("poly", pen, "pen") == INVALID ||
5378 GETINT("poly", id, "id") == INVALID ||
5379 GETINT("poly", curved, "curved") == INVALID ||
5380 GETINT("poly", fill, "fill") == INVALID ||
5381 GETINT("poly", dash, "dash") == INVALID ||
5382 GETINT("poly", rotation, "rotation") == INVALID ||
5383 GETINT("poly", aw, "arrow head width") == INVALID ||
5384 GETINT("poly", ah, "arrow head height") == INVALID ||
5385 GETINT("poly", locked, "locked") == INVALID) {
5386 free(*ObjPtr);
5387 free(poly_ptr);
5388 free(v);
5389 *ObjPtr = NULL;
5390 return;
5391 }
5392 if (id >= objId) objId = id+1;
5393 } else if (fileVersion <= 34) {
5394 if (GETINT("poly", style, "style") == INVALID ||
5395 GETINT("poly", width, "width") == INVALID ||
5396 GETINT("poly", pen, "pen") == INVALID ||
5397 GETINT("poly", id, "id") == INVALID ||
5398 GETINT("poly", curved, "curved") == INVALID ||
5399 GETINT("poly", fill, "fill") == INVALID ||
5400 GETINT("poly", dash, "dash") == INVALID ||
5401 GETINT("poly", rotation, "rotation") == INVALID ||
5402 GETINT("poly", aw, "arrow head width") == INVALID ||
5403 GETINT("poly", ah, "arrow head height") == INVALID ||
5404 GETINT("poly", locked, "locked") == INVALID ||
5405 GETINT("poly", transformed, "transformed") == INVALID ||
5406 GETINT("poly", invisible, "invisible") == INVALID ||
5407 GETSTR("poly", width_spec, "width_spec") == INVALID ||
5408 GETSTR("poly", aw_spec, "aw_spec") == INVALID ||
5409 GETSTR("poly", ah_spec, "ah_spec") == INVALID) {
5410 free(*ObjPtr);
5411 free(poly_ptr);
5412 free(v);
5413 *ObjPtr = NULL;
5414 return;
5415 }
5416 if (id >= objId) objId = id+1;
5417 UtilRemoveQuotes(width_spec);
5418 UtilRemoveQuotes(aw_spec);
5419 UtilRemoveQuotes(ah_spec);
5420 } else if (fileVersion <= 36) {
5421 if (GETINT("poly", style, "style") == INVALID ||
5422 GETINT("poly", width, "width") == INVALID ||
5423 GETINT("poly", pen, "pen") == INVALID ||
5424 GETINT("poly", id, "id") == INVALID ||
5425 GETINT("poly", curved, "curved") == INVALID ||
5426 GETINT("poly", fill, "fill") == INVALID ||
5427 GETINT("poly", dash, "dash") == INVALID ||
5428 GETINT("poly", rotation, "rotation") == INVALID ||
5429 GETINT("poly", aw, "arrow head width") == INVALID ||
5430 GETINT("poly", ah, "arrow head height") == INVALID ||
5431 GETINT("poly", locked, "locked") == INVALID ||
5432 GETINT("poly", transformed, "transformed") == INVALID ||
5433 GETINT("poly", invisible, "invisible") == INVALID ||
5434 GETSTR("poly", width_spec, "width_spec") == INVALID ||
5435 GETSTR("poly", aw_spec, "aw_spec") == INVALID ||
5436 GETSTR("poly", ah_spec, "ah_spec") == INVALID ||
5437 GETINT("poly", trans_pat, "trans_pat") == INVALID) {
5438 free(*ObjPtr);
5439 free(poly_ptr);
5440 free(v);
5441 *ObjPtr = NULL;
5442 return;
5443 }
5444 if (id >= objId) objId = id+1;
5445 UtilRemoveQuotes(width_spec);
5446 UtilRemoveQuotes(aw_spec);
5447 UtilRemoveQuotes(ah_spec);
5448 } else {
5449 if (GETINT("poly", style, "style") == INVALID ||
5450 GETINT("poly", width, "width") == INVALID ||
5451 GETINT("poly", pen, "pen") == INVALID ||
5452 GETINT("poly", id, "id") == INVALID ||
5453 GETINT("poly", curved, "curved") == INVALID ||
5454 GETINT("poly", fill, "fill") == INVALID ||
5455 GETINT("poly", dash, "dash") == INVALID ||
5456 GETINT("poly", rotation, "rotation") == INVALID ||
5457 GETINT("poly", locked, "locked") == INVALID ||
5458 GETINT("poly", transformed, "transformed") == INVALID ||
5459 GETINT("poly", invisible, "invisible") == INVALID ||
5460 GETSTR("poly", width_spec, "width_spec") == INVALID ||
5461 GETINT("poly", trans_pat, "trans_pat") == INVALID ||
5462 GETINT("poly", line_cap, "line_cap") == INVALID) {
5463 free(*ObjPtr);
5464 free(poly_ptr);
5465 free(v);
5466 *ObjPtr = NULL;
5467 return;
5468 }
5469 if (id >= objId) objId = id+1;
5470 UtilRemoveQuotes(width_spec);
5471 UtilRemoveQuotes(aw_spec);
5472 UtilRemoveQuotes(ah_spec);
5473 if (line_cap != LCAP_BUTT) {
5474 /* does not support other linecaps, yet */
5475 line_cap = LCAP_BUTT;
5476 }
5477 }
5478
5479 if (fileVersion <= 16 && width <= 6) {
5480 aw = origArrowHeadW[width];
5481 ah = origArrowHeadH[width];
5482 width = origWidthOfLine[width];
5483 }
5484 if (curved == LT_INTSPLINE && smooth != NULL) {
5485 free(smooth);
5486 smooth = NULL;
5487 }
5488 if (fileVersion <= 30) {
5489 switch (curved) {
5490 case LT_STRAIGHT:
5491 for (i=0; i < num_pts; i++) smooth[i] = FALSE;
5492 break;
5493 case LT_SPLINE:
5494 smooth[0] = smooth[num_pts-1] = FALSE;
5495 for (i=1; i < num_pts-1; i++) smooth[i] = TRUE;
5496 break;
5497 }
5498 } else if (!ReadSmoothHinge(FP, curved, num_pts, smooth)) {
5499 free(*ObjPtr);
5500 free(poly_ptr);
5501 free(v);
5502 *ObjPtr = NULL;
5503 return;
5504 }
5505 if (smooth != NULL && (smooth[0] != FALSE || smooth[num_pts-1] != FALSE)) {
5506 smooth[0] = smooth[num_pts-1] = FALSE;
5507 SetFileModified(TRUE);
5508
5509 sprintf(gszMsgBox, TgLoadCachedString(CSTID_BAD_SMOOTHHINGE_POLY_FIXED));
5510 if (PRTGIF) {
5511 fprintf(stderr, "%s\n", gszMsgBox);
5512 } else {
5513 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
5514 }
5515 }
5516 if (fileVersion >= 37) {
5517 int aindent=0;
5518 char aindent_spec[40];
5519
5520 (void)fgets(inbuf, MAXSTRING, FP);
5521 scanLineNum++;
5522 InitScan(inbuf, "\t\n, []");
5523
5524 /* for now, they both spec are identical */
5525 if (GETINT("poly", arrow_style, "arrow_style") == INVALID ||
5526 GETINT("poly", aw, "aw") == INVALID ||
5527 GETINT("poly", ah, "ah") == INVALID ||
5528 GETINT("poly", aindent, "aindent") == INVALID ||
5529 GETSTR("poly", aw_spec, "aw_spec") == INVALID ||
5530 GETSTR("poly", ah_spec, "ah_spec") == INVALID ||
5531 GETSTR("poly", aindent_spec, "aindent_spec") == INVALID ||
5532 GETINT("poly", arrow_style, "arrow_style") == INVALID ||
5533 GETINT("poly", aw, "aw") == INVALID ||
5534 GETINT("poly", ah, "ah") == INVALID ||
5535 GETINT("poly", aindent, "aindent") == INVALID ||
5536 GETSTR("poly", aw_spec, "aw_spec") == INVALID ||
5537 GETSTR("poly", ah_spec, "ah_spec") == INVALID ||
5538 GETSTR("poly", aindent_spec, "aindent_spec") == INVALID) {
5539 free(*ObjPtr);
5540 free(poly_ptr);
5541 free(v);
5542 *ObjPtr = NULL;
5543 return;
5544 }
5545 UtilRemoveQuotes(aw_spec);
5546 UtilRemoveQuotes(ah_spec);
5547 UtilRemoveQuotes(aindent_spec);
5548 }
5549 if (fileVersion >= 33 && transformed) {
5550 (void)fgets(inbuf, MAXSTRING, FP);
5551 scanLineNum++;
5552 InitScan(inbuf, "\t\n, ");
5553
5554 ctm = (struct XfrmMtrxRec *)malloc(sizeof(struct XfrmMtrxRec));
5555 if (ctm == NULL) FailAllocMessage();
5556 if (GETINT("poly", real_x, "real_x") == INVALID ||
5557 GETINT("poly", real_y, "real_y") == INVALID ||
5558 GETINT("poly", orig_obbox.ltx, "orig_obbox.ltx") == INVALID ||
5559 GETINT("poly", orig_obbox.lty, "orig_obbox.lty") == INVALID ||
5560 GETINT("poly", orig_obbox.rbx, "orig_obbox.rbx") == INVALID ||
5561 GETINT("poly", orig_obbox.rby, "orig_obbox.rby") == INVALID ||
5562 GETDBL("poly", ctm->m[CTM_SX], "CTM_SX") == INVALID ||
5563 GETDBL("poly", ctm->m[CTM_SIN], "CTM_SIN") == INVALID ||
5564 GETDBL("poly", ctm->m[CTM_MSIN], "CTM_MSIN") == INVALID ||
5565 GETDBL("poly", ctm->m[CTM_SY], "CTM_SY") == INVALID ||
5566 GETINT("poly", ctm->t[CTM_TX], "CTM_TX") == INVALID ||
5567 GETINT("poly", ctm->t[CTM_TY], "CTM_TY") == INVALID) {
5568 free(*ObjPtr);
5569 free(poly_ptr);
5570 free(v);
5571 *ObjPtr = NULL;
5572 free(ctm);
5573 return;
5574 }
5575 }
5576 if (fileVersion <= 32) {
5577 sprintf(width_spec, "%1d", width);
5578 sprintf(aw_spec, "%1d", aw);
5579 sprintf(ah_spec, "%1d", ah);
5580 }
5581
5582 fill = UpgradePenFill(fill);
5583 pen = UpgradePenFill(pen);
5584
5585 poly_ptr->style = style;
5586 poly_ptr->width = width;
5587 poly_ptr->aw = aw;
5588 poly_ptr->ah = ah;
5589 UtilStrCpyN(poly_ptr->width_spec, sizeof(poly_ptr->width_spec), width_spec);
5590 UtilStrCpyN(poly_ptr->aw_spec, sizeof(poly_ptr->aw_spec), aw_spec);
5591 UtilStrCpyN(poly_ptr->ah_spec, sizeof(poly_ptr->ah_spec), ah_spec);
5592 poly_ptr->pen = pen;
5593 poly_ptr->curved = curved;
5594 poly_ptr->fill = fill;
5595 poly_ptr->dash = dash;
5596
5597 poly_ptr->vlist = v;
5598 poly_ptr->smooth = smooth;
5599 poly_ptr->svlist = poly_ptr->asvlist = NULL;
5600 poly_ptr->intvlist = NULL;
5601
5602 poly_ptr->rotated_n = poly_ptr->rotated_asn = 0;
5603 poly_ptr->rotated_vlist = poly_ptr->rotated_asvlist = NULL;
5604
5605 (*ObjPtr)->x = ltx;
5606 (*ObjPtr)->y = lty;
5607 (*ObjPtr)->color = QuickFindColorIndex(*ObjPtr, color_str, &new_alloc, TRUE);
5608 UtilStrCpyN((*ObjPtr)->color_str, sizeof((*ObjPtr)->color_str), color_str);
5609 (*ObjPtr)->dirty = FALSE;
5610 (*ObjPtr)->id = id;
5611 (*ObjPtr)->rotation = rotation;
5612 (*ObjPtr)->locked = locked;
5613 (*ObjPtr)->type = OBJ_POLY;
5614 (*ObjPtr)->obbox.ltx = ltx;
5615 (*ObjPtr)->obbox.lty = lty;
5616 (*ObjPtr)->obbox.rbx = rbx;
5617 (*ObjPtr)->obbox.rby = rby;
5618 (*ObjPtr)->detail.p = poly_ptr;
5619 (*ObjPtr)->ctm = ctm;
5620 (*ObjPtr)->invisible = invisible;
5621 (*ObjPtr)->trans_pat = trans_pat;
5622 if (ctm != NULL) {
5623 memcpy(&(*ObjPtr)->orig_obbox, &orig_obbox, sizeof(struct BBRec));
5624 (*ObjPtr)->x = real_x;
5625 (*ObjPtr)->y = real_y;
5626 GetTransformedOBBoxOffsetVs(*ObjPtr, (*ObjPtr)->rotated_obbox);
5627 }
5628 AdjObjCache(*ObjPtr);
5629 AdjObjSplineVs(*ObjPtr);
5630 if (poly_ptr->curved != LT_INTSPLINE) {
5631 UpdPolyBBox(*ObjPtr, poly_ptr->n, poly_ptr->vlist);
5632 } else {
5633 UpdPolyBBox(*ObjPtr, poly_ptr->intn, poly_ptr->intvlist);
5634 }
5635 }
5636
5637 /* --------------------- SetPolyPropMask() --------------------- */
5638
SetPolyPropMask(ObjPtr,plMask,plSkip,pProp)5639 void SetPolyPropMask(ObjPtr, plMask, plSkip, pProp)
5640 struct ObjRec *ObjPtr;
5641 long *plMask, *plSkip;
5642 struct PropertiesRec *pProp;
5643 {
5644 struct PolyRec *poly_ptr=ObjPtr->detail.p;
5645
5646 SetCTMPropertyMask(ObjPtr->ctm, plMask, plSkip, pProp);
5647
5648 SetIntPropertyMask(PROP_MASK_COLOR, ObjPtr->color,
5649 colorMenuItems[ObjPtr->color], plMask, plSkip, pProp);
5650 SetIntPropertyMask(PROP_MASK_WIDTH, poly_ptr->width, poly_ptr->width_spec,
5651 plMask, plSkip, pProp);
5652 SetIntPropertyMask(PROP_MASK_AW, poly_ptr->aw, poly_ptr->aw_spec,
5653 plMask, plSkip, pProp);
5654 SetIntPropertyMask(PROP_MASK_AH, poly_ptr->ah, poly_ptr->ah_spec,
5655 plMask, plSkip, pProp);
5656
5657 SetIntPropertyMask(PROP_MASK_TRANSPAT, ObjPtr->trans_pat, NULL,
5658 plMask, plSkip, pProp);
5659 SetIntPropertyMask(PROP_MASK_FILL, poly_ptr->fill, NULL,
5660 plMask, plSkip, pProp);
5661 SetIntPropertyMask(PROP_MASK_PEN, poly_ptr->pen, NULL,
5662 plMask, plSkip, pProp);
5663 SetIntPropertyMask(PROP_MASK_DASH, poly_ptr->dash, NULL,
5664 plMask, plSkip, pProp);
5665 SetIntPropertyMask(PROP_MASK_CURVED, poly_ptr->curved, NULL,
5666 plMask, plSkip, pProp);
5667 SetIntPropertyMask(PROP_MASK_ARROW_STYLE, poly_ptr->style, NULL,
5668 plMask, plSkip, pProp);
5669 }
5670
5671 /* --------------------- FreePolyObj() --------------------- */
5672
FreePolyObj(ObjPtr)5673 void FreePolyObj(ObjPtr)
5674 struct ObjRec *ObjPtr;
5675 {
5676 if (ObjPtr->detail.p->ssvlist != NULL) free(ObjPtr->detail.p->ssvlist);
5677 if (ObjPtr->detail.p->svlist != NULL) free(ObjPtr->detail.p->svlist);
5678 if (ObjPtr->detail.p->asvlist != NULL) free(ObjPtr->detail.p->asvlist);
5679 if (ObjPtr->detail.p->intvlist != NULL) free(ObjPtr->detail.p->intvlist);
5680 if (ObjPtr->detail.p->rotated_vlist != NULL) {
5681 free(ObjPtr->detail.p->rotated_vlist);
5682 }
5683 if (ObjPtr->detail.p->rotated_asvlist != NULL) {
5684 free(ObjPtr->detail.p->rotated_asvlist);
5685 }
5686 free(ObjPtr->detail.p->vlist);
5687 if (ObjPtr->detail.p->smooth != NULL) free(ObjPtr->detail.p->smooth);
5688 if (ObjPtr->detail.p->ssmooth != NULL) free(ObjPtr->detail.p->ssmooth);
5689 free(ObjPtr->detail.p);
5690 free(ObjPtr);
5691 }
5692
5693 /* --------------------- InitPoly() --------------------- */
5694
InitPoly()5695 void InitPoly()
5696 {
5697 ResetWiringNodeInfo();
5698 CVListInit(&gStructSplineList);
5699 }
5700