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  *
7  * Any party obtaining a copy of these files is granted, free of charge, a
8  * full and unrestricted irrevocable, world-wide, paid up, royalty-free,
9  * nonexclusive right and license to deal in this software and documentation
10  * files (the "Software"), including without limitation the rights to use,
11  * copy, modify, merge, publish, distribute, sublicense and/or sell copies of
12  * the Software, and to permit persons who receive copies from any such
13  * party to do so, with the only requirement being that the above copyright
14  * and this permission notice remain intact.
15  *
16  */
17 
18 #include "fig.h"
19 #include "resources.h"
20 #include "object.h"
21 #include "mode.h"
22 #include "paintop.h"
23 #include "u_markers.h"
24 #include "w_drawprim.h"
25 #include "w_layers.h"
26 #include "w_zoom.h"
27 
28 #include <limits.h>	/* INT_MIN */
29 
30 #define set_marker(win,x,y,w,h) \
31 	XDrawRectangle(tool_d,(win),gccache[INV_PAINT], \
32 	     ZOOMX(x)-((w-1)/2),ZOOMY(y)-((w-1)/2),(w),(h))
33 
34 #define CHANGED_MASK(msk) \
35     ((oldmask & msk) != (newmask & msk))
36 
37 
38 
center_marker(int x,int y)39 void center_marker(int x, int y)
40 {
41 
42     pw_vector(canvas_win, x, y - (int)(CENTER_MARK/zoomscale),
43 	      x, y + (int)(CENTER_MARK/zoomscale), INV_PAINT, 1,
44 	      RUBBER_LINE, 0.0, DEFAULT);
45     pw_vector(canvas_win, x - (int)(CENTER_MARK/zoomscale),
46 	      y, x + (int)(CENTER_MARK/zoomscale), y, INV_PAINT, 1,
47 	      RUBBER_LINE, 0.0, DEFAULT);
48 
49 }
50 
toggle_csrhighlight(int x,int y)51 void toggle_csrhighlight(int x, int y)
52 {
53     set_line_stuff(1, RUBBER_LINE, 0.0, JOIN_MITER, CAP_BUTT, INV_PAINT, DEFAULT);
54     set_marker(canvas_win, x - 2, y - 2, MARK_SIZ, MARK_SIZ);
55     set_marker(canvas_win, x - 1, y - 1, MARK_SIZ-2, MARK_SIZ-2);
56 }
57 
ellipse_in_mask(void)58 int ellipse_in_mask(void)
59 {
60     return (cur_objmask & M_ELLIPSE);
61 }
62 
arc_in_mask(void)63 int arc_in_mask(void)
64 {
65     return (cur_objmask & M_ARC);
66 }
67 
compound_in_mask(void)68 int compound_in_mask(void)
69 {
70     return (cur_objmask & M_COMPOUND);
71 }
72 
anytext_in_mask(void)73 int anytext_in_mask(void)
74 {
75     return (cur_objmask & M_TEXT);
76 }
77 
validtext_in_mask(F_text * t)78 int validtext_in_mask(F_text *t)
79 {
80     return ((hidden_text(t) && (cur_objmask & M_TEXT_HIDDEN)) ||
81 	    ((!hidden_text(t)) && (cur_objmask & M_TEXT_NORMAL)));
82 }
83 
anyline_in_mask(void)84 int anyline_in_mask(void)
85 {
86     return (cur_objmask & M_POLYLINE);
87 }
88 
validline_in_mask(F_line * l)89 int validline_in_mask(F_line *l)
90 {
91     return ((((l->type == T_BOX) || (l->type == T_ARCBOX)) && (cur_objmask & M_POLYLINE_BOX)) ||
92 	    ((l->type == T_PICTURE) && (cur_objmask & M_POLYLINE_BOX)) ||
93 	    ((l->type == T_POLYLINE) && (cur_objmask & M_POLYLINE_LINE)) ||
94 	    ((l->type == T_POLYGON) && (cur_objmask & M_POLYLINE_POLYGON)));
95 }
96 
anyspline_in_mask(void)97 int anyspline_in_mask(void)
98 {
99     return (cur_objmask & M_SPLINE);
100 }
101 
validspline_in_mask(F_spline * s)102 int validspline_in_mask(F_spline *s)
103 {
104     return (((s->type == T_OPEN_INTERP) && (cur_objmask & M_SPLINE_O_INTERP)) ||
105 	    ((s->type == T_OPEN_APPROX) && (cur_objmask & M_SPLINE_O_APPROX))   ||
106 	    ((s->type == T_OPEN_XSPLINE) && (cur_objmask & M_SPLINE_O_XSPLINE)) ||
107 	    ((s->type == T_CLOSED_INTERP) && (cur_objmask & M_SPLINE_C_INTERP)) ||
108 	    ((s->type == T_CLOSED_APPROX) && (cur_objmask & M_SPLINE_C_APPROX)) ||
109 	    ((s->type == T_CLOSED_XSPLINE) && (cur_objmask & M_SPLINE_C_XSPLINE)));
110 }
111 
mask_toggle_ellipsemarker(F_ellipse * e)112 void mask_toggle_ellipsemarker(F_ellipse *e)
113 {
114     if (ellipse_in_mask())
115 	toggle_ellipsemarker(e);
116 }
117 
mask_toggle_arcmarker(F_arc * a)118 void mask_toggle_arcmarker(F_arc *a)
119 {
120     if (arc_in_mask())
121 	toggle_arcmarker(a);
122 }
123 
mask_toggle_compoundmarker(F_compound * c)124 void mask_toggle_compoundmarker(F_compound *c)
125 {
126     if (compound_in_mask())
127 	toggle_compoundmarker(c);
128 }
129 
mask_toggle_textmarker(F_text * t)130 void mask_toggle_textmarker(F_text *t)
131 {
132     if (validtext_in_mask(t))
133 	toggle_textmarker(t);
134 }
135 
mask_toggle_linemarker(F_line * l)136 void mask_toggle_linemarker(F_line *l)
137 {
138     if (validline_in_mask(l))
139 	toggle_linemarker(l);
140 }
141 
mask_toggle_splinemarker(F_spline * s)142 void mask_toggle_splinemarker(F_spline *s)
143 {
144     if (validspline_in_mask(s))
145 	toggle_splinemarker(s);
146 }
147 
toggle_markers(void)148 void toggle_markers(void)
149 {
150     toggle_markers_in_compound(&objects);
151 }
152 
toggle_markers_in_compound(F_compound * cmpnd)153 void toggle_markers_in_compound(F_compound *cmpnd)
154 {
155     F_ellipse	   *e;
156     F_arc	   *a;
157     F_line	   *l;
158     F_spline	   *s;
159     F_text	   *t;
160     F_compound	   *c;
161     register int    mask;
162 
163     mask = cur_objmask;
164     if (mask & M_ELLIPSE)
165 	for (e = cmpnd->ellipses; e != NULL; e = e->next)
166 	    if (active_layer(e->depth))
167 		toggle_ellipsemarker(e);
168     if (mask & M_TEXT)
169 	for (t = cmpnd->texts; t != NULL; t = t->next) {
170 	    if (active_layer(t->depth) &&
171 	        (((hidden_text(t) && (mask & M_TEXT_HIDDEN)) ||
172 		((!hidden_text(t)) && (mask & M_TEXT_NORMAL)))))
173 		    toggle_textmarker(t);
174 	}
175     if (mask & M_ARC)
176 	for (a = cmpnd->arcs; a != NULL; a = a->next)
177 	    if (active_layer(a->depth))
178 		toggle_arcmarker(a);
179     if (mask & M_POLYLINE)
180 	for (l = cmpnd->lines; l != NULL; l = l->next) {
181 	    if (active_layer(l->depth) &&
182 	        ((((l->type == T_BOX) ||
183 		  (l->type == T_ARCBOX)) && (mask & M_POLYLINE_BOX)) ||
184 		((l->type == T_PICTURE) && (mask & M_POLYLINE_BOX)) ||
185 		((l->type == T_POLYLINE) && (mask & M_POLYLINE_LINE)) ||
186 		((l->type == T_POLYGON) && (mask & M_POLYLINE_POLYGON))))
187 		toggle_linemarker(l);
188 	}
189     if (mask & M_SPLINE)
190 	for (s = cmpnd->splines; s != NULL; s = s->next) {
191 	    if (active_layer(s->depth) &&
192 	       (((s->type == T_OPEN_INTERP) && (mask & M_SPLINE_O_INTERP)) ||
193 		((s->type == T_OPEN_APPROX) && (mask & M_SPLINE_O_APPROX))   ||
194 		((s->type == T_OPEN_XSPLINE) && (mask & M_SPLINE_O_XSPLINE)) ||
195 	       ((s->type == T_CLOSED_INTERP) && (mask & M_SPLINE_C_INTERP)) ||
196 		((s->type == T_CLOSED_APPROX) && (mask & M_SPLINE_C_APPROX)) ||
197 		((s->type == T_CLOSED_XSPLINE) && (mask & M_SPLINE_C_XSPLINE))))
198 		toggle_splinemarker(s);
199 	}
200     if (mask & M_COMPOUND)
201 	for (c = cmpnd->compounds; c != NULL; c = c->next)
202 	    if (any_active_in_compound(c))
203 		toggle_compoundmarker(c);
204 }
205 
update_markers(int mask)206 void update_markers(int mask)
207 {
208     F_ellipse	   *e;
209     F_arc	   *a;
210     F_line	   *l;
211     F_spline	   *s;
212     F_text	   *t;
213     F_compound	   *c;
214     register int    oldmask, newmask;
215 
216     oldmask = cur_objmask;
217     newmask = mask;
218     if (CHANGED_MASK(M_ELLIPSE))
219 	for (e = objects.ellipses; e != NULL; e = e->next)
220 	    if (active_layer(e->depth))
221 		toggle_ellipsemarker(e);
222     if (CHANGED_MASK(M_TEXT_NORMAL) || CHANGED_MASK(M_TEXT_HIDDEN))
223 	for (t = objects.texts; t != NULL; t = t->next) {
224 	    if (active_layer(t->depth) &&
225 		((hidden_text(t) && CHANGED_MASK(M_TEXT_HIDDEN))   ||
226 		((!hidden_text(t)) && CHANGED_MASK(M_TEXT_NORMAL))))
227 		    toggle_textmarker(t);
228 	}
229     if (CHANGED_MASK(M_ARC))
230 	for (a = objects.arcs; a != NULL; a = a->next)
231 	    if (active_layer(a->depth))
232 		toggle_arcmarker(a);
233     if (CHANGED_MASK(M_POLYLINE_LINE) ||
234 	CHANGED_MASK(M_POLYLINE_POLYGON) ||
235 	CHANGED_MASK(M_POLYLINE_BOX))
236 	for (l = objects.lines; l != NULL; l = l->next) {
237 	    if (active_layer(l->depth) &&
238 		((((l->type == T_BOX || l->type == T_ARCBOX ||
239 		   l->type == T_PICTURE)) && CHANGED_MASK(M_POLYLINE_BOX)) ||
240 		((l->type == T_POLYLINE) && CHANGED_MASK(M_POLYLINE_LINE)) ||
241 		((l->type == T_POLYGON) && CHANGED_MASK(M_POLYLINE_POLYGON))))
242 		    toggle_linemarker(l);
243 	}
244     if (CHANGED_MASK(M_SPLINE_O_APPROX) || CHANGED_MASK(M_SPLINE_C_APPROX) ||
245 	CHANGED_MASK(M_SPLINE_O_INTERP) || CHANGED_MASK(M_SPLINE_C_INTERP) ||
246 	CHANGED_MASK(M_SPLINE_O_XSPLINE) || CHANGED_MASK(M_SPLINE_C_XSPLINE))
247 	for (s = objects.splines; s != NULL; s = s->next) {
248 	    if (active_layer(s->depth) &&
249 		(((s->type == T_OPEN_INTERP) && CHANGED_MASK(M_SPLINE_O_INTERP)) ||
250 		((s->type == T_OPEN_APPROX) && CHANGED_MASK(M_SPLINE_O_APPROX)) ||
251 		((s->type == T_OPEN_XSPLINE) && CHANGED_MASK(M_SPLINE_O_XSPLINE)) ||
252 		((s->type == T_CLOSED_INTERP) && CHANGED_MASK(M_SPLINE_C_INTERP)) ||
253 		((s->type == T_CLOSED_APPROX) && CHANGED_MASK(M_SPLINE_C_APPROX)) ||
254 		((s->type == T_CLOSED_XSPLINE) && CHANGED_MASK(M_SPLINE_C_XSPLINE))))
255 		    toggle_splinemarker(s);
256 	  }
257     if (CHANGED_MASK(M_COMPOUND))
258 	for (c = objects.compounds; c != NULL; c = c->next)
259 	    if (any_active_in_compound(c))
260 		toggle_compoundmarker(c);
261     cur_objmask = newmask;
262 }
263 
toggle_ellipsemarker(F_ellipse * e)264 void toggle_ellipsemarker(F_ellipse *e)
265 {
266     set_line_stuff(1, RUBBER_LINE, 0.0, JOIN_MITER, CAP_BUTT, INV_PAINT, DEFAULT);
267     set_marker(canvas_win, e->start.x - 2, e->start.y - 2, MARK_SIZ, MARK_SIZ);
268     set_marker(canvas_win, e->end.x - 2, e->end.y - 2, MARK_SIZ, MARK_SIZ);
269     if (e->tagged)
270 	toggle_ellipsehighlight(e);
271 }
272 
toggle_ellipsehighlight(F_ellipse * e)273 void toggle_ellipsehighlight(F_ellipse *e)
274 {
275     set_line_stuff(1, RUBBER_LINE, 0.0, JOIN_MITER, CAP_BUTT, INV_PAINT, DEFAULT);
276     set_marker(canvas_win, e->start.x, e->start.y, 1, 1);
277     set_marker(canvas_win, e->start.x - 1, e->start.y - 1, SM_MARK, SM_MARK);
278     set_marker(canvas_win, e->end.x, e->end.y, 1, 1);
279     set_marker(canvas_win, e->end.x - 1, e->end.y - 1, SM_MARK, SM_MARK);
280 }
281 
toggle_arcmarker(F_arc * a)282 void toggle_arcmarker(F_arc *a)
283 {
284     set_line_stuff(1, RUBBER_LINE, 0.0, JOIN_MITER, CAP_BUTT, INV_PAINT, DEFAULT);
285     set_marker(canvas_win,a->point[0].x-2,a->point[0].y-2,MARK_SIZ,MARK_SIZ);
286     set_marker(canvas_win,a->point[1].x-2,a->point[1].y-2,MARK_SIZ,MARK_SIZ);
287     set_marker(canvas_win,a->point[2].x-2,a->point[2].y-2,MARK_SIZ,MARK_SIZ);
288     if (a->tagged)
289 	toggle_archighlight(a);
290 }
291 
toggle_archighlight(F_arc * a)292 void toggle_archighlight(F_arc *a)
293 {
294     set_line_stuff(1, RUBBER_LINE, 0.0, JOIN_MITER, CAP_BUTT, INV_PAINT, DEFAULT);
295     set_marker(canvas_win, a->point[0].x, a->point[0].y, 1, 1);
296     set_marker(canvas_win, a->point[0].x-1, a->point[0].y-1, SM_MARK, SM_MARK);
297     set_marker(canvas_win, a->point[1].x, a->point[1].y, 1, 1);
298     set_marker(canvas_win, a->point[1].x-1, a->point[1].y-1, SM_MARK, SM_MARK);
299     set_marker(canvas_win, a->point[2].x, a->point[2].y, 1, 1);
300     set_marker(canvas_win, a->point[2].x-1, a->point[2].y-1, SM_MARK, SM_MARK);
301 }
302 
toggle_textmarker(F_text * t)303 void toggle_textmarker(F_text *t)
304 {
305     int		    dx, dy;
306 
307     set_line_stuff(1, RUBBER_LINE, 0.0, JOIN_MITER, CAP_BUTT, INV_PAINT, DEFAULT);
308     /* adjust for text angle */
309     dy = (int) ((double) t->ascent * cos(t->angle));
310     dx = (int) ((double) t->ascent * sin(t->angle));
311     set_marker(canvas_win,t->base_x-dx-2,t->base_y-dy-2,MARK_SIZ,MARK_SIZ);
312     /* only draw second marker if not on top of first (e.g. string with only
313        spaces has no height) */
314     if (dx != 0 || dy != 0)
315 	set_marker(canvas_win,t->base_x-2,t->base_y-2,MARK_SIZ,MARK_SIZ);
316     if (t->tagged)
317 	toggle_texthighlight(t);
318 }
319 
toggle_texthighlight(F_text * t)320 void toggle_texthighlight(F_text *t)
321 {
322     int		    dx, dy;
323 
324     set_line_stuff(1, RUBBER_LINE, 0.0, JOIN_MITER, CAP_BUTT, INV_PAINT, DEFAULT);
325     /* adjust for text angle */
326     dy = (int) ((double) t->ascent * cos(t->angle));
327     dx = (int) ((double) t->ascent * sin(t->angle));
328     set_marker(canvas_win, t->base_x-dx, t->base_y-dy, 1, 1);
329     set_marker(canvas_win, t->base_x-dx-1, t->base_y-dy-1, SM_MARK, SM_MARK);
330     set_marker(canvas_win, t->base_x, t->base_y, 1, 1);
331     set_marker(canvas_win, t->base_x-1, t->base_y-1, SM_MARK, SM_MARK);
332 }
333 
toggle_all_compoundmarkers(void)334 void toggle_all_compoundmarkers(void)
335 {
336     F_compound	   *c;
337     for (c=objects.compounds; c!=NULL ; c=c->next)
338 	toggle_compoundmarker(c);
339 }
340 
toggle_compoundmarker(F_compound * c)341 void toggle_compoundmarker(F_compound *c)
342 {
343     set_line_stuff(1, RUBBER_LINE, 0.0, JOIN_MITER, CAP_BUTT, INV_PAINT, DEFAULT);
344     set_marker(canvas_win,c->nwcorner.x-2,c->nwcorner.y-2,MARK_SIZ,MARK_SIZ);
345     set_marker(canvas_win,c->secorner.x-2,c->secorner.y-2,MARK_SIZ,MARK_SIZ);
346     set_marker(canvas_win,c->nwcorner.x-2,c->secorner.y-2,MARK_SIZ,MARK_SIZ);
347     set_marker(canvas_win,c->secorner.x-2,c->nwcorner.y-2,MARK_SIZ,MARK_SIZ);
348     if (c->tagged)
349 	toggle_compoundhighlight(c);
350 }
351 
toggle_compoundhighlight(F_compound * c)352 void toggle_compoundhighlight(F_compound *c)
353 {
354     set_line_stuff(1, RUBBER_LINE, 0.0, JOIN_MITER, CAP_BUTT, INV_PAINT, DEFAULT);
355     set_marker(canvas_win, c->nwcorner.x, c->nwcorner.y, 1, 1);
356     set_marker(canvas_win, c->nwcorner.x-1, c->nwcorner.y-1, SM_MARK, SM_MARK);
357     set_marker(canvas_win, c->secorner.x, c->secorner.y, 1, 1);
358     set_marker(canvas_win, c->secorner.x-1, c->secorner.y-1, SM_MARK, SM_MARK);
359     set_marker(canvas_win, c->nwcorner.x, c->secorner.y, 1, 1);
360     set_marker(canvas_win, c->nwcorner.x-1, c->secorner.y-1, SM_MARK, SM_MARK);
361     set_marker(canvas_win, c->secorner.x, c->nwcorner.y, 1, 1);
362     set_marker(canvas_win, c->secorner.x-1, c->nwcorner.y-1, SM_MARK, SM_MARK);
363 }
364 
toggle_linemarker(F_line * l)365 void toggle_linemarker(F_line *l)
366 {
367     F_point	   *p;
368     int		    fx, fy, x, y;
369 
370     x = y = INT_MIN;
371     set_line_stuff(1, RUBBER_LINE, 0.0, JOIN_MITER, CAP_BUTT, INV_PAINT, DEFAULT);
372     p = l->points;
373     fx = p->x;
374     fy = p->y;
375     for (p = p->next; p != NULL; p = p->next) {
376 	x = p->x;
377 	y = p->y;
378 	set_marker(canvas_win, x - 2, y - 2, MARK_SIZ, MARK_SIZ);
379     }
380     if (x != fx || y != fy || l->points->next == NULL) {
381 	set_marker(canvas_win, fx - 2, fy - 2, MARK_SIZ, MARK_SIZ);
382     }
383     if (l->tagged)
384 	toggle_linehighlight(l);
385 }
386 
toggle_linehighlight(F_line * l)387 void toggle_linehighlight(F_line *l)
388 {
389     F_point	   *p;
390     int		    fx, fy, x, y;
391 
392     x = y = INT_MIN;
393     set_line_stuff(1, RUBBER_LINE, 0.0, JOIN_MITER, CAP_BUTT, INV_PAINT, DEFAULT);
394     p = l->points;
395     fx = p->x;
396     fy = p->y;
397     for (p = p->next; p != NULL; p = p->next) {
398 	x = p->x;
399 	y = p->y;
400 	set_marker(canvas_win, x, y, 1, 1);
401 	set_marker(canvas_win, x - 1, y - 1, SM_MARK, SM_MARK);
402     }
403     if (x != fx || y != fy) {
404 	set_marker(canvas_win, fx, fy, 1, 1);
405 	set_marker(canvas_win, fx - 1, fy - 1, SM_MARK, SM_MARK);
406     }
407 }
408 
toggle_splinemarker(F_spline * s)409 void toggle_splinemarker(F_spline *s)
410 {
411     F_point	   *p;
412     int		    fx, fy, x, y;
413 
414     set_line_stuff(1, RUBBER_LINE, 0.0, JOIN_MITER, CAP_BUTT, INV_PAINT, DEFAULT);
415     p = s->points;
416     fx = p->x;
417     fy = p->y;
418     for (p = p->next; p != NULL; p = p->next) {
419 	x = p->x;
420 	y = p->y;
421 	set_marker(canvas_win, x - 2, y - 2, MARK_SIZ, MARK_SIZ);
422     }
423     if (x != fx || y != fy) {
424 	set_marker(canvas_win, fx - 2, fy - 2, MARK_SIZ, MARK_SIZ);
425     }
426     if (s->tagged)
427 	toggle_splinehighlight(s);
428 }
429 
toggle_splinehighlight(F_spline * s)430 void toggle_splinehighlight(F_spline *s)
431 {
432     F_point	   *p;
433     int		    fx, fy, x, y;
434 
435     set_line_stuff(1, RUBBER_LINE, 0.0, JOIN_MITER, CAP_BUTT, INV_PAINT, DEFAULT);
436     p = s->points;
437     fx = p->x;
438     fy = p->y;
439     for (p = p->next; p != NULL; p = p->next) {
440 	x = p->x;
441 	y = p->y;
442 	set_marker(canvas_win, x, y, 1, 1);
443 	set_marker(canvas_win, x - 1, y - 1, SM_MARK, SM_MARK);
444     }
445     if (x != fx || y != fy) {
446 	set_marker(canvas_win, fx, fy, 1, 1);
447 	set_marker(canvas_win, fx - 1, fy - 1, SM_MARK, SM_MARK);
448     }
449 }
450 
toggle_pointmarker(int x,int y)451 void toggle_pointmarker(int x, int y)
452 {
453   set_marker(canvas_win, x - MARK_SIZ/2, y - MARK_SIZ/2, MARK_SIZ, MARK_SIZ);
454 }
455