1 /*
2  * FIG : Facility for Interactive Generation of figures
3  * Copyright (c) 1991 by Paul King
4  * Parts Copyright (c) 1989-2007 by Brian V. Smith
5  *
6  * Any party obtaining a copy of these files is granted, free of charge, a
7  * full and unrestricted irrevocable, world-wide, paid up, royalty-free,
8  * nonexclusive right and license to deal in this software and documentation
9  * files (the "Software"), including without limitation the rights to use,
10  * copy, modify, merge, publish, distribute, sublicense and/or sell copies of
11  * the Software, and to permit persons who receive copies from any such
12  * party to do so, with the only requirement being that the above copyright
13  * and this permission notice remain intact.
14  *
15  */
16 
17 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20 #include "e_update.h"
21 
22 #include <stdlib.h>
23 #include <string.h>
24 #ifdef HAVE_STRINGS_H
25 #include <strings.h>
26 #endif
27 #include <X11/Intrinsic.h>	/* includes X11/Xlib.h */
28 
29 #include "resources.h"
30 #include "object.h"
31 #include "mode.h"
32 #include "paintop.h"
33 #include "d_text.h"
34 #include "e_scale.h"
35 #include "f_util.h"
36 #include "u_bound.h"
37 #include "u_create.h"
38 #include "u_draw.h"
39 #include "u_fonts.h"
40 #include "u_free.h"
41 #include "u_list.h"
42 #include "u_redraw.h"
43 #include "u_search.h"
44 #include "w_canvas.h"
45 #include "w_cursor.h"
46 #include "w_drawprim.h"
47 #include "w_indpanel.h"
48 #include "w_mousefun.h"
49 #include "w_msgpanel.h"
50 #include "w_util.h"
51 #include "xfig_math.h"
52 
53 
54 static Boolean	keep_depth = False;
55 static int	delta_depth;
56 
57 static void	init_update_object(F_line *p, int type, int x, int y,
58 					int px, int py);
59 static void	init_update_settings(F_line *p, int type, int x, int y,
60 					int px, int py);
61 
62 
63 #define min(a,b) ((a)<(b)) ? (a) : (b)
64 #define up_part(lv,rv,mask) \
65 		if (cur_updatemask & (mask)) \
66 		    (lv) = (rv)
67 #define up_depth_part(lv,rv) \
68 		if (cur_updatemask & I_DEPTH) \
69 		    (lv) = keep_depth ? \
70 			(min((lv)+delta_depth,MAX_DEPTH)) : (rv)
71 
72 
73 void up_dashdot (float styleval, int style, unsigned int mask);
74 void up_from_arrow (F_arrow *arrow, int thick);
75 void update_compound (F_compound *compound);
76 void update_line (F_line *line);
77 void update_text (F_text *text);
78 void update_ellipse (F_ellipse *ellipse);
79 void update_arc (F_arc *arc);
80 void update_spline (F_spline *spline);
81 void fix_fillstyle (void *object);
82 void up_arrow (F_line *object);
83 void update_lines (F_line *lines);
84 void update_splines (F_spline *splines);
85 void update_ellipses (F_ellipse *ellipses);
86 void update_arcs (F_arc *arcs);
87 void update_texts (F_text *texts);
88 void update_compounds (F_compound *compounds);
89 
90 void
update_selected(void)91 update_selected(void)
92 {
93     set_mousefun("update object", "update settings", "",
94 			LOC_OBJ, LOC_OBJ, LOC_OBJ);
95     canvas_kbd_proc = null_proc;
96     canvas_locmove_proc = null_proc;
97     canvas_ref_proc = null_proc;
98     init_searchproc_left(init_update_object);
99     init_searchproc_middle(init_update_settings);
100     canvas_leftbut_proc = object_search_left;
101     canvas_middlebut_proc = object_search_middle;
102     canvas_rightbut_proc = null_proc;
103     set_cursor(pick9_cursor);
104     /* manage on the update buttons */
105     manage_update_buts();
106     reset_action_on();
107 }
108 
109 static int
get_arrow_mode(F_line * object)110 get_arrow_mode(F_line *object)
111 {
112     if (!object->for_arrow && !object->back_arrow)
113 	return L_NOARROWS;
114     else if (object->for_arrow && !object->back_arrow)
115 	return L_FARROWS;
116     else if (!object->for_arrow && object->back_arrow)
117 	return L_BARROWS;
118     else
119 	return L_FBARROWS;
120 }
121 
122 static int
get_arrow_type(F_line * object)123 get_arrow_type(F_line *object)
124 {
125     int		    type;
126 
127     /* have to pick one or the other */
128     if (object->for_arrow)
129 	type = object->for_arrow->type*2 - 1 + object->for_arrow->style;
130     else if (object->back_arrow)
131 	type = object->back_arrow->type*2 - 1 + object->back_arrow->style;
132     else
133 	type = 0;
134     if (type < 0)
135 	type = 0;
136     return type;
137 }
138 
139 /* update the indicator buttons FROM the selected object */
140 
141 static void
init_update_settings(F_line * p,int type,int x,int y,int px,int py)142 init_update_settings(F_line *p, int type, int x, int y, int px, int py)
143 {
144 	(void)x; (void)y; (void)px; (void)py;
145     int		    old_psfont_flag, new_psfont_flag;
146     F_line	   *dline, *dtick1, *dtick2, *dbox;
147     F_text	   *dtext;
148 
149     switch (type) {
150       case O_COMPOUND:
151 	cur_c = (F_compound *) p;
152 
153 	/* if this is a dimension line, update the dimline settings from it */
154 	if (dimline_components(cur_c, &dline, &dtick1, &dtick2, &dbox)) {
155 	    if (dline) {
156 		cur_dimline_thick = dline->thickness;
157 		cur_dimline_style = dline->style;
158 		cur_dimline_color = dline->pen_color;
159 		if (dline->back_arrow) {
160 		    cur_dimline_leftarrow = dline->back_arrow->type*2 - 1 +
161 				dline->back_arrow->style;
162 		    cur_dimline_arrowlength = dline->back_arrow->ht;
163 		    cur_dimline_arrowwidth = dline->back_arrow->wd;
164 		} else {
165 		    cur_dimline_leftarrow = 0;
166 		}
167 		if (dline->for_arrow) {
168 		    cur_dimline_rightarrow = dline->for_arrow->type*2 - 1 +
169 				dline->for_arrow->style;
170 		    cur_dimline_arrowlength = dline->for_arrow->ht;
171 		    cur_dimline_arrowwidth = dline->for_arrow->wd;
172 		} else {
173 		    cur_dimline_rightarrow = 0;
174 		}
175 	        cur_dimline_ticks = (dtick1 || dtick2);
176 		if (dtick1)
177 		    cur_dimline_tickthick = dtick1->thickness;
178 		else
179 		    cur_dimline_tickthick = dtick2->thickness;
180 	    }
181 	    if (dbox) {
182 		cur_dimline_boxthick = dbox->thickness;
183 		cur_dimline_boxcolor = dbox->fill_color;
184 	    }
185 	    if ((dtext = cur_c->texts)) {
186 		cur_dimline_textcolor = dtext->color;
187 		cur_dimline_font = dtext->font;
188 		cur_dimline_fontsize = dtext->size;
189 		cur_dimline_psflag = (dtext->flags & PSFONT_TEXT)? 1:0;
190 		cur_dimline_fixed = (dtext->comments &&
191 				     (strncasecmp(dtext->comments,"fixed text", 10)==0));
192 	    }
193 	}
194 
195 	/* only update the depth setting from the smallest depth in the compound */
196 	if (cur_updatemask & I_DEPTH) {
197 	    cur_depth = find_smallest_depth(cur_c);
198 	}
199 	break;
200       case O_POLYLINE:
201 	cur_l = (F_line *) p;
202 	if (cur_l->type != T_PICTURE) {
203 		up_part(cur_linewidth, cur_l->thickness, I_LINEWIDTH);
204 		up_part(cur_fillstyle, cur_l->fill_style, I_FILLSTYLE);
205 		up_part(cur_pencolor, cur_l->pen_color, I_PEN_COLOR);
206 		up_part(cur_fillcolor, cur_l->fill_color, I_FILL_COLOR);
207 		up_part(cur_linestyle, cur_l->style, I_LINESTYLE);
208 		up_part(cur_joinstyle, cur_l->join_style, I_JOINSTYLE);
209 		up_part(cur_capstyle, cur_l->cap_style, I_CAPSTYLE);
210 		up_part(cur_styleval, cur_l->style_val*2./(cur_l->thickness+1.), I_LINESTYLE);
211 		/* update the dash length/dot gap value for cur_styleval */
212 		up_dashdot(cur_styleval, cur_l->style, I_LINESTYLE);
213 		up_part(cur_arrowmode, get_arrow_mode(cur_l), I_ARROWMODE);
214 		up_part(cur_arrowtype, get_arrow_type(cur_l), I_ARROWTYPE);
215 		if (cur_l->back_arrow)
216 			up_from_arrow(cur_l->back_arrow,cur_l->thickness);
217 		if (cur_l->for_arrow)
218 			up_from_arrow(cur_l->for_arrow,cur_l->thickness);
219 	} else if (cur_l->pic->pic_cache && cur_l->pic->pic_cache->subtype == T_PIC_XBM) {
220 		/* only XBM pictures have color */
221 		up_part(cur_pencolor, cur_l->pen_color, I_PEN_COLOR);
222 	}
223 	up_depth_part(cur_depth, cur_l->depth);
224 	if (cur_l->type == T_ARCBOX)
225 	    up_part(cur_boxradius, cur_l->radius, I_BOXRADIUS);
226 	break;
227       case O_TXT:
228 	cur_t = (F_text *) p;
229 	up_part(cur_textjust, cur_t->type, I_TEXTJUST);
230 	up_part(cur_pencolor, cur_t->color, I_PEN_COLOR);
231 	up_depth_part(cur_depth, cur_t->depth);
232 	up_part(cur_elltextangle, cur_t->angle/M_PI*180.0, I_ELLTEXTANGLE);
233 	old_psfont_flag = (cur_textflags & PSFONT_TEXT);
234 	new_psfont_flag = (cur_t->flags & PSFONT_TEXT);
235 	up_part(cur_textflags, cur_t->flags & ~PSFONT_TEXT, I_TEXTFLAGS);
236 	/* for the LaTeX/PostScript flag use I_FONT instead of I_TEXTFLAGS
237 	   so the font type will change if necessary */
238 	if (cur_updatemask & I_FONT)
239 	    cur_textflags |= new_psfont_flag;
240 	else
241 	    cur_textflags |= old_psfont_flag;
242 	if (using_ps) {	/* must use {} because macro has 'if' */
243 	    up_part(cur_ps_font, cur_t->font, I_FONT);
244 	} else {	/* must use {} because macro has 'if' */
245 	    up_part(cur_latex_font, cur_t->font, I_FONT);
246 	}
247 	up_part(cur_fontsize, cur_t->size, I_FONTSIZE);
248 	break;
249       case O_ELLIPSE:
250 	cur_e = (F_ellipse *) p;
251 	up_part(cur_linewidth, cur_e->thickness, I_LINEWIDTH);
252 	up_part(cur_elltextangle, cur_e->angle/M_PI*180.0, I_ELLTEXTANGLE);
253 	up_part(cur_fillstyle, cur_e->fill_style, I_FILLSTYLE);
254 	up_part(cur_pencolor, cur_e->pen_color, I_PEN_COLOR);
255 	up_part(cur_fillcolor, cur_e->fill_color, I_FILL_COLOR);
256 	up_part(cur_linestyle, cur_e->style, I_LINESTYLE);
257 	up_part(cur_styleval, (cur_e->style_val*2.)/(cur_e->thickness+1.), I_LINESTYLE);
258 	/* update the dash length/dot gap value for cur_styleval */
259 	up_dashdot(cur_styleval, cur_e->style, I_LINESTYLE);
260 	up_depth_part(cur_depth, cur_e->depth);
261 	break;
262       case O_ARC:
263 	cur_a = (F_arc *) p;
264 	up_part(cur_linewidth, cur_a->thickness, I_LINEWIDTH);
265 	up_part(cur_fillstyle, cur_a->fill_style, I_FILLSTYLE);
266 	up_part(cur_pencolor, cur_a->pen_color, I_PEN_COLOR);
267 	up_part(cur_fillcolor, cur_a->fill_color, I_FILL_COLOR);
268 	up_part(cur_arctype, cur_a->type, I_ARCTYPE);
269 	up_part(cur_linestyle, cur_a->style, I_LINESTYLE);
270 	up_part(cur_styleval, (cur_a->style_val*2.)/(cur_a->thickness+1.), I_LINESTYLE);
271 	/* update the dash length/dot gap value for cur_styleval */
272 	up_dashdot(cur_styleval, cur_a->style, I_LINESTYLE);
273 	up_part(cur_capstyle, cur_a->cap_style, I_CAPSTYLE);
274 	up_depth_part(cur_depth, cur_a->depth);
275 	up_part(cur_arrowmode, get_arrow_mode((F_line *)cur_a), I_ARROWMODE);
276 	up_part(cur_arrowtype, get_arrow_type((F_line *)cur_a), I_ARROWTYPE);
277 	if (cur_a->back_arrow)
278 		up_from_arrow(cur_a->back_arrow,cur_a->thickness);
279 	if (cur_a->for_arrow)
280 		up_from_arrow(cur_a->for_arrow,cur_a->thickness);
281 	break;
282       case O_SPLINE:
283 	cur_s = (F_spline *) p;
284 	up_part(cur_linewidth, cur_s->thickness, I_LINEWIDTH);
285 	up_part(cur_fillstyle, cur_s->fill_style, I_FILLSTYLE);
286 	up_part(cur_pencolor, cur_s->pen_color, I_PEN_COLOR);
287 	up_part(cur_fillcolor, cur_s->fill_color, I_FILL_COLOR);
288 	up_part(cur_linestyle, cur_s->style, I_LINESTYLE);
289 	up_part(cur_styleval, (cur_s->style_val*2.)/(cur_s->thickness+1.), I_LINESTYLE);
290 	/* update the dash length/dot gap value for cur_styleval */
291 	up_dashdot(cur_styleval, cur_s->style, I_LINESTYLE);
292 	if (cur_s->type == T_OPEN_APPROX || cur_s->type == T_OPEN_INTERP)
293 	    up_part(cur_capstyle, cur_s->cap_style, I_CAPSTYLE);
294 	up_depth_part(cur_depth, cur_s->depth);
295 	up_part(cur_arrowmode, get_arrow_mode((F_line *)cur_s), I_ARROWMODE);
296 	up_part(cur_arrowtype, get_arrow_type((F_line *)cur_s), I_ARROWTYPE);
297 	if (cur_s->back_arrow)
298 		up_from_arrow(cur_s->back_arrow,cur_s->thickness);
299 	if (cur_s->for_arrow)
300 		up_from_arrow(cur_s->for_arrow,cur_s->thickness);
301 	break;
302       default:
303 	return;
304     }
305     update_current_settings();
306     if (type == O_COMPOUND) {
307 	put_msg("Note: Only the (smallest) depth is retrieved from a compound object");
308 	beep();
309     } else {
310 	put_msg("Settings UPDATED");
311     }
312 }
313 
up_from_arrow(F_arrow * arrow,int thick)314 void up_from_arrow(F_arrow *arrow, int thick)
315 {
316 	up_part(cur_arrowthick, arrow->thickness,I_ARROWSIZE);
317 	up_part(cur_arrowwidth, arrow->wd,I_ARROWSIZE);
318 	up_part(cur_arrowheight,arrow->ht,I_ARROWSIZE);
319 	up_part(cur_arrow_multthick, arrow->thickness,I_ARROWSIZE);
320 	up_part(cur_arrow_multwidth, arrow->wd,I_ARROWSIZE);
321 	up_part(cur_arrow_multheight,arrow->ht,I_ARROWSIZE);
322 	if (cur_updatemask & I_ARROWSIZE) {
323 	    /* now get multiple to line width of object */
324 	    cur_arrow_multthick /= thick;
325 	    cur_arrow_multwidth /= thick;
326 	    cur_arrow_multheight /= thick;
327 	}
328 }
329 
330 /* update the selected object FROM the indicator buttons */
331 
332 static void
init_update_object(F_line * p,int type,int x,int y,int px,int py)333 init_update_object(F_line *p, int type, int x, int y, int px, int py)
334 {
335 	(void)x; (void)y; (void)px; (void)py;
336     int		    largest;
337     Boolean	    dontupdate;
338 
339     dontupdate = False;
340 
341     switch (type) {
342       case O_COMPOUND:
343 	set_temp_cursor(wait_cursor);
344 	cur_c = (F_compound *) p;
345 	new_c = copy_compound(cur_c);
346 
347 	/* keep the depths of the objects inside the compound the same
348 	   relative to each other, setting the depth of the *most shallow*
349 	   to the desired depth */
350 	keep_depth = True;
351 	largest = find_largest_depth(cur_c);
352 	/* find delta */
353 	delta_depth = cur_depth - find_smallest_depth(cur_c);
354 	/* if renumbering would make depths too large don't allow it */
355 	if ((delta_depth + largest > MAX_DEPTH) && (cur_updatemask & I_DEPTH)) {
356 	    if (popup_query(QUERY_YESNO,
357 		"Some depths would exceed maximum - those objects\nwill be set to maximum depth. Update anyway?") != RESULT_YES) {
358 	    delta_depth = 0;
359 	    dontupdate = True;
360 	}
361 	}
362 	update_compound(new_c);
363 	keep_depth = False;
364 
365 	change_compound(cur_c, new_c);
366 	/* redraw anything near the old comound */
367 	redisplay_compound(cur_c);
368 	/* draw the new compound */
369 	redisplay_compound(new_c);
370 	break;
371       case O_POLYLINE:
372 	set_temp_cursor(wait_cursor);
373 	cur_l = (F_line *) p;
374 	new_l = copy_line(cur_l);
375 	update_line(new_l);
376 	change_line(cur_l, new_l);
377 	/* redraw anything near the old line */
378 	redisplay_line(cur_l);
379 	/* draw the new line */
380 	redisplay_line(new_l);
381 	break;
382       case O_TXT:
383 	set_temp_cursor(wait_cursor);
384 	cur_t = (F_text *) p;
385 	new_t = copy_text(cur_t);
386 	update_text(new_t);
387 	change_text(cur_t, new_t);
388 	/* redraw anything near the old text */
389 	redisplay_text(cur_t);
390 	/* draw the new text */
391 	redisplay_text(new_t);
392 	break;
393       case O_ELLIPSE:
394 	set_temp_cursor(wait_cursor);
395 	cur_e = (F_ellipse *) p;
396 	new_e = copy_ellipse(cur_e);
397 	update_ellipse(new_e);
398 	change_ellipse(cur_e, new_e);
399 	/* redraw anything near the old ellipse */
400 	redisplay_ellipse(cur_e);
401 	/* draw the new ellipse */
402 	redisplay_ellipse(new_e);
403 	break;
404       case O_ARC:
405 	set_temp_cursor(wait_cursor);
406 	cur_a = (F_arc *) p;
407 	new_a = copy_arc(cur_a);
408 	update_arc(new_a);
409 	change_arc(cur_a, new_a);
410 	/* redraw anything near the old arc */
411 	redisplay_arc(cur_a);
412 	/* draw the new arc */
413 	redisplay_arc(new_a);
414 	break;
415       case O_SPLINE:
416 	set_temp_cursor(wait_cursor);
417 	cur_s = (F_spline *) p;
418 	new_s = copy_spline(cur_s);
419 	update_spline(new_s);
420 	change_spline(cur_s, new_s);
421 	/* redraw anything near the old spline */
422 	redisplay_spline(cur_s);
423 	/* draw the new spline */
424 	redisplay_spline(new_s);
425 	break;
426     default:
427 	return;
428     }
429     reset_cursor();
430     if (!dontupdate)
431 	put_msg("Object(s) UPDATED");
432 }
433 
update_ellipse(F_ellipse * ellipse)434 void update_ellipse(F_ellipse *ellipse)
435 {
436     draw_ellipse(ellipse, ERASE);
437     up_part(ellipse->thickness, cur_linewidth, I_LINEWIDTH);
438     up_part(ellipse->angle, cur_elltextangle*M_PI/180.0, I_ELLTEXTANGLE);
439     up_part(ellipse->style, cur_linestyle, I_LINESTYLE);
440     up_part(ellipse->style_val, cur_styleval * (cur_linewidth + 1) / 2,
441 	    I_LINESTYLE);
442     up_part(ellipse->fill_style, cur_fillstyle, I_FILLSTYLE);
443     up_part(ellipse->pen_color, cur_pencolor, I_PEN_COLOR);
444     up_part(ellipse->fill_color, cur_fillcolor, I_FILL_COLOR);
445     up_depth_part(ellipse->depth, cur_depth);
446     fix_fillstyle(ellipse);	/* make sure it has legal fill style if color changed */
447     /* updated object will be redisplayed by init_update_xxx() */
448 }
449 
update_arc(F_arc * arc)450 void update_arc(F_arc *arc)
451 {
452     draw_arc(arc, ERASE);
453     up_part(arc->thickness, cur_linewidth, I_LINEWIDTH);
454     up_part(arc->style, cur_linestyle, I_LINESTYLE);
455     up_part(arc->style_val, cur_styleval * (cur_linewidth + 1) / 2,
456 	    I_LINESTYLE);
457     up_part(arc->fill_style, cur_fillstyle, I_FILLSTYLE);
458     up_part(arc->type, cur_arctype, I_ARCTYPE);
459     up_part(arc->cap_style, cur_capstyle, I_CAPSTYLE);
460     up_part(arc->pen_color, cur_pencolor, I_PEN_COLOR);
461     up_part(arc->fill_color, cur_fillcolor, I_FILL_COLOR);
462     up_depth_part(arc->depth, cur_depth);
463     /* check new type - if pie-wedge and there are any arrows, delete them */
464     if (arc->type == T_PIE_WEDGE_ARC) {
465 	if (arc->for_arrow) {
466 	    free((char *) arc->for_arrow);
467 	    arc->for_arrow = NULL;
468 	}
469 	if (arc->back_arrow) {
470 	    free((char *) arc->back_arrow);
471 	    arc->back_arrow = NULL;
472 	}
473     } else {
474 	/* if not wedge type, update any arrow settings */
475 	up_arrow((F_line *)arc);
476     }
477     fix_fillstyle(arc);	/* make sure it has legal fill style if color changed */
478     /* updated object will be redisplayed by init_update_xxx() */
479 }
480 
update_line(F_line * line)481 void update_line(F_line *line)
482 {
483     draw_line(line, ERASE);
484 	up_part(line->thickness, cur_linewidth, I_LINEWIDTH);
485     if (line->type != T_PICTURE) {
486 	up_part(line->style, cur_linestyle, I_LINESTYLE);
487 	up_part(line->style_val, cur_styleval * (cur_linewidth + 1) / 2,
488 		I_LINESTYLE);
489 	up_part(line->join_style, cur_joinstyle, I_JOINSTYLE);
490 	up_part(line->cap_style, cur_capstyle, I_CAPSTYLE);
491 	up_part(line->pen_color, cur_pencolor, I_PEN_COLOR);
492 	up_part(line->fill_color, cur_fillcolor, I_FILL_COLOR);
493 	up_part(line->radius, cur_boxradius, I_BOXRADIUS);
494 	up_part(line->fill_style, cur_fillstyle, I_FILLSTYLE);
495     } else if (line->pic->pic_cache && line->pic->pic_cache->subtype == T_PIC_XBM) {
496 	/* only XBM pictures have color */
497 	up_part(line->pen_color, cur_pencolor, I_PEN_COLOR);
498     }
499     up_depth_part(line->depth, cur_depth);
500     /* only POLYLINES with more than one point may have arrow heads */
501     if (line->type == T_POLYLINE && line->points->next != NULL)
502 	up_arrow(line);
503     fix_fillstyle(line);	/* make sure it has legal fill style if color changed */
504     /* updated object will be redisplayed by init_update_xxx() */
505 }
506 
update_text(F_text * text)507 void update_text(F_text *text)
508 {
509     PR_SIZE	    size;
510     int		old_psfont_flag, new_psfont_flag;
511 
512     draw_text(text, ERASE);
513     up_part(text->type, cur_textjust, I_TEXTJUST);
514     up_part(text->font, using_ps ? cur_ps_font : cur_latex_font, I_FONT);
515     old_psfont_flag = (text->flags & PSFONT_TEXT);
516     new_psfont_flag = (cur_textflags & PSFONT_TEXT);
517     /* turn off any postscript flags */
518     text->flags &= ~PSFONT_TEXT;
519     /* set text flags to current settings */
520     up_part(text->flags, cur_textflags, I_TEXTFLAGS);
521     /* for the LaTeX/PostScript flag use I_FONT instead of I_TEXTFLAGS
522 	so the font type will change if necessary */
523     /* and update with new font type */
524     if (cur_updatemask & I_FONT)
525 	text->flags |= new_psfont_flag;
526     else
527 	text->flags |= old_psfont_flag;
528     up_part(text->size, cur_fontsize, I_FONTSIZE);
529     up_part(text->angle, cur_elltextangle*M_PI/180.0, I_ELLTEXTANGLE);
530     up_part(text->color, cur_pencolor, I_PEN_COLOR);
531     up_depth_part(text->depth, cur_depth);
532     size = textsize(lookfont(x_fontnum(psfont_text(text), text->font),
533 			text->size), strlen(text->cstring), text->cstring);
534     text->ascent = size.ascent;
535     text->descent = size.descent;
536     text->length = size.length;
537     reload_text_fstruct(text);	/* make sure fontstruct is current */
538     /* updated object will be redisplayed by init_update_xxx() */
539 }
540 
update_spline(F_spline * spline)541 void update_spline(F_spline *spline)
542 {
543     draw_spline(spline, ERASE);
544     up_part(spline->thickness, cur_linewidth, I_LINEWIDTH);
545     up_part(spline->style, cur_linestyle, I_LINESTYLE);
546     up_part(spline->style_val, cur_styleval * (cur_linewidth + 1) / 2,
547 	    I_LINESTYLE);
548     if (spline->type == T_OPEN_APPROX || spline->type == T_OPEN_INTERP)
549 	up_part(spline->cap_style, cur_capstyle, I_CAPSTYLE);
550     up_part(spline->fill_style, cur_fillstyle, I_FILLSTYLE);
551     up_part(spline->pen_color, cur_pencolor, I_PEN_COLOR);
552     up_part(spline->fill_color, cur_fillcolor, I_FILL_COLOR);
553     up_depth_part(spline->depth, cur_depth);
554     if (open_spline(spline))
555 	up_arrow((F_line *)spline);
556     fix_fillstyle(spline);	/* make sure it has legal fill style if color changed */
557     /* updated object will be redisplayed by init_update_xxx() */
558 }
559 
560 /* check that the fill style is legal for the color in the object */
561 /* WARNING: this procedure assumes that splines, lines, arcs and ellipses
562 	    all have the same structure up to the fill_style and color */
563 
fix_fillstyle(void * obj)564 void fix_fillstyle(void *obj)
565 {
566     F_line *object = obj;
567     if (object->fill_color == BLACK || object->fill_color == DEFAULT) {
568 	if (object->fill_style >= NUMSHADEPATS &&
569 		object->fill_style < NUMSHADEPATS+NUMTINTPATS)
570 	    object->fill_style = UNFILLED;
571     }
572     /* a little sanity check */
573     if (object->fill_style < DEFAULT)
574 	object->fill_style = DEFAULT;
575     if (object->fill_style >= NUMFILLPATS)
576 	object->fill_style = NUMFILLPATS;
577 }
578 
up_arrow(F_line * object)579 void up_arrow(F_line *object)
580 {
581     if (object->for_arrow) {
582 	up_part(object->for_arrow->type, ARROW_TYPE(cur_arrowtype), I_ARROWTYPE);
583 	up_part(object->for_arrow->style, ARROW_STYLE(cur_arrowtype), I_ARROWTYPE);
584 	if (use_abs_arrowvals) {
585 	    up_part(object->for_arrow->thickness,cur_arrowthick,I_ARROWSIZE);
586 	    up_part(object->for_arrow->wd,cur_arrowwidth,I_ARROWSIZE);
587 	    up_part(object->for_arrow->ht,cur_arrowheight,I_ARROWSIZE);
588 	} else {
589 	    up_part(object->for_arrow->thickness,
590 				cur_arrow_multthick*object->thickness, I_ARROWSIZE);
591 	    up_part(object->for_arrow->wd,
592 				cur_arrow_multwidth*object->thickness, I_ARROWSIZE);
593 	    up_part(object->for_arrow->ht,
594 				cur_arrow_multheight*object->thickness, I_ARROWSIZE);
595 	}
596     }
597     if (object->back_arrow) {
598 	up_part(object->back_arrow->type, ARROW_TYPE(cur_arrowtype), I_ARROWTYPE);
599 	up_part(object->back_arrow->style, ARROW_STYLE(cur_arrowtype), I_ARROWTYPE);
600 	if (use_abs_arrowvals) {
601 	    up_part(object->back_arrow->thickness,cur_arrowthick,I_ARROWSIZE);
602 	    up_part(object->back_arrow->wd,cur_arrowwidth,I_ARROWSIZE);
603 	    up_part(object->back_arrow->ht,cur_arrowheight,I_ARROWSIZE);
604 	} else {
605 	    up_part(object->back_arrow->thickness,
606 				cur_arrow_multthick*object->thickness,I_ARROWSIZE);
607 	    up_part(object->back_arrow->wd,
608 				cur_arrow_multwidth*object->thickness,I_ARROWSIZE);
609 	    up_part(object->back_arrow->ht,
610 				cur_arrow_multheight*object->thickness, I_ARROWSIZE);
611 	}
612     }
613 
614     if (! (cur_updatemask & I_ARROWMODE))
615 	return;
616 
617     if (autoforwardarrow_mode) {
618 	if (object->for_arrow) {
619 	    if (use_abs_arrowvals) {
620 		object->for_arrow->thickness = cur_arrowthick;
621 		object->for_arrow->wd = cur_arrowwidth;
622 		object->for_arrow->ht = cur_arrowheight;
623 	    } else {
624 		object->for_arrow->thickness = cur_arrow_multthick*cur_linewidth;
625 		object->for_arrow->wd = cur_arrow_multwidth*cur_linewidth;
626 		object->for_arrow->ht = cur_arrow_multheight*cur_linewidth;
627 	    }
628 	} else	/* no arrowhead at all yet, create a new one */
629 	    up_part(object->for_arrow, forward_arrow(), I_ARROWMODE);
630     } else {	/* delete arrowhead if one exists */
631 	if (object->for_arrow) {
632 	    free((char *) object->for_arrow);
633 	    object->for_arrow = NULL;
634 	}
635     }
636     if (autobackwardarrow_mode) {
637 	if (object->back_arrow) {
638 	    if (use_abs_arrowvals) {
639 		object->back_arrow->thickness = cur_arrowthick;
640 		object->back_arrow->wd = cur_arrowwidth;
641 		object->back_arrow->ht = cur_arrowheight;
642 	    } else {
643 		object->back_arrow->thickness = cur_arrow_multthick*cur_linewidth;
644 		object->back_arrow->wd = cur_arrow_multwidth*cur_linewidth;
645 		object->back_arrow->ht = cur_arrow_multheight*cur_linewidth;
646 	    }
647 	} else {	/* no arrowhead at all yet, create a new one */
648 	    up_part(object->back_arrow, backward_arrow(), I_ARROWMODE);
649 	}
650     } else {	/* delete arrowhead if one exists */
651 	if (object->back_arrow) {
652 	    free((char *) object->back_arrow);
653 	    object->back_arrow = NULL;
654 	}
655     }
656 }
657 
update_compound(F_compound * compound)658 void update_compound(F_compound *compound)
659 {
660     F_line	   *dline, *dtick1, *dtick2, *dbox;
661     F_text	   *dtext;
662 
663     /* if this is a dimension line, update its settings from the dimline settings */
664     if (dimline_components(compound, &dline, &dtick1, &dtick2, &dbox)) {
665 	if (dline) {
666 	    dline->thickness = cur_dimline_thick;
667 	    dline->style = cur_dimline_style;
668 	    dline->pen_color = cur_dimline_color;
669 
670 	    /* free old left arrow */
671 	    if (dline->back_arrow) {
672 		free((char *) dline->back_arrow);
673 		dline->back_arrow = NULL;
674 	    }
675 	    /* create new one if setting says so */
676 	    if (cur_dimline_leftarrow != -1)
677 		dline->back_arrow = backward_dim_arrow();
678 
679 	    /* free old right arrow */
680 	    if (dline->for_arrow) {
681 		free((char *) dline->for_arrow);
682 		dline->for_arrow = NULL;
683 	    }
684 	    /* create new one if setting says so */
685 	    if (cur_dimline_rightarrow != -1)
686 		dline->for_arrow = forward_dim_arrow();
687 
688 	    /* update text box */
689 	    if (dbox) {
690 		/* attach the polygon after the main line */
691 		dline->next = dbox;
692 		dbox->thickness = cur_dimline_boxthick;
693 		dbox->fill_color = cur_dimline_boxcolor;
694 	    }
695 	} /* if (dline) */
696 
697 	/* free any old ticks */
698 	if (dtick1)
699 	    free_linestorage(dtick1);
700 	if (dtick2)
701 	    free_linestorage(dtick2);
702 
703 	/* create new ones if user wants */
704 	if (cur_dimline_ticks) {
705 	    create_dimline_ticks(dline, &dtick1, &dtick2);
706 	    /* attach it to the previous object in the compound */
707 	    if (dbox)
708 		dbox->next = dtick1;
709 	    else
710 		dline->next = dtick1;
711 	    dtick1->next = dtick2;
712 	} else {
713 	    /* no ticks, terminate list of lines after box */
714 	    if (dbox)
715 		dbox->next = (F_line *) NULL;
716 	}
717        /* now put the new line list into the compound */
718        if (dline)
719 	   compound->lines = dline;
720        else
721 	   compound->lines = dbox;
722 
723 	/* finally, the text */
724 	if ((dtext = compound->texts)) {
725 	    dtext->color = cur_dimline_textcolor;
726 	    dtext->font = cur_dimline_font;
727 	    dtext->size = cur_dimline_fontsize;
728 	    dtext->flags = cur_dimline_psflag? PSFONT_TEXT: 0;
729 	    /* free any comments in the text */
730 	    if (dtext->comments)
731 		free((char *) dtext->comments);
732 	    if (cur_dimline_fixed)
733 		dtext->comments = strdup("fixed text");
734 	}
735 	/* now update the depths of the components */
736 	up_depth_part(dline->depth, cur_depth);
737 	if (dbox)
738 	    up_depth_part(dbox->depth,  cur_depth);
739 	if (dtick1)
740 	    up_depth_part(dtick1->depth, cur_depth);
741 	if (dtick2)
742 	    up_depth_part(dtick2->depth, cur_depth);
743 	if (dtext)
744 	    up_depth_part(dtext->depth, cur_depth);
745 
746 	/* finally, rescale if necessary */
747 	rescale_dimension_line(compound, 1.0, 1.0, 0, 0);
748 
749 	/* end of dimension line update */
750 
751     } else {
752 	/* ordinary compound */
753 	update_lines(compound->lines);
754 	update_splines(compound->splines);
755 	update_ellipses(compound->ellipses);
756 	update_arcs(compound->arcs);
757 	update_texts(compound->texts);
758 	update_compounds(compound->compounds);
759     }
760     compound_bound(compound, &compound->nwcorner.x, &compound->nwcorner.y,
761 		   &compound->secorner.x, &compound->secorner.y);
762 }
763 
update_arcs(F_arc * arcs)764 void update_arcs(F_arc *arcs)
765 {
766     F_arc	   *a;
767 
768     for (a = arcs; a != NULL; a = a->next)
769 	update_arc(a);
770 }
771 
update_compounds(F_compound * compounds)772 void update_compounds(F_compound *compounds)
773 {
774     F_compound	   *c;
775 
776     for (c = compounds; c != NULL; c = c->next)
777 	update_compound(c);
778 }
779 
update_ellipses(F_ellipse * ellipses)780 void update_ellipses(F_ellipse *ellipses)
781 {
782     F_ellipse	   *e;
783 
784     for (e = ellipses; e != NULL; e = e->next)
785 	update_ellipse(e);
786 }
787 
update_lines(F_line * lines)788 void update_lines(F_line *lines)
789 {
790     F_line	   *l;
791 
792     for (l = lines; l != NULL; l = l->next)
793 	update_line(l);
794 }
795 
update_splines(F_spline * splines)796 void update_splines(F_spline *splines)
797 {
798     F_spline	   *s;
799 
800     for (s = splines; s != NULL; s = s->next)
801 	update_spline(s);
802 }
803 
update_texts(F_text * texts)804 void update_texts(F_text *texts)
805 {
806     F_text	   *t;
807 
808     for (t = texts; t != NULL; t = t->next)
809 	update_text(t);
810 }
811 
up_dashdot(float styleval,int style,unsigned int mask)812 void up_dashdot(float styleval, int style, unsigned int mask)
813 {
814 	(void)mask;
815 
816 	if ((style == DASH_LINE) ||
817 	    (style == DASH_DOT_LINE) ||
818 	    (style == DASH_2_DOTS_LINE) ||
819 	    (style == DASH_3_DOTS_LINE)) {
820 		cur_dashlength = styleval;
821 	} else if (style == DOTTED_LINE) {
822 		cur_dotgap = styleval;
823 	}
824 }
825