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