1 /*
2 * FIG : Facility for Interactive Generation of figures
3 * Copyright (c) 1985-1988 by Supoj Sutanthavibul
4 * Parts Copyright (c) 1989-2007 by Brian V. Smith
5 * Parts Copyright (c) 1991 by Paul King
6 * Parts Copyright (c) 1995 by C. Blanc and C. Schlick
7 *
8 * Any party obtaining a copy of these files is granted, free of charge, a
9 * full and unrestricted irrevocable, world-wide, paid up, royalty-free,
10 * nonexclusive right and license to deal in this software and documentation
11 * files (the "Software"), including without limitation the rights to use,
12 * copy, modify, merge, publish, distribute, sublicense and/or sell copies of
13 * the Software, and to permit persons who receive copies from any such
14 * party to do so, with the only requirement being that the above copyright
15 * and this permission notice remain intact.
16 *
17 */
18
19 #include "fig.h"
20 #include "resources.h"
21 #include "mode.h"
22 #include "object.h"
23 #include "paintop.h"
24 #include "f_read.h"
25 #include "u_create.h"
26 #include "u_list.h"
27 #include "u_elastic.h"
28 #include "u_redraw.h"
29 #include "u_undo.h"
30 #include "w_layers.h"
31 #include "w_setup.h"
32
33 #include "u_draw.h"
34 #include "u_markers.h"
35
36 /*************************************/
37 /****** DELETE object from list ******/
38 /*************************************/
39
40
41 int point_on_perim (F_point *p, int llx, int lly, int urx, int ury);
42 int point_on_inside (F_point *p, int llx, int lly, int urx, int ury);
43
44 void
list_delete_arc(F_arc ** arc_list,F_arc * arc)45 list_delete_arc(F_arc **arc_list, F_arc *arc)
46 {
47 F_arc *a, *aa;
48
49 if (*arc_list == NULL)
50 return;
51 if (arc == NULL)
52 return;
53
54 if (arc_list == &objects.arcs)
55 remove_depth(O_ARC, arc->depth);
56 for (a = aa = *arc_list; aa != NULL; a = aa, aa = aa->next) {
57 if (aa == arc) {
58 if (aa == *arc_list)
59 *arc_list = (*arc_list)->next;
60 else
61 a->next = aa->next;
62 break;
63 }
64 }
65 arc->next = NULL;
66 }
67
68 void
list_delete_ellipse(F_ellipse ** ellipse_list,F_ellipse * ellipse)69 list_delete_ellipse(F_ellipse **ellipse_list, F_ellipse *ellipse)
70 {
71 F_ellipse *q, *r;
72
73 if (*ellipse_list == NULL)
74 return;
75 if (ellipse == NULL)
76 return;
77
78 if (ellipse_list == &objects.ellipses)
79 remove_depth(O_ELLIPSE, ellipse->depth);
80 for (q = r = *ellipse_list; r != NULL; q = r, r = r->next) {
81 if (r == ellipse) {
82 if (r == *ellipse_list)
83 *ellipse_list = (*ellipse_list)->next;
84 else
85 q->next = r->next;
86 break;
87 }
88 }
89 ellipse->next = NULL;
90 }
91
92 void
list_delete_line(F_line ** line_list,F_line * line)93 list_delete_line(F_line **line_list, F_line *line)
94 {
95 F_line *q, *r;
96
97 if (*line_list == NULL)
98 return;
99 if (line == NULL)
100 return;
101
102 if (line_list == &objects.lines)
103 remove_depth(O_POLYLINE, line->depth);
104 for (q = r = *line_list; r != NULL; q = r, r = r->next) {
105 if (r == line) {
106 if (r == *line_list)
107 *line_list = (*line_list)->next;
108 else
109 q->next = r->next;
110 break;
111 }
112 }
113 line->next = NULL;
114 }
115
116 void
list_delete_spline(F_spline ** spline_list,F_spline * spline)117 list_delete_spline(F_spline **spline_list, F_spline *spline)
118 {
119 F_spline *q, *r;
120
121 if (*spline_list == NULL)
122 return;
123 if (spline == NULL)
124 return;
125
126 if (spline_list == &objects.splines)
127 remove_depth(O_SPLINE, spline->depth);
128 for (q = r = *spline_list; r != NULL; q = r, r = r->next) {
129 if (r == spline) {
130 if (r == *spline_list)
131 *spline_list = (*spline_list)->next;
132 else
133 q->next = r->next;
134 break;
135 }
136 }
137 spline->next = NULL;
138 }
139
140 void
list_delete_text(F_text ** text_list,F_text * text)141 list_delete_text(F_text **text_list, F_text *text)
142 {
143 F_text *q, *r;
144
145 if (*text_list == NULL)
146 return;
147 if (text == NULL)
148 return;
149
150 if (text_list == &objects.texts)
151 remove_depth(O_TXT, text->depth);
152 for (q = r = *text_list; r != NULL; q = r, r = r->next)
153 if (r == text) {
154 if (r == *text_list)
155 *text_list = text->next;
156 else
157 q->next = text->next;
158 break;
159 }
160 text->next = NULL;
161 }
162
163 void
list_delete_compound(F_compound ** list,F_compound * compound)164 list_delete_compound(F_compound **list, F_compound *compound)
165 {
166 F_compound *c, *cc;
167
168 if (*list == NULL)
169 return;
170 if (compound == NULL)
171 return;
172
173 if (list == &objects.compounds)
174 remove_compound_depth(compound);
175
176 for (cc = c = *list; c != NULL; cc = c, c = c->next) {
177 if (c == compound) {
178 if (c == *list)
179 *list = (*list)->next;
180 else
181 cc->next = c->next;
182 break;
183 }
184 }
185 compound->next = NULL;
186 }
187
188 void
remove_depth(int type,int depth)189 remove_depth(int type, int depth)
190 {
191 int i;
192
193 object_depths[depth]--;
194 if (appres.DEBUG)
195 fprintf(stderr,"remove depth %d, count=%d\n",depth,object_depths[depth]);
196 /* now subtract one from the counter for this object type */
197 switch (type) {
198 case O_ARC:
199 --counts[depth].num_arcs;
200 if (appres.DEBUG)
201 fprintf(stderr,"Arc[%d] count=%d\n",depth,counts[depth].num_lines);
202 break;
203 case O_POLYLINE:
204 --counts[depth].num_lines;
205 if (appres.DEBUG)
206 fprintf(stderr,"Line[%d] count=%d\n",depth,counts[depth].num_lines);
207 break;
208 case O_ELLIPSE:
209 --counts[depth].num_ellipses;
210 if (appres.DEBUG)
211 fprintf(stderr,"Ellipse[%d] count=%d\n",depth,counts[depth].num_ellipses);
212 break;
213 case O_SPLINE:
214 --counts[depth].num_splines;
215 if (appres.DEBUG)
216 fprintf(stderr,"Spline[%d] count=%d\n",depth,counts[depth].num_splines);
217 break;
218 case O_TXT:
219 --counts[depth].num_texts;
220 if (appres.DEBUG)
221 fprintf(stderr,"Text[%d] count=%d\n",depth,counts[depth].num_texts);
222 break;
223 }
224 if (min_depth != -1 && (min_depth < depth && max_depth > depth) &&
225 object_depths[depth] != 0)
226 return;
227 /* if no objects at this depth, find new min/max */
228 for (i=0; i<=MAX_DEPTH; i++)
229 if (object_depths[i])
230 break;
231 if (i<=MAX_DEPTH) {
232 min_depth = i;
233 if (appres.DEBUG)
234 fprintf(stderr,"New min = %d\n",min_depth);
235 for (i=MAX_DEPTH; i>=0; i--)
236 if (object_depths[i])
237 break;
238 if (i>=0) {
239 max_depth = i;
240 if (appres.DEBUG)
241 fprintf(stderr,"New max = %d\n",max_depth);
242 }
243 } else {
244 min_depth = -1;
245 if (appres.DEBUG)
246 fprintf(stderr,"No objects\n");
247 }
248 /* adjust the layer buttons */
249 update_layers();
250 }
251
252 void
remove_compound_depth(F_compound * comp)253 remove_compound_depth(F_compound *comp)
254 {
255 F_arc *aa;
256 F_ellipse *ee;
257 F_line *ll;
258 F_spline *ss;
259 F_text *tt;
260 F_compound *cc;
261
262 if (comp == (F_compound *) 0)
263 return;
264
265 /* defer updating of layer buttons until we've added the entire compound */
266 defer_update_layers++;
267 for (aa=comp->arcs; aa; aa=aa->next)
268 remove_depth(O_ARC, aa->depth);
269 for (ee=comp->ellipses; ee; ee=ee->next)
270 remove_depth(O_ELLIPSE, ee->depth);
271 for (ll=comp->lines; ll; ll=ll->next)
272 remove_depth(O_POLYLINE, ll->depth);
273 for (ss=comp->splines; ss; ss=ss->next)
274 remove_depth(O_SPLINE, ss->depth);
275 for (tt=comp->texts; tt; tt=tt->next)
276 remove_depth(O_TXT, tt->depth);
277 for (cc=comp->compounds; cc; cc=cc->next)
278 remove_compound_depth(cc);
279 /* decrement the defer flag and update layer buttons if it hits 0 */
280 defer_update_layers--;
281 update_layers();
282 }
283
284
285 /********************************/
286 /****** ADD object to list ******/
287 /********************************/
288
289 void
list_add_arc(F_arc ** list,F_arc * a)290 list_add_arc(F_arc **list, F_arc *a)
291 {
292 F_arc *aa;
293
294 a->next = NULL;
295 if ((aa = last_arc(*list)) == NULL)
296 *list = a;
297 else
298 aa->next = a;
299 if (list == &objects.arcs)
300 while (a) {
301 add_depth(O_ARC, a->depth);
302 a = a->next;
303 }
304 }
305
306 void
list_add_ellipse(F_ellipse ** list,F_ellipse * e)307 list_add_ellipse(F_ellipse **list, F_ellipse *e)
308 {
309 F_ellipse *ee;
310
311 e->next = NULL;
312 if ((ee = last_ellipse(*list)) == NULL)
313 *list = e;
314 else
315 ee->next = e;
316 if (list == &objects.ellipses)
317 while (e) {
318 add_depth(O_ELLIPSE, e->depth);
319 e = e->next;
320 }
321 }
322
323 void
list_add_line(F_line ** list,F_line * l)324 list_add_line(F_line **list, F_line *l)
325 {
326 F_line *ll;
327
328 l->next = NULL;
329 if ((ll = last_line(*list)) == NULL)
330 *list = l;
331 else
332 ll->next = l;
333 if (list == &objects.lines)
334 while (l) {
335 add_depth(O_POLYLINE, l->depth);
336 l = l->next;
337 }
338 }
339
340 void
list_add_spline(F_spline ** list,F_spline * s)341 list_add_spline(F_spline **list, F_spline *s)
342 {
343 F_spline *ss;
344
345 s->next = NULL;
346 if ((ss = last_spline(*list)) == NULL)
347 *list = s;
348 else
349 ss->next = s;
350 if (list == &objects.splines)
351 while (s) {
352 add_depth(O_SPLINE, s->depth);
353 s = s->next;
354 }
355 }
356
357 void
list_add_text(F_text ** list,F_text * t)358 list_add_text(F_text **list, F_text *t)
359 {
360 F_text *tt;
361
362 t->next = NULL;
363 if ((tt = last_text(*list)) == NULL)
364 *list = t;
365 else
366 tt->next = t;
367 if (list == &objects.texts)
368 while (t) {
369 add_depth(O_TXT, t->depth);
370 t = t->next;
371 }
372 }
373
374 void
list_add_compound(F_compound ** list,F_compound * c)375 list_add_compound(F_compound **list, F_compound *c)
376 {
377 F_compound *cc;
378
379 c->next = NULL;
380 if ((cc = last_compound(*list)) == NULL)
381 *list = c;
382 else
383 cc->next = c;
384
385 if (list == &objects.compounds) {
386 while (c) {
387 add_compound_depth(c);
388 c = c->next;
389 }
390 }
391 }
392
393 /* increment objects_depth[depth] for a new object, and add to the
394 counter for this "type" (line, arc, etc) */
395
396 void
add_depth(int type,int depth)397 add_depth(int type, int depth)
398 {
399 int i;
400
401 object_depths[depth]++;
402
403 if (appres.DEBUG)
404 fprintf(stderr,"add depth %d, count=%d\n",depth,object_depths[depth]);
405 /* add one to the counter for this object type */
406 switch (type) {
407 case O_ARC:
408 ++counts[depth].num_arcs;
409 if (appres.DEBUG)
410 fprintf(stderr,"Arc[%d] count=%d\n",depth,counts[depth].num_arcs);
411 break;
412 case O_POLYLINE:
413 ++counts[depth].num_lines;
414 if (appres.DEBUG)
415 fprintf(stderr,"Line[%d] count=%d\n",depth,counts[depth].num_lines);
416 break;
417 case O_ELLIPSE:
418 ++counts[depth].num_ellipses;
419 if (appres.DEBUG)
420 fprintf(stderr,"Ellipse[%d] count=%d\n",depth,counts[depth].num_ellipses);
421 break;
422 case O_SPLINE:
423 ++counts[depth].num_splines;
424 if (appres.DEBUG)
425 fprintf(stderr,"Spline[%d] count=%d\n",depth,counts[depth].num_splines);
426 break;
427 case O_TXT:
428 ++counts[depth].num_texts;
429 if (appres.DEBUG)
430 fprintf(stderr,"Text[%d] count=%d\n",depth,counts[depth].num_texts);
431 break;
432 }
433 if (object_depths[depth] != 1)
434 return;
435 /* if exactly one object at this depth, see if this is new min or max */
436 for (i=0; i<=MAX_DEPTH; i++)
437 if (object_depths[i])
438 break;
439 min_depth = i;
440 if (appres.DEBUG)
441 fprintf(stderr,"New min = %d\n",min_depth);
442 for (i=MAX_DEPTH; i>=0; i--)
443 if (object_depths[i])
444 break;
445 if (i>=0) {
446 max_depth = i;
447 if (appres.DEBUG)
448 fprintf(stderr,"New max = %d\n",max_depth);
449 }
450 /* adjust the layer buttons */
451 update_layers();
452 }
453
454 void
add_compound_depth(F_compound * comp)455 add_compound_depth(F_compound *comp)
456 {
457 F_arc *aa;
458 F_ellipse *ee;
459 F_line *ll;
460 F_spline *ss;
461 F_text *tt;
462 F_compound *cc;
463
464 /* defer updating of layer buttons until we've added the entire compound */
465 defer_update_layers++;
466 for (aa=comp->arcs; aa; aa=aa->next)
467 add_depth(O_ARC, aa->depth);
468 for (ee=comp->ellipses; ee; ee=ee->next)
469 add_depth(O_ELLIPSE, ee->depth);
470 for (ll=comp->lines; ll; ll=ll->next)
471 add_depth(O_POLYLINE, ll->depth);
472 for (ss=comp->splines; ss; ss=ss->next)
473 add_depth(O_SPLINE, ss->depth);
474 for (tt=comp->texts; tt; tt=tt->next)
475 add_depth(O_TXT, tt->depth);
476 for (cc=comp->compounds; cc; cc=cc->next)
477 add_compound_depth(cc);
478 /* decrement the defer flag and update layer buttons if it hits 0 */
479 defer_update_layers--;
480 update_layers();
481 }
482
483 /**********************************/
484 /* routines to delete the objects */
485 /**********************************/
486
487 void
delete_line(F_line * old_l)488 delete_line(F_line *old_l)
489 {
490 list_delete_line(&objects.lines, old_l);
491 clean_up();
492 set_latestline(old_l);
493 set_action_object(F_DELETE, O_POLYLINE);
494 set_modifiedflag();
495 }
496
497 void
delete_arc(F_arc * old_a)498 delete_arc(F_arc *old_a)
499 {
500 list_delete_arc(&objects.arcs, old_a);
501 clean_up();
502 set_latestarc(old_a);
503 set_action_object(F_DELETE, O_ARC);
504 set_modifiedflag();
505 }
506
507 void
delete_ellipse(F_ellipse * old_e)508 delete_ellipse(F_ellipse *old_e)
509 {
510 list_delete_ellipse(&objects.ellipses, old_e);
511 clean_up();
512 set_latestellipse(old_e);
513 set_action_object(F_DELETE, O_ELLIPSE);
514 set_modifiedflag();
515 }
516
517 void
delete_text(F_text * old_t)518 delete_text(F_text *old_t)
519 {
520 list_delete_text(&objects.texts, old_t);
521 clean_up();
522 set_latesttext(old_t);
523 set_action_object(F_DELETE, O_TXT);
524 set_modifiedflag();
525 }
526
527 void
delete_spline(F_spline * old_s)528 delete_spline(F_spline *old_s)
529 {
530 list_delete_spline(&objects.splines, old_s);
531 clean_up();
532 set_latestspline(old_s);
533 set_action_object(F_DELETE, O_SPLINE);
534 set_modifiedflag();
535 }
536
537 void
delete_compound(F_compound * old_c)538 delete_compound(F_compound *old_c)
539 {
540 list_delete_compound(&objects.compounds, old_c);
541 clean_up();
542 set_latestcompound(old_c);
543 set_action_object(F_DELETE, O_COMPOUND);
544 set_modifiedflag();
545 }
546
547 /*******************************/
548 /* routines to add the objects */
549 /*******************************/
550
551 void
add_line(F_line * new_l)552 add_line(F_line *new_l)
553 {
554 list_add_line(&objects.lines, new_l);
555 clean_up();
556 set_latestline(new_l);
557 set_action_object(F_ADD, O_POLYLINE);
558 set_modifiedflag();
559 }
560
561 void
add_arc(F_arc * new_a)562 add_arc(F_arc *new_a)
563 {
564 list_add_arc(&objects.arcs, new_a);
565 clean_up();
566 set_latestarc(new_a);
567 set_action_object(F_ADD, O_ARC);
568 set_modifiedflag();
569 }
570
571 void
add_ellipse(F_ellipse * new_e)572 add_ellipse(F_ellipse *new_e)
573 {
574 list_add_ellipse(&objects.ellipses, new_e);
575 clean_up();
576 set_latestellipse(new_e);
577 set_action_object(F_ADD, O_ELLIPSE);
578 set_modifiedflag();
579 }
580
581 void
add_text(F_text * new_t)582 add_text(F_text *new_t)
583 {
584 list_add_text(&objects.texts, new_t);
585 clean_up();
586 set_latesttext(new_t);
587 set_action_object(F_ADD, O_TXT);
588 set_modifiedflag();
589 }
590
591 void
add_spline(F_spline * new_s)592 add_spline(F_spline *new_s)
593 {
594 list_add_spline(&objects.splines, new_s);
595 clean_up();
596 set_latestspline(new_s);
597 set_action_object(F_ADD, O_SPLINE);
598 set_modifiedflag();
599 }
600
601 void
add_compound(F_compound * new_c)602 add_compound(F_compound *new_c)
603 {
604 list_add_compound(&objects.compounds, new_c);
605 clean_up();
606 set_latestcompound(new_c);
607 set_action_object(F_ADD, O_COMPOUND);
608 set_modifiedflag();
609 }
610
611
612 void
change_line(F_line * old_l,F_line * new_l)613 change_line(F_line *old_l, F_line *new_l)
614 {
615 list_delete_line(&objects.lines, old_l);
616 list_add_line(&objects.lines, new_l);
617 clean_up();
618 old_l->next = new_l;
619 set_latestline(old_l);
620 set_action_object(F_EDIT, O_POLYLINE);
621 set_modifiedflag();
622 }
623
624 void
change_arc(F_arc * old_a,F_arc * new_a)625 change_arc(F_arc *old_a, F_arc *new_a)
626 {
627 list_delete_arc(&objects.arcs, old_a);
628 list_add_arc(&objects.arcs, new_a);
629 clean_up();
630 old_a->next = new_a;
631 set_latestarc(old_a);
632 set_action_object(F_EDIT, O_ARC);
633 set_modifiedflag();
634 }
635
636 void
change_ellipse(F_ellipse * old_e,F_ellipse * new_e)637 change_ellipse(F_ellipse *old_e, F_ellipse *new_e)
638 {
639 list_delete_ellipse(&objects.ellipses, old_e);
640 list_add_ellipse(&objects.ellipses, new_e);
641 clean_up();
642 old_e->next = new_e;
643 set_latestellipse(old_e);
644 set_action_object(F_EDIT, O_ELLIPSE);
645 set_modifiedflag();
646 }
647
648 void
change_text(F_text * old_t,F_text * new_t)649 change_text(F_text *old_t, F_text *new_t)
650 {
651 list_delete_text(&objects.texts, old_t);
652 list_add_text(&objects.texts, new_t);
653 clean_up();
654 old_t->next = new_t;
655 set_latesttext(old_t);
656 set_action_object(F_EDIT, O_TXT);
657 set_modifiedflag();
658 }
659
660 void
change_spline(F_spline * old_s,F_spline * new_s)661 change_spline(F_spline *old_s, F_spline *new_s)
662 {
663 list_delete_spline(&objects.splines, old_s);
664 list_add_spline(&objects.splines, new_s);
665 clean_up();
666 old_s->next = new_s;
667 set_latestspline(old_s);
668 set_action_object(F_EDIT, O_SPLINE);
669 set_modifiedflag();
670 }
671
672 void
change_compound(F_compound * old_c,F_compound * new_c)673 change_compound(F_compound *old_c, F_compound *new_c)
674 {
675 list_delete_compound(&objects.compounds, old_c);
676 list_add_compound(&objects.compounds, new_c);
677 clean_up();
678 old_c->next = new_c;
679 set_latestcompound(old_c);
680 set_action_object(F_EDIT, O_COMPOUND);
681 set_modifiedflag();
682 }
683
684 /* find the tails of all the object lists */
685
tail(F_compound * ob,F_compound * tails)686 void tail(F_compound *ob, F_compound *tails)
687 {
688 F_arc *a;
689 F_compound *c;
690 F_ellipse *e;
691 F_line *l;
692 F_spline *s;
693 F_text *t;
694
695 if (NULL != (a = ob->arcs))
696 for (; a->next != NULL; a = a->next)
697 ;
698 if (NULL != (c = ob->compounds))
699 for (; c->next != NULL; c = c->next)
700 ;
701 if (NULL != (e = ob->ellipses))
702 for (; e->next != NULL; e = e->next)
703 ;
704 if (NULL != (l = ob->lines))
705 for (; l->next != NULL; l = l->next)
706 ;
707 if (NULL != (s = ob->splines))
708 for (; s->next != NULL; s = s->next)
709 ;
710 if (NULL != (t = ob->texts))
711 for (; t->next != NULL; t = t->next)
712 ;
713
714 tails->arcs = a;
715 tails->compounds = c;
716 tails->ellipses = e;
717 tails->lines = l;
718 tails->splines = s;
719 tails->texts = t;
720 }
721
722 /*
723 * Make pointers in tails point to the last element of each list of l1 and
724 * Append the lists in l2 after those in l1. The tails pointers must be
725 * defined prior to calling append.
726 */
727
append_objects(F_compound * l1,F_compound * l2,F_compound * tails)728 void append_objects(F_compound *l1, F_compound *l2, F_compound *tails)
729 {
730 /* don't forget to account for the depths */
731 add_compound_depth(l2);
732
733 if (tails->arcs)
734 tails->arcs->next = l2->arcs;
735 else
736 l1->arcs = l2->arcs;
737 if (tails->compounds)
738 tails->compounds->next = l2->compounds;
739 else
740 l1->compounds = l2->compounds;
741 if (tails->ellipses)
742 tails->ellipses->next = l2->ellipses;
743 else
744 l1->ellipses = l2->ellipses;
745 if (tails->lines)
746 tails->lines->next = l2->lines;
747 else
748 l1->lines = l2->lines;
749 if (tails->splines)
750 tails->splines->next = l2->splines;
751 else
752 l1->splines = l2->splines;
753 if (tails->texts)
754 tails->texts->next = l2->texts;
755 else
756 l1->texts = l2->texts;
757 }
758
759 /* Cut is the dual of append. */
760
cut_objects(F_compound * objects,F_compound * tails)761 void cut_objects(F_compound *objects, F_compound *tails)
762 {
763 if (tails->arcs) {
764 remove_arc_depths(tails->arcs->next);
765 tails->arcs->next = NULL;
766 } else if (objects->arcs) {
767 remove_arc_depths(objects->arcs);
768 objects->arcs = NULL;
769 }
770 if (tails->compounds) {
771 remove_compound_depth(tails->compounds->next);
772 tails->compounds->next = NULL;
773 } else if (objects->compounds) {
774 remove_compound_depth(objects->compounds);
775 objects->compounds = NULL;
776 }
777 if (tails->ellipses) {
778 remove_ellipse_depths(tails->ellipses->next);
779 tails->ellipses->next = NULL;
780 } else if (objects->ellipses) {
781 remove_ellipse_depths(objects->ellipses);
782 objects->ellipses = NULL;
783 }
784 if (tails->lines) {
785 remove_line_depths(tails->lines->next);
786 tails->lines->next = NULL;
787 } else if (objects->lines) {
788 remove_line_depths(objects->lines);
789 objects->lines = NULL;
790 }
791 if (tails->splines) {
792 remove_spline_depths(tails->splines->next);
793 tails->splines->next = NULL;
794 } else if (objects->splines) {
795 remove_spline_depths(objects->splines);
796 objects->splines = NULL;
797 }
798 if (tails->texts) {
799 remove_text_depths(tails->texts->next);
800 tails->texts->next = NULL;
801 } else if (objects->texts) {
802 remove_text_depths(objects->texts);
803 objects->texts = NULL;
804 }
805 }
806
807 void
remove_arc_depths(F_arc * a)808 remove_arc_depths(F_arc *a)
809 {
810 for ( ; a; a= a->next)
811 remove_depth(O_ARC, a->depth);
812 }
813
814 void
remove_ellipse_depths(F_ellipse * e)815 remove_ellipse_depths(F_ellipse *e)
816 {
817 for ( ; e; e = e->next)
818 remove_depth(O_ELLIPSE, e->depth);
819 }
820
821 void
remove_line_depths(F_line * l)822 remove_line_depths(F_line *l)
823 {
824 for ( ; l; l = l->next)
825 remove_depth(O_POLYLINE, l->depth);
826 }
827
828 void
remove_spline_depths(F_spline * s)829 remove_spline_depths(F_spline *s)
830 {
831 for ( ; s; s = s->next)
832 remove_depth(O_SPLINE, s->depth);
833 }
834
835 void
remove_text_depths(F_text * t)836 remove_text_depths(F_text *t)
837 {
838 for ( ; t; t = t->next)
839 remove_depth(O_TXT, t->depth);
840 }
841
842 void
append_point(int x,int y,F_point ** point)843 append_point(int x, int y, F_point **point) /** used in d_arcbox **/
844 {
845 F_point *p;
846
847 if ((p = create_point()) == NULL)
848 return;
849
850 p->x = x;
851 p->y = y;
852 p->next = NULL;
853 (*point)->next = p;
854 *point = p;
855 }
856
857 Boolean
insert_point(int x,int y,F_point * point)858 insert_point(int x, int y, F_point *point)
859 {
860 F_point *p;
861
862 if ((p = create_point()) == NULL)
863 return False;
864
865 p->x = x;
866 p->y = y;
867 p->next = (point)->next;
868 (point)->next = p;
869 return True;
870 }
871
872 Boolean
append_sfactor(double s,F_sfactor * cpoint)873 append_sfactor(double s, F_sfactor *cpoint)
874 {
875 F_sfactor *newpoint;
876
877 if ((newpoint = create_sfactor()) == NULL)
878 return False;
879 newpoint->s = s;
880 newpoint->next = cpoint->next;
881 cpoint->next = newpoint;
882 return True;
883 }
884
885
886 Boolean
first_spline_point(int x,int y,double s,F_spline * spline)887 first_spline_point(int x, int y, double s, F_spline *spline)
888 {
889 F_point *newpoint;
890 F_sfactor *cpoint;
891
892 if ((newpoint = create_point()) == NULL)
893 return False;
894 if ((cpoint = create_sfactor()) == NULL)
895 return False;
896
897 newpoint->x = x;
898 newpoint->y = y;
899 newpoint->next = spline->points;
900 spline->points = newpoint;
901 cpoint->s = s;
902 cpoint->next = spline->sfactors;
903 spline->sfactors = cpoint;
904 return True;
905 }
906
num_points(F_point * points)907 int num_points(F_point *points)
908 {
909 int n;
910 F_point *p;
911
912 for (p = points, n = 0; p != NULL; p = p->next, n++)
913 ;
914 return (n);
915 }
916
917 F_text *
last_text(F_text * list)918 last_text(F_text *list)
919 {
920 F_text *tt;
921
922 if (list == NULL)
923 return NULL;
924
925 for (tt = list; tt->next != NULL; tt = tt->next)
926 ;
927 return tt;
928 }
929
930 F_line *
last_line(F_line * list)931 last_line(F_line *list)
932 {
933 F_line *ll;
934
935 if (list == NULL)
936 return NULL;
937
938 for (ll = list; ll->next != NULL; ll = ll->next)
939 ;
940 return ll;
941 }
942
943 F_spline *
last_spline(F_spline * list)944 last_spline(F_spline *list)
945 {
946 F_spline *ss;
947
948 if (list == NULL)
949 return NULL;
950
951 for (ss = list; ss->next != NULL; ss = ss->next)
952 ;
953 return ss;
954 }
955
956 F_arc *
last_arc(F_arc * list)957 last_arc(F_arc *list)
958 {
959 F_arc *tt;
960
961 if (list == NULL)
962 return NULL;
963
964 for (tt = list; tt->next != NULL; tt = tt->next)
965 ;
966 return tt;
967 }
968
969 F_ellipse *
last_ellipse(F_ellipse * list)970 last_ellipse(F_ellipse *list)
971 {
972 F_ellipse *tt;
973
974 if (list == NULL)
975 return NULL;
976
977 for (tt = list; tt->next != NULL; tt = tt->next)
978 ;
979 return tt;
980 }
981
982 F_compound *
last_compound(F_compound * list)983 last_compound(F_compound *list)
984 {
985 F_compound *tt;
986
987 if (list == NULL)
988 return NULL;
989
990 for (tt = list; tt->next != NULL; tt = tt->next)
991 ;
992 return tt;
993 }
994
995 F_point *
last_point(F_point * list)996 last_point(F_point *list)
997 {
998 F_point *tt;
999
1000 if (list == NULL)
1001 return NULL;
1002
1003 for (tt = list; tt->next != NULL; tt = tt->next)
1004 ;
1005 return tt;
1006 }
1007
1008 F_sfactor *
last_sfactor(F_sfactor * list)1009 last_sfactor(F_sfactor *list)
1010 {
1011 F_sfactor *tt;
1012
1013 if (list == NULL)
1014 return NULL;
1015
1016 for (tt = list; tt->next != NULL; tt = tt->next)
1017 ;
1018 return tt;
1019 }
1020
1021 F_point *
search_line_point(F_line * line,int x,int y)1022 search_line_point(F_line *line, int x, int y)
1023 {
1024 F_point *point;
1025
1026 for (point = line->points ;
1027 point != NULL && (point->x != x || point->y != y); point = point->next);
1028 return point;
1029 }
1030
1031 F_point *
search_spline_point(F_spline * spline,int x,int y)1032 search_spline_point(F_spline *spline, int x, int y)
1033 {
1034 F_point *point;
1035
1036 for (point = spline->points ;
1037 point != NULL && (point->x != x || point->y != y); point = point->next);
1038 return point;
1039 }
1040
1041
1042 F_sfactor *
search_sfactor(F_spline * spline,F_point * selected_point)1043 search_sfactor(F_spline *spline, F_point *selected_point)
1044 {
1045 F_sfactor *c_point = spline->sfactors;
1046 F_point *cursor;
1047
1048 for (cursor = spline->points ; cursor != selected_point ;
1049 cursor = cursor->next)
1050 c_point = c_point->next;
1051 return c_point;
1052 }
1053
1054
1055 F_arc *
prev_arc(F_arc * list,F_arc * arc)1056 prev_arc(F_arc *list, F_arc *arc)
1057 {
1058 F_arc *csr;
1059
1060 if (list == arc)
1061 return NULL;
1062
1063 for (csr = list; csr->next != arc; csr = csr->next)
1064 ;
1065 return csr;
1066 }
1067
1068 F_compound *
prev_compound(F_compound * list,F_compound * compound)1069 prev_compound(F_compound *list, F_compound *compound)
1070 {
1071 F_compound *csr;
1072
1073 if (list == compound)
1074 return NULL;
1075
1076 for (csr = list; csr->next != compound; csr = csr->next)
1077 ;
1078 return csr;
1079 }
1080
1081 F_ellipse *
prev_ellipse(F_ellipse * list,F_ellipse * ellipse)1082 prev_ellipse(F_ellipse *list, F_ellipse *ellipse)
1083 {
1084 F_ellipse *csr;
1085
1086 if (list == ellipse)
1087 return NULL;
1088
1089 for (csr = list; csr->next != ellipse; csr = csr->next)
1090 ;
1091 return csr;
1092 }
1093
1094 F_line *
prev_line(F_line * list,F_line * line)1095 prev_line(F_line *list, F_line *line)
1096 {
1097 F_line *csr;
1098
1099 if (list == line)
1100 return NULL;
1101
1102 for (csr = list; csr->next != line; csr = csr->next)
1103 ;
1104 return csr;
1105 }
1106
1107 F_spline *
prev_spline(F_spline * list,F_spline * spline)1108 prev_spline(F_spline *list, F_spline *spline)
1109 {
1110 F_spline *csr;
1111
1112 if (list == spline)
1113 return NULL;
1114
1115 for (csr = list; csr->next != spline; csr = csr->next)
1116 ;
1117 return csr;
1118 }
1119
1120 F_text *
prev_text(F_text * list,F_text * text)1121 prev_text(F_text *list, F_text *text)
1122 {
1123 F_text *csr;
1124
1125 if (list == text)
1126 return NULL;
1127
1128 for (csr = list; csr->next != text; csr = csr->next)
1129 ;
1130 return csr;
1131 }
1132
1133 F_point *
prev_point(F_point * list,F_point * point)1134 prev_point(F_point *list, F_point *point)
1135 {
1136 F_point *csr;
1137
1138 if (list == point)
1139 return NULL;
1140
1141 for (csr = list; csr->next != point; csr = csr->next)
1142 ;
1143 return csr;
1144 }
1145
1146 int
object_count(F_compound * list)1147 object_count(F_compound *list)
1148 {
1149 register int cnt;
1150 F_arc *a;
1151 F_text *t;
1152 F_compound *c;
1153 F_ellipse *e;
1154 F_line *l;
1155 F_spline *s;
1156
1157 cnt = 0;
1158 for (a = list->arcs; a != NULL; a = a->next, cnt++)
1159 ;
1160 for (t = list->texts; t != NULL; t = t->next, cnt++)
1161 ;
1162 for (c = list->compounds; c != NULL; c = c->next, cnt++)
1163 ;
1164 for (e = list->ellipses; e != NULL; e = e->next, cnt++)
1165 ;
1166 for (l = list->lines; l != NULL; l = l->next, cnt++)
1167 ;
1168 for (s = list->splines; s != NULL; s = s->next, cnt++)
1169 ;
1170 return (cnt);
1171 }
1172
set_tags(F_compound * list,int tag)1173 void set_tags(F_compound *list, int tag)
1174 {
1175 F_arc *a;
1176 F_text *t;
1177 F_compound *c;
1178 F_ellipse *e;
1179 F_line *l;
1180 F_spline *s;
1181
1182 for (a = list->arcs; a != NULL; a = a->next) {
1183 mask_toggle_arcmarker(a);
1184 a->tagged = tag;
1185 mask_toggle_arcmarker(a);
1186 }
1187 for (t = list->texts; t != NULL; t = t->next) {
1188 mask_toggle_textmarker(t);
1189 t->tagged = tag;
1190 mask_toggle_textmarker(t);
1191 }
1192 for (c = list->compounds; c != NULL; c = c->next) {
1193 mask_toggle_compoundmarker(c);
1194 c->tagged = tag;
1195 mask_toggle_compoundmarker(c);
1196 }
1197 for (e = list->ellipses; e != NULL; e = e->next) {
1198 mask_toggle_ellipsemarker(e);
1199 e->tagged = tag;
1200 mask_toggle_ellipsemarker(e);
1201 }
1202 for (l = list->lines; l != NULL; l = l->next) {
1203 mask_toggle_linemarker(l);
1204 l->tagged = tag;
1205 mask_toggle_linemarker(l);
1206 }
1207 for (s = list->splines; s != NULL; s = s->next) {
1208 mask_toggle_splinemarker(s);
1209 s->tagged = tag;
1210 mask_toggle_splinemarker(s);
1211 }
1212 }
1213
1214 void
get_links(int llx,int lly,int urx,int ury)1215 get_links(int llx, int lly, int urx, int ury)
1216 {
1217 F_line *l;
1218 F_point *a;
1219 F_linkinfo *j, *k;
1220
1221 j = NULL;
1222 for (l = objects.lines; l != NULL; l = l->next)
1223 if (l->type == T_POLYLINE) {
1224 a = l->points;
1225 if (point_on_perim(a, llx, lly, urx, ury)) {
1226 if ((k = new_link(l, a, a->next)) == NULL)
1227 return;
1228 if (j == NULL)
1229 cur_links = k;
1230 else
1231 j->next = k;
1232 j = k;
1233 if (k->prevpt != NULL)
1234 k->two_pts = (k->prevpt->next == NULL);
1235 continue;
1236 }
1237 if (a->next == NULL)/* single point, no need to check further */
1238 continue;
1239 a = last_point(l->points);
1240 if (point_on_perim(a, llx, lly, urx, ury)) {
1241 if ((k = new_link(l, a, prev_point(l->points, a))) == NULL)
1242 return;
1243 if (j == NULL)
1244 cur_links = k;
1245 else
1246 j->next = k;
1247 j = k;
1248 if (k->prevpt != NULL)
1249 k->two_pts = (prev_point(l->points, k->prevpt) == NULL);
1250 continue;
1251 }
1252 }
1253 }
1254
1255 static int LINK_TOL = 3 * PIX_PER_INCH / DISPLAY_PIX_PER_INCH;
1256
1257 int
point_on_perim(F_point * p,int llx,int lly,int urx,int ury)1258 point_on_perim(F_point *p, int llx, int lly, int urx, int ury)
1259 {
1260 return ((abs(p->x - llx) <= LINK_TOL && p->y >= lly - LINK_TOL
1261 && p->y <= ury + LINK_TOL) ||
1262 (abs(p->x - urx) <= LINK_TOL && p->y >= lly - LINK_TOL
1263 && p->y <= ury + LINK_TOL) ||
1264 (abs(p->y - lly) <= LINK_TOL && p->x >= llx - LINK_TOL
1265 && p->x <= urx + LINK_TOL) ||
1266 (abs(p->y - ury) <= LINK_TOL && p->x >= llx - LINK_TOL
1267 && p->x <= urx + LINK_TOL));
1268 }
1269 /*
1270 ** get_interior_links and point_on_inside, added by Ian Brown Feb 1995.
1271 ** This is to allow links within compound objects.
1272 */
1273
1274 void
get_interior_links(int llx,int lly,int urx,int ury)1275 get_interior_links(int llx, int lly, int urx, int ury)
1276 {
1277 F_line *l;
1278 F_point *a;
1279 F_linkinfo *j, *k;
1280
1281 j = NULL;
1282 for (l = objects.lines; l != NULL; l = l->next)
1283 if (l->type == T_POLYLINE) {
1284 a = l->points;
1285 if (point_on_inside(a, llx, lly, urx, ury)) {
1286 if ((k = new_link(l, a, a->next)) == NULL)
1287 return;
1288 if (j == NULL)
1289 cur_links = k;
1290 else
1291 j->next = k;
1292 j = k;
1293 if (k->prevpt != NULL)
1294 k->two_pts = (k->prevpt->next == NULL);
1295 continue;
1296 }
1297 if (a->next == NULL)/* single point, no need to check further */
1298 continue;
1299 a = last_point(l->points);
1300 if (point_on_inside(a, llx, lly, urx, ury)) {
1301 if ((k = new_link(l, a, prev_point(l->points, a))) == NULL)
1302 return;
1303 if (j == NULL)
1304 cur_links = k;
1305 else
1306 j->next = k;
1307 j = k;
1308 if (k->prevpt != NULL)
1309 k->two_pts = (prev_point(l->points, k->prevpt) == NULL);
1310 continue;
1311 }
1312 }
1313 }
1314
1315 int
point_on_inside(F_point * p,int llx,int lly,int urx,int ury)1316 point_on_inside(F_point *p, int llx, int lly, int urx, int ury)
1317 {
1318 return ((p->x >= llx) && (p->x <= urx) &&
1319 (p->y >= lly) && (p->y <= ury));
1320
1321 }
1322
1323 void
adjust_links(int mode,F_linkinfo * links,int dx,int dy,int cx,int cy,float sx,float sy,Boolean copying)1324 adjust_links(int mode, F_linkinfo *links,
1325 int dx, int dy, /* delta */
1326 int cx, int cy, /* center of scale - NOT USED YET */
1327 float sx, float sy, /* scale factor - NOT USED YET */
1328 Boolean copying)
1329 {
1330 F_linkinfo *k;
1331 F_line *l;
1332
1333 if (mode != SMART_OFF)
1334 for (k = links; k != NULL; k = k->next) {
1335 if (copying) {
1336 l = copy_line(k->line);
1337 list_add_line(&objects.lines, l);
1338 } else {
1339 mask_toggle_linemarker(k->line);
1340 draw_line(k->line, ERASE);
1341 }
1342 if (mode == SMART_SLIDE && k->prevpt != NULL) {
1343 if (k->endpt->x == k->prevpt->x)
1344 k->prevpt->x += dx;
1345 else
1346 k->prevpt->y += dy;
1347 }
1348 k->endpt->x += dx;
1349 k->endpt->y += dy;
1350 draw_line(k->line, PAINT);
1351 mask_toggle_linemarker(k->line);
1352 }
1353 }
1354