1 /*
2 * FIG : Facility for Interactive Generation of figures
3 * Copyright (c) 1985-1988 by Supoj Sutanthavibul
4 * Parts Copyright (c) 1989-2015 by Brian V. Smith
5 * Parts Copyright (c) 1991 by Paul King
6 * Parts Copyright (c) 2016-2020 by Thomas Loimer
7 *
8 * Parts Copyright (c) 1995 by C. Blanc and C. Schlick
9 *
10 * Any party obtaining a copy of these files is granted, free of charge, a
11 * full and unrestricted irrevocable, world-wide, paid up, royalty-free,
12 * nonexclusive right and license to deal in this software and documentation
13 * files (the "Software"), including without limitation the rights to use,
14 * copy, modify, merge, publish, distribute, sublicense and/or sell copies of
15 * the Software, and to permit persons who receive copies from any such
16 * party to do so, with the only requirement being that the above copyright
17 * and this permission notice remain intact.
18 *
19 */
20
21
22 #include <stdlib.h>
23 #include <stdio.h>
24
25 #include "mode.h"
26 #include "object.h"
27 #include "e_edit.h"
28 #include "e_scale.h"
29 #include "u_create.h"
30 #include "u_free.h"
31 #include "u_list.h"
32 #include "w_cursor.h"
33 #include "w_modepanel.h"
34 #include "w_mousefun.h"
35 #include "w_msgpanel.h"
36 #include "w_setup.h"
37 #include "w_util.h"
38
39 static char Err_mem[] = "Running out of memory.";
40
41
42 /****************** ARROWS ****************/
43
44
45 F_arrow *
create_arrow(void)46 create_arrow(void)
47 {
48 F_arrow *a;
49
50 if ((a = (F_arrow *) malloc(ARROW_SIZE)) == NULL)
51 put_msg(Err_mem);
52 return a;
53 }
54
55 F_arrow *
forward_arrow(void)56 forward_arrow(void)
57 {
58 F_arrow *a;
59
60 if ((a = create_arrow()) == NULL) {
61 put_msg(Err_mem);
62 return NULL;
63 }
64
65 a->type = ARROW_TYPE(cur_arrowtype);
66 a->style = ARROW_STYLE(cur_arrowtype);
67 if (use_abs_arrowvals) {
68 a->thickness = cur_arrowthick;
69 a->wd = cur_arrowwidth;
70 a->ht = cur_arrowheight;
71 } else {
72 a->thickness = cur_arrow_multthick*cur_linewidth;
73 a->wd = cur_arrow_multwidth*cur_linewidth;
74 a->ht = cur_arrow_multheight*cur_linewidth;
75 }
76 return a;
77 }
78
79 F_arrow *
backward_arrow(void)80 backward_arrow(void)
81 {
82 F_arrow *a;
83
84 if ((a = create_arrow()) == NULL) {
85 put_msg(Err_mem);
86 return NULL;
87 }
88
89 a->type = ARROW_TYPE(cur_arrowtype);
90 a->style = ARROW_STYLE(cur_arrowtype);
91 if (use_abs_arrowvals) {
92 a->thickness = cur_arrowthick;
93 a->wd = cur_arrowwidth;
94 a->ht = cur_arrowheight;
95 } else {
96 a->thickness = cur_arrow_multthick*cur_linewidth;
97 a->wd = cur_arrow_multwidth*cur_linewidth;
98 a->ht = cur_arrow_multheight*cur_linewidth;
99 }
100 return a;
101 }
102
103 F_arrow *
new_arrow(int type,int style,float thickness,float wd,float ht)104 new_arrow(int type, int style, float thickness, float wd, float ht)
105 {
106 F_arrow *a;
107
108 if ((a = create_arrow()) == NULL) {
109 put_msg(Err_mem);
110 return NULL;
111 }
112
113 /* check arrow type for legality */
114 if (type > NUM_ARROW_TYPES/2) { /* type*2+style = NUM_ARROW_TYPES */
115 type = style = 0;
116 }
117 /* only open or filled allowed */
118 if (style > 1)
119 style = 0;
120
121 /* if thickness is <= 0 or > 10 inches, make reasonable values */
122 if (thickness <= 0.0 || thickness > 10.0 * DISPLAY_PIX_PER_INCH)
123 thickness = cur_arrowthick;
124 /* if width is <= 0 or > 20 inches, make reasonable values */
125 if (wd <= 0.0)
126 wd = cur_arrowwidth;
127 /* if height is < 0 or > 50 inches, make reasonable values */
128 if (ht < 0.0 || ht > 50.0 * DISPLAY_PIX_PER_INCH)
129 ht = cur_arrowheight;
130 a->type = type;
131 a->style = style;
132 a->thickness = thickness;
133 a->wd = wd;
134 a->ht = ht;
135 return a;
136 }
137
138 /************************ COMMENTS *************************/
139
140 void
copy_comments(char ** source,char ** dest)141 copy_comments(char **source, char **dest)
142 {
143 if (*source == NULL) {
144 *dest = NULL;
145 return;
146 }
147 if ((*dest = (char*) new_string(strlen(*source))) == NULL)
148 return;
149 strcpy(*dest,*source);
150 }
151
152 /************************ SMART LINKS *************************/
153
154 F_linkinfo *
new_link(F_line * l,F_point * ep,F_point * pp)155 new_link(F_line *l, F_point *ep, F_point *pp)
156 {
157 F_linkinfo *k;
158
159 if ((k = (F_linkinfo *) malloc(LINKINFO_SIZE)) == NULL) {
160 put_msg(Err_mem);
161 return NULL;
162 }
163 k->line = l;
164 k->endpt = ep;
165 k->prevpt = pp;
166 k->next = NULL;
167 return k;
168 }
169
170 /************************ POINTS *************************/
171
172 F_point *
create_point(void)173 create_point(void)
174 {
175 F_point *p;
176
177 if ((p = (F_point *) malloc(POINT_SIZE)) == NULL) {
178 put_msg(Err_mem);
179 return NULL;
180 }
181 p->x = 0;
182 p->y = 0;
183 p->next = NULL;
184 return p;
185 }
186
187 F_sfactor *
create_sfactor(void)188 create_sfactor(void)
189 {
190 F_sfactor *cp;
191
192 if ((cp = (F_sfactor *) malloc(CONTROL_SIZE)) == NULL) {
193 put_msg(Err_mem);
194 return NULL;
195 }
196 cp->next = NULL;
197 return cp;
198 }
199
200 F_point *
copy_points(F_point * orig_pt)201 copy_points(F_point *orig_pt)
202 {
203 F_point *new_pt, *prev_pt, *first_pt;
204
205 if ((new_pt = create_point()) == NULL)
206 return NULL;
207
208 first_pt = new_pt;
209 *new_pt = *orig_pt;
210 new_pt->next = NULL;
211 prev_pt = new_pt;
212 for (orig_pt = orig_pt->next; orig_pt != NULL; orig_pt = orig_pt->next) {
213 if ((new_pt = create_point()) == NULL) {
214 free_points(first_pt);
215 return NULL;
216 }
217 prev_pt->next = new_pt;
218 *new_pt = *orig_pt;
219 new_pt->next = NULL;
220 prev_pt = new_pt;
221 }
222 return first_pt;
223 }
224
225 F_sfactor *
copy_sfactors(F_sfactor * orig_sf)226 copy_sfactors(F_sfactor *orig_sf)
227 {
228 F_sfactor *new_sf, *prev_sf, *first_sf;
229
230 if ((new_sf = create_sfactor()) == NULL)
231 return NULL;
232
233 first_sf = new_sf;
234 *new_sf = *orig_sf;
235 new_sf->next = NULL;
236 prev_sf = new_sf;
237 for (orig_sf = orig_sf->next; orig_sf != NULL; orig_sf = orig_sf->next) {
238 if ((new_sf = create_sfactor()) == NULL) {
239 free_sfactors(first_sf);
240 return NULL;
241 }
242 prev_sf->next = new_sf;
243 *new_sf = *orig_sf;
244 new_sf->next = NULL;
245 prev_sf = new_sf;
246 }
247 return first_sf;
248 }
249
250 /* reverse points in list */
251
252 void
reverse_points(F_point * orig_pt)253 reverse_points(F_point *orig_pt)
254 {
255 F_point *cur_pt;
256 int npts,i;
257 F_point *tmp_pts;
258
259 /* count how many points are in the list */
260 cur_pt = orig_pt;
261 for (npts=0; cur_pt; cur_pt=cur_pt->next)
262 npts++;
263 /* make a temporary stack (array) */
264 tmp_pts = (F_point *) malloc(npts*sizeof(F_point));
265 cur_pt = orig_pt;
266 /* and put them on in reverse order */
267 for (i=npts-1; i>=0; i--) {
268 tmp_pts[i].x = cur_pt->x;
269 tmp_pts[i].y = cur_pt->y;
270 cur_pt = cur_pt->next;
271 }
272 /* now reverse them */
273 cur_pt = orig_pt;
274 for (i=0; i<npts; i++) {
275 cur_pt->x = tmp_pts[i].x;
276 cur_pt->y = tmp_pts[i].y;
277 cur_pt = cur_pt->next;
278 }
279 /* free the temp array */
280 free(tmp_pts);
281 }
282
283 /* reverse sfactors in list */
284
285 void
reverse_sfactors(F_sfactor * orig_sf)286 reverse_sfactors(F_sfactor *orig_sf)
287 {
288 F_sfactor *cur_sf;
289 int nsf,i;
290 F_sfactor *tmp_sf;
291
292 /* count how many sfactors are in the list */
293 cur_sf = orig_sf;
294 for (nsf=0; cur_sf; cur_sf=cur_sf->next)
295 nsf++;
296 /* make a temporary stack (array) */
297 tmp_sf = (F_sfactor *) malloc(nsf*sizeof(F_sfactor));
298 cur_sf = orig_sf;
299 /* and put them on in reverse order */
300 for (i=nsf-1; i>=0; i--) {
301 tmp_sf[i].s = cur_sf->s;
302 cur_sf = cur_sf->next;
303 }
304 /* now reverse them */
305 cur_sf = orig_sf;
306 for (i=0; i<nsf; i++) {
307 cur_sf->s = tmp_sf[i].s;
308 cur_sf = cur_sf->next;
309 }
310 /* free the temp array */
311 free(tmp_sf);
312 }
313
314 /************************ ARCS *************************/
315
316 F_arc *
create_arc(void)317 create_arc(void)
318 {
319 F_arc *a;
320
321 if ((a = (F_arc *) malloc(ARCOBJ_SIZE)) == NULL) {
322 put_msg(Err_mem);
323 return NULL;
324 }
325 a->tagged = 0;
326 a->next = NULL;
327 a->type = 0;
328 a->for_arrow = NULL;
329 a->back_arrow = NULL;
330 a->comments = NULL;
331 a->depth = 0;
332 a->thickness = 0;
333 a->pen_color = BLACK;
334 a->fill_color = DEFAULT;
335 a->fill_style = UNFILLED;
336 a->pen_style = -1;
337 a->style = SOLID_LINE;
338 a->style_val = 0.0;
339 a->cap_style = CAP_BUTT;
340 a->direction = 0;
341 a->angle = 0.0;
342 return a;
343 }
344
345 F_arc *
copy_arc(F_arc * a)346 copy_arc(F_arc *a)
347 {
348 F_arc *arc;
349 F_arrow *arrow;
350
351 if ((arc = create_arc()) == NULL)
352 return NULL;
353
354 /* copy static items first */
355 *arc = *a;
356 arc->next = NULL;
357
358 /* do comments next */
359 copy_comments(&a->comments, &arc->comments);
360
361 if (a->for_arrow) {
362 if ((arrow = create_arrow()) == NULL) {
363 free((char *) arc);
364 return NULL;
365 }
366 arc->for_arrow = arrow;
367 *arrow = *a->for_arrow;
368 }
369 if (a->back_arrow) {
370 if ((arrow = create_arrow()) == NULL) {
371 free((char *) arc);
372 return NULL;
373 }
374 arc->back_arrow = arrow;
375 *arrow = *a->back_arrow;
376 }
377 return arc;
378 }
379
380 /************************ ELLIPSES *************************/
381
382 F_ellipse *
create_ellipse(void)383 create_ellipse(void)
384 {
385 F_ellipse *e;
386
387 if ((e = (F_ellipse *) malloc(ELLOBJ_SIZE)) == NULL) {
388 put_msg(Err_mem);
389 return NULL;
390 }
391 e->tagged = 0;
392 e->next = NULL;
393 e->comments = NULL;
394 return e;
395 }
396
397 F_ellipse *
copy_ellipse(F_ellipse * e)398 copy_ellipse(F_ellipse *e)
399 {
400 F_ellipse *ellipse;
401
402 if ((ellipse = create_ellipse()) == NULL)
403 return NULL;
404
405 /* copy static items first */
406 *ellipse = *e;
407 ellipse->next = NULL;
408
409 /* do comments next */
410 copy_comments(&e->comments, &ellipse->comments);
411
412 return ellipse;
413 }
414
415 /************************ LINES *************************/
416
417 F_line *
create_line(void)418 create_line(void)
419 {
420 F_line *l;
421
422 if ((l = (F_line *) malloc(LINOBJ_SIZE)) == NULL) {
423 put_msg(Err_mem);
424 return NULL;
425 }
426 l->tagged = 0;
427 l->next = NULL;
428 l->pic = NULL;
429 l->for_arrow = NULL;
430 l->back_arrow = NULL;
431 l->points = NULL;
432 l->radius = DEFAULT;
433 l->comments = NULL;
434 return l;
435 }
436
437 F_pic *
create_pic(void)438 create_pic(void)
439 {
440 F_pic *pic;
441
442 if ((pic = (F_pic *) malloc(PIC_SIZE)) == NULL) {
443 put_msg(Err_mem);
444 return NULL;
445 }
446 pic->mask = (Pixmap) 0;
447 pic->new = False;
448 pic->pic_cache = NULL;
449 return pic;
450 }
451
452 /* create a new picture entry for the repository */
453
454 struct _pics *
create_picture_entry(void)455 create_picture_entry(void)
456 {
457 struct _pics *picture;
458
459 picture = malloc(sizeof(struct _pics));
460
461 picture->file = NULL;
462 picture->bitmap = NULL;
463 picture->transp = TRANSP_NONE;
464 picture->numcols = 0;
465 picture->refcount = 0;
466 picture->prev = picture->next = NULL;
467 if (appres.DEBUG)
468 fprintf(stderr,"create picture entry %p\n", picture);
469 return picture;
470 }
471
472 F_line *
copy_line(F_line * l)473 copy_line(F_line *l)
474 {
475 F_line *line;
476 F_arrow *arrow;
477 int width, height;
478 GC one_bit_gc;
479
480 if ((line = create_line()) == NULL)
481 return NULL;
482
483 /* copy static items first */
484 *line = *l;
485 line->next = NULL;
486
487 /* do comments next */
488 copy_comments(&l->comments, &line->comments);
489
490 if (l->for_arrow) {
491 if ((arrow = create_arrow()) == NULL) {
492 free((char *) line);
493 return NULL;
494 }
495 line->for_arrow = arrow;
496 *arrow = *l->for_arrow;
497 }
498 if (l->back_arrow) {
499 if ((arrow = create_arrow()) == NULL) {
500 free((char *) line);
501 return NULL;
502 }
503 line->back_arrow = arrow;
504 *arrow = *l->back_arrow;
505 }
506 line->points = copy_points(l->points);
507 if (NULL == line->points) {
508 put_msg(Err_mem);
509 free_linestorage(line);
510 return NULL;
511 }
512 /* copy picture information */
513 if (l->pic) {
514 if ((line->pic = create_pic()) == NULL) {
515 free((char *) line);
516 return NULL;
517 }
518 /* copy all the numbers and the pointer to the picture repository (pic->pic_cache) */
519 memcpy(line->pic, l->pic, PIC_SIZE);
520 /* increase reference count for this picture */
521 if (line->pic->pic_cache)
522 line->pic->pic_cache->refcount++;
523
524 width = l->pic->pix_width;
525 height = l->pic->pix_height;
526 /* copy pixmap */
527 if (l->pic->pixmap != 0) {
528 line->pic->pixmap = XCreatePixmap(tool_d, tool_w,
529 width, height, tool_dpth);
530 XCopyArea(tool_d, l->pic->pixmap, line->pic->pixmap, gccache[PAINT],
531 0, 0, width, height, 0, 0);
532 }
533 /* and copy any mask (GIF transparency) */
534 if (l->pic->mask != 0) {
535 line->pic->mask = XCreatePixmap(tool_d, tool_w, width, height, 1);
536 /* need a 1-bit deep GC to copy it */
537 one_bit_gc = XCreateGC(tool_d, line->pic->mask, (unsigned long) 0, 0);
538 XSetForeground(tool_d, one_bit_gc, 0);
539 XCopyArea(tool_d, l->pic->mask, line->pic->mask, one_bit_gc,
540 0, 0, width, height, 0, 0);
541 }
542 }
543 return line;
544 }
545
546 /************************ SPLINES *************************/
547
548 F_spline *
create_spline(void)549 create_spline(void)
550 {
551 F_spline *s;
552
553 if ((s = (F_spline *) malloc(SPLOBJ_SIZE)) == NULL) {
554 put_msg(Err_mem);
555 return NULL;
556 }
557 s->tagged = 0;
558 s->next = NULL;
559 s->comments = NULL;
560 return s;
561 }
562
563 F_spline *
copy_spline(F_spline * s)564 copy_spline(F_spline *s)
565 {
566 F_spline *spline;
567 F_arrow *arrow;
568
569 if ((spline = create_spline()) == NULL)
570 return NULL;
571
572 /* copy static items first */
573 *spline = *s;
574 spline->next = NULL;
575
576 /* do comments next */
577 copy_comments(&s->comments, &spline->comments);
578
579 if (s->for_arrow) {
580 if ((arrow = create_arrow()) == NULL) {
581 free((char *) spline);
582 return NULL;
583 }
584 spline->for_arrow = arrow;
585 *arrow = *s->for_arrow;
586 }
587 if (s->back_arrow) {
588 if ((arrow = create_arrow()) == NULL) {
589 free((char *) spline);
590 return NULL;
591 }
592 spline->back_arrow = arrow;
593 *arrow = *s->back_arrow;
594 }
595 spline->points = copy_points(s->points);
596 if (NULL == spline->points) {
597 put_msg(Err_mem);
598 free_splinestorage(spline);
599 return NULL;
600 }
601
602 if (s->sfactors == NULL)
603 return spline;
604 spline->sfactors = copy_sfactors(s->sfactors);
605 if (NULL == spline->sfactors) {
606 put_msg(Err_mem);
607 free_splinestorage(spline);
608 return NULL;
609 }
610
611 return spline;
612 }
613
614 /************************ TEXTS *************************/
615
616 F_text *
create_text(void)617 create_text(void)
618 {
619 F_text *t;
620
621 if ((t = (F_text *) malloc(TEXOBJ_SIZE)) == NULL) {
622 put_msg(Err_mem);
623 return NULL;
624 }
625 t->tagged = 0;
626 t->fontstruct = 0;
627 t->comments = NULL;
628 t->cstring = NULL;
629 t->next = NULL;
630 return t;
631 }
632
633 /* allocate len+1 characters in a new string */
634
635 char *
new_string(int len)636 new_string(int len)
637 {
638 char *c;
639
640 if ((c = (char *) calloc((unsigned) len + 1, sizeof(char))) == NULL)
641 put_msg(Err_mem);
642 return c;
643 }
644
645 F_text *
copy_text(F_text * t)646 copy_text(F_text *t)
647 {
648 F_text *text;
649
650 if ((text = create_text()) == NULL)
651 return NULL;
652
653 /* copy static items first */
654 *text = *t;
655 text->next = NULL;
656
657 /* do comments next */
658 copy_comments(&t->comments, &text->comments);
659
660 if ((text->cstring = new_string(strlen(t->cstring))) == NULL) {
661 free((char *) text);
662 return NULL;
663 }
664 strcpy(text->cstring, t->cstring);
665 return text;
666 }
667
668 /************************ COMPOUNDS *************************/
669
670 F_compound *
create_compound(void)671 create_compound(void)
672 {
673 F_compound *c;
674
675 if ((c = (F_compound *) malloc(COMOBJ_SIZE)) == NULL) {
676 put_msg(Err_mem);
677 return NULL;
678 }
679 c->nwcorner.x = 0;
680 c->nwcorner.y = 0;
681 c->secorner.x = 0;
682 c->secorner.y = 0;
683 c->distrib = 0;
684 c->tagged = 0;
685 c->arcs = NULL;
686 c->compounds = NULL;
687 c->ellipses = NULL;
688 c->lines = NULL;
689 c->splines = NULL;
690 c->texts = NULL;
691 c->comments = NULL;
692 c->parent = NULL;
693 c->GABPtr = NULL;
694 c->next = NULL;
695
696 return c;
697 }
698
699 F_compound *
copy_compound(F_compound * c)700 copy_compound(F_compound *c)
701 {
702 F_ellipse *e, *ee;
703 F_arc *a, *aa;
704 F_line *l, *ll;
705 F_spline *s, *ss;
706 F_text *t, *tt;
707 F_compound *cc, *ccc, *compound;
708
709 if ((compound = create_compound()) == NULL)
710 return NULL;
711
712 compound->nwcorner = c->nwcorner;
713 compound->secorner = c->secorner;
714 compound->arcs = NULL;
715 compound->ellipses = NULL;
716 compound->lines = NULL;
717 compound->splines = NULL;
718 compound->texts = NULL;
719 compound->compounds = NULL;
720 compound->next = NULL;
721
722 /* do comments first */
723 copy_comments(&c->comments, &compound->comments);
724
725 for (e = c->ellipses; e != NULL; e = e->next) {
726 if (NULL == (ee = copy_ellipse(e))) {
727 put_msg(Err_mem);
728 return NULL;
729 }
730 list_add_ellipse(&compound->ellipses, ee);
731 }
732 for (a = c->arcs; a != NULL; a = a->next) {
733 if (NULL == (aa = copy_arc(a))) {
734 put_msg(Err_mem);
735 return NULL;
736 }
737 list_add_arc(&compound->arcs, aa);
738 }
739 for (l = c->lines; l != NULL; l = l->next) {
740 if (NULL == (ll = copy_line(l))) {
741 put_msg(Err_mem);
742 return NULL;
743 }
744 list_add_line(&compound->lines, ll);
745 }
746 for (s = c->splines; s != NULL; s = s->next) {
747 if (NULL == (ss = copy_spline(s))) {
748 put_msg(Err_mem);
749 return NULL;
750 }
751 list_add_spline(&compound->splines, ss);
752 }
753 for (t = c->texts; t != NULL; t = t->next) {
754 if (NULL == (tt = copy_text(t))) {
755 put_msg(Err_mem);
756 return NULL;
757 }
758 list_add_text(&compound->texts, tt);
759 }
760 for (cc = c->compounds; cc != NULL; cc = cc->next) {
761 if (NULL == (ccc = copy_compound(cc))) {
762 put_msg(Err_mem);
763 return NULL;
764 }
765 list_add_compound(&compound->compounds, ccc);
766 }
767 return compound;
768 }
769
770 /********************** DIMENSION LINES **********************/
771
772 /* Make a dimension line given an ordinary line
773
774 It consists of:
775 1. the line drawn by the user,
776 2. "tick" lines at each endpoint if cur_dimline_ticks == True,
777 3. the length in a box overlaid in the middle of the line
778
779 all rolled into a compound object
780
781 Call with add_to_figure = True to add to main figure objects
782 */
783
784 F_compound*
create_dimension_line(F_line * line,Boolean add_to_figure)785 create_dimension_line(F_line *line, Boolean add_to_figure)
786 {
787 F_compound *comp;
788 F_line *box, *tick1, *tick2;
789 F_text *text;
790 F_point *pnt;
791
792 /* make a new compound */
793 comp = create_compound();
794 /* if fixed text, put in an unchanging comment for the compound */
795 /* (rescale_dimension_line will create the comment if the text not fixed (=length)) */
796 if (cur_dimline_fixed) {
797 comp->comments = strdup("Dimension line: User-defined text");
798 } else {
799 comp->comments = strdup("Dimension line:");
800 }
801
802 /* need two objects *on top of* the basic line */
803 if (line->depth < 2) {
804 line->depth = 2;
805 }
806
807 /* put the main line in the compound */
808 comp->lines = line;
809
810 /* put a comment in the main line */
811 line->comments = strdup("main dimension line");
812 line->thickness = cur_dimline_thick;
813 line->fill_style = UNFILLED;
814 line->style = cur_dimline_style;
815 if (line->style == DOTTED_LINE)
816 line->style_val = cur_dotgap * (cur_dimline_thick + 1) / 2;
817 else
818 line->style_val = cur_dashlength * (cur_dimline_thick + 1) / 2;
819 line->pen_color = cur_dimline_color;
820 if (cur_dimline_leftarrow != -1) {
821 line->back_arrow = backward_dim_arrow();
822 }
823 if (cur_dimline_rightarrow != -1) {
824 line->for_arrow = forward_dim_arrow();
825 }
826
827 /***************************************/
828 /* make the text object for the length */
829 /***************************************/
830
831 text = create_text();
832 text->depth = line->depth-2;
833 text->cstring = (char *) NULL; /* the string will be put in later */
834 text->color = cur_dimline_textcolor;
835 text->font = cur_dimline_font;
836 text->size = cur_dimline_fontsize;
837 text->flags = cur_dimline_psflag? PSFONT_TEXT: 0;
838 text->pen_style = -1;
839 text->type = T_CENTER_JUSTIFIED;
840
841 /* put it in the compound */
842 comp->texts = text;
843
844 /*****************************/
845 /* make the box for the text */
846 /*****************************/
847
848 box = create_line();
849 box->comments = strdup("text box");
850 box->depth = line->depth-1;
851 box->type = T_POLYGON;
852 box->style = SOLID_LINE;
853 box->style_val = 0.0;
854 box->thickness = cur_dimline_boxthick;
855 box->pen_color = cur_pencolor;
856 box->fill_color = cur_dimline_boxcolor;
857 box->fill_style = NUMSHADEPATS-1; /* full saturation color */
858 box->pen_style = -1;
859 box->join_style = cur_joinstyle;
860 box->cap_style = CAP_BUTT;
861
862 /* make 5 points for the box */
863 pnt = create_point();
864 box->points = pnt;
865 pnt->next = create_point();
866 pnt = pnt->next;
867 pnt->next = create_point();
868 pnt = pnt->next;
869 pnt->next = create_point();
870 pnt = pnt->next;
871 pnt->next = create_point();
872
873 /* add this to the lines in the compound */
874 comp->lines->next = box;
875
876 /********************************************************************/
877 /* make the two ticks at the endpoints if cur_dimline_ticks == True */
878 /********************************************************************/
879
880 if (cur_dimline_ticks) {
881 create_dimline_ticks(line, &tick1, &tick2);
882
883 /* add this to the lines in the compound */
884 box->next = tick1;
885
886 /* add this to the lines in the compound */
887 tick1->next = tick2;
888 } else
889 box->next = (F_line *) NULL;
890
891 /* if user wants fixed text, add an empty string and a comment to the text part. */
892 if (cur_dimline_fixed) {
893 text->comments = strdup("fixed text");
894 /* if not adding to figure, this must be the dimension line setting panel */
895 if (!add_to_figure)
896 text->cstring = strdup("user text");
897 else
898 text->cstring = strdup("");
899 }
900
901 /* add it to the figure */
902 if (add_to_figure) {
903 add_compound(comp);
904 /* if fixed text, popup editor so user can edit text */
905 if (cur_dimline_fixed) {
906 clear_mousefun();
907 set_mousefun("","","", "", "", "");
908 turn_off_current();
909 set_cursor(arrow_cursor);
910 /* make the shapes (ticks, etc) */
911 rescale_dimension_line(comp, 1.0, 1.0, 0, 0);
912 /* tells the editor to switch back to line mode when done */
913 edit_remember_dimline_mode = True;
914 /* now let the user change the text */
915 edit_item(comp, O_COMPOUND, 0, 0);
916 }
917 }
918 /* calculate angles, box size etc */
919 /* if user just edited it (both cur_dimline_fixed and add_to_figure = True) then
920 it has already been scaled */
921 if (!cur_dimline_fixed || !add_to_figure) {
922 rescale_dimension_line(comp, 1.0, 1.0, 0, 0);
923 }
924
925 /* return it to the caller */
926 return comp;
927 }
928
929 /*
930 * make the two ticks for the endpoints
931 * the actual values of the ticks' points are computed in rescale_dimension_line()
932 */
933
934 void
create_dimline_ticks(F_line * line,F_line ** tick1,F_line ** tick2)935 create_dimline_ticks(F_line *line, F_line **tick1, F_line **tick2)
936 {
937 F_point *pnt;
938 F_line *tick;
939
940 /* first tick */
941
942 tick = create_line();
943 /* copy the attributes from the main line */
944 *tick = *line;
945 /* set thickness */
946 tick->thickness = cur_dimline_tickthick;
947 /* make solid */
948 tick->style = SOLID_LINE;
949 tick->comments = strdup("tick");
950 /* zero the arrows and next pointer */
951 tick->for_arrow = tick->back_arrow = (F_arrow *) NULL;
952 tick->next = (F_line *) NULL;
953 pnt = create_point();
954 tick->points = pnt;
955 pnt->next = create_point();
956 *tick1 = tick;
957
958 /* now the other tick */
959
960 tick = create_line();
961 /* copy the attributes from the main line */
962 *tick = *line;
963 /* set thickness */
964 tick->thickness = cur_dimline_tickthick;
965 /* make solid */
966 tick->style = SOLID_LINE;
967 tick->comments = strdup("tick");
968 /* zero the arrows and next pointer */
969 tick->for_arrow = tick->back_arrow = (F_arrow *) NULL;
970 tick->next = (F_line *) NULL;
971 pnt = create_point();
972 tick->points = pnt;
973 pnt->next = create_point();
974 *tick2 = tick;
975 }
976
977 F_arrow*
backward_dim_arrow(void)978 backward_dim_arrow(void)
979 {
980 F_arrow *a;
981
982 if ((a = create_arrow()) == NULL) {
983 put_msg("Running out of memory");
984 return NULL;
985 }
986
987 a->type = ARROW_TYPE(cur_dimline_leftarrow);
988 a->style = ARROW_STYLE(cur_dimline_leftarrow);
989 a->thickness = cur_dimline_thick;
990 if (a->thickness == 0.0)
991 a->thickness = 1.0;
992 a->wd = cur_dimline_arrowwidth*cur_dimline_thick;
993 a->ht = cur_dimline_arrowlength*cur_dimline_thick;
994 if (a->wd == 0.0)
995 a->wd = 1.0;
996 if (a->ht == 0.0)
997 a->ht = 1.0;
998 return a;
999 }
1000
1001 F_arrow*
forward_dim_arrow(void)1002 forward_dim_arrow(void)
1003 {
1004 F_arrow *a;
1005
1006 if ((a = create_arrow()) == NULL) {
1007 put_msg("Running out of memory");
1008 return NULL;
1009 }
1010
1011 a->type = ARROW_TYPE(cur_dimline_rightarrow);
1012 a->style = ARROW_STYLE(cur_dimline_rightarrow);
1013 a->thickness = cur_dimline_thick;
1014 if (a->thickness == 0.0)
1015 a->thickness = 1.0;
1016 a->wd = cur_dimline_arrowwidth*cur_dimline_thick;
1017 a->ht = cur_dimline_arrowlength*cur_dimline_thick;
1018 if (a->wd == 0.0)
1019 a->wd = 1.0;
1020 if (a->ht == 0.0)
1021 a->ht = 1.0;
1022 return a;
1023 }
1024