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