1 /*
2  * FIG : Facility for Interactive Generation of figures
3  * Copyright (c) 1985-1988 by Supoj Sutanthavibul
4  * Parts Copyright (c) 1989-2015 by Brian V. Smith
5  * Parts Copyright (c) 1991 by Paul King
6  * Parts Copyright (c) 2016-2018 by Thomas Loimer
7  *
8  * Any party obtaining a copy of these files is granted, free of charge, a
9  * full and unrestricted irrevocable, world-wide, paid up, royalty-free,
10  * nonexclusive right and license to deal in this software and documentation
11  * files (the "Software"), including without limitation the rights to use,
12  * copy, modify, merge, publish, distribute, sublicense and/or sell copies of
13  * the Software, and to permit persons who receive copies from any such
14  * party to do so, with the only requirement being that the above copyright
15  * and this permission notice remain intact.
16  *
17  */
18 
19 #include "fig.h"
20 #include "figx.h"
21 #include "resources.h"
22 #include "object.h"
23 #include "mode.h"
24 #include "paintop.h"
25 #include "d_text.h"
26 #include "e_edit.h"
27 #include "u_create.h"
28 #include "u_draw.h"
29 #include "u_fonts.h"
30 #include "w_drawprim.h"
31 #include "w_file.h"
32 #include "w_fontbits.h"
33 #include "w_indpanel.h"
34 #include "w_color.h"
35 #include "w_mousefun.h"
36 #include "w_msgpanel.h"
37 #include "w_setup.h"
38 #include "w_style.h"
39 #include "w_util.h"
40 #include "w_zoom.h"
41 
42 #include "f_util.h"
43 #include "u_bound.h"
44 #include "u_free.h"
45 #include "u_list.h"
46 #include "u_markers.h"
47 #include "u_redraw.h"
48 #include "w_canvas.h"
49 #include "w_grid.h"
50 #include "w_rulers.h"
51 
52 #define MAX_SCROLL_WD 50
53 
54 /* EXPORTS */
55 
56 Boolean	update_buts_managed;
57 Widget	choice_popup;
58 void	show_depth(ind_sw_info *sw), show_zoom(ind_sw_info *sw);
59 void	show_fillstyle(ind_sw_info *sw);
60 void	fontpane_popup(int *psfont_adr, int *latexfont_adr, int *psflag_adr, void (*showfont_fn) (/* ??? */), Widget show_widget);
61 void	make_pulldown_menu_images(choice_info *entries, Cardinal nent, Pixmap *images, char **texts, Widget parent, XtCallbackProc callback);
62 void	tog_selective_update(long unsigned int mask);
63 unsigned long cur_indmask;	/* mask showing which indicator buttons are mapped */
64 void	inc_zoom_centered(ind_sw_info *sw);
65 void	dec_zoom_centered(ind_sw_info *sw);
66 void	fit_zoom(ind_sw_info *sw);
67 ind_sw_info ind_switches[];
68 ind_sw_info *fill_style_sw;
69 ind_sw_info *pen_color_button, *fill_color_button, *depth_button;
70 unsigned long	cur_indmask = 0;	/* start showing only zoom and grid buttons */
71 
72 /* LOCAL */
73 
74 #define MAX_FLAGS	 3	/* number of text flags (cur_flagshown) */
75 #define MAX_ARROWPARMS	 3	/* number of arrow size parms (cur_arrowshown) */
76 #define MAX_DIMLINEPARMS 15	/* number of dimension line parms (cur_dimline) */
77 
78 static int	cur_anglegeom = L_UNCONSTRAINED;
79 static int	cur_flagshown = 0;
80 static int	cur_arrowsizeshown = 0;
81 static int	cur_dimlineshown = 0;
82 static Pixel	arrow_size_bg, arrow_size_fg;
83 static Boolean	save_use_abs;
84 
85 #ifndef XAW3D1_5E
86 /* popup message over button when mouse enters it */
87 static void     ind_balloon_trigger(Widget widget, XtPointer closure, XEvent *event, Boolean *continue_to_dispatch);
88 static void     ind_unballoon(Widget widget, XtPointer closure, XEvent *event, Boolean *continue_to_dispatch);
89 #endif /* XAW3D1_5E */
90 
91 /***** value panel set translations *****/
92 static String set_translations =
93 	"<Key>Return: ClearMousefunKbd()SetValue()\n\
94 	Meta<Key>Q: QuitNval()\n\
95 	<Key>Escape: QuitNval()\n\
96 	Ctrl<Key>J: no-op(RingBell)\n\
97 	Ctrl<Key>M: no-op(RingBell)\n\
98 	Ctrl<Key>X: EmptyTextKey()\n\
99 	Ctrl<Key>U: multiply(4)\n\
100 	<Key>F18: PastePanelKey()\n";
101 
102 /***** value panel translations, prototypes and actions *****/
103 static String   nval_translations =
104 	"<Key>Escape: QuitNval()\n\
105         <Message>WM_PROTOCOLS: QuitNval()\n";
106 
107 static void	nval_panel_set(Widget w, XButtonEvent *ev);
108 static void	nval_panel_cancel(Widget w, XButtonEvent *ev);
109 static XtActionsRec     nval_actions[] =
110 {
111     {"SetValue", (XtActionProc) nval_panel_set},
112     {"QuitNval", (XtActionProc) nval_panel_cancel},
113 };
114 
115 /***** dimension line panel translations *****/
116 static	void	dimline_panel_cancel(Widget w, XButtonEvent *ev);
117 static	void	dimline_panel_ok(Widget w, XButtonEvent *ev);
118 static String   dimline_translations =
119 	"<Key>Escape: QuitDimline()\n\
120         <Message>WM_PROTOCOLS: QuitDimline()";
121 static XtActionsRec     dimline_actions[] =
122 {
123     {"QuitDimline", (XtActionProc) dimline_panel_cancel},
124 };
125 
126 /***** choice panel cancel actions and translations *****/
127 static String   choice_translations =
128 	"<Key>Escape: QuitChoice()\n\
129         <Message>WM_PROTOCOLS: QuitChoice()";
130 static void     choice_panel_cancel(Widget w, XButtonEvent *ev);
131 static XtActionsRec     choice_actions[] =
132 {
133     {"QuitChoice", (XtActionProc) choice_panel_cancel},
134 };
135 
136 DeclareStaticArgs(20);
137 
138 /* declarations for value buttons */
139 
140 /* this flag is used to get around a bug in XFree86 3.3.1 where when an update
141    is done from an object to the indicator panel, the images don't update properly.
142    This will make the update button be unmapped then remapped to force the image
143    to be updated. From Heiko Schroeder (hschroe@ebs.wilhelmshaven-online.de) */
144 	Boolean	update_buts_managed = False;
145 
146 /* and these can be static */
147 
148 /* declarations for choice buttons */
149 static	void	darken_fill(ind_sw_info *sw), lighten_fill(ind_sw_info *sw);
150 static	void	inc_choice(ind_sw_info *sw), dec_choice(ind_sw_info *sw);
151 static	void	show_valign(ind_sw_info *sw), show_halign(ind_sw_info *sw), show_textjust(ind_sw_info *sw);
152 static	void	show_arrowmode(ind_sw_info *sw), show_arrowtype(ind_sw_info *sw);
153 static	void	show_arrowsize(ind_sw_info *sw), inc_arrowsize(ind_sw_info *sw), dec_arrowsize(ind_sw_info *sw);
154 static	void	show_linestyle(ind_sw_info *sw), show_joinstyle(ind_sw_info *sw), show_capstyle(ind_sw_info *sw);
155 static	void	show_anglegeom(ind_sw_info *sw), show_arctype(ind_sw_info *sw);
156 static	void	show_pointposn(ind_sw_info *sw), show_gridmode(ind_sw_info *sw), show_linkmode(ind_sw_info *sw);
157 static	void	show_linewidth(ind_sw_info *sw), inc_linewidth(ind_sw_info *sw), dec_linewidth(ind_sw_info *sw);
158 static	void	show_boxradius(ind_sw_info *sw), inc_boxradius(ind_sw_info *sw), dec_boxradius(ind_sw_info *sw);
159 static	void	show_font(ind_sw_info *sw), inc_font(ind_sw_info *sw), dec_font(ind_sw_info *sw);
160 static	void	show_flags(ind_sw_info *sw), inc_flags(ind_sw_info *sw), dec_flags(ind_sw_info *sw);
161 static	void	show_fontsize(ind_sw_info *sw), inc_fontsize(ind_sw_info *sw), dec_fontsize(ind_sw_info *sw);
162 static	void	show_textstep(ind_sw_info *sw), inc_textstep(ind_sw_info *sw), dec_textstep(ind_sw_info *sw);
163 static	void	show_rotnangle(ind_sw_info *sw), show_rotnangle_0(ind_sw_info *sw, int panel), inc_rotnangle(ind_sw_info *sw), dec_rotnangle(ind_sw_info *sw);
164 static	void	show_elltextangle(ind_sw_info *sw), inc_elltextangle(ind_sw_info *sw), dec_elltextangle(ind_sw_info *sw);
165 static	void	show_numsides(ind_sw_info *sw), inc_numsides(ind_sw_info *sw), dec_numsides(ind_sw_info *sw);
166 static	void	show_numcopies(ind_sw_info *sw), inc_numcopies(ind_sw_info *sw), dec_numcopies(ind_sw_info *sw);
167 static	void	show_numxcopies(ind_sw_info *sw), inc_numxcopies(ind_sw_info *sw), dec_numxcopies(ind_sw_info *sw);
168 static	void	show_numycopies(ind_sw_info *sw), inc_numycopies(ind_sw_info *sw), dec_numycopies(ind_sw_info *sw);
169 static	void	inc_depth(ind_sw_info *sw), dec_depth(ind_sw_info *sw);
170 static	void	show_tangnormlen(ind_sw_info *sw), inc_tangnormlen(ind_sw_info *sw), dec_tangnormlen(ind_sw_info *sw);
171 static	void	show_dimline(ind_sw_info *sw), inc_dimline(ind_sw_info *sw), dec_dimline(ind_sw_info *sw);
172 static	void	dimline_style_select(Widget w, XtPointer new_style, XtPointer call_data);
173 static	void	popup_fonts(ind_sw_info *sw);
174 static	void	note_state(Widget w, XtPointer closure, XtPointer call_data);
175 static void set_all_update(Widget w, XtPointer data, XEvent *event, Boolean *cont);
176 static void clr_all_update(Widget w, XtPointer data, XEvent *event, Boolean *cont);
177 static void tog_all_update(Widget w, XtPointer data, XEvent *event, Boolean *cont);
178 
179 static	void	zoom_to_fit(Widget w, XtPointer closure, XtPointer call_data);
180 
181 static	char	indbuf[30];
182 static	float	old_display_zoomscale = -1.0;
183 static	float	old_rotnangle	= -1.0;
184 static	float	old_elltextangle = -1.0;
185 
186 Dimension	UPD_CTRL_WD;
187 
188 Widget		set_upd, upd_tog,
189 		clr_upd, tog_upd, upd_ctrl_lab, upd_ctrl_btns;
190 Widget		abstoggle, multtoggle;
191 
192 /* indicator switch definitions */
193 
194 static choice_info anglegeom_choices[] = {
195     {L_UNCONSTRAINED, &unconstrained_ic,},
196     {L_LATEXLINE, &latexline_ic,},
197     {L_LATEXARROW, &latexarrow_ic,},
198     {L_MOUNTHATTAN, &mounthattan_ic,},
199     {L_MANHATTAN, &manhattan_ic,},
200     {L_MOUNTAIN, &mountain_ic,},
201 };
202 #define NUM_ANGLEGEOM_CHOICES (sizeof(anglegeom_choices)/sizeof(choice_info))
203 
204 static choice_info valign_choices[] = {
205     {ALIGN_NONE, &none_ic,},
206     {ALIGN_TOP, &valignt_ic,},
207     {ALIGN_CENTER, &valignc_ic,},
208     {ALIGN_BOTTOM, &valignb_ic,},
209     {ALIGN_DISTRIB_C, &valigndc_ic,},
210     {ALIGN_DISTRIB_E, &valignde_ic,},
211     {ALIGN_ABUT, &valigna_ic,},
212 };
213 #define NUM_VALIGN_CHOICES (sizeof(valign_choices)/sizeof(choice_info))
214 
215 static choice_info halign_choices[] = {
216     {ALIGN_NONE, &none_ic,},
217     {ALIGN_LEFT, &halignl_ic,},
218     {ALIGN_CENTER, &halignc_ic,},
219     {ALIGN_RIGHT, &halignr_ic,},
220     {ALIGN_DISTRIB_C, &haligndc_ic,},
221     {ALIGN_DISTRIB_E, &halignde_ic,},
222     {ALIGN_ABUT, &haligna_ic,},
223 };
224 #define NUM_HALIGN_CHOICES (sizeof(halign_choices)/sizeof(choice_info))
225 
226 static choice_info gridmode_choices[] = {
227     {GRID_0, &none_ic,},
228     {GRID_1, &grid1_ic,},
229     {GRID_2, &grid2_ic,},
230     {GRID_3, &grid3_ic,},
231     {GRID_4, &grid4_ic,},
232     {GRID_ISO_1, &grid_iso1_ic,},			// isometric grid
233     {GRID_ISO_2, &grid_iso2_ic,},
234     {GRID_ISO_3, &grid_iso3_ic,},
235     {GRID_ISO_4, &grid_iso4_ic,},
236 };
237 #define NUM_GRIDMODE_CHOICES (sizeof(gridmode_choices)/sizeof(choice_info))
238 
239 static choice_info pointposn_choices[] = {
240     {P_ANY, &any_ic,},
241     {P_MAGNET, &fine_grid_ic,},
242     {P_GRID1, &grid1_ic,},
243     {P_GRID2, &grid2_ic,},
244     {P_GRID3, &grid3_ic,},
245     {P_GRID4, &grid4_ic,},
246 };
247 #define NUM_POINTPOSN_CHOICES (sizeof(pointposn_choices)/sizeof(choice_info))
248 
249 static choice_info arrowmode_choices[] = {
250     {L_NOARROWS, &noarrows_ic,},
251     {L_FARROWS, &farrows_ic,},
252     {L_FBARROWS, &fbarrows_ic,},
253     {L_BARROWS, &barrows_ic,},
254 };
255 #define NUM_ARROWMODE_CHOICES (sizeof(arrowmode_choices)/sizeof(choice_info))
256 
257 /* the following are used for the dimension-line arrowhead selection */
258 /* e_edit.c also uses these */
259 
260 choice_info dim_arrowtype_choices[] = {
261     {-1, &arrow0_ic,},
262     {0, &arrow0_ic,},
263     {1, &arrow1o_ic,},
264     {2, &arrow1f_ic,},
265     {3, &arrow2o_ic,},
266     {4, &arrow2f_ic,},
267     {5, &arrow3o_ic,},
268     {6, &arrow3f_ic,},
269 #ifdef ARROWS4TO14
270     {7, &arrow4o_ic,},
271     {8, &arrow4f_ic,},
272     {9, &arrow5o_ic,},
273     {10, &arrow5f_ic,},
274     {11, &arrow6o_ic,},
275     {12, &arrow6f_ic,},
276     {13, &arrow7o_ic,},
277     {14, &arrow7f_ic,},
278     {15, &arrow8o_ic,},
279     {16, &arrow8f_ic,},
280     {17, &arrow9a_ic,},
281     {18, &arrow9b_ic,},
282     {19, &arrow10o_ic,},
283     {20, &arrow10f_ic,},
284     {21, &arrow11o_ic,},
285     {22, &arrow11f_ic,},
286     {23, &arrow12o_ic,},
287     {24, &arrow12f_ic,},
288     {25, &arrow13a_ic,},
289     {26, &arrow13b_ic,},
290     {27, &arrow14a_ic,},
291     {28, &arrow14b_ic,},
292 #endif /* ARROWS4TO14 */
293 };
294 #define NUM_DIM_ARROWTYPE_CHOICES (sizeof(dim_arrowtype_choices)/sizeof(choice_info))
295 
296 /* these are used only for the arrow type button on the ind panel */
297 
298 choice_info arrowtype_choices[] = {
299     {0, &arrow0_ic,},
300     {1, &arrow1o_ic,},
301     {2, &arrow1f_ic,},
302     {3, &arrow2o_ic,},
303     {4, &arrow2f_ic,},
304     {5, &arrow3o_ic,},
305     {6, &arrow3f_ic,},
306 #ifdef ARROWS4TO14
307     {7, &arrow4o_ic,},
308     {8, &arrow4f_ic,},
309     {9, &arrow5o_ic,},
310     {10, &arrow5f_ic,},
311     {11, &arrow6o_ic,},
312     {12, &arrow6f_ic,},
313     {13, &arrow7o_ic,},
314     {14, &arrow7f_ic,},
315     {15, &arrow8o_ic,},
316     {16, &arrow8f_ic,},
317     {17, &arrow9a_ic,},
318     {18, &arrow9b_ic,},
319     {19, &arrow10o_ic,},
320     {20, &arrow10f_ic,},
321     {21, &arrow11o_ic,},
322     {22, &arrow11f_ic,},
323     {23, &arrow12o_ic,},
324     {24, &arrow12f_ic,},
325     {25, &arrow13a_ic,},
326     {26, &arrow13b_ic,},
327     {27, &arrow14a_ic,},
328     {28, &arrow14b_ic,},
329 #endif /* ARROWS4TO14 */
330 };
331 #define NUM_ARROWTYPE_CHOICES (sizeof(arrowtype_choices)/sizeof(choice_info))
332 
333 static choice_info textjust_choices[] = {
334     {T_LEFT_JUSTIFIED, &textL_ic,},
335     {T_CENTER_JUSTIFIED, &textC_ic,},
336     {T_RIGHT_JUSTIFIED, &textR_ic,},
337 };
338 #define NUM_TEXTJUST_CHOICES (sizeof(textjust_choices)/sizeof(choice_info))
339 
340 static choice_info arctype_choices[] = {
341     {T_OPEN_ARC, &open_arc_ic,},
342     {T_PIE_WEDGE_ARC, &pie_wedge_arc_ic,},
343 };
344 #define NUM_ARCTYPE_CHOICES (sizeof(arctype_choices)/sizeof(choice_info))
345 
346 choice_info linestyle_choices[] = {
347     {SOLID_LINE, &solidline_ic,},
348     {DASH_LINE, &dashline_ic,},
349     {DOTTED_LINE, &dottedline_ic,},
350     {DASH_DOT_LINE, &dashdotline_ic,},
351     {DASH_2_DOTS_LINE, &dash2dotsline_ic,},
352     {DASH_3_DOTS_LINE, &dash3dotsline_ic,},
353 };
354 
355 choice_info joinstyle_choices[] = {
356     {JOIN_MITER, &joinmiter_ic,},
357     {JOIN_ROUND, &joinround_ic,},
358     {JOIN_BEVEL, &joinbevel_ic,},
359 };
360 
361 choice_info capstyle_choices[] = {
362     {CAP_BUTT,    &capbutt_ic,},
363     {CAP_ROUND,   &capround_ic,},
364     {CAP_PROJECT, &capproject_ic,},
365 };
366 
367 static choice_info linkmode_choices[] = {
368     {SMART_OFF, &smartoff_ic,},
369     {SMART_MOVE, &smartmove_ic,},
370     {SMART_SLIDE, &smartslide_ic,},
371 };
372 #define NUM_LINKMODE_CHOICES (sizeof(linkmode_choices)/sizeof(choice_info))
373 
374 choice_info	fillstyle_choices[NUMFILLPATS + 1];
375 
376 choice_info	color_choices[NUM_STD_COLS + 1];
377 ind_sw_info	*zoom_sw;
378 ind_sw_info	*fill_style_sw;
379 
380 #define		inc_action(z)	(z->inc_func)(z)
381 #define		dec_action(z)	(z->dec_func)(z)
382 #define		show_action(z)	(z->show_func)(z)
383 
384 ind_sw_info	ind_switches[] = {
385     {I_FVAL, 0, "Zoom", "", NARROW_IND_SW_WD,		/* always show zoom button */
386 	NULL, &display_zoomscale, inc_zoom_centered, dec_zoom_centered,
387 	show_zoom, 0 /* MIN_ZOOM */, MAX_ZOOM, 1.0},
388     {I_CHOICE, 0, "Grid", "Mode", DEF_IND_SW_WD,	/* and grid button */			// isometric grid
389 	&cur_gridmode, NULL, inc_choice, dec_choice, show_gridmode, 0, 0, 0.0,
390 	gridmode_choices, NUM_GRIDMODE_CHOICES, (NUM_GRIDMODE_CHOICES+1)/2},
391     {I_CHOICE, I_POINTPOSN, "Point", "Posn", DEF_IND_SW_WD,
392 	&cur_pointposn, NULL, inc_choice, dec_choice, show_pointposn, 0, 0, 0.0,
393 	pointposn_choices, NUM_POINTPOSN_CHOICES, NUM_POINTPOSN_CHOICES},
394     {I_IVAL, I_DEPTH, "Depth", "", NARROW_IND_SW_WD,
395 	&cur_depth, NULL, inc_depth, dec_depth, show_depth, MIN_DEPTH, MAX_DEPTH, 1.0},
396     {I_FVAL, I_ROTNANGLE, "Rotn", "Angle", WIDE_IND_SW_WD,
397 	NULL, &cur_rotnangle, inc_rotnangle, dec_rotnangle, show_rotnangle, -360.0, 360.0, 1.0},
398     {I_IVAL, I_NUMSIDES, "Num", "Sides", NARROW_IND_SW_WD,
399 	&cur_numsides, NULL, inc_numsides, dec_numsides, show_numsides,
400 	MIN_POLY_SIDES, MAX_POLY_SIDES, 1.0},
401     {I_IVAL, I_NUMCOPIES, "Num", "Copies", NARROW_IND_SW_WD,
402 	&cur_numcopies, NULL, inc_numcopies, dec_numcopies, show_numcopies, 1, 99, 1.0},
403     {I_IVAL, I_NUMXCOPIES, "Num X", "Copies", NARROW_IND_SW_WD,
404 	&cur_numxcopies, NULL, inc_numxcopies, dec_numxcopies, show_numxcopies, 1, 99, 1.0},
405     {I_IVAL, I_NUMYCOPIES, "Num Y", "Copies", NARROW_IND_SW_WD,
406 	&cur_numycopies, NULL, inc_numycopies, dec_numycopies, show_numycopies, 1, 99, 1.0},
407     {I_CHOICE, I_VALIGN, "Vert", "Align", DEF_IND_SW_WD,
408 	&cur_valign, NULL, inc_choice, dec_choice, show_valign, 0, 0, 0.0,
409 	valign_choices, NUM_VALIGN_CHOICES, NUM_VALIGN_CHOICES},
410     {I_CHOICE, I_HALIGN, "Horiz", "Align", DEF_IND_SW_WD,
411 	&cur_halign, NULL, inc_choice, dec_choice, show_halign, 0, 0, 0.0,
412 	halign_choices, NUM_HALIGN_CHOICES, NUM_HALIGN_CHOICES},
413     {I_CHOICE, I_ANGLEGEOM, "Angle", "Geom", DEF_IND_SW_WD,
414 	&cur_anglegeom, NULL, inc_choice, dec_choice, show_anglegeom, 0, 0, 0.0,
415 	anglegeom_choices, NUM_ANGLEGEOM_CHOICES, NUM_ANGLEGEOM_CHOICES},
416     {I_CHOICE, I_PEN_COLOR, "PenColor", "", XWIDE_IND_SW_WD,
417 	(int *) &cur_pencolor, NULL, next_pencolor, prev_pencolor, show_pencolor, 0, 0, 0.0,
418 	color_choices, NUM_STD_COLS + 1, 7},
419     {I_CHOICE, I_FILL_COLOR, "FillColor", "", XWIDE_IND_SW_WD,
420 	(int *) &cur_fillcolor, NULL, next_fillcolor, prev_fillcolor, show_fillcolor,0, 0, 0.0,
421 	color_choices, NUM_STD_COLS + 1, 7},
422     {I_CHOICE, I_FILLSTYLE, "Fill", "Style", DEF_IND_SW_WD,
423 	&cur_fillstyle, NULL, darken_fill, lighten_fill, show_fillstyle,0, 0, 0.0,
424 	fillstyle_choices, NUMFILLPATS + 1, 11},
425     {I_CHOICE, I_ARCTYPE, "Arc", "Type", DEF_IND_SW_WD,
426 	&cur_arctype, NULL, inc_choice, dec_choice, show_arctype, 0, 0, 0.0,
427 	arctype_choices, NUM_ARCTYPE_CHOICES, NUM_ARCTYPE_CHOICES},
428     {I_CHOICE, I_LINKMODE, "Smart", "Links", DEF_IND_SW_WD,
429 	&cur_linkmode, NULL, inc_choice, dec_choice, show_linkmode, 0, 0, 0.0,
430 	linkmode_choices, NUM_LINKMODE_CHOICES, NUM_LINKMODE_CHOICES},
431     {I_IVAL, I_LINEWIDTH, "Line", "Width", DEF_IND_SW_WD,
432 	&cur_linewidth, NULL, inc_linewidth, dec_linewidth, show_linewidth,
433 	0, MAX_LINE_WIDTH, 1.0},
434     {I_CHOICE, I_LINESTYLE, "Line", "Style", DEF_IND_SW_WD,
435 	&cur_linestyle, NULL, inc_choice, dec_choice, show_linestyle, 0, 0, 0.0,
436 	linestyle_choices, NUM_LINESTYLE_TYPES, NUM_LINESTYLE_TYPES},
437     {I_FVAL, I_TANGNORMLEN, "Tangent/Norm", "Length", WIDE_IND_SW_WD,
438 	NULL, &cur_tangnormlen, inc_tangnormlen, dec_tangnormlen, show_tangnormlen, MIN_TANGNORMLEN, MAX_TANGNORMLEN, 0.2},
439     {I_CHOICE, I_JOINSTYLE, "Join", "Style", DEF_IND_SW_WD,
440 	&cur_joinstyle, NULL, inc_choice, dec_choice, show_joinstyle, 0, 0, 0.0,
441 	joinstyle_choices, NUM_JOINSTYLE_TYPES, NUM_JOINSTYLE_TYPES},
442     {I_CHOICE, I_CAPSTYLE, "Cap", "Style", DEF_IND_SW_WD,
443 	&cur_capstyle, NULL, inc_choice, dec_choice, show_capstyle, 0, 0, 0.0,
444 	capstyle_choices, NUM_CAPSTYLE_TYPES, NUM_CAPSTYLE_TYPES},
445     {I_CHOICE, I_ARROWMODE, "Arrow", "Mode", DEF_IND_SW_WD,
446 	&cur_arrowmode, NULL, inc_choice, dec_choice, show_arrowmode, 0, 0, 0.0,
447 	arrowmode_choices, NUM_ARROWMODE_CHOICES, NUM_ARROWMODE_CHOICES},
448     {I_CHOICE, I_ARROWTYPE, "Arrow", "Type", DEF_IND_SW_WD,
449 	&cur_arrowtype, NULL, inc_choice, dec_choice, show_arrowtype, 0, 0, 0.0,
450 	arrowtype_choices, NUM_ARROWTYPE_CHOICES, 9},
451     {I_CHOICE, I_ARROWSIZE, "Arrow Size", "", WIDE_IND_SW_WD,
452 	NULL, NULL, inc_arrowsize, dec_arrowsize, show_arrowsize, 0, 0, 0.0},
453     {I_IVAL, I_BOXRADIUS, "Box", "Curve", DEF_IND_SW_WD,
454 	&cur_boxradius, NULL, inc_boxradius, dec_boxradius, show_boxradius,
455 	MIN_BOX_RADIUS, MAX_BOX_RADIUS, 1.0},
456     {I_DIMLINE, I_DIMLINE, "Dimension line", "", XWIDE_IND_SW_WD,
457 	NULL, NULL, inc_dimline, dec_dimline, show_dimline, 0, 0, 0.0},
458     {I_CHOICE, I_TEXTJUST, "Text", "Just", DEF_IND_SW_WD,
459 	&cur_textjust, NULL, inc_choice, dec_choice, show_textjust, 0, 0, 0.0,
460 	textjust_choices, NUM_TEXTJUST_CHOICES, NUM_TEXTJUST_CHOICES},
461     {I_FVAL, I_ELLTEXTANGLE, "Text/Ellipse", "Angle", XWIDE_IND_SW_WD,
462 	NULL, &cur_elltextangle, inc_elltextangle, dec_elltextangle, show_elltextangle,
463 	-360, 360, 1.0},
464     {I_IVAL, I_TEXTFLAGS, "Text Flags", "", WIDE_IND_SW_WD,
465 	&cur_textflags, NULL, inc_flags, dec_flags, show_flags, 0, 0, 0.0},
466     {I_IVAL, I_FONTSIZE, "Text", "Size", NARROW_IND_SW_WD,
467 	&cur_fontsize, NULL, inc_fontsize, dec_fontsize, show_fontsize,
468 	MIN_FONT_SIZE, MAX_FONT_SIZE, 1.0},
469     {I_FVAL, I_TEXTSTEP, "Text", "Step", NARROW_IND_SW_WD,
470 	NULL, &cur_textstep, inc_textstep, dec_textstep, show_textstep, 0, 1000, 0.1},
471     {I_IVAL, I_FONT, "Text", "Font", FONT_IND_SW_WD,
472 	&cur_ps_font, NULL, inc_font, dec_font, show_font, 0, 0, 0.0},
473 };
474 
475 #define		NUM_IND_SW	(sizeof(ind_switches) / sizeof(ind_sw_info))
476 
477 
478 /* button selection event handler */
479 static void	sel_ind_but(Widget widget, XtPointer closure, XEvent *event, Boolean *continue_to_dispatch);
480 
481 /* arguments for the update indicator boxes in the indicator buttons */
482 
483 static Arg	upd_args[] =
484 {
485     /* 0 */ {XtNwidth, (XtArgVal) 8},
486     /* 1 */ {XtNheight, (XtArgVal) 8},
487     /* 2 */ {XtNborderWidth, (XtArgVal) 1},
488     /* 3 */ {XtNtop, (XtArgVal) XtChainTop},
489     /* 4 */ {XtNright, (XtArgVal) XtChainRight},
490     /* 5 */ {XtNstate, (XtArgVal) True},
491     /* 6 */ {XtNvertDistance, (XtArgVal) 0},
492     /* 7 */ {XtNhorizDistance, (XtArgVal) 0},
493     /* 8 */ {XtNlabel, (XtArgVal) " "},
494 };
495 
496 static XtActionsRec ind_actions[] =
497 {
498     {"EnterIndSw", (XtActionProc) draw_mousefun_ind},
499     {"LeaveIndSw", (XtActionProc) clear_mousefun},
500     {"ZoomIn", (XtActionProc) wheel_inc_zoom},
501     {"ZoomOut", (XtActionProc) wheel_dec_zoom},
502     {"ZoomFit", (XtActionProc) fit_zoom},
503 };
504 
505 static String	ind_translations =
506 "<EnterWindow>:EnterIndSw()highlight()\n\
507     <LeaveWindow>:LeaveIndSw()unhighlight()\n";
508 
509 /* bitmaps for set/clear and toggle buttons (10x10) */
510 static unsigned char set_bits[] = {
511    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
512    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
513 static unsigned char clr_bits[] = {
514    0xff, 0x03, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
515    0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0xff, 0x03};
516 static unsigned char tog_bits[] = {
517    0xff, 0x03, 0x01, 0x02, 0x03, 0x02, 0x07, 0x02, 0x0f, 0x02, 0x1f, 0x02,
518    0x3f, 0x02, 0x7f, 0x02, 0xff, 0x02, 0xff, 0x03};
519 
520 /* create a ind_sw_info struct for the update widget
521    so we can use the balloon routines or the Tip widget */
522 
523 static ind_sw_info upd_sw_info, upd_set_sw_info, upd_clr_sw_info, upd_tog_sw_info;
524 
525 
526 
527 void
init_ind_panel(Widget tool)528 init_ind_panel(Widget tool)
529 {
530     ind_sw_info	*sw;
531     Widget	 tw; /* temporary widget to get scrollbar widget */
532     int		 i;
533 
534     /* Make a widget which contains the label and toggle/set/clear form.
535        This will be managed and unmanaged as needed.  It's parent is the
536        main form (tool) and the ind_panel will be chained to it when it
537        is managed */
538 
539     FirstArg(XtNdefaultDistance, 0);
540     NextArg(XtNborderWidth, INTERNAL_BW);
541     NextArg(XtNorientation, XtorientVertical);
542     NextArg(XtNhSpace, 0);
543     NextArg(XtNvSpace, 1);
544     NextArg(XtNresizable, False);
545     NextArg(XtNfromVert, canvas_sw);
546     NextArg(XtNtop, XtChainBottom);	/* don't resize when form changes */
547     NextArg(XtNbottom, XtChainBottom);
548     NextArg(XtNleft, XtChainLeft);
549     NextArg(XtNright, XtChainLeft);
550 
551     upd_ctrl = XtCreateWidget("upd_ctrl_form", boxWidgetClass,
552 			tool, Args, ArgCount);
553     /* popup when mouse passes over button */
554     strcpy(upd_sw_info.line1,"Selects which settings are updated");
555     upd_sw_info.line2[0] = '\0';
556     upd_sw_info.sw_width = 70;  /* rough guess */
557 #ifndef XAW3D1_5E
558     XtAddEventHandler(upd_ctrl, EnterWindowMask, False,
559 			ind_balloon_trigger, (XtPointer) &upd_sw_info);
560     XtAddEventHandler(upd_ctrl, LeaveWindowMask, False,
561 			ind_unballoon, (XtPointer) &upd_sw_info);
562 #endif /* XAW3D1_5E */
563 
564     FirstArg(XtNborderWidth, 0);
565     NextArg(XtNjustify, XtJustifyCenter);
566     NextArg(XtNfont, button_font);
567     NextArg(XtNlabel, "  Update \n  Control ");
568     NextArg(XtNinternalHeight, 0);
569     upd_ctrl_lab = XtCreateManagedWidget("upd_ctrl_label", labelWidgetClass,
570 			upd_ctrl, Args, ArgCount);
571 #ifndef XAW3D1_5E
572     XtAddEventHandler(upd_ctrl_lab, EnterWindowMask, False,
573 			ind_balloon_trigger, (XtPointer) &upd_sw_info);
574     XtAddEventHandler(upd_ctrl_lab, LeaveWindowMask, False,
575 			ind_unballoon, (XtPointer) &upd_sw_info);
576 #endif /* XAW3D1_5E */
577 
578     FirstArg(XtNdefaultDistance, 0);
579     NextArg(XtNborderWidth, 0);
580     NextArg(XtNorientation, XtorientHorizontal);
581     NextArg(XtNhSpace, 3);
582     NextArg(XtNvSpace, 0);
583     upd_ctrl_btns = XtCreateManagedWidget("upd_ctrl_btns", boxWidgetClass,
584 			upd_ctrl, Args, ArgCount);
585 
586     FirstArg(XtNheight, UPD_BITS);
587     NextArg(XtNwidth, UPD_BITS);
588     NextArg(XtNinternalWidth, UPD_INT);
589     NextArg(XtNinternalHeight, UPD_INT);
590     NextArg(XtNborderWidth, UPD_BORD);
591     set_upd = XtCreateManagedWidget("set_upd", commandWidgetClass,
592 			upd_ctrl_btns, Args, ArgCount);
593     XtAddEventHandler(set_upd, ButtonReleaseMask, False,
594 			set_all_update, (XtPointer) 0);
595 
596     strcpy(upd_set_sw_info.line1,"Sets all update flags");
597     upd_set_sw_info.line2[0] = '\0';
598     upd_set_sw_info.sw_width = UPD_BITS+6;
599 #ifndef XAW3D1_5E
600     XtAddEventHandler(set_upd, EnterWindowMask, False,
601 			ind_balloon_trigger, (XtPointer) &upd_set_sw_info);
602     XtAddEventHandler(set_upd, LeaveWindowMask, False,
603 			ind_unballoon, (XtPointer) &upd_set_sw_info);
604 #endif /* XAW3D1_5E */
605 
606     clr_upd = XtCreateManagedWidget("clr_upd", commandWidgetClass,
607 			upd_ctrl_btns, Args, ArgCount);
608     XtAddEventHandler(clr_upd, ButtonReleaseMask, False,
609 			clr_all_update, (XtPointer) 0);
610 
611     strcpy(upd_clr_sw_info.line1,"Clears all update flags");
612     upd_clr_sw_info.line2[0] = '\0';
613     upd_clr_sw_info.sw_width = UPD_BITS+6;
614 #ifndef XAW3D1_5E
615     XtAddEventHandler(clr_upd, EnterWindowMask, False,
616 			ind_balloon_trigger, (XtPointer) &upd_clr_sw_info);
617     XtAddEventHandler(clr_upd, LeaveWindowMask, False,
618 			ind_unballoon, (XtPointer) &upd_clr_sw_info);
619 #endif /* XAW3D1_5E */
620 
621     tog_upd = XtCreateManagedWidget("tog_upd", commandWidgetClass,
622 			upd_ctrl_btns, Args, ArgCount);
623     XtAddEventHandler(tog_upd, ButtonReleaseMask, False,
624 			tog_all_update, (XtPointer) 0);
625 
626     strcpy(upd_tog_sw_info.line1,"Toggles all update flags");
627     upd_tog_sw_info.line2[0] = '\0';
628     upd_tog_sw_info.sw_width = UPD_BITS+6;
629 #ifndef XAW3D1_5E
630     XtAddEventHandler(tog_upd, EnterWindowMask, False,
631 			ind_balloon_trigger, (XtPointer) &upd_tog_sw_info);
632     XtAddEventHandler(tog_upd, LeaveWindowMask, False,
633 			ind_unballoon, (XtPointer) &upd_tog_sw_info);
634 #endif /* XAW3D1_5E */
635 
636     /* start with all components affected by update */
637     cur_updatemask = I_UPDATEMASK;
638 
639     /**********************************/
640     /* Now the indicator panel itself */
641     /**********************************/
642 
643     /* make a scrollable viewport in case all the buttons don't fit */
644     /* resize this later when we know how high the scrollbar is */
645     /* When the update control is managed, make the fromHoriz that widget */
646 
647     FirstArg(XtNallowHoriz, True);
648     NextArg(XtNwidth, INDPANEL_WD);
649     /* does he want to always see ALL of the indicator buttons? */
650     if (appres.showallbuttons) {	/* yes, but set cur_indmask to all later */
651 	i = 2*DEF_IND_SW_HT+5*INTERNAL_BW; /* two rows high when showing all buttons */
652     } else {
653 	i = DEF_IND_SW_HT + 2*INTERNAL_BW;
654     }
655     /* account for the scrollbar thickness */
656     i += MAX_SCROLL_WD;
657     /* and force it to be created so we can see how thick it is */
658     NextArg(XtNforceBars, True);
659 
660     NextArg(XtNheight, i);
661     NextArg(XtNborderWidth, 0);
662     NextArg(XtNuseBottom, True);
663     NextArg(XtNfromVert, canvas_sw);
664     NextArg(XtNtop, XtChainBottom);	/* don't resize height when main form changes */
665     NextArg(XtNbottom, XtChainBottom);
666     NextArg(XtNleft, XtChainLeft);	/* but do resize width when main form widens */
667     NextArg(XtNright, XtChainRight);
668 
669     ind_panel = XtCreateManagedWidget("ind_panel", viewportWidgetClass, tool,
670 			Args, ArgCount);
671 
672     FirstArg(XtNheight, i);
673     NextArg(XtNhSpace, 0);
674     NextArg(XtNvSpace, 0);
675     NextArg(XtNresizable, True);
676     NextArg(XtNborderWidth, 0);
677     if (appres.showallbuttons) {
678 	NextArg(XtNorientation, XtorientVertical);	/* use two rows */
679     } else {
680 	NextArg(XtNorientation, XtorientHorizontal);	/* expand horizontally */
681     }
682 
683     ind_box = XtCreateManagedWidget("ind_box", boxWidgetClass, ind_panel,
684 			       Args, ArgCount);
685 
686 
687     for (i = 0; i < NUM_IND_SW; ++i) {
688 	sw = &ind_switches[i];
689 	sw->panel = (Widget) NULL;	/* not created yet */
690 
691 	FirstArg(XtNwidth, sw->sw_width);
692 	NextArg(XtNheight, DEF_IND_SW_HT);
693 	NextArg(XtNdefaultDistance, 0);
694 	NextArg(XtNborderWidth, INTERNAL_BW);
695 	sw->formw = XtCreateWidget("button_form", formWidgetClass,
696 			     ind_box, Args, ArgCount);
697 
698 	/* make an update button in the upper-right corner of the main button */
699 	if (sw->func & I_UPDATEMASK) {
700 	    upd_args[7].value = sw->sw_width
701 					- upd_args[0].value
702 					- 2*upd_args[2].value;
703 	    sw->updbut = XtCreateWidget("update", toggleWidgetClass,
704 			     sw->formw, upd_args, XtNumber(upd_args));
705 	    sw->update = True;
706 	    XtAddCallback(sw->updbut, XtNcallback, note_state, (XtPointer) sw);
707 	}
708 
709 	/* now create the command button */
710 	FirstArg(XtNlabel, " ");
711 	NextArg(XtNwidth, sw->sw_width);
712 	NextArg(XtNheight, DEF_IND_SW_HT);
713 	NextArg(XtNresizable, False);
714 	NextArg(XtNborderWidth, 0);
715 	NextArg(XtNresize, False);
716 	NextArg(XtNresizable, False);
717 	NextArg(XtNbackgroundPixmap, NULL);
718 	sw->button = XtCreateManagedWidget("button", commandWidgetClass,
719 			     sw->formw, Args, ArgCount);
720 	/* map this button if it is needed */
721 	if (sw->func & cur_indmask)
722 	    XtManageChild(sw->formw);
723 
724 	/* allow left & right buttons */
725 	/* (callbacks pass same data for ANY button) */
726 	XtAddEventHandler(sw->button, ButtonReleaseMask, False,
727 			  sel_ind_but, (XtPointer) sw);
728 #ifndef XAW3D1_5E
729 	/* popup when mouse passes over button */
730 	XtAddEventHandler(sw->button, EnterWindowMask, False,
731 			  ind_balloon_trigger, (XtPointer) sw);
732 	XtAddEventHandler(sw->button, LeaveWindowMask, False,
733 			  ind_unballoon, (XtPointer) sw);
734 #endif /* XAW3D1_5E */
735 	XtOverrideTranslations(sw->button,
736 			       XtParseTranslationTable(ind_translations));
737     }
738 
739     /* now get the real height of the scrollbar and resize the ind_panel if necessary */
740     tw = XtNameToWidget(ind_panel, "horizontal");
741     if (tw != NULL) {
742 	Dimension    td1; /* temporary variable to get scrollbar thickness */
743 	Dimension    td2; /* temporary variable to get indpanel height */
744 	Dimension    bdw; /* temporary variable to get scrollbar border width */
745 
746 	FirstArg(XtNthumb, None);	/* make solid scrollbar instead of tiled */
747 	SetValues(tw);
748 
749 	FirstArg(XtNthickness, &td1);
750 	NextArg(XtNborderWidth, &bdw);
751 	GetValues(tw);
752 	FirstArg(XtNheight, &td2);
753 	GetValues(ind_panel);
754 	/* make it no shorter than the control panel height */
755 	td2 = max2(td2 - MAX_SCROLL_WD + td1 + 4 + bdw, UPD_CTRL_HT);
756 	XtUnmanageChild(ind_panel);
757 	FirstArg(XtNheight, td2);
758 	SetValues(ind_box);
759 	SetValues(ind_panel);
760 	/* now turn off the scrollbar until we need it */
761 	FirstArg(XtNforceBars, False);
762 	SetValues(ind_panel);
763 	XtManageChild(ind_panel);
764     }
765 
766     if (appres.showallbuttons) {
767 	cur_indmask = I_ALL;	/* now turn all indicator buttons */
768 	appres.showallbuttons = False;
769 	update_indpanel(cur_indmask);
770 	appres.showallbuttons = True;
771     }
772     update_indpanel(cur_indmask);
773     /* set up action and translation for mousefun kbd icon */
774     init_kbd_actions();
775 }
776 
777 void
add_ind_actions(void)778 add_ind_actions(void)
779 {
780     XtAppAddActions(tool_app, ind_actions, XtNumber(ind_actions));
781 }
782 
783 static void
note_state(Widget w,XtPointer closure,XtPointer call_data)784 note_state(Widget w, XtPointer closure, XtPointer call_data)
785 {
786     ind_sw_info *sw = (ind_sw_info *) closure;
787 
788     /* toggle update status of this indicator */
789     /* for some reason, the state is the opposite of reality */
790     sw->update = !sw->update;
791     if (sw->update)
792 	cur_updatemask |= sw->func;	/* turn on update status */
793     else
794 	cur_updatemask &= ~sw->func;	/* turn off update status */
795 }
796 
797 /* toggle the update buttons in all the widgets */
798 static void
tog_all_update(Widget w,XtPointer data,XEvent * event,Boolean * cont)799 tog_all_update(Widget w, XtPointer data, XEvent *event, Boolean *cont)
800 {
801     int i;
802 
803     cur_updatemask = ~cur_updatemask;	/* tuggle all */
804     for (i = 0; i < NUM_IND_SW; ++i) {
805 	if (ind_switches[i].updbut == NULL)
806 		continue;
807 	ind_switches[i].update = !ind_switches[i].update;
808 	FirstArg(XtNstate, ind_switches[i].update);
809 	SetValues(ind_switches[i].updbut);
810     }
811     put_msg("Update command status TOGGLED for all buttons");
812 }
813 
814 /* turn on the update buttons in all the widgets */
815 static void
set_all_update(Widget w,XtPointer data,XEvent * event,Boolean * cont)816 set_all_update(Widget w, XtPointer data, XEvent *event, Boolean *cont)
817 {
818     int i;
819 
820     cur_updatemask = I_UPDATEMASK;	/* turn all on */
821     for (i = 0; i < NUM_IND_SW; ++i) {
822 	if (ind_switches[i].updbut == NULL)
823 		continue;
824 	ind_switches[i].update = True;
825 	FirstArg(XtNstate, True);
826 	SetValues(ind_switches[i].updbut);
827     }
828     put_msg("Update commands are now ENABLED for all buttons");
829 }
830 
831 /* turn off the update buttons in all the widgets */
832 static void
clr_all_update(Widget w,XtPointer data,XEvent * event,Boolean * cont)833 clr_all_update(Widget w, XtPointer data, XEvent *event, Boolean *cont)
834 {
835     int i;
836 
837     for (i = 0; i < NUM_IND_SW; ++i) {
838     cur_updatemask = 0;			/* turn all off */
839 	if (ind_switches[i].updbut == NULL)
840 		continue;
841 	ind_switches[i].update = False;
842 	FirstArg(XtNstate, False);
843 	SetValues(ind_switches[i].updbut);
844     }
845     put_msg("Update commands will be IGNORED for all buttons");
846 }
847 
manage_update_buts(void)848 void manage_update_buts(void)
849 {
850     int		    i;
851     for (i = 0; i < NUM_IND_SW; ++i)
852 	if (ind_switches[i].func & I_UPDATEMASK)
853 	    XtManageChild(ind_switches[i].updbut);
854     update_buts_managed = True;
855 }
856 
unmanage_update_buts(void)857 void unmanage_update_buts(void)
858 {
859     int		    i;
860     for (i = 0; i < NUM_IND_SW; ++i)
861 	if (ind_switches[i].func & I_UPDATEMASK)
862 	    XtUnmanageChild(ind_switches[i].updbut);
863     update_buts_managed = False;
864 }
865 
setup_ind_panel(void)866 void setup_ind_panel(void)
867 {
868     int		    i;
869     ind_sw_info	   *isw;
870     Pixmap	    p;
871     Pixel	    fg,bg;
872 
873     /* get the foreground and background from the indicator widget */
874     /* and create a gc with those values */
875     ind_button_gc = XCreateGC(tool_d, XtWindow(ind_panel), (unsigned long) 0, NULL);
876     FirstArg(XtNforeground, &ind_but_fg);
877     NextArg(XtNbackground, &ind_but_bg);
878     GetValues(ind_switches[0].button);
879     XSetBackground(tool_d, ind_button_gc, ind_but_bg);
880     XSetForeground(tool_d, ind_button_gc, ind_but_fg);
881     XSetFont(tool_d, ind_button_gc, button_font->fid);
882 
883     /* also create gc with fore=background for blanking areas */
884     ind_blank_gc = XCreateGC(tool_d, XtWindow(ind_panel), (unsigned long) 0, NULL);
885     XSetBackground(tool_d, ind_blank_gc, ind_but_bg);
886     XSetForeground(tool_d, ind_blank_gc, ind_but_bg);
887 
888     /* create a gc for the fill and border color 'palettes' */
889     fill_color_gc = XCreateGC(tool_d, XtWindow(ind_panel), (unsigned long) 0, NULL);
890     pen_color_gc = XCreateGC(tool_d, XtWindow(ind_panel), (unsigned long) 0, NULL);
891 
892     /* initialize the fill style gc and pixmaps */
893     init_fill_pm();
894     init_fill_gc();
895 
896     for (i = 0; i < NUM_IND_SW; ++i) {
897 	isw = &ind_switches[i];
898 	/* keep track of a few switches */
899 	if (ind_switches[i].func == I_FILLSTYLE)
900 	    fill_style_sw = isw;
901 	else if (strcmp(ind_switches[i].line1,"Zoom")==0)
902 	    zoom_sw = isw;
903 	else if (ind_switches[i].func == I_PEN_COLOR)
904 	    pen_color_button = isw;	/* to update its pixmap in the indicator panel */
905 	else if (ind_switches[i].func == I_FILL_COLOR)
906 	    fill_color_button = isw;	/* to update its pixmap in the indicator panel */
907 	else if (ind_switches[i].func == I_DEPTH)
908 	    depth_button = isw;	/* to update depth when user right-clicks on depth checkbox */
909 
910 	p = XCreatePixmap(tool_d, XtWindow(isw->button), isw->sw_width,
911 			  DEF_IND_SW_HT, tool_dpth);
912 	XFillRectangle(tool_d, p, ind_blank_gc, 0, 0,
913 		       isw->sw_width, DEF_IND_SW_HT);
914 	XDrawImageString(tool_d, p, ind_button_gc, 3, 12, isw->line1, strlen(isw->line1));
915 	XDrawImageString(tool_d, p, ind_button_gc, 3, 25, isw->line2, strlen(isw->line2));
916 
917 	isw->pixmap = p;
918 	FirstArg(XtNbackgroundPixmap, p);
919 	SetValues(isw->button);
920 	/* generate pixmaps if this is a choice panel */
921 	if (ind_switches[i].type == I_CHOICE)
922 	    generate_choice_pixmaps(isw);
923     }
924 
925     /* setup the pixmap in the color button */
926     show_pencolor();
927     show_fillcolor();
928 
929     /* now put cute little images in update buttons (full box (set), empty box (clear)
930        and half full (toggle) */
931     FirstArg(XtNforeground, &fg);
932     NextArg(XtNbackground, &bg);
933     for (i = 0; i < NUM_IND_SW; ++i)		/* find one of the update buttons */
934 	if (ind_switches[i].func & I_UPDATEMASK) { /* and get its fg and bg colors */
935 	    GetValues(ind_switches[i].updbut);
936 	    break;
937 	}
938 
939     p = XCreatePixmapFromBitmapData(tool_d, XtWindow(ind_panel),
940 		    (char *) set_bits, UPD_BITS, UPD_BITS, fg, bg, tool_dpth);
941     FirstArg(XtNbitmap, p);
942     SetValues(set_upd);
943     p = XCreatePixmapFromBitmapData(tool_d, XtWindow(ind_panel),
944 		    (char *) clr_bits, UPD_BITS, UPD_BITS, fg, bg, tool_dpth);
945     FirstArg(XtNbitmap, p);
946     SetValues(clr_upd);
947     p = XCreatePixmapFromBitmapData(tool_d, XtWindow(ind_panel),
948 		    (char *) tog_bits, UPD_BITS, UPD_BITS, fg, bg, tool_dpth);
949     FirstArg(XtNbitmap, p);
950     SetValues(tog_upd);
951 
952     XDefineCursor(tool_d, XtWindow(ind_panel), arrow_cursor);
953     update_current_settings();
954 
955     FirstArg(XtNmappedWhenManaged, True);
956     SetValues(ind_panel);
957 
958     /* get the width of the update control panel */
959     FirstArg(XtNwidth, &UPD_CTRL_WD);
960     GetValues(upd_ctrl);
961 
962 }
963 
964 #ifndef XAW3D1_5E
965 /* come here when the mouse passes over a button in the indicator panel */
966 
967 static	Widget ind_balloon_popup = (Widget) 0;
968 static	Widget balloon_label;
969 static	XtIntervalId balloon_id = (XtIntervalId) 0;
970 static	Widget balloon_w;
971 static	XtPointer clos;
972 
973 static void ind_balloon(void);
974 
975 static void
ind_balloon_trigger(Widget widget,XtPointer closure,XEvent * event,Boolean * continue_to_dispatch)976 ind_balloon_trigger(Widget widget, XtPointer closure, XEvent *event, Boolean *continue_to_dispatch)
977 {
978 	if (!appres.showballoons)
979 		return;
980 	balloon_w = widget;
981 	clos = closure;
982 	/* if an old balloon is still up, destroy it */
983 	if ((balloon_id != 0) || (ind_balloon_popup != (Widget) 0)) {
984 		ind_unballoon((Widget) 0, (XtPointer) 0, (XEvent*) 0, (Boolean*) 0);
985 	}
986 	balloon_id = XtAppAddTimeOut(tool_app, appres.balloon_delay,
987 			(XtTimerCallbackProc) ind_balloon, (XtPointer) NULL);
988 }
989 
990 static void
ind_balloon(void)991 ind_balloon(void)
992 {
993 	Position  x, y, appx, appy;
994 	ind_sw_info *isw = (ind_sw_info *) clos;
995 	char	  msg[60];
996 	Widget	  box;
997 
998 	XtTranslateCoords(balloon_w, isw->sw_width+5, 0, &x, &y);
999 	XtTranslateCoords(tool, TOOL_WD, 0, &appx, &appy);
1000 	/* if part of the button is hidden in the scroll area, put the balloon
1001 	   at the right edge of xfig's main window */
1002 	if (x > appx)
1003 		x = appx+2;
1004 
1005 	/* set the position */
1006 	FirstArg(XtNx, x);
1007 	NextArg(XtNy, y);
1008 	ind_balloon_popup = XtCreatePopupShell("ind_balloon_popup",overrideShellWidgetClass,
1009 				tool, Args, ArgCount);
1010 	FirstArg(XtNborderWidth, 0);
1011 	NextArg(XtNhSpace, 0);
1012 	NextArg(XtNvSpace, 0);
1013 	box = XtCreateManagedWidget("box", boxWidgetClass, ind_balloon_popup,
1014 				Args, ArgCount);
1015 	FirstArg(XtNborderWidth, 0);
1016 	sprintf(msg,"%s %s",isw->line1,isw->line2);
1017 	NextArg(XtNlabel, msg);
1018 	balloon_label = XtCreateManagedWidget("label", labelWidgetClass,
1019 				    box, Args, ArgCount);
1020 
1021 	XtPopup(ind_balloon_popup,XtGrabNone);
1022 	XtRemoveTimeOut(balloon_id);
1023 	balloon_id = (XtIntervalId) 0;
1024 }
1025 
1026 /* come here when the mouse leaves a button in the indicator panel */
1027 
1028 static void
ind_unballoon(Widget widget,XtPointer closure,XEvent * event,Boolean * continue_to_dispatch)1029 ind_unballoon(Widget widget, XtPointer closure, XEvent *event, Boolean *continue_to_dispatch)
1030 {
1031     if (balloon_id)
1032 	XtRemoveTimeOut(balloon_id);
1033     balloon_id = (XtIntervalId) 0;
1034     if (ind_balloon_popup != (Widget) 0) {
1035 	XtDestroyWidget(ind_balloon_popup);
1036 	ind_balloon_popup = (Widget) 0;
1037     }
1038 }
1039 #endif /* XAW3D1_5E */
1040 
generate_choice_pixmaps(ind_sw_info * isw)1041 void generate_choice_pixmaps(ind_sw_info *isw)
1042 {
1043     int		    i;
1044     choice_info	   *tmp_choice;
1045 
1046     tmp_choice = isw->choices;
1047     for (i = 0; i < isw->numchoices; tmp_choice++, i++) {
1048 	if (tmp_choice->icon != 0)
1049 	    tmp_choice->pixmap = XCreatePixmapFromBitmapData(tool_d,
1050 				XtWindow(ind_panel),
1051 				tmp_choice->icon->bits,
1052 				tmp_choice->icon->width,
1053 				tmp_choice->icon->height,
1054 				ind_but_fg, ind_but_bg, tool_dpth);
1055     }
1056 }
1057 
update_indpanel(long unsigned int mask)1058 void update_indpanel(long unsigned int mask)
1059 {
1060 #ifdef XAW3D1_5E
1061     char	msg[60];
1062 #endif /* XAW3D1_5E */
1063     register int    i;
1064     register ind_sw_info *isw;
1065 
1066     /*
1067      * We must test for the widgets, as this is called by
1068      * w_cmdpanel.c:refresh_view_menu().
1069      */
1070 
1071 #ifdef XAW3D1_5E
1072     if (upd_ctrl)
1073 	if (appres.showballoons)
1074 	    XawTipEnable(upd_ctrl, upd_sw_info.line1);
1075 	else
1076 	    XawTipDisable(upd_ctrl);
1077     if (upd_ctrl_lab)
1078 	if (appres.showballoons)
1079 	    XawTipEnable(upd_ctrl_lab, upd_sw_info.line1);
1080 	else
1081 	    XawTipDisable(upd_ctrl_lab);
1082     if (set_upd)
1083 	if (appres.showballoons)
1084 	    XawTipEnable(set_upd, upd_set_sw_info.line1);
1085 	else
1086 	    XawTipDisable(set_upd);
1087     if (clr_upd)
1088 	if (appres.showballoons)
1089 	    XawTipEnable(clr_upd, upd_clr_sw_info.line1);
1090 	else
1091 	    XawTipDisable(clr_upd);
1092     if (tog_upd)
1093 	if (appres.showballoons)
1094 	    XawTipEnable(tog_upd, upd_tog_sw_info.line1);
1095 	else
1096 	    XawTipDisable(tog_upd);
1097     for (isw = ind_switches, i = 0; i < NUM_IND_SW; isw++, i++) {
1098 	if (!isw->button)
1099 	    continue;
1100 	if (appres.showballoons) {
1101 	    sprintf(msg, "%s", isw->line1);
1102 	    if (strlen(isw->line2))
1103 		sprintf(msg + strlen(msg), " %s", isw->line2);
1104 	    XawTipEnable(isw->button, msg);
1105 	} else
1106 	    XawTipDisable(isw->button);
1107     }
1108 #endif /* XAW3D1_5E */
1109 
1110     /* only update current mask if user wants to see relevant ind buttons */
1111     if (appres.showallbuttons)
1112 	return;
1113 
1114     if (!ind_box)
1115 	return;
1116 
1117     cur_indmask = mask;
1118     XtUnmanageChild(ind_box);
1119     for (isw = ind_switches, i = 0; i < NUM_IND_SW; isw++, i++) {
1120 	/* show buttons with func=0 (zoom and grid) */
1121 	if ((isw->func == 0) || (isw->func & cur_indmask)) {
1122 	    XtManageChild(isw->formw);
1123 	} else {
1124 	    XtUnmanageChild(isw->formw);
1125 	}
1126     }
1127     { /* fix scrollbar */
1128        Dimension w,h;
1129        FirstArg(XtNwidth, &w);
1130        NextArg(XtNheight, &h);
1131        GetValues(ind_box);
1132        XtMakeResizeRequest(ind_box, w, h+1, NULL,NULL);
1133     }
1134 
1135     XtManageChild(ind_box);
1136 }
1137 
1138 /* come here when a button is pressed in the indicator panel */
1139 
1140 static void
sel_ind_but(Widget widget,XtPointer closure,XEvent * event,Boolean * continue_to_dispatch)1141 sel_ind_but(Widget widget, XtPointer closure, XEvent *event, Boolean *continue_to_dispatch)
1142 {
1143     XButtonEvent xbutton;
1144     ind_sw_info *isw = (ind_sw_info *) closure;
1145 
1146 #ifndef XAW3D1_5E
1147     /* since this command popups a window, destroy the balloon popup now. */
1148     ind_unballoon((Widget) 0, (XtPointer) 0, (XEvent*) 0, (Boolean*) 0);
1149     app_flush();
1150 #endif /* XAW3D1_5E */
1151 
1152     xbutton = event->xbutton;
1153     /* see if wheel mouse */
1154     switch (xbutton.button) {
1155 	case Button4: xbutton.button = Button2;
1156 		      break;
1157 	case Button5: xbutton.button = Button3;
1158 		      break;
1159     }
1160     if ((xbutton.button == Button2)  ||
1161               (xbutton.button == Button3 && xbutton.state & Mod1Mask)) { /* middle button */
1162 	dec_action(isw);
1163     } else if (xbutton.button == Button3) {	/* right button */
1164 	inc_action(isw);
1165     } else {			/* left button */
1166 	if (isw->func == I_FONT)
1167 	    popup_fonts(isw);
1168 	else if (isw->func == I_TEXTFLAGS)
1169 	    popup_flags_panel(isw);
1170 	else if (isw->func == I_ARROWSIZE)
1171 	    popup_arrowsize_panel(isw);
1172 	else if (isw->type == I_IVAL || isw->type == I_FVAL)
1173 	    popup_nval_panel(isw);
1174 	else if (isw->type == I_CHOICE)
1175 	    popup_choice_panel(isw);
1176 	else if (isw->type == I_DIMLINE)
1177 	    popup_dimline_panel(isw);
1178     }
1179 }
1180 
1181 static void
update_string_pixmap(ind_sw_info * isw,char * buf,int xpos,int ypos)1182 update_string_pixmap(ind_sw_info *isw, char *buf, int xpos, int ypos)
1183 {
1184     XDrawImageString(tool_d, isw->pixmap, ind_button_gc,
1185 		     xpos, ypos, buf, strlen(buf));
1186     if (isw->updbut && update_buts_managed)
1187 	XtUnmanageChild(isw->updbut);
1188     /*
1189      * Fool the toolkit by changing the background pixmap to 0 then giving it
1190      * the modified one again.	Otherwise, it sees that the pixmap ID is not
1191      * changed and doesn't actually draw it into the widget window
1192      */
1193     FirstArg(XtNbackgroundPixmap, 0);
1194     SetValues(isw->button);
1195     /* put the pixmap in the widget background */
1196     FirstArg(XtNbackgroundPixmap, isw->pixmap);
1197     SetValues(isw->button);
1198     if (isw->updbut && update_buts_managed)
1199 	XtManageChild(isw->updbut);
1200 }
1201 
1202 static void
update_choice_pixmap(ind_sw_info * isw,int mode)1203 update_choice_pixmap(ind_sw_info *isw, int mode)
1204 {
1205     choice_info	   *tmp_choice;
1206 
1207     if (isw->updbut && update_buts_managed)
1208 	XtUnmanageChild(isw->updbut);
1209     /* put the pixmap in the widget background */
1210     tmp_choice = isw->choices + mode;
1211     XCopyArea(tool_d, tmp_choice->pixmap, isw->pixmap, ind_button_gc,
1212 	      0, 0, tmp_choice->icon->width, tmp_choice->icon->height, 32, 0);
1213     /*
1214      * Fool the toolkit by changing the background pixmap to 0 then giving it
1215      * the modified one again.	Otherwise, it sees that the pixmap ID is not
1216      * changed and doesn't actually draw it into the widget window
1217      */
1218     FirstArg(XtNbackgroundPixmap, 0);
1219     SetValues(isw->button);
1220     /* put the pixmap in the widget background */
1221     FirstArg(XtNbackgroundPixmap, isw->pixmap);
1222     SetValues(isw->button);
1223     if (isw->updbut && update_buts_managed)
1224 	XtManageChild(isw->updbut);
1225 }
1226 
1227 Widget	choice_popup;
1228 static ind_sw_info *choice_i;
1229 static Widget	nval_popup, form, cancel, set;
1230 static Widget	beside, below, newvalue, label;
1231 static Widget	dash_length, dot_gap;
1232 static ind_sw_info *nval_i;
1233 
1234 /* handle arrow sizes settings */
1235 
1236 static Widget   arrow_thick_w, arrow_width_w, arrow_height_w;
1237 static Widget   arrow_mult_thick_w, arrow_mult_width_w, arrow_mult_height_w;
1238 static Widget	a_t_spin, m_t_spin, a_w_spin, m_w_spin, a_h_spin, m_h_spin;
1239 
1240 static void
arrowsize_panel_dismiss(void)1241 arrowsize_panel_dismiss(void)
1242 {
1243     XtDestroyWidget(nval_popup);
1244     XtSetSensitive(nval_i->button, True);
1245 }
1246 
1247 static void
arrowsize_panel_cancel(Widget w,XButtonEvent * ev)1248 arrowsize_panel_cancel(Widget w, XButtonEvent *ev)
1249 {
1250     use_abs_arrowvals = save_use_abs;
1251     arrowsize_panel_dismiss();
1252 }
1253 
1254 static void
arrowsize_panel_set(Widget w,XButtonEvent * ev)1255 arrowsize_panel_set(Widget w, XButtonEvent *ev)
1256 {
1257     cur_arrowwidth = (float) atof(panel_get_value(arrow_width_w));
1258     if (cur_arrowwidth == 0.0)
1259 	    cur_arrowwidth = 1.0;
1260     cur_arrowthick = (float) atof(panel_get_value(arrow_thick_w));
1261     if (cur_arrowthick == 0.0)
1262 	    cur_arrowthick = 1.0;
1263     cur_arrowheight = (float) atof(panel_get_value(arrow_height_w));
1264     if (cur_arrowheight == 0.0)
1265 	    cur_arrowheight = 1.0;
1266     cur_arrow_multwidth = (float) atof(panel_get_value(arrow_mult_width_w));
1267     if (cur_arrow_multwidth == 0.0)
1268 	    cur_arrow_multwidth = 1.0;
1269     cur_arrow_multthick = (float) atof(panel_get_value(arrow_mult_thick_w));
1270     if (cur_arrow_multthick == 0.0)
1271 	    cur_arrow_multthick = 1.0;
1272     cur_arrow_multheight = (float) atof(panel_get_value(arrow_mult_height_w));
1273     if (cur_arrow_multheight == 0.0)
1274 	    cur_arrow_multheight = 1.0;
1275     arrowsize_panel_dismiss();
1276     show_action(nval_i);
1277 }
1278 
1279 static void
set_arrow_size_state(Widget w,XtPointer closure,XtPointer call_data)1280 set_arrow_size_state(Widget w, XtPointer closure, XtPointer call_data)
1281 {
1282     Boolean	    state;
1283     intptr_t	    which;
1284     Pixel	    bg1, bg2, fg1, fg2;
1285 
1286     /* check state of the toggle and set/remove checkmark */
1287     FirstArg(XtNstate, &state);
1288     GetValues(w);
1289 
1290     if (state ) {
1291 	FirstArg(XtNbitmap, check_pm);
1292     } else {
1293 	FirstArg(XtNbitmap, null_check_pm);
1294     }
1295     SetValues(w);
1296 
1297     /* set the sensitivity of the toggle button to the opposite of its state
1298        so that the user must press the other one now */
1299     XtSetSensitive(w, !state);
1300     /* and make the *other* button the opposite state */
1301     if (w==abstoggle)
1302 	XtSetSensitive(multtoggle, state);
1303     else
1304 	XtSetSensitive(abstoggle, state);
1305 
1306     /* which button */
1307     FirstArg(XtNradioData, &which);
1308     GetValues(w);
1309     if (which == 1)		/* "multiple button", invert state */
1310 	state = !state;
1311 
1312     /* set global state */
1313     use_abs_arrowvals = state;
1314 
1315     /* make spinners sensitive or insensitive */
1316     XtSetSensitive(a_t_spin, state);
1317     XtSetSensitive(a_w_spin, state);
1318     XtSetSensitive(a_h_spin, state);
1319 
1320     state = !state;
1321     XtSetSensitive(m_t_spin, state);
1322     XtSetSensitive(m_w_spin, state);
1323     XtSetSensitive(m_h_spin, state);
1324 
1325     /* now make the insensitive ones gray and the sensitive ones their original bg */
1326     bg1 = state? dark_gray_color: arrow_size_bg;
1327     bg2 = state? arrow_size_bg: dark_gray_color;
1328     fg1 = state? lt_gray_color: arrow_size_fg;
1329     fg2 = state? arrow_size_fg: lt_gray_color;
1330 
1331     FirstArg(XtNbackground, bg1);
1332     NextArg(XtNforeground, fg1);
1333     SetValues(arrow_thick_w);
1334     SetValues(arrow_width_w);
1335     SetValues(arrow_height_w);
1336 
1337     FirstArg(XtNbackground, bg2);
1338     NextArg(XtNforeground, fg2);
1339     SetValues(arrow_mult_thick_w);
1340     SetValues(arrow_mult_width_w);
1341     SetValues(arrow_mult_height_w);
1342 }
1343 
1344 /* panel to handle the three arrow sizes (thickness, width and height) */
1345 
popup_arrowsize_panel(ind_sw_info * isw)1346 void popup_arrowsize_panel(ind_sw_info *isw)
1347 {
1348     Position	    x_val, y_val;
1349     Dimension	    width, height;
1350     char	    buf[50];
1351     static Boolean  actions_added=False;
1352     Widget	    abslabel;
1353 
1354     /* save state of abs/mult in case user cancels */
1355     save_use_abs = use_abs_arrowvals;
1356 
1357     nval_i = isw;
1358     XtSetSensitive(nval_i->button, False);
1359 
1360     FirstArg(XtNwidth, &width);
1361     NextArg(XtNheight, &height);
1362     GetValues(tool);
1363     /* position the popup 1/3 in from left and 2/3 down from top */
1364     XtTranslateCoords(tool, (Position) (width / 3), (Position) (2 * height / 3),
1365 		      &x_val, &y_val);
1366 
1367     FirstArg(XtNx, x_val);
1368     NextArg(XtNy, y_val);
1369     NextArg(XtNtitle, "Xfig: Arrow Size Panel");
1370     NextArg(XtNcolormap, tool_cm);
1371 
1372     nval_popup = XtCreatePopupShell("set_nval_panel",
1373 				    transientShellWidgetClass, tool,
1374 				    Args, ArgCount);
1375     /* put in the widget so we don't have to create it next time */
1376     isw->panel = nval_popup;
1377 
1378     XtOverrideTranslations(nval_popup,
1379                        XtParseTranslationTable(nval_translations));
1380     if (!actions_added) {
1381         XtAppAddActions(tool_app, nval_actions, XtNumber(nval_actions));
1382 	actions_added = True;
1383     }
1384     form = XtCreateManagedWidget("arrowsize_form", formWidgetClass, nval_popup, NULL, 0);
1385 
1386     /* label for title - "Arrow Size" */
1387     FirstArg(XtNborderWidth, 0);
1388     NextArg(XtNresizable, True);
1389     NextArg(XtNlabel, "Arrow Size");
1390     NextArg(XtNtop, XtChainTop);
1391     NextArg(XtNbottom, XtChainTop);
1392     NextArg(XtNleft, XtChainLeft);
1393     NextArg(XtNright, XtChainLeft);
1394     label = XtCreateManagedWidget("arrow_size_panel", labelWidgetClass, form, Args, ArgCount);
1395 
1396     /* toggle for using absolute values */
1397     FirstArg(XtNwidth, 20);
1398     NextArg(XtNheight, 20);
1399     NextArg(XtNfromVert, label);
1400     NextArg(XtNinternalWidth, 1);
1401     NextArg(XtNinternalHeight, 1);
1402     NextArg(XtNfont, bold_font);
1403     NextArg(XtNlabel, "  ");
1404     NextArg(XtNbitmap, (use_abs_arrowvals?check_pm:null_check_pm));
1405     NextArg(XtNsensitive, (use_abs_arrowvals?False:True));	/* make opposite button sens */
1406     NextArg(XtNstate, use_abs_arrowvals); /* initial state */
1407     NextArg(XtNradioData, 0);		/* when this is pressed the value is 0 */
1408     NextArg(XtNtop, XtChainTop);
1409     NextArg(XtNbottom, XtChainTop);
1410     NextArg(XtNleft, XtChainLeft);
1411     NextArg(XtNright, XtChainLeft);
1412     abstoggle = XtCreateManagedWidget("abstoggle", toggleWidgetClass, form, Args, ArgCount);
1413     XtAddCallback(abstoggle, XtNcallback, set_arrow_size_state, (XtPointer) NULL);
1414 
1415     /* label - "Absolute Values" */
1416 
1417     FirstArg(XtNborderWidth, 0);
1418     NextArg(XtNfromVert, label);
1419     NextArg(XtNfromHoriz, abstoggle);
1420     NextArg(XtNresizable, True);
1421     NextArg(XtNleft, XtChainLeft);
1422     NextArg(XtNright, XtChainLeft);
1423     NextArg(XtNlabel, "Absolute   \nValues");
1424     NextArg(XtNtop, XtChainTop);
1425     NextArg(XtNbottom, XtChainTop);
1426     NextArg(XtNleft, XtChainLeft);
1427     NextArg(XtNright, XtChainLeft);
1428     abslabel = XtCreateManagedWidget("abslabel", labelWidgetClass, form, Args, ArgCount);
1429 
1430     /* label - "Multiple of Line Width" */
1431 
1432     FirstArg(XtNborderWidth, 0);
1433     NextArg(XtNfromVert, label);
1434     NextArg(XtNfromHoriz, abslabel);
1435     NextArg(XtNhorizDistance, 6);
1436     NextArg(XtNresizable, True);
1437     NextArg(XtNlabel, "Multiple of\nLine Width");
1438     NextArg(XtNtop, XtChainTop);
1439     NextArg(XtNbottom, XtChainTop);
1440     NextArg(XtNleft, XtChainLeft);
1441     NextArg(XtNright, XtChainLeft);
1442     beside = XtCreateManagedWidget("multlabel", labelWidgetClass, form,
1443 				Args, ArgCount);
1444 
1445     /* toggle for using multiple of line width  */
1446     FirstArg(XtNwidth, 20);
1447     NextArg(XtNheight, 20);
1448     NextArg(XtNfromVert, label);
1449     NextArg(XtNfromHoriz, beside);
1450     NextArg(XtNinternalWidth, 1);
1451     NextArg(XtNinternalHeight, 1);
1452     NextArg(XtNfont, bold_font);
1453     NextArg(XtNlabel, "  ");
1454     NextArg(XtNbitmap, (use_abs_arrowvals?null_check_pm:check_pm));
1455     NextArg(XtNsensitive, (use_abs_arrowvals?True:False));	/* make opposite button sens */
1456     NextArg(XtNstate, !use_abs_arrowvals); /* initial state */
1457     NextArg(XtNradioData, 1);		/* when this is pressed the value is 1 */
1458     NextArg(XtNradioGroup, abstoggle);	/* this is the other radio button in the group */
1459     NextArg(XtNtop, XtChainTop);
1460     NextArg(XtNbottom, XtChainTop);
1461     NextArg(XtNleft, XtChainLeft);
1462     NextArg(XtNright, XtChainLeft);
1463     multtoggle = XtCreateManagedWidget("multtoggle", toggleWidgetClass, form,
1464 				Args, ArgCount);
1465     XtAddCallback(multtoggle, XtNcallback, set_arrow_size_state, (XtPointer) NULL);
1466 
1467     /* make arrow thickness label and entries */
1468 
1469     /* make a spinner entry widget for abs values */
1470     sprintf(buf,"%.1f",cur_arrowthick);
1471     a_t_spin = beside = MakeFloatSpinnerEntry(form, &arrow_thick_w, "arrow_thickness",
1472 		abslabel, (Widget) NULL, (XtCallbackProc) 0, buf, 0.1, 10000.0, 1.0, 50);
1473 
1474     FirstArg(XtNfromHoriz, beside);
1475     NextArg(XtNfromVert, abslabel);
1476     NextArg(XtNborderWidth, 0);
1477     NextArg(XtNtop, XtChainTop);
1478     NextArg(XtNbottom, XtChainTop);
1479     NextArg(XtNleft, XtChainLeft);
1480     NextArg(XtNright, XtChainLeft);
1481     beside = XtCreateManagedWidget("Thickness ", labelWidgetClass, form, Args, ArgCount);
1482 
1483     /* make a spinner for Thickness = Multiple of line width */
1484     sprintf(buf,"%.1f",cur_arrow_multthick);
1485     m_t_spin = below = MakeFloatSpinnerEntry(form, &arrow_mult_thick_w, "arrow_mult_thickness",
1486 		abslabel, beside, (XtCallbackProc) 0, buf, 0.1, 10000.0, 1.0, 50);
1487 
1488     /* save the "normal" background so we can switch between that and gray (insensitive) */
1489     FirstArg(XtNbackground, &arrow_size_bg);
1490     NextArg(XtNforeground, &arrow_size_fg);
1491     GetValues(arrow_mult_thick_w);
1492 
1493     /* make arrow width label and entries */
1494 
1495     /* make a spinner entry widget for abs values */
1496     sprintf(buf,"%.1f",cur_arrowwidth);
1497     a_w_spin = beside = MakeFloatSpinnerEntry(form, &arrow_width_w, "arrow_width",
1498 		below, (Widget) NULL, (XtCallbackProc) 0, buf, 0.1, 10000.0, 1.0, 50);
1499 
1500     FirstArg(XtNfromHoriz, beside);
1501     NextArg(XtNfromVert, below);
1502     NextArg(XtNborderWidth, 0);
1503     NextArg(XtNtop, XtChainTop);
1504     NextArg(XtNbottom, XtChainTop);
1505     NextArg(XtNleft, XtChainLeft);
1506     NextArg(XtNright, XtChainLeft);
1507     beside = XtCreateManagedWidget("  Width   ", labelWidgetClass, form, Args, ArgCount);
1508 
1509     /* make a spinner for Width = Multiple of line width */
1510     sprintf(buf,"%.1f",cur_arrow_multwidth);
1511     m_w_spin = below = MakeFloatSpinnerEntry(form, &arrow_mult_width_w, "arrow_mult_width",
1512 		below, beside, (XtCallbackProc) 0, buf, 0.1, 10000.0, 1.0, 50);
1513 
1514     /* make arrow length label and entries */
1515 
1516     /* make a spinner entry widget for abs values */
1517     sprintf(buf,"%.1f",cur_arrowheight);
1518     a_h_spin = beside = MakeFloatSpinnerEntry(form, &arrow_height_w, "arrow_height",
1519 		below, (Widget) NULL, (XtCallbackProc) 0, buf, 0.1, 10000.0, 1.0, 50);
1520 
1521     FirstArg(XtNfromHoriz, beside);
1522     NextArg(XtNfromVert, below);
1523     NextArg(XtNborderWidth, 0);
1524     NextArg(XtNtop, XtChainTop);
1525     NextArg(XtNbottom, XtChainTop);
1526     NextArg(XtNleft, XtChainLeft);
1527     NextArg(XtNright, XtChainLeft);
1528     beside = XtCreateManagedWidget("  Length  ", labelWidgetClass, form, Args, ArgCount);
1529 
1530     /* make a spinner for Height = Multiple of line width */
1531     sprintf(buf,"%.1f",cur_arrow_multheight);
1532     m_h_spin = below = MakeFloatSpinnerEntry(form, &arrow_mult_height_w, "arrow_mult_height",
1533 		below, beside, (XtCallbackProc) 0, buf, 0.1, 10000.0, 1.0, 50);
1534 
1535     /* make spinners sensitive or insensitive */
1536     XtSetSensitive(a_t_spin, use_abs_arrowvals);
1537     XtSetSensitive(a_w_spin, use_abs_arrowvals);
1538     XtSetSensitive(a_h_spin, use_abs_arrowvals);
1539 
1540     XtSetSensitive(m_t_spin, !use_abs_arrowvals);
1541     XtSetSensitive(m_w_spin, !use_abs_arrowvals);
1542     XtSetSensitive(m_h_spin, !use_abs_arrowvals);
1543 
1544     /* set the state of the widgets */
1545     set_arrow_size_state(abstoggle, NULL, NULL);
1546     set_arrow_size_state(multtoggle, NULL, NULL);
1547 
1548     /***************************************/
1549     /* finally, the Set and Cancel buttons */
1550     /***************************************/
1551 
1552     FirstArg(XtNlabel, "Cancel");
1553     NextArg(XtNfromVert, below);
1554     NextArg(XtNborderWidth, INTERNAL_BW);
1555     NextArg(XtNtop, XtChainTop);
1556     NextArg(XtNbottom, XtChainTop);
1557     NextArg(XtNleft, XtChainLeft);
1558     NextArg(XtNright, XtChainLeft);
1559     cancel = XtCreateManagedWidget("cancel", commandWidgetClass,
1560 				   form, Args, ArgCount);
1561     XtAddEventHandler(cancel, ButtonReleaseMask, False,
1562 		      (XtEventHandler) arrowsize_panel_cancel, (XtPointer) NULL);
1563 
1564     FirstArg(XtNlabel, " Set  ");
1565     NextArg(XtNfromVert, below);
1566     NextArg(XtNfromHoriz, cancel);
1567     NextArg(XtNborderWidth, INTERNAL_BW);
1568     NextArg(XtNtop, XtChainTop);
1569     NextArg(XtNbottom, XtChainTop);
1570     NextArg(XtNleft, XtChainLeft);
1571     NextArg(XtNright, XtChainLeft);
1572     set = XtCreateManagedWidget("set", commandWidgetClass,
1573 				form, Args, ArgCount);
1574     XtAddEventHandler(set, ButtonReleaseMask, False,
1575 		      (XtEventHandler) arrowsize_panel_set, (XtPointer) NULL);
1576 
1577     XtPopup(nval_popup, XtGrabExclusive);
1578     /* if the file message window is up add it to the grab */
1579     file_msg_add_grab();
1580     (void) XSetWMProtocols(tool_d, XtWindow(nval_popup), &wm_delete_window, 1);
1581     /* insure that the most recent colormap is installed */
1582     set_cmap(XtWindow(nval_popup));
1583 
1584     XtInstallAccelerators(form, cancel);
1585 }
1586 
1587 /* Update current dash length or dot gap including */
1588 /* the corresponding string value in the indicator panel. */
1589 
1590 /* handle choice settings */
1591 
1592 void
choice_panel_dismiss(void)1593 choice_panel_dismiss(void)
1594 {
1595     XtPopdown(choice_popup);
1596     XtSetSensitive(choice_i->button, True);
1597 }
1598 
1599 static void
choice_panel_cancel(Widget w,XButtonEvent * ev)1600 choice_panel_cancel(Widget w, XButtonEvent *ev)
1601 {
1602     choice_panel_dismiss();
1603 }
1604 
1605 static void
choice_panel_set(Widget w,choice_info * sel_choice,XButtonEvent * ev)1606 choice_panel_set(Widget w, choice_info *sel_choice, XButtonEvent *ev)
1607 {
1608     (*choice_i->i_varadr) = sel_choice->value;
1609     show_action(choice_i);
1610 
1611     /* auxiliary info */
1612     switch (choice_i->func) {
1613       case I_LINESTYLE:
1614 	/* dash length */
1615 	cur_dashlength = (float) atof(panel_get_value(dash_length));
1616 	if (cur_dashlength <= 0.0)
1617 	    cur_dashlength = DEF_DASHLENGTH;
1618 
1619 	/* dot gap */
1620 	cur_dotgap = (float) atof(panel_get_value(dot_gap));
1621 	if (cur_dotgap <= 0.0)
1622 	    cur_dotgap = DEF_DOTGAP;
1623 
1624 	if(cur_linestyle==DASH_LINE || cur_linestyle==DASH_DOT_LINE ||
1625            cur_linestyle==DASH_2_DOTS_LINE ||
1626            cur_linestyle==DASH_3_DOTS_LINE)
1627 	  cur_styleval=cur_dashlength;
1628 	else if(cur_linestyle==DOTTED_LINE)
1629 	  cur_styleval=cur_dotgap;
1630 
1631 	break;
1632     }
1633 
1634     choice_panel_dismiss();
1635 }
1636 
popup_choice_panel(ind_sw_info * isw)1637 void popup_choice_panel(ind_sw_info *isw)
1638 {
1639     Position	    x_val, y_val;
1640     Dimension	    width, height;
1641     char	    buf[50];
1642     choice_info	   *tmp_choice;
1643     Pixmap	    p;
1644     int		    i, count;
1645     static Boolean  actions_added=False;
1646     Widget	    obeside;
1647 
1648     choice_i = isw;
1649     XtSetSensitive(choice_i->button, False);
1650 
1651     /* if already created, just pop it up */
1652     if (isw->panel) {
1653 	choice_popup = isw->panel;
1654 	if (isw->func == I_PEN_COLOR || isw->func == I_FILL_COLOR) {
1655 		/* activate the one the user pressed (pen or fill) */
1656 		pen_fill_activate(isw->func);
1657 		/* and store current pen and fill colors in the panels */
1658 		restore_mixed_colors();
1659 		/* finally, count the number of user colors */
1660 		count_user_colors();
1661 		/* and color the color cell borders */
1662 		color_borders();
1663 		/* make the "delete unused colors" button sensitive if there are user colors */
1664 		if (num_usr_cols != 0)
1665 		    XtSetSensitive(delunusedColors, True);
1666 		else
1667 		    XtSetSensitive(delunusedColors, False);
1668 	} else if (isw->func == I_LINESTYLE) {
1669 		/* update current dash length/dot gap indicators */
1670 		sprintf(buf, "%.1f", cur_dashlength);
1671 		FirstArg(XtNstring, buf);
1672 		SetValues(dash_length);
1673 		sprintf(buf, "%.1f", cur_dotgap);
1674 		FirstArg(XtNstring, buf);
1675 		SetValues(dot_gap);
1676 	}
1677 	if (appres.DEBUG)
1678 	    XtPopup(choice_popup, XtGrabNone);	/* makes debugging easier */
1679 	else
1680 	    XtPopup(choice_popup, XtGrabExclusive);
1681 	/* if the file message window is up add it to the grab */
1682 	file_msg_add_grab();
1683 	/* insure that the most recent colormap is installed */
1684 	set_cmap(XtWindow(isw->panel));
1685 	return;
1686     }
1687 
1688     FirstArg(XtNwidth, &width);
1689     NextArg(XtNheight, &height);
1690     GetValues(tool);
1691     if (isw->func == I_PEN_COLOR || isw->func == I_FILL_COLOR) {
1692         /* initially position the popup 1/3 in from left and 1/5 down from top */
1693         XtTranslateCoords(tool, (Position) (width / 3), (Position) (height / 5),
1694 		      &x_val, &y_val);
1695     } else {
1696         /* initially position the popup 1/3 in from left and 2/3 down from top */
1697         XtTranslateCoords(tool, (Position) (width / 3), (Position) (2 * height / 3),
1698 		      &x_val, &y_val);
1699     }
1700 
1701     FirstArg(XtNx, x_val);
1702     NextArg(XtNy, y_val);
1703     NextArg(XtNresize, False);
1704     NextArg(XtNresizable, False);
1705     /* make a title for the panel */
1706     sprintf(buf,"Xfig: %s %s Panel",isw->line1,isw->line2);
1707     NextArg(XtNtitle, buf);
1708     NextArg(XtNcolormap, tool_cm);
1709 
1710     choice_popup = XtCreatePopupShell("set_choice_panel",
1711 				      transientShellWidgetClass, tool,
1712 				      Args, ArgCount);
1713 
1714     /* put in the widget so we don't have to create it next time */
1715     isw->panel = choice_popup;
1716 
1717     XtOverrideTranslations(choice_popup,
1718                        XtParseTranslationTable(choice_translations));
1719     if (!actions_added) {
1720         XtAppAddActions(tool_app, choice_actions, XtNumber(choice_actions));
1721 	actions_added = True;
1722     }
1723 
1724     form = XtCreateManagedWidget("choice_form", formWidgetClass, choice_popup, NULL, 0);
1725 
1726     /* label first */
1727     FirstArg(XtNborderWidth, 0);
1728     NextArg(XtNtop, XtChainTop);
1729     NextArg(XtNbottom, XtChainTop);
1730     NextArg(XtNleft, XtChainLeft);
1731     NextArg(XtNright, XtChainLeft);
1732     /* color panel? */
1733     if (isw->func == I_PEN_COLOR || isw->func == I_FILL_COLOR) {
1734 	/* yes */
1735 	sprintf(buf, "Colors");
1736     } else {
1737 	/* no, other */
1738 	sprintf(buf, "%s %s", isw->line1, isw->line2);
1739     }
1740     label = XtCreateManagedWidget(buf, labelWidgetClass, form, Args, ArgCount);
1741 
1742     /* create the cancel button here, but only manage it if this is the color panel
1743        (we'll put it at the bottom for the others) */
1744 
1745     FirstArg(XtNlabel, "Cancel");
1746     NextArg(XtNfromVert, label);	/* this will be changed for the non-color panels */
1747     NextArg(XtNresize, False);
1748     NextArg(XtNresizable, False);
1749     NextArg(XtNborderWidth, INTERNAL_BW);
1750     NextArg(XtNtop, XtChainTop);
1751     NextArg(XtNbottom, XtChainTop);
1752     NextArg(XtNleft, XtChainLeft);
1753     NextArg(XtNright, XtChainLeft);
1754     cancel = XtCreateWidget("cancel", commandWidgetClass, form, Args, ArgCount);
1755     XtAddEventHandler(cancel, ButtonReleaseMask, False,
1756 		      (XtEventHandler) choice_panel_cancel, (XtPointer) NULL);
1757 
1758     /* manage it now only if this is the color panel */
1759     if (isw->func == I_PEN_COLOR || isw->func == I_FILL_COLOR)
1760 	XtManageChild(cancel);
1761 
1762     /* colors have the additional "extended color" panel */
1763     if (isw->func == I_PEN_COLOR || isw->func == I_FILL_COLOR) {
1764 	create_color_panel(form,label,cancel,isw);
1765 	/* if this is a color popup button copy the panel id to the other one too */
1766 	/* (e.g. if this is the pen color pop, copy id to fill color panel */
1767 	if (isw->func == I_FILL_COLOR)
1768 	    pen_color_button->panel = isw->panel;
1769 	else if (isw->func == I_PEN_COLOR)
1770 	    fill_color_button->panel = isw->panel;
1771 	return;
1772     }
1773 
1774     tmp_choice = isw->choices;
1775 
1776     for (i = 0; i < isw->numchoices; tmp_choice++, i++) {
1777 	if (isw->func == I_FILLSTYLE) {
1778 	    if (cur_fillcolor == BLACK || cur_fillcolor == WHITE ||
1779 		cur_fillcolor == DEFAULT) {
1780 		    if (i > NUMSHADEPATS && i <= NUMSHADEPATS+NUMTINTPATS)
1781 			continue;		/* skip the tints for black and white */
1782 	    }
1783 	    p = fillstyle_choices[i].pixmap;
1784 	    tmp_choice->value = i-1;		/* fill value = i-1 */
1785 	} else {
1786 	    p = tmp_choice->pixmap;
1787 	}
1788 
1789 	/* check for new row of buttons */
1790 	if (i==0 || count >= isw->sw_per_row) {
1791 	    if (i == 0)
1792 		below = label;
1793 	    else
1794 		below = beside;
1795 	    beside = (Widget) NULL;
1796 	    count = 0;
1797 	}
1798 	/* create a title for the pattern section */
1799 	if (isw->func == I_FILLSTYLE && i == NUMSHADEPATS+NUMTINTPATS+1) {
1800 	    FirstArg(XtNlabel, "Patterns");
1801 	    NextArg(XtNfromVert, obeside);
1802 	    NextArg(XtNborderWidth, 0);
1803 	    NextArg(XtNtop, XtChainTop);
1804 	    NextArg(XtNbottom, XtChainTop);
1805 	    NextArg(XtNleft, XtChainLeft);
1806 	    NextArg(XtNright, XtChainLeft);
1807 	    below = XtCreateManagedWidget("pattern_label", labelWidgetClass,
1808 					form, Args, ArgCount);
1809 	    beside = (Widget) 0;
1810 	    count = 0;
1811 	}
1812 	FirstArg(XtNfromVert, below);
1813 	NextArg(XtNfromHoriz, beside);
1814 	NextArg(XtNbackgroundPixmap, p);
1815 	NextArg(XtNwidth, tmp_choice->icon->width);
1816 	NextArg(XtNheight, tmp_choice->icon->height);
1817 	NextArg(XtNresize, False);
1818 	NextArg(XtNresizable, False);
1819 	NextArg(XtNborderWidth, INTERNAL_BW);
1820 	NextArg(XtNtop, XtChainTop);
1821 	NextArg(XtNbottom, XtChainTop);
1822 	NextArg(XtNleft, XtChainLeft);
1823 	NextArg(XtNright, XtChainLeft);
1824 	beside = XtCreateManagedWidget((String)" ", commandWidgetClass,
1825 				       form, Args, ArgCount);
1826 	obeside = beside;
1827 	XtAddEventHandler(beside, ButtonReleaseMask, False,
1828 			  (XtEventHandler) choice_panel_set, (XtPointer) tmp_choice);
1829 	count++;
1830     }
1831     below = beside;
1832 
1833     /* auxiliary info */
1834     switch (isw->func) {
1835       case I_LINESTYLE:
1836 	/* dash length */
1837 	FirstArg(XtNfromVert, beside);
1838 	NextArg(XtNborderWidth, 0);
1839 	NextArg(XtNlabel, "Default dash length");
1840 	NextArg(XtNtop, XtChainTop);
1841 	NextArg(XtNbottom, XtChainTop);
1842 	NextArg(XtNleft, XtChainLeft);
1843 	NextArg(XtNright, XtChainLeft);
1844 	label = XtCreateManagedWidget("default_dash_length",
1845 				    labelWidgetClass, form, Args, ArgCount);
1846 
1847 	sprintf(buf, "%.1f", cur_dashlength);
1848 	below = MakeFloatSpinnerEntry(form, &dash_length, "dash_length", beside, label,
1849 			(XtCallbackProc) 0, buf, 0.0, 10000.0, 1.0, 50);
1850 
1851 	/* enable mousefun kbd icon */
1852 	XtAugmentTranslations(dash_length,
1853 		XtParseTranslationTable(kbd_translations));
1854 
1855 	/* dot gap */
1856 	FirstArg(XtNfromVert, below);
1857 	NextArg(XtNborderWidth, 0);
1858 	NextArg(XtNlabel, "    Default dot gap");
1859 	NextArg(XtNtop, XtChainTop);
1860 	NextArg(XtNbottom, XtChainTop);
1861 	NextArg(XtNleft, XtChainLeft);
1862 	NextArg(XtNright, XtChainLeft);
1863 	label = XtCreateManagedWidget("default_dot_gap",
1864 				    labelWidgetClass, form, Args, ArgCount);
1865 
1866 	sprintf(buf, "%.1f", cur_dotgap);
1867 	below = MakeFloatSpinnerEntry(form, &dot_gap, "dot_gap", below, label,
1868 			(XtCallbackProc) 0, buf, 0.0, 10000.0, 1.0, 50);
1869 
1870 	/* enable mousefun kbd icon */
1871 	XtAugmentTranslations(dot_gap,
1872 		XtParseTranslationTable(kbd_translations));
1873 	break;
1874     }
1875 
1876     /* now position the cancel button below the last button created and manage it */
1877     FirstArg(XtNfromVert, below);
1878     SetValues(cancel);
1879     XtManageChild(cancel);
1880 
1881     if (appres.DEBUG)
1882 	XtPopup(choice_popup, XtGrabNone);	/* makes debugging easier */
1883     else
1884         XtPopup(choice_popup, XtGrabExclusive);
1885     /* if the file message window is up add it to the grab */
1886     file_msg_add_grab();
1887     (void) XSetWMProtocols(tool_d, XtWindow(choice_popup), &wm_delete_window, 1);
1888     /* insure that the most recent colormap is installed */
1889     set_cmap(XtWindow(choice_popup));
1890 
1891     XtInstallAccelerators(form, cancel);
1892 }
1893 
1894 /* handle text flag settings */
1895 
1896 static intptr_t hidden_text_flag, special_text_flag, rigid_text_flag;
1897 static Widget   hidden_text_panel, rigid_text_panel, special_text_panel;
1898 
1899 static void
flags_panel_dismiss(void)1900 flags_panel_dismiss(void)
1901 {
1902     XtDestroyWidget(nval_popup);
1903     XtSetSensitive(nval_i->button, True);
1904 }
1905 
1906 static void
flags_panel_cancel(Widget w,XButtonEvent * ev)1907 flags_panel_cancel(Widget w, XButtonEvent *ev)
1908 {
1909     flags_panel_dismiss();
1910 }
1911 
1912 static void
flags_panel_set(Widget w,XButtonEvent * ev)1913 flags_panel_set(Widget w, XButtonEvent *ev)
1914 {
1915     if (hidden_text_flag)
1916 	cur_textflags |= HIDDEN_TEXT;
1917     else
1918 	cur_textflags &= ~HIDDEN_TEXT;
1919     if (special_text_flag)
1920 	cur_textflags |= SPECIAL_TEXT;
1921     else
1922 	cur_textflags &= ~SPECIAL_TEXT;
1923     if (rigid_text_flag)
1924 	cur_textflags |= RIGID_TEXT;
1925     else
1926 	cur_textflags &= ~RIGID_TEXT;
1927     flags_panel_dismiss();
1928     show_action(nval_i);
1929 }
1930 
1931 static void
hidden_text_select(Widget w,XtPointer new_hidden_text,XtPointer call_data)1932 hidden_text_select(Widget w, XtPointer new_hidden_text, XtPointer call_data)
1933 {
1934     FirstArg(XtNlabel, XtName(w));
1935     SetValues(hidden_text_panel);
1936     hidden_text_flag = (intptr_t) new_hidden_text;
1937     if (hidden_text_flag)
1938 	put_msg("Text will be displayed as hidden");
1939     else
1940 	put_msg("Text will be displayed normally");
1941 }
1942 
1943 static void
rigid_text_select(Widget w,XtPointer new_rigid_text,XtPointer call_data)1944 rigid_text_select(Widget w, XtPointer new_rigid_text, XtPointer call_data)
1945 {
1946     FirstArg(XtNlabel, XtName(w));
1947     SetValues(rigid_text_panel);
1948     rigid_text_flag = (intptr_t) new_rigid_text;
1949     if (rigid_text_flag)
1950 	put_msg("Text in compound group will not scale with compound");
1951     else
1952 	put_msg("Text in compound group will scale with compound");
1953 }
1954 
1955 static void
special_text_select(Widget w,XtPointer new_special_text,XtPointer call_data)1956 special_text_select(Widget w, XtPointer new_special_text, XtPointer call_data)
1957 {
1958     FirstArg(XtNlabel, XtName(w));
1959     SetValues(special_text_panel);
1960     special_text_flag = (intptr_t) new_special_text;
1961     if (special_text_flag)
1962 	put_msg("Text may contain characters with special meaning for TeX/LaTeX");
1963     else
1964 	put_msg("Characters special to TeX will be quoted during print/export");
1965 }
1966 
popup_flags_panel(ind_sw_info * isw)1967 void popup_flags_panel(ind_sw_info *isw)
1968 {
1969     Position	    x_val, y_val;
1970     Dimension	    width, height;
1971     char	    buf[50];
1972     static Boolean  actions_added=False;
1973     static char    *hidden_text_items[] = {
1974     "Normal", "Hidden"};
1975     static char    *rigid_text_items[] = {
1976     "Normal", "Rigid "};
1977     static char    *special_text_items[] = {
1978     "Normal", "TeX   "};
1979 
1980     nval_i = isw;
1981     XtSetSensitive(nval_i->button, False);
1982 
1983     rigid_text_flag = (intptr_t) ((cur_textflags & RIGID_TEXT) ? 1 : 0);
1984     special_text_flag = (intptr_t) ((cur_textflags & SPECIAL_TEXT) ? 1 : 0);
1985     hidden_text_flag = (intptr_t) ((cur_textflags & HIDDEN_TEXT) ? 1 : 0);
1986 
1987     FirstArg(XtNwidth, &width);
1988     NextArg(XtNheight, &height);
1989     GetValues(tool);
1990     /* position the popup 1/3 in from left and 2/3 down from top */
1991     XtTranslateCoords(tool, (Position) (width / 3), (Position) (2 * height / 3),
1992 		      &x_val, &y_val);
1993 
1994     FirstArg(XtNx, x_val);
1995     NextArg(XtNy, y_val);
1996     NextArg(XtNtitle, "Xfig: Text Flags Panel");
1997     NextArg(XtNcolormap, tool_cm);
1998 
1999     nval_popup = XtCreatePopupShell("set_nval_panel",
2000 				    transientShellWidgetClass, tool,
2001 				    Args, ArgCount);
2002     /* put in the widget so we don't have to create it next time */
2003     isw->panel = nval_popup;
2004 
2005     XtOverrideTranslations(nval_popup,
2006                        XtParseTranslationTable(nval_translations));
2007     if (!actions_added) {
2008         XtAppAddActions(tool_app, nval_actions, XtNumber(nval_actions));
2009 	actions_added = True;
2010     }
2011     form = XtCreateManagedWidget("flags_form", formWidgetClass, nval_popup, NULL, 0);
2012 
2013     FirstArg(XtNborderWidth, 0);
2014     sprintf(buf, "%s %s", isw->line1, isw->line2);
2015     NextArg(XtNtop, XtChainTop);
2016     NextArg(XtNbottom, XtChainTop);
2017     NextArg(XtNleft, XtChainLeft);
2018     NextArg(XtNright, XtChainLeft);
2019     label = XtCreateManagedWidget(buf, labelWidgetClass, form, Args, ArgCount);
2020 
2021     /* make hidden text menu */
2022 
2023     FirstArg(XtNfromVert, label);
2024     NextArg(XtNborderWidth, 0);
2025     NextArg(XtNtop, XtChainTop);
2026     NextArg(XtNbottom, XtChainTop);
2027     NextArg(XtNleft, XtChainLeft);
2028     NextArg(XtNright, XtChainLeft);
2029     beside = XtCreateManagedWidget("Hidden Flag", labelWidgetClass,
2030                                    form, Args, ArgCount);
2031 
2032     FirstArg(XtNfromVert, label);
2033     NextArg(XtNfromHoriz, beside);
2034     NextArg(XtNleftBitmap, menu_arrow);	/* use menu arrow for pull-down */
2035     NextArg(XtNtop, XtChainTop);
2036     NextArg(XtNbottom, XtChainTop);
2037     NextArg(XtNleft, XtChainLeft);
2038     NextArg(XtNright, XtChainLeft);
2039     hidden_text_panel = XtCreateManagedWidget(
2040                  hidden_text_items[hidden_text_flag], menuButtonWidgetClass,
2041                                               form, Args, ArgCount);
2042     below = hidden_text_panel;
2043     make_pulldown_menu(hidden_text_items,
2044                                        XtNumber(hidden_text_items), -1, "",
2045                                      hidden_text_panel, hidden_text_select);
2046 
2047     /* make rigid text menu */
2048 
2049     FirstArg(XtNfromVert, below);
2050     NextArg(XtNborderWidth, 0);
2051     NextArg(XtNtop, XtChainTop);
2052     NextArg(XtNbottom, XtChainTop);
2053     NextArg(XtNleft, XtChainLeft);
2054     NextArg(XtNright, XtChainLeft);
2055     beside = XtCreateManagedWidget(" Rigid Flag", labelWidgetClass,
2056                                    form, Args, ArgCount);
2057 
2058     FirstArg(XtNfromVert, below);
2059     NextArg(XtNfromHoriz, beside);
2060     NextArg(XtNleftBitmap, menu_arrow);	/* use menu arrow for pull-down */
2061     NextArg(XtNtop, XtChainTop);
2062     NextArg(XtNbottom, XtChainTop);
2063     NextArg(XtNleft, XtChainLeft);
2064     NextArg(XtNright, XtChainLeft);
2065     rigid_text_panel = XtCreateManagedWidget(
2066                    rigid_text_items[rigid_text_flag], menuButtonWidgetClass,
2067                                              form, Args, ArgCount);
2068     below = rigid_text_panel;
2069     make_pulldown_menu(rigid_text_items,
2070                                       XtNumber(rigid_text_items), -1, "",
2071                                       rigid_text_panel, rigid_text_select);
2072 
2073     /* make special text menu */
2074 
2075     FirstArg(XtNfromVert, below);
2076     NextArg(XtNborderWidth, 0);
2077     NextArg(XtNtop, XtChainTop);
2078     NextArg(XtNbottom, XtChainTop);
2079     NextArg(XtNleft, XtChainLeft);
2080     NextArg(XtNright, XtChainLeft);
2081     beside = XtCreateManagedWidget("   TeX Flag", labelWidgetClass,
2082                                    form, Args, ArgCount);
2083 
2084     FirstArg(XtNfromVert, below);
2085     NextArg(XtNfromHoriz, beside);
2086     NextArg(XtNleftBitmap, menu_arrow);	/* use menu arrow for pull-down */
2087     NextArg(XtNtop, XtChainTop);
2088     NextArg(XtNbottom, XtChainTop);
2089     NextArg(XtNleft, XtChainLeft);
2090     NextArg(XtNright, XtChainLeft);
2091     special_text_panel = XtCreateManagedWidget(
2092                                       special_text_items[special_text_flag],
2093                                menuButtonWidgetClass, form, Args, ArgCount);
2094     below = special_text_panel;
2095     make_pulldown_menu(special_text_items,
2096                                         XtNumber(special_text_items), -1, "",
2097                                    special_text_panel, special_text_select);
2098 
2099     FirstArg(XtNlabel, "Cancel");
2100     NextArg(XtNfromVert, below);
2101     NextArg(XtNborderWidth, INTERNAL_BW);
2102     NextArg(XtNtop, XtChainTop);
2103     NextArg(XtNbottom, XtChainTop);
2104     NextArg(XtNleft, XtChainLeft);
2105     NextArg(XtNright, XtChainLeft);
2106     cancel = XtCreateManagedWidget("cancel", commandWidgetClass,
2107 				   form, Args, ArgCount);
2108     XtAddEventHandler(cancel, ButtonReleaseMask, False,
2109 		      (XtEventHandler) flags_panel_cancel, (XtPointer) NULL);
2110 
2111     FirstArg(XtNlabel, " Set  ");
2112     NextArg(XtNfromVert, below);
2113     NextArg(XtNfromHoriz, cancel);
2114     NextArg(XtNborderWidth, INTERNAL_BW);
2115     NextArg(XtNtop, XtChainTop);
2116     NextArg(XtNbottom, XtChainTop);
2117     NextArg(XtNleft, XtChainLeft);
2118     NextArg(XtNright, XtChainLeft);
2119     set = XtCreateManagedWidget("set", commandWidgetClass,
2120 				form, Args, ArgCount);
2121     XtAddEventHandler(set, ButtonReleaseMask, False,
2122 		      (XtEventHandler) flags_panel_set, (XtPointer) NULL);
2123 
2124     XtPopup(nval_popup, XtGrabExclusive);
2125     /* if the file message window is up add it to the grab */
2126     file_msg_add_grab();
2127     (void) XSetWMProtocols(tool_d, XtWindow(nval_popup), &wm_delete_window, 1);
2128     /* insure that the most recent colormap is installed */
2129     set_cmap(XtWindow(nval_popup));
2130 
2131     XtInstallAccelerators(form, cancel);
2132 }
2133 
2134 /* handle integer and floating point settings */
2135 
2136 static void
nval_panel_dismiss(void)2137 nval_panel_dismiss(void)
2138 {
2139     XtDestroyWidget(nval_popup);
2140     XtSetSensitive(nval_i->button, True);
2141 }
2142 
2143 Widget zoomcheck;
2144 
2145 static void
toggle_int_zoom(Widget w,XtPointer closure,XtPointer call_data)2146 toggle_int_zoom(Widget w, XtPointer closure, XtPointer call_data)
2147 {
2148     integral_zoom = !integral_zoom;
2149     if ( integral_zoom ) {
2150 	FirstArg(XtNbitmap, check_pm);
2151     } else {
2152 	FirstArg(XtNbitmap, null_check_pm);
2153     }
2154     SetValues(zoomcheck);
2155 }
2156 
2157 static void
nval_panel_cancel(Widget w,XButtonEvent * ev)2158 nval_panel_cancel(Widget w, XButtonEvent *ev)
2159 {
2160     nval_panel_dismiss();
2161 }
2162 
2163 static void
nval_panel_set(Widget w,XButtonEvent * ev)2164 nval_panel_set(Widget w, XButtonEvent *ev)
2165 {
2166     int		    new_i_value;
2167     float	    new_f_value;
2168 
2169     if (nval_i->type == I_IVAL) {
2170 	new_i_value = atoi(panel_get_value(newvalue));
2171 	(*nval_i->i_varadr) = new_i_value;
2172     } else {
2173 	new_f_value = (float) atof(panel_get_value(newvalue));
2174 	(*nval_i->f_varadr) = new_f_value;
2175     }
2176     nval_panel_dismiss();
2177     show_action(nval_i);
2178 }
2179 
2180 
popup_nval_panel(ind_sw_info * isw)2181 void popup_nval_panel(ind_sw_info *isw)
2182 {
2183     Position	    x_val, y_val;
2184     Dimension	    width, height;
2185     char	    buf[50];
2186     static Boolean  actions_added=False;
2187     int		    vdist;
2188 
2189     nval_i = isw;
2190     XtSetSensitive(nval_i->button, False);
2191 
2192     FirstArg(XtNwidth, &width);
2193     NextArg(XtNheight, &height);
2194     GetValues(tool);
2195     /* position the popup 1/3 in from left and 2/3 down from top */
2196     XtTranslateCoords(tool, (Position) (width / 3), (Position) (2 * height / 3),
2197 		      &x_val, &y_val);
2198 
2199     FirstArg(XtNx, x_val);
2200     NextArg(XtNy, y_val);
2201     /* make a title for the panel */
2202     sprintf(buf,"Xfig: %s %s Panel",isw->line1,isw->line2);
2203     NextArg(XtNtitle, buf);
2204     NextArg(XtNcolormap, tool_cm);
2205 
2206     nval_popup = XtCreatePopupShell("set_nval_panel",
2207 				    transientShellWidgetClass, tool,
2208 				    Args, ArgCount);
2209 
2210     XtOverrideTranslations(nval_popup,
2211                        XtParseTranslationTable(nval_translations));
2212     if (!actions_added) {
2213         XtAppAddActions(tool_app, nval_actions, XtNumber(nval_actions));
2214 	actions_added = True;
2215     }
2216     form = XtCreateManagedWidget("nval_form", formWidgetClass, nval_popup, NULL, 0);
2217 
2218     FirstArg(XtNborderWidth, 0);
2219     sprintf(buf, "%s %s", isw->line1, isw->line2);
2220     NextArg(XtNtop, XtChainTop);
2221     NextArg(XtNbottom, XtChainTop);
2222     NextArg(XtNleft, XtChainLeft);
2223     NextArg(XtNright, XtChainLeft);
2224     label = XtCreateManagedWidget(buf, labelWidgetClass, form, Args, ArgCount);
2225 
2226     FirstArg(XtNfromVert, label);
2227     NextArg(XtNborderWidth, 0);
2228     NextArg(XtNlabel, "Value");
2229     NextArg(XtNtop, XtChainTop);
2230     NextArg(XtNbottom, XtChainTop);
2231     NextArg(XtNleft, XtChainLeft);
2232     NextArg(XtNright, XtChainLeft);
2233     newvalue = XtCreateManagedWidget("valueLabel", labelWidgetClass,
2234 				     form, Args, ArgCount);
2235     /* int or float? */
2236     if (isw->type == I_IVAL) {
2237 	sprintf(buf, "%d", (*isw->i_varadr));
2238 	below = MakeIntSpinnerEntry(form, &newvalue, "value", label, newvalue,
2239 		(XtCallbackProc) 0, buf, isw->min, isw->max, (int)isw->inc, 45);
2240     } else {
2241 	sprintf(buf, "%.2f", (*isw->f_varadr));
2242 	below = MakeFloatSpinnerEntry(form, &newvalue, "value", label, newvalue,
2243 		(XtCallbackProc) 0, buf, (float)isw->min, (float)isw->max, isw->inc, 55);
2244     }
2245     /* focus keyboard on text widget */
2246     XtSetKeyboardFocus(form, newvalue);
2247 
2248     /* set value on carriage return */
2249     XtOverrideTranslations(newvalue, XtParseTranslationTable(set_translations));
2250     /* enable mousefun kbd icon */
2251     XtAugmentTranslations(newvalue, XtParseTranslationTable(kbd_translations));
2252 
2253     /* for the zoom panel, make an "integer zoom checkbutton" and
2254        a "Fit to canvas" button */
2255 
2256     vdist = 4;
2257     if (strcasecmp(isw->line1,"zoom")==0) {
2258 	FirstArg(XtNlabel, " Fit to canvas ");
2259 	NextArg(XtNfromVert, below);
2260 	NextArg(XtNvertDistance, 10);
2261 	NextArg(XtNborderWidth, INTERNAL_BW);
2262 	NextArg(XtNtop, XtChainTop);
2263 	NextArg(XtNbottom, XtChainTop);
2264 	NextArg(XtNleft, XtChainLeft);
2265 	NextArg(XtNright, XtChainLeft);
2266 	below = XtCreateManagedWidget("fit_to_canvas", commandWidgetClass,
2267 				   form, Args, ArgCount);
2268 	XtAddCallback(below, XtNcallback, zoom_to_fit, (XtPointer) NULL);
2269 
2270 	FirstArg(XtNwidth, 20);
2271 	NextArg(XtNheight, 20);
2272 	NextArg(XtNfont, bold_font);
2273 	NextArg(XtNfromVert, below);
2274 	if ( integral_zoom ) {
2275 	    NextArg(XtNbitmap, check_pm);
2276 	} else {
2277 	    NextArg(XtNbitmap, null_check_pm);
2278 	}
2279 	NextArg(XtNlabel, " ");
2280 	NextArg(XtNstate, integral_zoom);
2281 	NextArg(XtNinternalWidth, 1);
2282 	NextArg(XtNinternalHeight, 1);
2283 	NextArg(XtNtop, XtChainTop);
2284 	NextArg(XtNbottom, XtChainTop);
2285 	NextArg(XtNleft, XtChainLeft);
2286 	NextArg(XtNright, XtChainLeft);
2287 	zoomcheck = XtCreateManagedWidget("intzoom_check", toggleWidgetClass,
2288 				form, Args, ArgCount);
2289 
2290 	FirstArg(XtNlabel,"Integer zoom");
2291 	NextArg(XtNheight, 18);
2292 	NextArg(XtNfromHoriz, zoomcheck);
2293 	NextArg(XtNhorizDistance, 2);
2294 	NextArg(XtNfromVert, below);
2295 	NextArg(XtNtop, XtChainTop);
2296 	NextArg(XtNbottom, XtChainTop);
2297 	NextArg(XtNleft, XtChainLeft);
2298 	NextArg(XtNright, XtChainLeft);
2299 	below = XtCreateManagedWidget("intzoom_label", labelWidgetClass,
2300 				form, Args, ArgCount);
2301 	XtAddCallback(zoomcheck, XtNcallback, toggle_int_zoom, (XtPointer) NULL);
2302 	/* make more space before the set/cancel buttons */
2303 	vdist = 10;
2304     }
2305 
2306     FirstArg(XtNlabel, "Cancel");
2307     NextArg(XtNfromVert, below);
2308     NextArg(XtNvertDistance, vdist);
2309     NextArg(XtNborderWidth, INTERNAL_BW);
2310     NextArg(XtNtop, XtChainTop);
2311     NextArg(XtNbottom, XtChainTop);
2312     NextArg(XtNleft, XtChainLeft);
2313     NextArg(XtNright, XtChainLeft);
2314     cancel = XtCreateManagedWidget("cancel", commandWidgetClass,
2315 				   form, Args, ArgCount);
2316     XtAddEventHandler(cancel, ButtonReleaseMask, False,
2317 		      (XtEventHandler) nval_panel_cancel, (XtPointer) NULL);
2318 
2319     FirstArg(XtNlabel, " Set  ");
2320     NextArg(XtNfromVert, below);
2321     NextArg(XtNfromHoriz, cancel);
2322     NextArg(XtNvertDistance, vdist);
2323     NextArg(XtNborderWidth, INTERNAL_BW);
2324     NextArg(XtNtop, XtChainTop);
2325     NextArg(XtNbottom, XtChainTop);
2326     NextArg(XtNleft, XtChainLeft);
2327     NextArg(XtNright, XtChainLeft);
2328     set = XtCreateManagedWidget("set", commandWidgetClass,
2329 				form, Args, ArgCount);
2330     XtAddEventHandler(set, ButtonReleaseMask, False,
2331 		      (XtEventHandler) nval_panel_set, (XtPointer) NULL);
2332 
2333     XtPopup(nval_popup, XtGrabExclusive);
2334     /* if the file message window is up add it to the grab */
2335     file_msg_add_grab();
2336     (void) XSetWMProtocols(tool_d, XtWindow(nval_popup), &wm_delete_window, 1);
2337     /* insure that the most recent colormap is installed */
2338     set_cmap(XtWindow(nval_popup));
2339 
2340     XtInstallAccelerators(form, cancel);
2341 }
2342 
2343 /**********************/
2344 /*   DIMENSION LINE   */
2345 /**********************/
2346 
2347 static int	dimline_thick;
2348 static int	dimline_style;
2349 static int	dimline_color;
2350 static int	dimline_leftarrow;
2351 static int	dimline_rightarrow;
2352 static float	dimline_arrowlength;
2353 static float	dimline_arrowwidth;
2354 static Boolean	dimline_ticks;
2355 static int	dimline_tickthick;
2356 static int	dimline_boxthick;
2357 static int	dimline_boxcolor;
2358 static int	dimline_textcolor;
2359 static int	dimline_font;
2360 static int	dimline_fontsize;
2361 static int	dimline_psflag;
2362 static Boolean	dimline_fixed, dimline_actual;
2363 static int	dim_ps_font, dim_latex_font;
2364 static int	dimline_prec;
2365 
2366 static int	savecur_dimline_thick;
2367 static int	savecur_dimline_style;
2368 static int	savecur_dimline_color;
2369 static int	savecur_dimline_leftarrow;
2370 static int	savecur_dimline_rightarrow;
2371 static float	savecur_dimline_arrowlength;
2372 static float	savecur_dimline_arrowwidth;
2373 static Boolean	savecur_dimline_ticks;
2374 static int	savecur_dimline_tickthick;
2375 static int	savecur_dimline_boxthick;
2376 static int	savecur_dimline_boxcolor;
2377 static int	savecur_dimline_textcolor;
2378 static int	savecur_dimline_font;
2379 static int	savecur_dimline_fontsize;
2380 static int	savecur_dimline_psflag;
2381 static Boolean	savecur_dimline_fixed;
2382 static int	savecur_dimline_prec;
2383 
2384 static Widget	line_thick_w, arrow_width_w, arrow_length_w;
2385 static Widget	tick_thick_w;
2386 static Widget	box_thick_w, font_size_w, dimline_style_panel;
2387 static Widget	left_arrow_type_panel, right_arrow_type_panel;
2388 static Widget	font_button;
2389 static Pixmap	dimline_examp_pixmap = (Pixmap) 0;
2390 static Widget	exampline;
2391 static Widget	fixed_chk, actual_chk;
2392 static Widget	dimline_precw;
2393 
2394 static void	left_arrow_type_select(Widget w, XtPointer new_type, XtPointer call_data);
2395 static void	right_arrow_type_select(Widget w, XtPointer new_type, XtPointer call_data);
2396 static void	dimline_font_popup(Widget w, XtPointer user_data, XtPointer call_data);
2397 static void	dimline_set_font_image(Widget widget);
2398 static void	set_fixed_text(Widget w, XtPointer fixed, XtPointer dum);
2399 static void	set_actual_text(Widget w, XtPointer actual, XtPointer dum);
2400 static void     dimline_panel_preview(Widget w, XtPointer user_data, XtPointer call_data);
2401 
2402 
2403 static void	line_color_select(Widget w, XtPointer new_color, XtPointer call_data);
2404 static Widget	line_color_button, line_color_panel;
2405 
2406 static void	box_color_select(Widget w, XtPointer new_color, XtPointer call_data);
2407 static Widget	box_color_button, box_color_panel;
2408 
2409 static void	text_color_select(Widget w, XtPointer new_color, XtPointer call_data);
2410 static Widget	text_color_button, text_color_panel;
2411 
2412 /* length of example dimension line for IP and SI units */
2413 
2414 #define DIMLINE_IP_LENGTH 3.75
2415 #define DIMLINE_SI_LENGTH 9.5
2416 #define DIMLINE_PIXMAP_WIDTH (int)(max2(DIMLINE_IP_LENGTH*DISPLAY_PIX_PER_INCH, \
2417 					DIMLINE_SI_LENGTH*DISPLAY_PIX_PER_INCH/2.54) + 10)
2418 #define DIMLINE_PIXMAP_HEIGHT 40
2419 
popup_dimline_panel(ind_sw_info * isw)2420 void popup_dimline_panel(ind_sw_info *isw)
2421 {
2422     Position	    x_val, y_val;
2423     Dimension	    width, height;
2424     Widget	    lineform, arrowform, boxform, tickform, textform, stringform;
2425     static Boolean  actions_added=False;
2426 
2427     choice_i = isw;
2428     XtSetSensitive(choice_i->button, False);
2429 
2430     /* get current settings for dimension lines */
2431     dimline_thick = cur_dimline_thick;
2432     dimline_style = cur_dimline_style;
2433     dimline_color = cur_dimline_color;
2434     dimline_leftarrow = cur_dimline_leftarrow;
2435     dimline_rightarrow = cur_dimline_rightarrow;
2436     dimline_arrowlength = cur_dimline_arrowlength;
2437     dimline_arrowwidth = cur_dimline_arrowwidth;
2438     dimline_ticks = cur_dimline_ticks;
2439     dimline_tickthick = cur_dimline_tickthick;
2440     dimline_boxthick = cur_dimline_boxthick;
2441     dimline_boxcolor = cur_dimline_boxcolor;
2442     dimline_textcolor = cur_dimline_textcolor;
2443     dimline_font = cur_dimline_font;
2444     dimline_fontsize = cur_dimline_fontsize;
2445     dimline_psflag = cur_dimline_psflag;
2446     dimline_fixed = cur_dimline_fixed;
2447     dimline_actual = !dimline_fixed;
2448     dimline_prec = cur_dimline_prec;
2449 
2450     FirstArg(XtNwidth, &width);
2451     NextArg(XtNheight, &height);
2452     GetValues(tool);
2453     /* initially position the popup 1/3 in from left and 1/4 down from top */
2454     XtTranslateCoords(tool, (Position) (width / 3), (Position) (height / 4),
2455 		      &x_val, &y_val);
2456 
2457     FirstArg(XtNx, x_val);
2458     NextArg(XtNy, y_val);
2459     NextArg(XtNresize, False);
2460     NextArg(XtNresizable, False);
2461     NextArg(XtNtitle, "Xfig: Dimension Line Settings");
2462     NextArg(XtNcolormap, tool_cm);
2463 
2464     choice_popup = XtCreatePopupShell("set_dimline_panel",
2465 				      transientShellWidgetClass, tool,
2466 				      Args, ArgCount);
2467 
2468     /* put in the widget so we don't have to create it next time */
2469     isw->panel = choice_popup;
2470 
2471     /* the main form */
2472     form = XtCreateManagedWidget("dimline_form", formWidgetClass, choice_popup, NULL, 0);
2473 
2474     /* label for title - "Dimension Line Settings" */
2475     FirstArg(XtNborderWidth, 0);
2476     NextArg(XtNresizable, True);
2477     NextArg(XtNlabel, "Dimension Line Settings");
2478     NextArg(XtNtop, XtChainTop);
2479     NextArg(XtNbottom, XtChainTop);
2480     NextArg(XtNleft, XtChainLeft);
2481     NextArg(XtNright, XtChainLeft);
2482     below = XtCreateManagedWidget("dimension_line_panel", labelWidgetClass,
2483 				form, Args, ArgCount);
2484 
2485     /* make an example line that shows current settings as a label */
2486 
2487     /* make a pixmap to draw it into */
2488     if (dimline_examp_pixmap == (Pixmap) 0)
2489 	dimline_examp_pixmap = XCreatePixmap(tool_d, canvas_win,
2490 					DIMLINE_PIXMAP_WIDTH, DIMLINE_PIXMAP_HEIGHT, tool_dpth);
2491     /* clear it */
2492     XFillRectangle(tool_d, dimline_examp_pixmap, ind_blank_gc, 0, 0,
2493 	       DIMLINE_PIXMAP_WIDTH, 30);
2494 
2495     /* now make the label widget to display the pixmap */
2496     FirstArg(XtNfromVert, below);
2497     NextArg(XtNborderWidth, 0);
2498     NextArg(XtNwidth, DIMLINE_PIXMAP_WIDTH);
2499     NextArg(XtNheight, 30);
2500     NextArg(XtNtop, XtChainTop);
2501     NextArg(XtNbottom, XtChainTop);
2502     NextArg(XtNleft, XtChainLeft);
2503     NextArg(XtNright, XtChainLeft);
2504     exampline = XtCreateManagedWidget("", labelWidgetClass,
2505 				    form, Args, ArgCount);
2506     draw_cur_dimline();		/* this draws it into dimline_examp_pixmap */
2507 
2508     /******************************/
2509     /* frame for Line information */
2510     /******************************/
2511 
2512     FirstArg(XtNborderWidth, 1);
2513     NextArg(XtNfromVert, exampline);
2514     NextArg(XtNtop, XtChainTop);
2515     NextArg(XtNbottom, XtChainTop);
2516     NextArg(XtNleft, XtChainLeft);
2517     NextArg(XtNright, XtChainLeft);
2518     lineform = XtCreateManagedWidget("lineform", formWidgetClass, form, Args, ArgCount);
2519 
2520     /* "Line" label */
2521     FirstArg(XtNlabel, "Line");
2522     below = XtCreateManagedWidget("dimension_line_panel", labelWidgetClass,
2523 				    lineform, Args, ArgCount);
2524 
2525     /* thickness label */
2526     FirstArg(XtNlabel, "Thickness");
2527     NextArg(XtNborderWidth, 0);
2528     NextArg(XtNfromVert, below);
2529     NextArg(XtNhorizDistance, 4);
2530     beside = XtCreateManagedWidget("thickness_label", labelWidgetClass,
2531 				    lineform, Args, ArgCount);
2532     /* thickness spinner */
2533     sprintf(indbuf,"%d",dimline_thick);
2534     beside = MakeIntSpinnerEntry(lineform, &line_thick_w, "line_thickness",
2535 		below, beside, dimline_panel_preview, indbuf, 0, MAX_LINE_WIDTH, 1, 30);
2536 
2537     below = beside;
2538 
2539     /* Style label */
2540     FirstArg(XtNlabel, "Style    ");
2541     NextArg(XtNborderWidth, 0);
2542     NextArg(XtNfromVert, below);
2543     NextArg(XtNvertDistance, 4);
2544     NextArg(XtNhorizDistance, 4);
2545     beside = XtCreateManagedWidget("style_label", labelWidgetClass,
2546 				    lineform, Args, ArgCount);
2547 
2548     FirstArg(XtNfromVert, below);
2549     NextArg(XtNfromHoriz, beside);
2550     NextArg(XtNbitmap, linestyle_pixmaps[dimline_style]);
2551     dimline_style_panel = XtCreateManagedWidget("dimline_style", menuButtonWidgetClass,
2552 				    lineform, Args, ArgCount);
2553     below = dimline_style_panel;
2554     make_pulldown_menu_images(linestyle_choices, NUM_LINESTYLE_TYPES,
2555 		linestyle_pixmaps, NULL, dimline_style_panel, dimline_style_select);
2556 
2557     (void) color_selection_panel("Color    ","line_color", "Line color", lineform, below, beside,
2558 			&line_color_button, &line_color_panel, dimline_color,
2559 			line_color_select);
2560 
2561     /*************************/
2562     /* now form for Box info */
2563     /*************************/
2564 
2565     FirstArg(XtNborderWidth, 1);
2566     NextArg(XtNfromVert, lineform);
2567     NextArg(XtNvertDistance, 4);
2568     NextArg(XtNtop, XtChainTop);
2569     NextArg(XtNbottom, XtChainTop);
2570     NextArg(XtNleft, XtChainLeft);
2571     NextArg(XtNright, XtChainLeft);
2572     boxform = XtCreateManagedWidget("boxform", formWidgetClass, form, Args, ArgCount);
2573 
2574     /* "Box" label */
2575     FirstArg(XtNlabel, "Box");
2576     below = XtCreateManagedWidget("box_label", labelWidgetClass,
2577 				    boxform, Args, ArgCount);
2578 
2579     /* Thickness label */
2580     FirstArg(XtNlabel, "Thickness");
2581     NextArg(XtNborderWidth, 0);
2582     NextArg(XtNfromVert, below);
2583     NextArg(XtNhorizDistance, 4);
2584     beside = XtCreateManagedWidget("box_thickness_label", labelWidgetClass,
2585 				    boxform, Args, ArgCount);
2586     /* thickness spinner */
2587     sprintf(indbuf,"%d",dimline_boxthick);
2588     beside = MakeIntSpinnerEntry(boxform, &box_thick_w, "box_line_thickness",
2589 		below, beside, dimline_panel_preview, indbuf, 0, MAX_LINE_WIDTH, 1, 30);
2590 
2591     below = beside;
2592 
2593     (void) color_selection_panel("Color    ","box_color", "Box color", boxform, below, beside,
2594 			&box_color_button, &box_color_panel, dimline_boxcolor,
2595 			box_color_select);
2596 
2597     /********************************/
2598     /* now frame for Arrowhead info */
2599     /********************************/
2600 
2601     FirstArg(XtNborderWidth, 1);
2602     NextArg(XtNfromVert, exampline);
2603     NextArg(XtNvertDistance, 4);
2604     NextArg(XtNfromHoriz, lineform);
2605     NextArg(XtNhorizDistance, 4);
2606     NextArg(XtNtop, XtChainTop);
2607     NextArg(XtNbottom, XtChainTop);
2608     NextArg(XtNleft, XtChainLeft);
2609     NextArg(XtNright, XtChainLeft);
2610     arrowform = XtCreateManagedWidget("arrowform", formWidgetClass, form, Args, ArgCount);
2611 
2612     /* "Arrows" label */
2613     FirstArg(XtNlabel, "Arrows");
2614     below = XtCreateManagedWidget("arrow_label", labelWidgetClass,
2615 				    arrowform, Args, ArgCount);
2616 
2617     /* Types label */
2618     FirstArg(XtNlabel, "Types");
2619     NextArg(XtNborderWidth, 0);
2620     NextArg(XtNfromVert, below);
2621     NextArg(XtNhorizDistance, 4);
2622     beside = XtCreateManagedWidget("types_arrow_label", labelWidgetClass,
2623 				    arrowform, Args, ArgCount);
2624 
2625     /* Left arrow menu button */
2626     FirstArg(XtNfromVert, below);
2627     NextArg(XtNfromHoriz, beside);
2628     NextArg(XtNlabel, "");
2629     NextArg(XtNinternalWidth, 0);
2630     NextArg(XtNinternalHeight, 0);
2631     NextArg(XtNbitmap, arrow_pixmaps[dimline_leftarrow+1]);
2632     left_arrow_type_panel = XtCreateManagedWidget("Arrowtype",
2633 				    menuButtonWidgetClass,
2634 				    arrowform, Args, ArgCount);
2635     beside = left_arrow_type_panel;
2636 
2637     /* make pulldown menu with arrow type images */
2638 
2639     make_pulldown_menu_images(dim_arrowtype_choices,
2640 		NUM_DIM_ARROWTYPE_CHOICES, arrow_pixmaps, NULL,
2641 		left_arrow_type_panel, left_arrow_type_select);
2642 
2643     /* Right arrow menu button */
2644     FirstArg(XtNfromVert, below);
2645     NextArg(XtNfromHoriz, beside);
2646     NextArg(XtNlabel, "");
2647     NextArg(XtNinternalWidth, 0);
2648     NextArg(XtNinternalHeight, 0);
2649     NextArg(XtNbitmap, arrow_pixmaps[dimline_rightarrow+1]);
2650     right_arrow_type_panel = XtCreateManagedWidget("Arrowtype",
2651 				    menuButtonWidgetClass,
2652 				    arrowform, Args, ArgCount);
2653     below = right_arrow_type_panel;
2654 
2655     /* make pulldown menu with arrow type images */
2656     make_pulldown_menu_images(dim_arrowtype_choices,
2657 		NUM_DIM_ARROWTYPE_CHOICES, arrow_pixmaps, NULL,
2658 		right_arrow_type_panel, right_arrow_type_select);
2659 
2660     /* Length label */
2661     FirstArg(XtNlabel, "Length");
2662     NextArg(XtNborderWidth, 0);
2663     NextArg(XtNfromVert, below);
2664     NextArg(XtNvertDistance, 6);
2665     NextArg(XtNhorizDistance, 4);
2666     beside = XtCreateManagedWidget("arrow_length_label", labelWidgetClass,
2667 				    arrowform, Args, ArgCount);
2668     /* length spinner */
2669     sprintf(indbuf,"%.1f",dimline_arrowlength);
2670     beside = MakeFloatSpinnerEntry(arrowform, &arrow_length_w, "arrow_length",
2671 		below, beside, dimline_panel_preview, indbuf, 0.1, 200.0, 1.0, 50);
2672 
2673     below = beside;
2674 
2675     /* Width label */
2676     FirstArg(XtNlabel, "Width ");
2677     NextArg(XtNborderWidth, 0);
2678     NextArg(XtNfromVert, below);
2679     NextArg(XtNhorizDistance, 4);
2680     beside = XtCreateManagedWidget("arrow_width_label", labelWidgetClass,
2681 				    arrowform, Args, ArgCount);
2682     /* width spinner */
2683     sprintf(indbuf,"%.1f",dimline_arrowwidth);
2684     beside = MakeFloatSpinnerEntry(arrowform, &arrow_width_w, "arrow_width",
2685 		below, beside, dimline_panel_preview, indbuf, 0.1, 200.0, 1.0, 50);
2686 
2687     /****************************/
2688     /* now frame for Ticks info */
2689     /****************************/
2690 
2691     FirstArg(XtNborderWidth, 1);
2692     NextArg(XtNfromVert, lineform);
2693     NextArg(XtNvertDistance, 4);
2694     NextArg(XtNfromHoriz, boxform);
2695     NextArg(XtNhorizDistance, 4);
2696     NextArg(XtNtop, XtChainTop);
2697     NextArg(XtNbottom, XtChainTop);
2698     NextArg(XtNleft, XtChainLeft);
2699     NextArg(XtNright, XtChainLeft);
2700     tickform = XtCreateManagedWidget("tickform", formWidgetClass, form, Args, ArgCount);
2701 
2702     /* "Ticks" label */
2703     FirstArg(XtNlabel, "Ticks");
2704     below = XtCreateManagedWidget("ticks_label", labelWidgetClass,
2705 				    tickform, Args, ArgCount);
2706 
2707     /* "Ticks" checkbutton */
2708     below = CreateCheckbutton("Show ticks", "ticks", tickform, below, (Widget) NULL,
2709 				MANAGE, LARGE_CHK, &dimline_ticks,
2710 				dimline_panel_preview, (Widget *) NULL);
2711 
2712     /* Tick Thickness label */
2713     FirstArg(XtNlabel, "Thickness");
2714     NextArg(XtNborderWidth, 0);
2715     NextArg(XtNfromVert, below);
2716     NextArg(XtNhorizDistance, 4);
2717     beside = XtCreateManagedWidget("tick_thickness_label", labelWidgetClass,
2718 				    tickform, Args, ArgCount);
2719     /* thickness spinner */
2720     sprintf(indbuf,"%d",dimline_tickthick);
2721     (void) MakeIntSpinnerEntry(tickform, &tick_thick_w, "tick_line_thickness",
2722 		below, beside, dimline_panel_preview, indbuf, 0, MAX_LINE_WIDTH, 1, 28);
2723 
2724     /***************************/
2725     /* now frame for Text info */
2726     /***************************/
2727 
2728     FirstArg(XtNborderWidth, 1);
2729     NextArg(XtNfromVert, boxform);
2730     NextArg(XtNvertDistance, 4);
2731     NextArg(XtNtop, XtChainTop);
2732     NextArg(XtNbottom, XtChainTop);
2733     NextArg(XtNleft, XtChainLeft);
2734     NextArg(XtNright, XtChainLeft);
2735     textform = XtCreateManagedWidget("textform", formWidgetClass, form, Args, ArgCount);
2736 
2737     /* "Text" label */
2738     FirstArg(XtNlabel, "Text");
2739     below = XtCreateManagedWidget("text_label", labelWidgetClass,
2740 				    textform, Args, ArgCount);
2741 
2742     /* Font label */
2743     FirstArg(XtNlabel, "Font ");
2744     NextArg(XtNborderWidth, 0);
2745     NextArg(XtNfromVert, below);
2746     NextArg(XtNhorizDistance, 4);
2747     beside = XtCreateManagedWidget("font_label", labelWidgetClass,
2748 				    textform, Args, ArgCount);
2749     /* make the popup font menu */
2750     FirstArg(XtNfromVert, below);
2751     NextArg(XtNvertDistance, 2);
2752     NextArg(XtNfromHoriz, beside);
2753     NextArg(XtNwidth, MAX_FONTIMAGE_WIDTH);
2754     NextArg(XtNinternalWidth, 2);
2755     NextArg(XtNbitmap, dimline_psflag?
2756 			psfont_menu_bitmaps[dimline_font + 1] :
2757 			latexfont_menu_bitmaps[dimline_font]);
2758     font_button = XtCreateManagedWidget("font", commandWidgetClass, textform, Args, ArgCount);
2759     XtAddCallback(font_button, XtNcallback, dimline_font_popup, (XtPointer) NULL);
2760 
2761     below = font_button;
2762 
2763     /* Size label */
2764     FirstArg(XtNlabel, "Size ");
2765     NextArg(XtNborderWidth, 0);
2766     NextArg(XtNfromVert, below);
2767     NextArg(XtNvertDistance, 4);
2768     NextArg(XtNhorizDistance, 4);
2769     beside = XtCreateManagedWidget("font_size_label", labelWidgetClass,
2770 				    textform, Args, ArgCount);
2771     /* size spinner */
2772     sprintf(indbuf,"%d",dimline_fontsize);
2773     beside = MakeIntSpinnerEntry(textform, &font_size_w, "font_size",
2774 		below, beside, dimline_panel_preview, indbuf,
2775 		MIN_FONT_SIZE, MAX_FONT_SIZE, 1, 30);
2776 
2777     below = beside;
2778 
2779     below = color_selection_panel("Color","text_color", "Text color", textform, below, beside,
2780 			&text_color_button, &text_color_panel, dimline_textcolor,
2781 			text_color_select);
2782 
2783     /* String label */
2784     FirstArg(XtNlabel, "String");
2785     NextArg(XtNborderWidth, 0);
2786     NextArg(XtNfromVert, below);
2787     NextArg(XtNvertDistance, 6);
2788     NextArg(XtNhorizDistance, 4);
2789     below = XtCreateManagedWidget("string_label", labelWidgetClass,
2790 				    textform, Args, ArgCount);
2791 
2792     /* make a borderless form so that we may shift the checkboxes a little */
2793     FirstArg(XtNborderWidth, 0);
2794     NextArg(XtNfromVert, below);
2795     NextArg(XtNvertDistance, 2);
2796     NextArg(XtNhorizDistance, 6);
2797     NextArg(XtNtop, XtChainTop);
2798     NextArg(XtNbottom, XtChainTop);
2799     NextArg(XtNleft, XtChainLeft);
2800     NextArg(XtNright, XtChainLeft);
2801     stringform = XtCreateManagedWidget("stringform", formWidgetClass, textform, Args, ArgCount);
2802 
2803     /* Actual dimension text checkbutton */
2804     below = CreateCheckbutton("Actual dimension shown               ", "actual_chk", stringform,
2805 		(Widget) NULL, (Widget) NULL, MANAGE, LARGE_CHK, &dimline_actual,
2806 		(XtCallbackProc) set_actual_text, &actual_chk);
2807 
2808     /* Decimal places label */
2809     FirstArg(XtNlabel, "Decimal places");
2810     NextArg(XtNborderWidth, 0);
2811     NextArg(XtNfromVert, below);
2812     NextArg(XtNhorizDistance, 26);
2813     beside = XtCreateManagedWidget("precision_label", labelWidgetClass,
2814 				    stringform, Args, ArgCount);
2815     /* number of decimal places spinner */
2816     sprintf(indbuf,"%d",dimline_prec);
2817     below = MakeIntSpinnerEntry(stringform, &dimline_precw, "precision",
2818 		below, beside, dimline_panel_preview, indbuf,
2819 		0, 10, 1, 30);
2820 
2821     /* Fixed text checkbutton */
2822     below = CreateCheckbutton("User defined text (not actual length)", "fixed_chk", stringform,
2823 		below, (Widget) NULL, MANAGE, LARGE_CHK, &dimline_fixed,
2824 		(XtCallbackProc) set_fixed_text, &fixed_chk);
2825 
2826     /* make the checkbox NOT checked sensitive and vice versa */
2827     XtSetSensitive(actual_chk, dimline_fixed);
2828     XtSetSensitive(fixed_chk, !dimline_fixed);
2829 
2830     /***************************************/
2831     /* finally, the Set and Cancel buttons */
2832     /***************************************/
2833 
2834     FirstArg(XtNlabel, "Cancel");
2835     NextArg(XtNfromVert, textform);
2836     NextArg(XtNborderWidth, INTERNAL_BW);
2837     NextArg(XtNtop, XtChainTop);
2838     NextArg(XtNbottom, XtChainTop);
2839     NextArg(XtNleft, XtChainLeft);
2840     NextArg(XtNright, XtChainLeft);
2841     cancel = XtCreateManagedWidget("cancel", commandWidgetClass,
2842 				   form, Args, ArgCount);
2843     XtAddEventHandler(cancel, ButtonReleaseMask, False,
2844 		      (XtEventHandler) choice_panel_dismiss, (XtPointer) NULL);
2845 
2846     FirstArg(XtNlabel, " Ok  ");
2847     NextArg(XtNfromVert, textform);
2848     NextArg(XtNfromHoriz, cancel);
2849     NextArg(XtNhorizDistance, 10);
2850     NextArg(XtNborderWidth, INTERNAL_BW);
2851     NextArg(XtNtop, XtChainTop);
2852     NextArg(XtNbottom, XtChainTop);
2853     NextArg(XtNleft, XtChainLeft);
2854     NextArg(XtNright, XtChainLeft);
2855     set = XtCreateManagedWidget("ok", commandWidgetClass,
2856 				form, Args, ArgCount);
2857     XtAddEventHandler(set, ButtonReleaseMask, False,
2858 		      (XtEventHandler) dimline_panel_ok, (XtPointer) NULL);
2859 
2860     XtOverrideTranslations(choice_popup,
2861                        XtParseTranslationTable(dimline_translations));
2862     if (!actions_added) {
2863         XtAppAddActions(tool_app, dimline_actions, XtNumber(dimline_actions));
2864 	actions_added = True;
2865     }
2866 
2867     if (appres.DEBUG)
2868 	XtPopup(choice_popup, XtGrabNone);	/* makes debugging easier */
2869     else
2870         XtPopup(choice_popup, XtGrabExclusive);
2871     /* if the file message window is up add it to the grab */
2872     file_msg_add_grab();
2873     (void) XSetWMProtocols(tool_d, XtWindow(choice_popup), &wm_delete_window, 1);
2874     /* insure that the most recent colormap is installed */
2875     set_cmap(XtWindow(choice_popup));
2876 
2877     XtInstallAccelerators(form, cancel);
2878 }
2879 
2880 static void
line_color_select(Widget w,XtPointer client_data,XtPointer call_data)2881 line_color_select(Widget w, XtPointer client_data, XtPointer call_data)
2882 {
2883 	ptr_int	new_color = {client_data};
2884 
2885     dimline_color = (Color) new_color.val;
2886     color_select(line_color_button, dimline_color);
2887     if (line_color_panel) {
2888 	XtPopdown(line_color_panel);
2889 	dimline_panel_preview(NULL,NULL,NULL);
2890     }
2891 }
2892 
2893 static void
box_color_select(Widget w,XtPointer client_data,XtPointer call_data)2894 box_color_select(Widget w, XtPointer client_data, XtPointer call_data)
2895 {
2896 	ptr_int	new_color = {client_data};
2897 
2898     dimline_boxcolor = (Color) new_color.val;
2899     color_select(box_color_button, dimline_boxcolor);
2900     if (box_color_panel) {
2901 	XtPopdown(box_color_panel);
2902 	dimline_panel_preview(NULL,NULL,NULL);
2903     }
2904 }
2905 
2906 static void
text_color_select(Widget w,XtPointer client_data,XtPointer call_data)2907 text_color_select(Widget w, XtPointer client_data, XtPointer call_data)
2908 {
2909 	ptr_int	new_color = {client_data};
2910 
2911     dimline_textcolor = (Color) new_color.val;
2912     color_select(text_color_button, dimline_textcolor);
2913     if (text_color_panel) {
2914 	XtPopdown(text_color_panel);
2915 	dimline_panel_preview(NULL,NULL,NULL);
2916     }
2917 }
2918 
2919 static void
set_fixed_text(Widget w,XtPointer fixed,XtPointer dum)2920 set_fixed_text(Widget w, XtPointer fixed, XtPointer dum)
2921 {
2922     Boolean	   *fixed_text = (Boolean *) fixed;
2923 
2924     dimline_fixed = *fixed_text;
2925     /* make this checkbox insensitive so the user will have to check the other one */
2926     XtSetSensitive(w, False);
2927     /* and make the other sensitive */
2928     XtSetSensitive(actual_chk, True);
2929     /* toggle other checkbox now */
2930     toggle_checkbutton(actual_chk, (XtPointer) &dimline_actual, (XtPointer) 0);
2931     dimline_panel_preview(NULL,NULL,NULL);
2932 }
2933 
2934 static void
set_actual_text(Widget w,XtPointer actual,XtPointer dum)2935 set_actual_text(Widget w, XtPointer actual, XtPointer dum)
2936 {
2937     Boolean	   *actual_text = (Boolean *) actual;
2938 
2939     dimline_actual = *actual_text;
2940     /* make this checkbox insensitive so the user will have to check the other one */
2941     XtSetSensitive(w, False);
2942     /* and make the other sensitive */
2943     XtSetSensitive(fixed_chk, True);
2944     /* toggle other checkbox now */
2945     toggle_checkbutton(fixed_chk, (XtPointer) &dimline_fixed, (XtPointer) 0);
2946     dimline_panel_preview(NULL,NULL,NULL);
2947 }
2948 
draw_cur_dimline(void)2949 void draw_cur_dimline(void)
2950 {
2951     F_line	*line, *tick1, *tick2, *poly;
2952     F_compound	*dimline_example;
2953     F_point	*point;
2954     Boolean	save_showlen, save_shownums;
2955 
2956     /* make the a dimension line */
2957     line = create_line();
2958     /* we'll fill in some parms - create_dimension_line() will do the rest */
2959     line->type = T_POLYLINE;
2960     line->fill_color = DEFAULT;
2961     line->cap_style = CAP_BUTT;
2962     line->join_style = JOIN_MITER;
2963     line->pen_style = DEFAULT;
2964     point = create_point();
2965     point->x = 75;
2966     point->y = 275;
2967     line->points = point;
2968     /* make it 3-3/4 inches long */
2969     append_point((int)((appres.INCHES? DIMLINE_IP_LENGTH*PIX_PER_INCH:
2970 				       DIMLINE_SI_LENGTH*PIX_PER_CM)+75), 275, &point);
2971     /* make a dimension line from that line */
2972     dimline_example = create_dimension_line(line, False);
2973 
2974     /* clear it */
2975     XFillRectangle(tool_d, dimline_examp_pixmap, ind_blank_gc, 0, 0,
2976 	       DIMLINE_PIXMAP_WIDTH, DIMLINE_PIXMAP_HEIGHT);
2977 
2978     /* temporarily turn off any "show line lengths" or "show vertex numbers" */
2979     save_showlen = appres.showlengths;
2980     save_shownums = appres.shownums;
2981     appres.showlengths = appres.shownums = False;
2982 
2983     /* now draw it into our pixmap */
2984     canvas_win = (Window) dimline_examp_pixmap;
2985     preview_in_progress = True;
2986     /* locate the line components of the dimension line */
2987     dimline_components(dimline_example, &line, &tick1, &tick2, &poly);
2988     draw_line(line,PAINT);
2989     if (tick1)
2990 	draw_line(tick1,PAINT);
2991     if (tick2)
2992 	draw_line(tick2,PAINT);
2993     draw_line(poly,PAINT);
2994     draw_text(dimline_example->texts,PAINT);
2995 
2996     /* restore the canvas */
2997     canvas_win = main_canvas;
2998     /* and the showlengths and shownums settings */
2999     appres.showlengths = save_showlen;
3000     appres.shownums = save_shownums;
3001     preview_in_progress = False;
3002 
3003     /* fool the toolkit... you know the drill by now */
3004     XtUnmanageChild(exampline);
3005     FirstArg(XtNbitmap, (Pixmap) 0);
3006     SetValues(exampline);
3007     FirstArg(XtNbitmap, dimline_examp_pixmap);
3008     SetValues(exampline);
3009     XtManageChild(exampline);
3010     /* finally, free the dimline */
3011     free_compound(&dimline_example);
3012 }
3013 
3014 static void
dimline_style_select(Widget w,XtPointer new_style,XtPointer call_data)3015 dimline_style_select(Widget w, XtPointer new_style, XtPointer call_data)
3016 {
3017     choice_info	    *choice;
3018 
3019     choice = (choice_info *) new_style;
3020     FirstArg(XtNbitmap, choice->pixmap);
3021     SetValues(dimline_style_panel);
3022 
3023     dimline_style = choice->value;
3024     dimline_panel_preview(NULL,NULL,NULL);
3025 }
3026 
3027 static void
left_arrow_type_select(Widget w,XtPointer new_type,XtPointer call_data)3028 left_arrow_type_select(Widget w, XtPointer new_type, XtPointer call_data)
3029 {
3030     choice_info	   *choice = (choice_info*) new_type;
3031 
3032     FirstArg(XtNbitmap, arrow_pixmaps[choice->value+1]);
3033     SetValues(left_arrow_type_panel);
3034 
3035     dimline_leftarrow = choice->value;
3036     dimline_panel_preview(NULL,NULL,NULL);
3037 }
3038 
3039 static void
right_arrow_type_select(Widget w,XtPointer new_type,XtPointer call_data)3040 right_arrow_type_select(Widget w, XtPointer new_type, XtPointer call_data)
3041 {
3042     choice_info	   *choice = (choice_info*) new_type;
3043 
3044     FirstArg(XtNbitmap, arrow_pixmaps[choice->value+1]);
3045     SetValues(right_arrow_type_panel);
3046 
3047     dimline_rightarrow = choice->value;
3048     dimline_panel_preview(NULL,NULL,NULL);
3049 }
3050 
3051 /* come here when user presses font menu button */
3052 
3053 static void
dimline_font_popup(Widget w,XtPointer user_data,XtPointer call_data)3054 dimline_font_popup(Widget w, XtPointer user_data, XtPointer call_data)
3055 {
3056     fontpane_popup(&dim_ps_font, &dim_latex_font, &dimline_psflag,
3057 		   dimline_set_font_image, font_button);
3058 }
3059 
3060 static void
dimline_set_font_image(Widget widget)3061 dimline_set_font_image(Widget widget)
3062 {
3063     dimline_font = dimline_psflag? dim_ps_font: dim_latex_font;
3064     FirstArg(XtNbitmap, dimline_psflag ?
3065 	     psfont_menu_bitmaps[dimline_font + 1] :
3066 	     latexfont_menu_bitmaps[dimline_font]);
3067     SetValues(widget);
3068     dimline_panel_preview(NULL,NULL,NULL);
3069 }
3070 
3071 /* Dimension line preview */
3072 
3073 static void
dimline_panel_preview(Widget w,XtPointer new_type,XtPointer call_data)3074 dimline_panel_preview(Widget w, XtPointer new_type, XtPointer call_data)
3075 {
3076     /* save current global settings */
3077     savecur_dimline_thick = cur_dimline_thick;
3078     savecur_dimline_style = cur_dimline_style;
3079     savecur_dimline_color = cur_dimline_color;
3080     savecur_dimline_leftarrow = cur_dimline_leftarrow;
3081     savecur_dimline_rightarrow = cur_dimline_rightarrow;
3082     savecur_dimline_arrowlength = cur_dimline_arrowlength;
3083     savecur_dimline_arrowwidth = cur_dimline_arrowwidth;
3084     savecur_dimline_ticks = cur_dimline_ticks;
3085     savecur_dimline_tickthick = cur_dimline_tickthick;
3086     savecur_dimline_boxthick = cur_dimline_boxthick;
3087     savecur_dimline_boxcolor = cur_dimline_boxcolor;
3088     savecur_dimline_textcolor = cur_dimline_textcolor;
3089     savecur_dimline_font = cur_dimline_font;
3090     savecur_dimline_fontsize = cur_dimline_fontsize;
3091     savecur_dimline_psflag = cur_dimline_psflag;
3092     savecur_dimline_fixed = cur_dimline_fixed;
3093     savecur_dimline_prec = cur_dimline_prec;
3094 
3095     /* get current values from spinners */
3096     get_dimline_values();
3097 
3098     /* just update the example dimension line pixmap */
3099     draw_cur_dimline();
3100 
3101     /* restore current global settings */
3102     cur_dimline_thick = savecur_dimline_thick;
3103     cur_dimline_style = savecur_dimline_style;
3104     cur_dimline_color = savecur_dimline_color;
3105     cur_dimline_leftarrow = savecur_dimline_leftarrow;
3106     cur_dimline_rightarrow = savecur_dimline_rightarrow;
3107     cur_dimline_arrowlength = savecur_dimline_arrowlength;
3108     cur_dimline_arrowwidth = savecur_dimline_arrowwidth;
3109     cur_dimline_ticks = savecur_dimline_ticks;
3110     cur_dimline_tickthick = savecur_dimline_tickthick;
3111     cur_dimline_boxthick = savecur_dimline_boxthick;
3112     cur_dimline_boxcolor = savecur_dimline_boxcolor;
3113     cur_dimline_textcolor = savecur_dimline_textcolor;
3114     cur_dimline_font = savecur_dimline_font;
3115     cur_dimline_fontsize = savecur_dimline_fontsize;
3116     cur_dimline_psflag = savecur_dimline_psflag;
3117     cur_dimline_fixed = savecur_dimline_fixed;
3118     cur_dimline_prec = savecur_dimline_prec;
3119 }
3120 
3121 /* Dimension line "Ok" button callback */
3122 
3123 static void
dimline_panel_ok(Widget w,XButtonEvent * ev)3124 dimline_panel_ok(Widget w, XButtonEvent *ev)
3125 {
3126     get_dimline_values();
3127     show_dimline(choice_i);
3128     dimline_panel_cancel(w, ev);
3129 }
3130 
3131 /* Dimension line "Cancel" button callback */
3132 
3133 static void
dimline_panel_cancel(Widget w,XButtonEvent * ev)3134 dimline_panel_cancel(Widget w, XButtonEvent *ev)
3135 {
3136     XtDestroyWidget(choice_popup);
3137     line_color_panel = (Widget) 0;
3138     box_color_panel = (Widget) 0;
3139     text_color_panel = (Widget) 0;
3140     XtSetSensitive(choice_i->button, True);
3141 }
3142 
3143 /* copy new settings for dimension lines to global */
3144 
get_dimline_values(void)3145 void get_dimline_values(void)
3146 {
3147     cur_dimline_thick = atoi(panel_get_value(line_thick_w));
3148     cur_dimline_style = dimline_style;
3149     cur_dimline_color = dimline_color;
3150     cur_dimline_leftarrow = dimline_leftarrow;
3151     cur_dimline_rightarrow = dimline_rightarrow;
3152     cur_dimline_arrowlength = atof(panel_get_value(arrow_length_w));
3153     cur_dimline_arrowwidth = atof(panel_get_value(arrow_width_w));
3154     cur_dimline_ticks = dimline_ticks;
3155     cur_dimline_tickthick = atoi(panel_get_value(tick_thick_w));
3156     cur_dimline_boxthick = atoi(panel_get_value(box_thick_w));
3157     cur_dimline_boxcolor = dimline_boxcolor;
3158     cur_dimline_textcolor = dimline_textcolor;
3159     cur_dimline_font = dimline_font;
3160     cur_dimline_fontsize = atoi(panel_get_value(font_size_w));
3161     cur_dimline_psflag = dimline_psflag;
3162     cur_dimline_fixed = dimline_fixed;
3163     cur_dimline_prec = atoi(panel_get_value(dimline_precw));
3164 }
3165 
3166 /********************************************************
3167 
3168 	commands to change indicator settings
3169 
3170 ********************************************************/
3171 
update_current_settings(void)3172 void update_current_settings(void)
3173 {
3174     int		    i;
3175     ind_sw_info	   *isw;
3176 
3177     for (i = 0; i < NUM_IND_SW; ++i) {
3178 	isw = &ind_switches[i];
3179 	show_action(isw);
3180     }
3181 }
3182 
3183 static void
dec_choice(ind_sw_info * sw)3184 dec_choice(ind_sw_info *sw)
3185 {
3186     if (--(*sw->i_varadr) < 0)
3187 	(*sw->i_varadr) = sw->numchoices - 1;
3188     show_action(sw);
3189 }
3190 
3191 static void
inc_choice(ind_sw_info * sw)3192 inc_choice(ind_sw_info *sw)
3193 {
3194     if (++(*sw->i_varadr) > sw->numchoices - 1)
3195 	(*sw->i_varadr) = 0;
3196     show_action(sw);
3197 }
3198 
3199 /* ARROW MODE		 */
3200 
3201 static void
show_arrowmode(ind_sw_info * sw)3202 show_arrowmode(ind_sw_info *sw)
3203 {
3204     update_choice_pixmap(sw, cur_arrowmode);
3205     switch (cur_arrowmode) {
3206     case L_NOARROWS:
3207 	autobackwardarrow_mode = 0;
3208 	autoforwardarrow_mode = 0;
3209 	put_msg("NO ARROWS");
3210 	break;
3211     case L_FARROWS:
3212 	autobackwardarrow_mode = 0;
3213 	autoforwardarrow_mode = 1;
3214 	put_msg("Auto FORWARD ARROWS");
3215 	break;
3216     case L_FBARROWS:
3217 	autobackwardarrow_mode = 1;
3218 	autoforwardarrow_mode = 1;
3219 	put_msg("Auto FORWARD and BACKWARD ARROWS");
3220 	break;
3221     case L_BARROWS:
3222 	autobackwardarrow_mode = 1;
3223 	autoforwardarrow_mode = 0;
3224 	put_msg("Auto BACKWARD ARROWS");
3225 	break;
3226     }
3227 }
3228 /* ARROW TYPE		 */
3229 
3230 static void
show_arrowtype(ind_sw_info * sw)3231 show_arrowtype(ind_sw_info *sw)
3232 {
3233     update_choice_pixmap(sw, cur_arrowtype);
3234     if (cur_arrowtype == -1)
3235 	cur_arrowtype = 0;
3236     if (cur_arrowtype == 0)
3237 	put_msg("Arrow type 0");
3238     else if (cur_arrowtype % 2)
3239 	put_msg("Hollow arrow type %d",cur_arrowtype/2);
3240     else
3241 	put_msg("Solid arrow type %d",cur_arrowtype/2);
3242 }
3243 
3244 /* ARROW SIZES */
3245 
3246 static void
inc_arrowsize(ind_sw_info * sw)3247 inc_arrowsize(ind_sw_info *sw)
3248 {
3249     if (++cur_arrowsizeshown >= MAX_ARROWPARMS)
3250 	cur_arrowsizeshown = 0;
3251     show_arrowsize(sw);
3252 }
3253 
3254 static void
dec_arrowsize(ind_sw_info * sw)3255 dec_arrowsize(ind_sw_info *sw)
3256 {
3257     if (--cur_arrowsizeshown < 0)
3258 	cur_arrowsizeshown = MAX_ARROWPARMS-1;
3259     show_arrowsize(sw);
3260 }
3261 
3262 static void
show_arrowsize(ind_sw_info * sw)3263 show_arrowsize(ind_sw_info *sw)
3264 {
3265     char c;
3266     float thick, width, height;
3267     if (use_abs_arrowvals) {
3268 	c = ' ';
3269 	thick = cur_arrowthick;
3270 	width = cur_arrowwidth;
3271 	height = cur_arrowheight;
3272     } else {
3273 	thick = cur_arrow_multthick;
3274 	width = cur_arrow_multwidth;
3275 	height = cur_arrow_multheight;
3276 	c = 'x';
3277     }
3278 
3279     put_msg("Arrows: Thickness=%.1f, Width=%.1f, Length=%.1f (Button 1 to change)",
3280 		thick, width, height);
3281 
3282     /* write the current setting in the background pixmap */
3283     switch(cur_arrowsizeshown) {
3284 	case 0:
3285 	    sprintf(indbuf, "Thk=%.1f %c  ",thick,c);
3286 	    break;
3287 	case 1:
3288 	    sprintf(indbuf, "Wid=%.1f %c  ",width,c);
3289 	    break;
3290 	default:
3291 	    sprintf(indbuf, "Len=%.1f %c  ",height,c);
3292     }
3293     update_string_pixmap(sw, indbuf, 6, 26);
3294 }
3295 
3296 /* DIMENSION LINE SETTINGS */
3297 
3298 static void
inc_dimline(ind_sw_info * sw)3299 inc_dimline(ind_sw_info *sw)
3300 {
3301     if (++cur_dimlineshown >= MAX_DIMLINEPARMS)
3302 	cur_dimlineshown = 0;
3303     show_dimline(sw);
3304 }
3305 
3306 static void
dec_dimline(ind_sw_info * sw)3307 dec_dimline(ind_sw_info *sw)
3308 {
3309     if (--cur_dimlineshown < 0)
3310 	cur_dimlineshown = MAX_DIMLINEPARMS-1;
3311     show_dimline(sw);
3312 }
3313 
3314 static void
show_dimline(ind_sw_info * sw)3315 show_dimline(ind_sw_info *sw)
3316 {
3317 
3318     /* first check if the user's font number is consistent with the using_ps flag */
3319     if (!using_ps && (cur_dimline_font >= NUM_LATEX_FONTS))
3320 	cur_dimline_font = DEF_LATEX_FONT;
3321 
3322     put_msg("Dimension lines: Thick=%d, Ticks=%s, Font=%s, Size=%d (Button 1 to change)",
3323 	cur_dimline_thick, cur_dimline_ticks? "yes": "no",
3324 	using_ps? ps_fontinfo[cur_dimline_font].name: latex_fontinfo[cur_dimline_font].name,
3325 	cur_dimline_fontsize);
3326     switch(cur_dimlineshown) {
3327 	case 0:
3328 	    sprintf(indbuf, "Line thick=%d", cur_dimline_thick);
3329 	    break;
3330 	case 1:
3331 	    if (cur_dimline_color < NUM_STD_COLS)
3332 		sprintf(indbuf, "Line col=%s", short_clrNames[cur_dimline_color+1]);
3333 	    else
3334 		sprintf(indbuf, "Line col=%d", cur_dimline_color);
3335 	    break;
3336 	case 2:
3337 	    sprintf(indbuf, "L arrow typ=%d", cur_dimline_leftarrow);
3338 	    break;
3339 	case 3:
3340 	    sprintf(indbuf, "R arrow typ=%d", cur_dimline_rightarrow);
3341 	    break;
3342 	case 4:
3343 	    sprintf(indbuf, "Arrow len=%.2f", cur_dimline_arrowlength);
3344 	    break;
3345 	case 5:
3346 	    sprintf(indbuf, "Arrow wid=%.2f", cur_dimline_arrowwidth);
3347 	    break;
3348 	case 6:
3349 	    sprintf(indbuf, "Ticks: %s", cur_dimline_ticks? "yes": "no");
3350 	    break;
3351 	case 7:
3352 	    sprintf(indbuf, "Tick thk=%d", cur_dimline_tickthick);
3353 	    break;
3354 	case 8:
3355 	    sprintf(indbuf, "Box thk=%d", cur_dimline_boxthick);
3356 	    break;
3357 	case 9:
3358 	    if (cur_dimline_boxcolor < NUM_STD_COLS)
3359 		sprintf(indbuf, "Box col=%s", short_clrNames[cur_dimline_boxcolor+1]);
3360 	    else
3361 		sprintf(indbuf, "Box col=%d", cur_dimline_boxcolor);
3362 	    break;
3363 	case 10:
3364 	    if (cur_dimline_textcolor < NUM_STD_COLS)
3365 		sprintf(indbuf, "Text col=%s", short_clrNames[cur_dimline_textcolor+1]);
3366 	    else
3367 		sprintf(indbuf, "Text col=%d", cur_dimline_textcolor);
3368 	    break;
3369 	case 11:
3370 	    sprintf(indbuf, "Text font=%d", cur_dimline_font);
3371 	    break;
3372 	case 12:
3373 	    sprintf(indbuf, "Text size=%d", cur_dimline_fontsize);
3374 	    break;
3375 	case 13:
3376 	    sprintf(indbuf, "Text fixed: %s", cur_dimline_fixed? "yes": "no");
3377 	    break;
3378 	case 14:
3379 	    sprintf(indbuf, "Dec. place: %d", cur_dimline_prec);
3380 	    break;
3381     }
3382     /* pad out */
3383     strcat(indbuf,"    ");
3384 
3385     update_string_pixmap(sw, indbuf, 3, 26);
3386 }
3387 
3388 /* LINE WIDTH		 */
3389 
3390 static void
dec_linewidth(ind_sw_info * sw)3391 dec_linewidth(ind_sw_info *sw)
3392 {
3393     --cur_linewidth;
3394     show_linewidth(sw);
3395 }
3396 
3397 static void
inc_linewidth(ind_sw_info * sw)3398 inc_linewidth(ind_sw_info *sw)
3399 {
3400     ++cur_linewidth;
3401     show_linewidth(sw);
3402 }
3403 
3404 static void
show_linewidth(ind_sw_info * sw)3405 show_linewidth(ind_sw_info *sw)
3406 {
3407     XGCValues	    gcv;
3408     XCharStruct	    size;
3409     int		    dum, height;
3410 
3411     if (cur_linewidth > MAX_LINE_WIDTH)
3412 	cur_linewidth = MAX_LINE_WIDTH;
3413     else if (cur_linewidth < 0)
3414 	cur_linewidth = 0;
3415 
3416     /* erase by drawing wide, inverted (white) line */
3417     pw_vector(sw->pixmap, DEF_IND_SW_WD / 2 + 2, DEF_IND_SW_HT / 2,
3418 	      sw->sw_width - 2, DEF_IND_SW_HT / 2, ERASE,
3419 	      DEF_IND_SW_HT, PANEL_LINE, 0.0, DEFAULT);
3420     /* draw current line thickness into pixmap */
3421     if (cur_linewidth > 0)	/* don't draw line for zero-thickness */
3422 	pw_vector(sw->pixmap, DEF_IND_SW_WD / 2 + 2, DEF_IND_SW_HT / 2,
3423 		  sw->sw_width - 2, DEF_IND_SW_HT / 2, PAINT,
3424 		  cur_linewidth, PANEL_LINE, 0.0, DEFAULT);
3425 
3426     /* now write the width in the middle of the line */
3427     if (cur_linewidth < 10)
3428 	sprintf(indbuf, " %0d", cur_linewidth);
3429     else
3430 	sprintf(indbuf, "%0d", cur_linewidth);
3431     /* get size of string for positioning */
3432     XTextExtents(button_font, indbuf, strlen(indbuf), &dum, &dum, &dum, &size);
3433     height = size.ascent+size.descent;
3434     /* if the line width if small, draw black text with white background around it.
3435        Otherwise, draw it xor'ed on the thick line we just drew */
3436     if (cur_linewidth < 10) {
3437 	gcv.foreground = x_color(BLACK);
3438 	gcv.background = x_color(WHITE);
3439 	XChangeGC(tool_d, ind_button_gc, GCForeground|GCBackground, &gcv);
3440 	XDrawImageString(tool_d, sw->pixmap, ind_button_gc,
3441 			DEF_IND_SW_WD-size.width-6, (DEF_IND_SW_HT+height)/2,
3442 		        indbuf, strlen(indbuf));
3443     } else {
3444 	gcv.foreground = x_color(WHITE) ^ x_color(BLACK);
3445 	gcv.background = x_color(WHITE);
3446 	gcv.function = GXxor;
3447 	XChangeGC(tool_d, ind_button_gc, GCForeground|GCBackground|GCFunction, &gcv);
3448 	XDrawString(tool_d, sw->pixmap, ind_button_gc,
3449 			DEF_IND_SW_WD-size.width-6, (DEF_IND_SW_HT+height)/2,
3450 		        indbuf, strlen(indbuf));
3451     }
3452     /*
3453      * Fool the toolkit by changing the background pixmap to 0 then giving it
3454      * the modified one again.	Otherwise, it sees that the pixmap ID is not
3455      * changed and doesn't actually draw it into the widget window
3456      */
3457     if (sw->updbut && update_buts_managed)
3458 	XtUnmanageChild(sw->updbut);
3459     FirstArg(XtNbackgroundPixmap, 0);
3460     SetValues(sw->button);
3461     /* put the pixmap in the widget background */
3462     FirstArg(XtNbackgroundPixmap, sw->pixmap);
3463     SetValues(sw->button);
3464     if (sw->updbut && update_buts_managed)
3465 	XtManageChild(sw->updbut);
3466 
3467     /* restore indicator button gc colors and function */
3468     gcv.foreground = ind_but_fg;
3469     gcv.background = ind_but_bg;
3470     gcv.function = GXcopy;
3471     XChangeGC(tool_d, ind_button_gc, GCForeground|GCBackground|GCFunction, &gcv);
3472 
3473     put_msg("LINE Thickness = %d", cur_linewidth);
3474 }
3475 
3476 /* TANGENT/NORMAL line length */
3477 
3478 static void
inc_tangnormlen(ind_sw_info * sw)3479 inc_tangnormlen(ind_sw_info *sw)
3480 {
3481     cur_tangnormlen += 0.1;
3482     show_tangnormlen(sw);
3483 }
3484 
3485 static void
dec_tangnormlen(ind_sw_info * sw)3486 dec_tangnormlen(ind_sw_info *sw)
3487 {
3488     cur_tangnormlen -= 0.1;
3489     show_tangnormlen(sw);
3490 }
3491 
3492 static void
show_tangnormlen(ind_sw_info * sw)3493 show_tangnormlen(ind_sw_info *sw)
3494 {
3495     if (cur_tangnormlen < 0)
3496 	cur_tangnormlen = 0;
3497     else if (cur_tangnormlen > MAX_TANGNORMLEN)
3498 	cur_tangnormlen = MAX_TANGNORMLEN;
3499 
3500     put_msg("Tangent/normal line length %.2f %s", cur_tangnormlen, appres.INCHES? "in": "cm");
3501 
3502     /* write the length in the background pixmap */
3503     indbuf[0] = indbuf[1] = indbuf[2] = indbuf[3] = indbuf[4] = '\0';
3504     sprintf(indbuf, "%5.2f", cur_tangnormlen);
3505     update_string_pixmap(sw, indbuf, sw->sw_width - 33, 25);
3506 }
3507 
3508 /* ANGLE GEOMETRY		 */
3509 
3510 static void
show_anglegeom(ind_sw_info * sw)3511 show_anglegeom(ind_sw_info *sw)
3512 {
3513     update_choice_pixmap(sw, cur_anglegeom);
3514     switch (cur_anglegeom) {
3515     case L_UNCONSTRAINED:
3516 	manhattan_mode = 0;
3517 	mountain_mode = 0;
3518 	latexline_mode = 0;
3519 	latexarrow_mode = 0;
3520 	put_msg("UNCONSTRAINED geometry (for POLYLINE and SPLINE)");
3521 	break;
3522     case L_MOUNTHATTAN:
3523 	mountain_mode = 1;
3524 	manhattan_mode = 1;
3525 	latexline_mode = 0;
3526 	latexarrow_mode = 0;
3527 	put_msg("MOUNT-HATTAN geometry (for POLYLINE and SPLINE)");
3528 	break;
3529     case L_MANHATTAN:
3530 	manhattan_mode = 1;
3531 	mountain_mode = 0;
3532 	latexline_mode = 0;
3533 	latexarrow_mode = 0;
3534 	put_msg("MANHATTAN geometry (for POLYLINE and SPLINE)");
3535 	break;
3536     case L_MOUNTAIN:
3537 	mountain_mode = 1;
3538 	manhattan_mode = 0;
3539 	latexline_mode = 0;
3540 	latexarrow_mode = 0;
3541 	put_msg("MOUNTAIN geometry (for POLYLINE and SPLINE)");
3542 	break;
3543     case L_LATEXLINE:
3544 	latexline_mode = 1;
3545 	manhattan_mode = 0;
3546 	mountain_mode = 0;
3547 	latexarrow_mode = 0;
3548 	put_msg("LATEX LINE geometry: allow only LaTeX line slopes");
3549 	break;
3550     case L_LATEXARROW:
3551 	latexarrow_mode = 1;
3552 	manhattan_mode = 0;
3553 	mountain_mode = 0;
3554 	latexline_mode = 0;
3555 	put_msg("LATEX ARROW geometry: allow only LaTeX arrow slopes");
3556 	break;
3557     }
3558 }
3559 
3560 /* ARC TYPE */
3561 
3562 static void
show_arctype(ind_sw_info * sw)3563 show_arctype(ind_sw_info *sw)
3564 {
3565     update_choice_pixmap(sw, cur_arctype);
3566     switch (cur_arctype) {
3567     case T_OPEN_ARC:
3568 	put_msg("OPEN arc");
3569 	break;
3570     case T_PIE_WEDGE_ARC:
3571 	put_msg("PIE WEDGE (closed) arc");
3572 	break;
3573     }
3574 }
3575 
3576 
3577 /* JOIN STYLE		 */
3578 
3579 static void
show_joinstyle(ind_sw_info * sw)3580 show_joinstyle(ind_sw_info *sw)
3581 {
3582     update_choice_pixmap(sw, cur_joinstyle);
3583     switch (cur_joinstyle) {
3584     case JOIN_MITER:
3585 	put_msg("MITER line join style");
3586 	break;
3587     case JOIN_ROUND:
3588 	put_msg("ROUND line join style");
3589 	break;
3590     case JOIN_BEVEL:
3591 	put_msg("BEVEL line join style");
3592 	break;
3593     }
3594 }
3595 
3596 /* CAP STYLE		 */
3597 
3598 static void
show_capstyle(ind_sw_info * sw)3599 show_capstyle(ind_sw_info *sw)
3600 {
3601     update_choice_pixmap(sw, cur_capstyle);
3602     switch (cur_capstyle) {
3603     case CAP_BUTT:
3604 	put_msg("BUTT line cap style");
3605 	break;
3606     case CAP_ROUND:
3607 	put_msg("ROUND line cap style");
3608 	break;
3609     case CAP_PROJECT:
3610 	put_msg("PROJECTING line cap style");
3611 	break;
3612     }
3613 }
3614 
3615 /* LINE STYLE		 */
3616 
3617 static void
show_linestyle(ind_sw_info * sw)3618 show_linestyle(ind_sw_info *sw)
3619 {
3620     if (cur_dashlength <= 0.0)
3621        cur_dashlength = DEF_DASHLENGTH;
3622     if (cur_dotgap <= 0.0)
3623        cur_dotgap = DEF_DOTGAP;
3624     update_choice_pixmap(sw, cur_linestyle);
3625     switch (cur_linestyle) {
3626     case SOLID_LINE:
3627 	put_msg("SOLID LINE STYLE");
3628 	break;
3629     case DASH_LINE:
3630 	cur_styleval = cur_dashlength;
3631 	put_msg("DASH LINE STYLE");
3632 	break;
3633     case DOTTED_LINE:
3634 	cur_styleval = cur_dotgap;
3635 	put_msg("DOTTED LINE STYLE");
3636 	break;
3637     case DASH_DOT_LINE:
3638         cur_styleval = cur_dashlength;
3639 	put_msg("DASH-DOT LINE STYLE");
3640 	break;
3641     case DASH_2_DOTS_LINE:
3642         cur_styleval = cur_dashlength;
3643 	put_msg("DASH-DOT-DOT LINE STYLE");
3644 	break;
3645     case DASH_3_DOTS_LINE:
3646         cur_styleval = cur_dashlength;
3647 	put_msg("DASH-DOT-DOT-DOT LINE STYLE");
3648 	break;
3649     }
3650 }
3651 
3652 /* VERTICAL ALIGNMENT	 */
3653 
3654 static void
show_valign(ind_sw_info * sw)3655 show_valign(ind_sw_info *sw)
3656 {
3657     update_choice_pixmap(sw, cur_valign);
3658     switch (cur_valign) {
3659     case ALIGN_NONE:
3660 	put_msg("No vertical alignment");
3661 	break;
3662     case ALIGN_TOP:
3663 	put_msg("Vertically align to TOP");
3664 	break;
3665     case ALIGN_CENTER:
3666 	put_msg("Center vertically when aligning");
3667 	break;
3668     case ALIGN_BOTTOM:
3669 	put_msg("Vertically align to BOTTOM");
3670 	break;
3671     case ALIGN_DISTRIB_C:
3672 	put_msg("Vertically DISTRIBUTE objects, equal distance between CENTRES");
3673 	break;
3674     case ALIGN_DISTRIB_E:
3675 	put_msg("Vertically DISTRIBUTE objects, equal distance between EDGES");
3676 	break;
3677     case ALIGN_ABUT:
3678 	put_msg("Vertically ABUT the objects together");
3679 	break;
3680     }
3681 }
3682 
3683 /* HORIZ ALIGNMENT	 */
3684 
3685 static void
show_halign(ind_sw_info * sw)3686 show_halign(ind_sw_info *sw)
3687 {
3688     update_choice_pixmap(sw, cur_halign);
3689     switch (cur_halign) {
3690     case ALIGN_NONE:
3691 	put_msg("No horizontal alignment");
3692 	break;
3693     case ALIGN_LEFT:
3694 	put_msg("Horizontally align to LEFT");
3695 	break;
3696     case ALIGN_CENTER:
3697 	put_msg("Center horizontally when aligning");
3698 	break;
3699     case ALIGN_RIGHT:
3700 	put_msg("Horizontally align to RIGHT");
3701 	break;
3702     case ALIGN_DISTRIB_C:
3703 	put_msg("Horizontally DISTRIBUTE objects, equal distance between CENTRES");
3704 	break;
3705     case ALIGN_DISTRIB_E:
3706 	put_msg("Horizontally DISTRIBUTE objects, equal distance between EDGES");
3707 	break;
3708     case ALIGN_ABUT:
3709 	put_msg("Horizontally ABUT the objects together");
3710 	break;
3711     }
3712 }
3713 
3714 /* GRID MODE	 */		// isometric grid
3715 
3716 static void
show_gridmode(sw)3717 show_gridmode(sw)
3718     ind_sw_info	   *sw;
3719 {
3720     update_choice_pixmap(sw, cur_gridmode);
3721 
3722     /* check the new mode */
3723     if (cur_gridmode == GRID_0) {
3724 		put_msg("No grid");
3725     } else if( cur_gridmode <= GRID_4 ) {
3726 	    cur_gridtype = GRID_SQUARE;
3727 		put_msg( "%s grid", grid_name[cur_gridunit][cur_gridmode] );
3728     } else {
3729 		/*cur_gridmode = cur_gridmode - GRID_4;*/
3730 		cur_gridtype = GRID_ISO;
3731 		put_msg( "%s isometric grid", grid_name[cur_gridunit][cur_gridmode - GRID_4] );
3732     }
3733 
3734     /* display new grid */
3735     setup_grid();
3736 }
3737 
3738 /* POINT POSITION	 */
3739 
3740 static void
show_pointposn(ind_sw_info * sw)3741 show_pointposn(ind_sw_info *sw)
3742 {
3743     char	    buf[80];
3744 
3745     /* because of the weird numbering we're using, we have to check this here */
3746     if (cur_pointposn > P_GRID4)
3747 	cur_pointposn = P_ANY;
3748 
3749     update_choice_pixmap(sw, cur_pointposn);
3750     switch (cur_pointposn) {
3751       case P_ANY:
3752 	put_msg("Arbitrary Positioning of Points");
3753 	break;
3754       default:
3755 	sprintf(buf,
3756 	  "MAGNET MODE: entered points rounded to the nearest %s increment",
3757 		grid_name[cur_gridunit][cur_pointposn-1]);
3758 	put_msg(buf);
3759 	break;
3760     }
3761 }
3762 
3763 /* SMART LINK MODE */
3764 
3765 static void
show_linkmode(ind_sw_info * sw)3766 show_linkmode(ind_sw_info *sw)
3767 {
3768     update_choice_pixmap(sw, cur_linkmode);
3769     switch (cur_linkmode) {
3770     case SMART_OFF:
3771 	put_msg("Do not adjust links automatically");
3772 	break;
3773     case SMART_MOVE:
3774 	put_msg("Adjust links automatically by moving endpoint");
3775 	break;
3776     case SMART_SLIDE:
3777 	put_msg("Adjust links automatically by sliding endlink");
3778 	break;
3779     }
3780 }
3781 
3782 /* TEXT JUSTIFICATION	 */
3783 
3784 static void
show_textjust(ind_sw_info * sw)3785 show_textjust(ind_sw_info *sw)
3786 {
3787     update_choice_pixmap(sw, cur_textjust);
3788     switch (cur_textjust) {
3789     case T_LEFT_JUSTIFIED:
3790 	put_msg("Left justify text");
3791 	break;
3792     case T_CENTER_JUSTIFIED:
3793 	put_msg("Center text");
3794 	break;
3795     case T_RIGHT_JUSTIFIED:
3796 	put_msg("Right justify text");
3797 	break;
3798     }
3799 }
3800 
3801 /* BOX RADIUS	 */
3802 
3803 static void
dec_boxradius(ind_sw_info * sw)3804 dec_boxradius(ind_sw_info *sw)
3805 {
3806     --cur_boxradius;
3807     show_boxradius(sw);
3808 }
3809 
3810 static void
inc_boxradius(ind_sw_info * sw)3811 inc_boxradius(ind_sw_info *sw)
3812 {
3813     ++cur_boxradius;
3814     show_boxradius(sw);
3815 }
3816 
3817 #define MAXRADIUS 30
3818 
3819 static void
show_boxradius(ind_sw_info * sw)3820 show_boxradius(ind_sw_info *sw)
3821 {
3822     if (cur_boxradius > MAXRADIUS)
3823 	cur_boxradius = MAXRADIUS;
3824     else if (cur_boxradius < 3)
3825 	cur_boxradius = 3;
3826     /* erase by drawing wide, inverted (white) line */
3827     pw_vector(sw->pixmap, DEF_IND_SW_WD / 2, DEF_IND_SW_HT / 2,
3828 	      DEF_IND_SW_WD, DEF_IND_SW_HT / 2, ERASE,
3829 	      DEF_IND_SW_HT, PANEL_LINE, 0.0, DEFAULT);
3830     /* draw current radius into pixmap */
3831     curve(sw->pixmap, MAX_DEPTH+1, 0, cur_boxradius, -cur_boxradius, 0,
3832 	  DRAW_POINTS, DONT_DRAW_CENTER, 1, cur_boxradius, cur_boxradius,
3833 	  DEF_IND_SW_WD - 2, DEF_IND_SW_HT - 2, PAINT, 1, PANEL_LINE, 0.0, UNFILLED,
3834 	  DEFAULT, DEFAULT, CAP_BUTT);
3835 
3836     /*
3837      * Fool the toolkit by changing the background pixmap to 0 then giving it
3838      * the modified one again.	Otherwise, it sees that the pixmap ID is not
3839      * changed and doesn't actually draw it into the widget window
3840      */
3841     if (sw->updbut && update_buts_managed)
3842 	XtUnmanageChild(sw->updbut);
3843     FirstArg(XtNbackgroundPixmap, 0);
3844     SetValues(sw->button);
3845     /* put the pixmap in the widget background */
3846     FirstArg(XtNbackgroundPixmap, sw->pixmap);
3847     SetValues(sw->button);
3848     put_msg("ROUNDED-CORNER BOX Radius = %d", cur_boxradius);
3849     if (sw->updbut && update_buts_managed)
3850 	XtManageChild(sw->updbut);
3851 }
3852 
3853 /* FILL STYLE */
3854 
3855 static void
darken_fill(ind_sw_info * sw)3856 darken_fill(ind_sw_info *sw)
3857 {
3858     cur_fillstyle++;
3859     if ((cur_fillcolor == BLACK || cur_fillcolor == DEFAULT ||
3860 	 cur_fillcolor == WHITE) && cur_fillstyle == NUMSHADEPATS)
3861 		cur_fillstyle = NUMSHADEPATS+NUMTINTPATS;	/* skip to patterns */
3862     else if (cur_fillstyle >= NUMFILLPATS)
3863 	    cur_fillstyle = UNFILLED;
3864     show_fillstyle(sw);
3865 }
3866 
3867 static void
lighten_fill(ind_sw_info * sw)3868 lighten_fill(ind_sw_info *sw)
3869 {
3870     cur_fillstyle--;
3871     if (cur_fillstyle < UNFILLED)
3872 	    cur_fillstyle = NUMFILLPATS-1;	/* set to patterns */
3873     if ((cur_fillcolor == BLACK || cur_fillcolor == DEFAULT ||
3874 	 cur_fillcolor == WHITE) && cur_fillstyle == NUMSHADEPATS+NUMTINTPATS-1)
3875 	    cur_fillstyle = NUMSHADEPATS-1;	/* no tints */
3876     show_fillstyle(sw);
3877 }
3878 
3879 void
show_fillstyle(ind_sw_info * sw)3880 show_fillstyle(ind_sw_info *sw)
3881 {
3882     /* we must check the validity of the fill style again in case the user changed
3883        colors.  In that case, there may be an illegal fill value (e.g. for black
3884        there are no "tints" */
3885     if (cur_fillcolor == COLOR_NONE ||
3886 	 (cur_fillcolor == BLACK || cur_fillcolor == DEFAULT || cur_fillcolor == WHITE) &&
3887 	    (cur_fillstyle >= NUMSHADEPATS && cur_fillstyle < NUMSHADEPATS+NUMTINTPATS))
3888 		cur_fillstyle = UNFILLED;  /* no fill color or no tints, set unfilled */
3889     XSetFillStyle(tool_d, ind_button_gc, FillTiled);
3890     if (cur_fillstyle == UNFILLED) {
3891 	XSetTile(tool_d, ind_button_gc, fillstyle_choices[0].pixmap);
3892 	XFillRectangle(tool_d, sw->pixmap, ind_button_gc, 32, 0, 32, 32);
3893 	put_msg("NO-FILL MODE");
3894     } else {
3895 	/* put the pixmap in the widget background */
3896 	XSetTile(tool_d, ind_button_gc, fillstyle_choices[cur_fillstyle+1].pixmap);
3897 	XFillRectangle(tool_d, sw->pixmap, ind_button_gc, 35, 4, 26, 24);
3898 	if (cur_fillstyle < NUMSHADEPATS+NUMTINTPATS)
3899 	   put_msg("FILL MODE (black density/color intensity = %d%%)",
3900 		(cur_fillstyle * 200) / (NUMSHADEPATS+NUMTINTPATS - 1));
3901 	else
3902 	   put_msg("FILL pattern %d",cur_fillstyle-NUMSHADEPATS-NUMTINTPATS);
3903     }
3904     XSetFillStyle(tool_d, ind_button_gc, FillSolid);
3905     if (sw->updbut && update_buts_managed)
3906 	XtUnmanageChild(sw->updbut);
3907     FirstArg(XtNbackgroundPixmap, 0);
3908     SetValues(sw->button);
3909     /* put the pixmap in the widget background */
3910     FirstArg(XtNbackgroundPixmap, sw->pixmap);
3911     SetValues(sw->button);
3912     if (sw->updbut && update_buts_managed)
3913 	XtManageChild(sw->updbut);
3914 }
3915 
3916 /* change the colors of the fill style indicators */
3917 
recolor_fillstyles(void)3918 void recolor_fillstyles(void)
3919 {
3920     int		    i,j;
3921     float	    save_dispzoom, savezoom;
3922     Pixmap	    savepm;
3923     float	    savepm_zoom;
3924 
3925     save_dispzoom = display_zoomscale;
3926     savezoom = zoomscale;
3927     display_zoomscale = 1.0;
3928     zoomscale = display_zoomscale/ZOOM_FACTOR;
3929 
3930     for (i = 0; i < NUMFILLPATS; i++) {
3931 	j = i-(NUMTINTPATS+NUMSHADEPATS);
3932 	if (j >= 0) {				/* actual patterns */
3933 	    savepm = fill_pm[i];
3934 	    savepm_zoom = fill_pm_zoom[i];
3935 	    /* use the one create at zoom = 1 */
3936 	    fill_pm[i] = fill_but_pm[j];
3937 	    fill_pm_zoom[i] = fill_but_pm_zoom[j];
3938 	}
3939 	set_fill_gc(i, PAINT, cur_pencolor, cur_fillcolor, 0, 0);
3940 	/* skip tints for black, white and default */
3941 	if ((cur_fillcolor == WHITE || cur_fillcolor == BLACK || cur_fillcolor == DEFAULT) &&
3942 	    (i >= NUMSHADEPATS && i < NUMTINTPATS+NUMSHADEPATS))
3943 		continue;
3944 	XFillRectangle(tool_d, fillstyle_choices[i+1].pixmap, fillgc, 0, 0, 32, 32);
3945 	if (j >= 0) {
3946 	    fill_pm[i] = savepm;
3947 	    fill_pm_zoom[i] = savepm_zoom;
3948 	}
3949     }
3950     display_zoomscale = save_dispzoom;
3951     zoomscale = savezoom;
3952 }
3953 
3954 /**********************/
3955 /*     TEXT FLAGS     */
3956 /**********************/
3957 
3958 static void
inc_flags(ind_sw_info * sw)3959 inc_flags(ind_sw_info *sw)
3960 {
3961     if (++cur_flagshown >= MAX_FLAGS)
3962 	cur_flagshown = 0;
3963     show_flags(sw);
3964 }
3965 
3966 static void
dec_flags(ind_sw_info * sw)3967 dec_flags(ind_sw_info *sw)
3968 {
3969     if (--cur_flagshown < 0)
3970 	cur_flagshown = MAX_FLAGS-1;
3971     show_flags(sw);
3972 }
3973 
3974 static void
show_flags(ind_sw_info * sw)3975 show_flags(ind_sw_info *sw)
3976 {
3977     put_msg("Text flags: Hidden=%s, TeX=%s, Rigid=%s (Button 1 to change)",
3978 		(cur_textflags & HIDDEN_TEXT) ? "on" : "off",
3979 		(cur_textflags & SPECIAL_TEXT) ? "on" : "off",
3980 		(cur_textflags & RIGID_TEXT) ? "on" : "off");
3981 
3982     /* write the text/ellipse angle in the background pixmap */
3983     switch(cur_flagshown) {
3984 	case 0:
3985 	    sprintf(indbuf, "hidden=%s",
3986 			(cur_textflags & HIDDEN_TEXT) ? "on " : "off");
3987 	    break;
3988 	case 1:
3989 	    sprintf(indbuf, "TeX=%s",
3990 			(cur_textflags & SPECIAL_TEXT) ? "on    " : "off   ");
3991 	    break;
3992 	default:
3993 	    sprintf(indbuf, "rigid=%s",
3994 			(cur_textflags & RIGID_TEXT) ? "on  " : "off ");
3995     }
3996     update_string_pixmap(sw, indbuf, 6, 26);
3997 }
3998 
3999 /**********************/
4000 /*        FONT        */
4001 /**********************/
4002 
4003 static void
inc_font(ind_sw_info * sw)4004 inc_font(ind_sw_info *sw)
4005 {
4006     if (using_ps)
4007 	cur_ps_font++;
4008     else
4009 	cur_latex_font++;
4010     show_font(sw);
4011 }
4012 
4013 static void
dec_font(ind_sw_info * sw)4014 dec_font(ind_sw_info *sw)
4015 {
4016     if (using_ps)
4017 	cur_ps_font--;
4018     else
4019 	cur_latex_font--;
4020     show_font(sw);
4021 }
4022 
4023 static void
show_font(ind_sw_info * sw)4024 show_font(ind_sw_info *sw)
4025 {
4026     if (using_ps) {
4027 	if (cur_ps_font >= NUM_FONTS)
4028 	    cur_ps_font = DEFAULT;
4029 	else if (cur_ps_font < DEFAULT)
4030 	    cur_ps_font = NUM_FONTS - 1;
4031     } else {
4032 	if (cur_latex_font >= NUM_LATEX_FONTS)
4033 	    cur_latex_font = 0;
4034 	else if (cur_latex_font < 0)
4035 	    cur_latex_font = NUM_LATEX_FONTS - 1;
4036     }
4037 
4038     /* erase larger fontpane bits if we switched to smaller (Latex) */
4039     XFillRectangle(tool_d, sw->pixmap, ind_blank_gc, 0, 0,
4040 	       32 + max2(PS_FONTPANE_WD, LATEX_FONTPANE_WD), DEF_IND_SW_HT);
4041     /* and redraw info */
4042     XDrawImageString(tool_d, sw->pixmap, ind_button_gc, 3, 12, sw->line1,
4043 		     strlen(sw->line1));
4044     XDrawImageString(tool_d, sw->pixmap, ind_button_gc, 3, 25, sw->line2,
4045 		     strlen(sw->line2));
4046 
4047     XCopyArea(tool_d, using_ps ? psfont_menu_bitmaps[cur_ps_font + 1] :
4048 	      latexfont_menu_bitmaps[cur_latex_font],
4049 	      sw->pixmap, ind_button_gc, 0, 0,
4050 	      using_ps ? PS_FONTPANE_WD : LATEX_FONTPANE_WD,
4051 	      using_ps ? PS_FONTPANE_HT : LATEX_FONTPANE_HT,
4052 	  using_ps ? 32 : 32 + (PS_FONTPANE_WD - LATEX_FONTPANE_WD) / 2, 6);
4053 
4054     if (sw->updbut && update_buts_managed)
4055 	XtUnmanageChild(sw->updbut);
4056     FirstArg(XtNbackgroundPixmap, 0);
4057     SetValues(sw->button);
4058     /* put the pixmap in the widget background */
4059     FirstArg(XtNbackgroundPixmap, sw->pixmap);
4060     SetValues(sw->button);
4061     put_msg("Font: %s", using_ps ? ps_fontinfo[cur_ps_font + 1].name :
4062 	    latex_fontinfo[cur_latex_font].name);
4063     if (sw->updbut && update_buts_managed)
4064 	XtManageChild(sw->updbut);
4065 }
4066 
4067 /* popup menu of fonts */
4068 
4069 static int	psflag;
4070 static ind_sw_info *return_sw;
4071 
4072 static void	show_font_return(Widget w);
4073 
4074 static void
popup_fonts(ind_sw_info * sw)4075 popup_fonts(ind_sw_info *sw)
4076 {
4077     return_sw = sw;
4078     psflag = using_ps ? 1 : 0;
4079     fontpane_popup(&cur_ps_font, &cur_latex_font, &psflag,
4080 		   show_font_return, sw->button);
4081 }
4082 
4083 static void
show_font_return(Widget w)4084 show_font_return(Widget w)
4085 {
4086     if (psflag)
4087 	cur_textflags = cur_textflags | PSFONT_TEXT;
4088     else
4089 	cur_textflags = cur_textflags & (~PSFONT_TEXT);
4090     show_font(return_sw);
4091 }
4092 
4093 /* FONT SIZE */
4094 
4095 static void
inc_fontsize(ind_sw_info * sw)4096 inc_fontsize(ind_sw_info *sw)
4097 {
4098     if (cur_fontsize >= 100) {
4099 	cur_fontsize = (cur_fontsize / 10) * 10;	/* round first */
4100 	cur_fontsize += 10;
4101     } else if (cur_fontsize >= 50) {
4102 	cur_fontsize = (cur_fontsize / 5) * 5;
4103 	cur_fontsize += 5;
4104     } else if (cur_fontsize >= 20) {
4105 	cur_fontsize = (cur_fontsize / 2) * 2;
4106 	cur_fontsize += 2;
4107     } else
4108 	cur_fontsize++;
4109     show_fontsize(sw);
4110 }
4111 
4112 static void
dec_fontsize(ind_sw_info * sw)4113 dec_fontsize(ind_sw_info *sw)
4114 {
4115     if (cur_fontsize > 100) {
4116 	cur_fontsize = (cur_fontsize / 10) * 10;	/* round first */
4117 	cur_fontsize -= 10;
4118     } else if (cur_fontsize > 50) {
4119 	cur_fontsize = (cur_fontsize / 5) * 5;
4120 	cur_fontsize -= 5;
4121     } else if (cur_fontsize > 20) {
4122 	cur_fontsize = (cur_fontsize / 2) * 2;
4123 	cur_fontsize -= 2;
4124     } else if (cur_fontsize > MIN_FONT_SIZE)
4125 	cur_fontsize--;
4126     show_fontsize(sw);
4127 }
4128 
4129 static void
show_fontsize(ind_sw_info * sw)4130 show_fontsize(ind_sw_info *sw)
4131 {
4132     if (cur_fontsize < MIN_FONT_SIZE)
4133 	cur_fontsize = MIN_FONT_SIZE;
4134     else if (cur_fontsize > MAX_FONT_SIZE)
4135 	cur_fontsize = MAX_FONT_SIZE;
4136 
4137     put_msg("Font size %d", cur_fontsize);
4138     /* write the font size in the background pixmap */
4139     indbuf[0] = indbuf[1] = indbuf[2] = indbuf[3] = indbuf[4] = '\0';
4140     sprintf(indbuf, "%4d", cur_fontsize);
4141     update_string_pixmap(sw, indbuf, sw->sw_width - 28, 20);
4142 }
4143 
4144 /* ELLIPSE/TEXT ANGLE */
4145 
4146 static void
inc_elltextangle(ind_sw_info * sw)4147 inc_elltextangle(ind_sw_info *sw)
4148 {
4149 
4150     if (cur_elltextangle < 0.0)
4151 	cur_elltextangle = ((int) ((cur_elltextangle-14.999)/15.0))*15.0;
4152     else
4153 	cur_elltextangle = ((int) (cur_elltextangle/15.0))*15.0;
4154     cur_elltextangle += 15.0;
4155     show_elltextangle(sw);
4156 }
4157 
4158 static void
dec_elltextangle(ind_sw_info * sw)4159 dec_elltextangle(ind_sw_info *sw)
4160 {
4161     if (cur_elltextangle < 0.0)
4162 	cur_elltextangle = ((int) (cur_elltextangle/15.0))*15.0;
4163     else
4164 	cur_elltextangle = ((int) ((cur_elltextangle+14.999)/15.0))*15.0;
4165     cur_elltextangle -= 15.0;
4166     show_elltextangle(sw);
4167 }
4168 
4169 static void
show_elltextangle(ind_sw_info * sw)4170 show_elltextangle(ind_sw_info *sw)
4171 {
4172     cur_elltextangle = round(cur_elltextangle*10.0)/10.0;
4173     if (cur_elltextangle <= -360.0 || cur_elltextangle >= 360)
4174 	cur_elltextangle = 0.0;
4175 
4176     put_msg("Text/Ellipse angle %.1f", cur_elltextangle);
4177     if (cur_elltextangle == old_elltextangle)
4178 	return;
4179 
4180     /* write the text/ellipse angle in the background pixmap */
4181     indbuf[0]=indbuf[1]=indbuf[2]=indbuf[3]=indbuf[4]=indbuf[5]=' ';
4182     sprintf(indbuf, "%5.1f", cur_elltextangle);
4183     update_string_pixmap(sw, indbuf, sw->sw_width - 40, 26);
4184     old_elltextangle = cur_elltextangle;
4185 }
4186 
4187 /* ROTATION ANGLE */
4188 
4189 static void
inc_rotnangle(ind_sw_info * sw)4190 inc_rotnangle(ind_sw_info *sw)
4191 {
4192     if (cur_rotnangle < 15.0 || cur_rotnangle >= 180.0)
4193 	cur_rotnangle = 15.0;
4194     else if (cur_rotnangle < 30.0)
4195 	cur_rotnangle = 30.0;
4196     else if (cur_rotnangle < 45.0)
4197 	cur_rotnangle = 45.0;
4198     else if (cur_rotnangle < 60.0)
4199 	cur_rotnangle = 60.0;
4200     else if (cur_rotnangle < 90.0)
4201 	cur_rotnangle = 90.0;
4202     else if (cur_rotnangle < 120.0)
4203 	cur_rotnangle = 120.0;
4204     else if (cur_rotnangle < 180.0)
4205 	cur_rotnangle = 180.0;
4206     show_rotnangle(sw);
4207 }
4208 
4209 static void
dec_rotnangle(ind_sw_info * sw)4210 dec_rotnangle(ind_sw_info *sw)
4211 {
4212     if (cur_rotnangle > 180.0 || cur_rotnangle <= 15.0)
4213 	cur_rotnangle = 180.0;
4214     else if (cur_rotnangle > 120.0)
4215 	cur_rotnangle = 120.0;
4216     else if (cur_rotnangle > 90.0)
4217 	cur_rotnangle = 90.0;
4218     else if (cur_rotnangle > 60.0)
4219 	cur_rotnangle = 60.0;
4220     else if (cur_rotnangle > 45.0)
4221 	cur_rotnangle = 45.0;
4222     else if (cur_rotnangle > 30.0)
4223 	cur_rotnangle = 30.0;
4224     else if (cur_rotnangle > 15.0)
4225 	cur_rotnangle = 15.0;
4226     show_rotnangle(sw);
4227 }
4228 
4229 static void
show_rotnangle(ind_sw_info * sw)4230 show_rotnangle(ind_sw_info *sw)
4231 {
4232     show_rotnangle_0(sw, 1);
4233 }
4234 
4235 /* called by angle measuring &c */
4236 
4237 static void
show_rotnangle_0(ind_sw_info * sw,int panel)4238 show_rotnangle_0(ind_sw_info *sw, int panel)
4239                /* called from panel? */
4240 {
4241     int i;
4242 
4243     if (cur_rotnangle < -360.0)
4244 	cur_rotnangle = -360.0;
4245     else if (cur_rotnangle > 360.0)
4246 	cur_rotnangle = 360.0;
4247 
4248     if (panel)
4249         put_msg("Angle of rotation %.2f", cur_rotnangle);
4250     if (cur_rotnangle == old_rotnangle)
4251 	return;
4252 
4253     /* write the rotation angle in the background pixmap */
4254     for (i = 0; i < 8; i++)
4255       indbuf[i] = '\0';
4256     sprintf(indbuf, "%6.2f", cur_rotnangle);
4257     update_string_pixmap(sw, indbuf, sw->sw_width - 40, 22);
4258 
4259     if (panel) {
4260     /* change markers if we changed to or from 90/180 degrees (except at start)  */
4261         if (old_rotnangle != -1.0) {
4262 	    if (fabs(cur_rotnangle) == 90.0 || fabs(cur_rotnangle) == 180.0)
4263 	       update_markers(M_ALL);
4264 	    else if (fabs(old_rotnangle) == 90.0 || fabs(old_rotnangle) == 180.0)
4265 	       update_markers(M_ROTATE_ANGLE);
4266 	}
4267     }
4268     old_rotnangle = cur_rotnangle;
4269 }
4270 
4271 void
set_and_show_rotnangle(float value)4272 set_and_show_rotnangle(float value)
4273 {
4274     int i;
4275     ind_sw_info	   *sw;
4276 
4277     cur_rotnangle = value;
4278     for (i = 0; i < NUM_IND_SW; i++) {
4279       sw = ind_switches + i;
4280       if (sw->func == I_ROTNANGLE) {
4281         show_rotnangle_0(sw, 0);
4282         break;
4283       }
4284     }
4285 }
4286 
4287 /* NUMSIDES */
4288 
4289 static void
inc_numsides(ind_sw_info * sw)4290 inc_numsides(ind_sw_info *sw)
4291 {
4292     cur_numsides++;
4293     show_numsides(sw);
4294 }
4295 
4296 static void
dec_numsides(ind_sw_info * sw)4297 dec_numsides(ind_sw_info *sw)
4298 {
4299     cur_numsides--;
4300     show_numsides(sw);
4301 }
4302 
4303 static void
show_numsides(ind_sw_info * sw)4304 show_numsides(ind_sw_info *sw)
4305 {
4306     if (cur_numsides < 3)
4307 	cur_numsides = 3;
4308     else if (cur_numsides > MAX_POLY_SIDES)
4309 	cur_numsides = MAX_POLY_SIDES;
4310 
4311     put_msg("Number of sides %3d", cur_numsides);
4312     /* write the number of sides in the background pixmap */
4313     indbuf[0] = indbuf[1] = indbuf[2] = indbuf[3] = indbuf[4] = '\0';
4314     sprintf(indbuf, "%3d", cur_numsides);
4315     update_string_pixmap(sw, indbuf, sw->sw_width - 22, 20);
4316 }
4317 
4318 /* NUMCOPIES */
4319 
4320 static void
inc_numcopies(ind_sw_info * sw)4321 inc_numcopies(ind_sw_info *sw)
4322 {
4323     cur_numcopies++;
4324     show_numcopies(sw);
4325 }
4326 
4327 static void
dec_numcopies(ind_sw_info * sw)4328 dec_numcopies(ind_sw_info *sw)
4329 {
4330     cur_numcopies--;
4331     show_numcopies(sw);
4332 }
4333 
4334 static void
show_numcopies(ind_sw_info * sw)4335 show_numcopies(ind_sw_info *sw)
4336 {
4337     if (cur_numcopies < 1)
4338 	cur_numcopies = 1;
4339     else if (cur_numcopies > 99)
4340 	cur_numcopies = 99;
4341 
4342     put_msg("Number of copies %2d", cur_numcopies);
4343     /* write the number of copies in the background pixmap */
4344     indbuf[0] = indbuf[1] = indbuf[2] = indbuf[3] = indbuf[4] = '\0';
4345     sprintf(indbuf, "%2d", cur_numcopies);
4346     update_string_pixmap(sw, indbuf, sw->sw_width - 18, 20);
4347 }
4348 
4349 /* NUMXCOPIES */
4350 
4351 static void
inc_numxcopies(ind_sw_info * sw)4352 inc_numxcopies(ind_sw_info *sw)
4353 {
4354     cur_numxcopies++;
4355     show_numxcopies(sw);
4356 }
4357 
4358 static void
dec_numxcopies(ind_sw_info * sw)4359 dec_numxcopies(ind_sw_info *sw)
4360 {
4361     cur_numxcopies--;
4362     show_numxcopies(sw);
4363 }
4364 
4365 static void
show_numxcopies(ind_sw_info * sw)4366 show_numxcopies(ind_sw_info *sw)
4367 {
4368     if (cur_numxcopies < 0)
4369 	cur_numxcopies = 0;
4370     else if (cur_numxcopies > 999)
4371 	cur_numxcopies = 999;
4372 
4373     if (!cur_numxcopies)
4374       put_msg("Number of copies %2d in x-direction", cur_numxcopies);
4375     /* write the number of x copies in the background pixmap */
4376     indbuf[0] = indbuf[1] = indbuf[2] = indbuf[3] = indbuf[4] = '\0';
4377     sprintf(indbuf, "%2d", cur_numxcopies);
4378     update_string_pixmap(sw, indbuf, sw->sw_width - 18, 20);
4379 }
4380 
4381 /* NUMYCOPIES */
4382 
4383 static void
inc_numycopies(ind_sw_info * sw)4384 inc_numycopies(ind_sw_info *sw)
4385 {
4386     cur_numycopies++;
4387     show_numycopies(sw);
4388 }
4389 
4390 static void
dec_numycopies(ind_sw_info * sw)4391 dec_numycopies(ind_sw_info *sw)
4392 {
4393     cur_numycopies--;
4394     show_numycopies(sw);
4395 }
4396 
4397 static void
show_numycopies(ind_sw_info * sw)4398 show_numycopies(ind_sw_info *sw)
4399 {
4400     if (cur_numycopies < 0)
4401 	cur_numycopies = 0;
4402     else if (cur_numycopies > 999)
4403 	cur_numycopies = 999;
4404 
4405     if (!cur_numycopies)
4406       put_msg("Number of copies %2d in y-direction", cur_numycopies);
4407     /* write the number of y copies in the background pixmap */
4408     indbuf[0] = indbuf[1] = indbuf[2] = indbuf[3] = indbuf[4] = '\0';
4409     sprintf(indbuf, "%2d", cur_numycopies);
4410     update_string_pixmap(sw, indbuf, sw->sw_width - 18, 20);
4411 }
4412 
4413 /* ZOOM */
4414 
4415 /* zoom in */
4416 void
inc_zoom(void)4417 inc_zoom(void)
4418 {
4419     float	 intzoom;
4420 
4421     /* don't allow zooming while previewing */
4422     if (preview_in_progress || check_action_on())
4423 	return;
4424 
4425     if (display_zoomscale < (float) 0.1) {
4426 	display_zoomscale = (int)(display_zoomscale * 100.0 + 0.1) + 1.0;
4427 	display_zoomscale /= 100.0;
4428     } else if (display_zoomscale < 1.0) {
4429 	if (display_zoomscale < 0.1)
4430 	    display_zoomscale = 0.1;
4431 	else
4432 	    display_zoomscale += 0.1; /* always quantized */
4433 	display_zoomscale = (int)(display_zoomscale*10.0+0.01);
4434 	display_zoomscale /= 10.0;
4435     } else {
4436 	if (integral_zoom) {
4437 	    intzoom = round(display_zoomscale * 1.5);
4438 	    /* if user wants integral zoom, but 1.5 factor isn't enough, just increment zoom by 1 */
4439 	    if (intzoom == display_zoomscale)
4440 		intzoom++;
4441 	    display_zoomscale = intzoom;
4442 	} else
4443 	    display_zoomscale = display_zoomscale * 1.5;
4444     }
4445 }
4446 
4447 /* zoom out */
4448 void
dec_zoom(void)4449 dec_zoom(void)
4450 {
4451     float	 intzoom;
4452 
4453     /* don't allow zooming while previewing */
4454     if (preview_in_progress || check_action_on())
4455 	return;
4456 
4457     if (display_zoomscale <= (float) 0.1) {
4458 	display_zoomscale = ((int)(display_zoomscale * 100.0 + 0.1)) - 1.0;
4459 	display_zoomscale /= 100.0;
4460 	if (display_zoomscale <= MIN_ZOOM)
4461 	    display_zoomscale = MIN_ZOOM;
4462     } else if (display_zoomscale < (float) 0.3) {
4463 	display_zoomscale = 0.1; /* always quantized */
4464     } else if (display_zoomscale <= (float) 1.0) {
4465 	display_zoomscale -= 0.1; /* always quantized */
4466 	display_zoomscale = (int)(display_zoomscale*10.0+0.01);
4467 	display_zoomscale /= 10.0;
4468     } else {
4469 	if (integral_zoom) {
4470 	    intzoom = round(display_zoomscale / 1.5);
4471 	    /* if user wants integral zoom, but 1.5 factor isn't enough, just decrement zoom by 1 */
4472 	    if (intzoom == display_zoomscale)
4473 		intzoom--;
4474 	    display_zoomscale = intzoom;
4475 	} else
4476 	    display_zoomscale = display_zoomscale / 1.5;
4477 	if (display_zoomscale < (float) 1.0)
4478 		display_zoomscale = 1.0;
4479     }
4480 }
4481 
4482 /* zoom in or out, keeping location x,y fixed */
4483 void
zoom_focus(int x,int y,void (* zoom)())4484 zoom_focus(int x, int y, void(* zoom)())
4485 {
4486 	double	stretch;
4487 
4488 	/*
4489 	 * zoomxoff = -(CANVAS_WD/2.)*ZOOM_FACTOR/prev_zoom + zoomxoff +
4490 	 *		(CANVAS_WD/2.)*ZOOM_FACTOR/display_zoomscale;
4491 	 * stretch = 0.5*ZOOM_FACTOR*(-1./prev_zoom + 1./display_zoomscale);
4492 	 * and: zoomscale = display_zoomscale / ZOOM_FACTOR;
4493 	 */
4494 
4495 	stretch = 1. / display_zoomscale;	/* previous zoomscale */
4496 	zoom();
4497 	stretch -= 1. / display_zoomscale;	/* new zoomscale */
4498 	stretch *= ZOOM_FACTOR;
4499 	zoomxoff += stretch * x;
4500 	zoomyoff += stretch * y;
4501 
4502 	/* use zoom_sw instead of one passed to us because we might have come
4503            here from an accelerator */
4504 	show_zoom(zoom_sw);
4505 }
4506 
4507 void
inc_zoom_centered(ind_sw_info * sw)4508 inc_zoom_centered(ind_sw_info *sw)
4509 {
4510 	zoom_focus(CANVAS_WD/2, CANVAS_HT/2, inc_zoom);
4511 }
4512 
4513 void
dec_zoom_centered(ind_sw_info * sw)4514 dec_zoom_centered(ind_sw_info *sw)
4515 {
4516 	zoom_focus(CANVAS_WD/2, CANVAS_HT/2, dec_zoom);
4517 }
4518 
4519 /* zoom in either from wheel or accelerator, centering canvas on mouse */
4520 void
wheel_inc_zoom()4521 wheel_inc_zoom()
4522 {
4523     Window	 root, child;
4524     int		 x1, y1, junk;
4525 
4526     /* don't allow zooming while previewing */
4527     if (preview_in_progress || check_action_on())
4528 	return;
4529 
4530     XQueryPointer(tool_d, canvas_win, &root, &child,
4531 		  &junk, &junk, &x1, &y1, (unsigned int*) &junk);
4532 
4533     if (x1 < 0 || x1 > CANVAS_WD || y1 < 0 || y1 > CANVAS_HT) {
4534 	    x1 = CANVAS_WD / 2;
4535 	    y1 = CANVAS_HT / 2;
4536     }
4537     zoom_focus(x1, y1, inc_zoom);
4538 }
4539 
4540 
4541 /* zoom out either from wheel or accelerator, centering canvas on mouse */
4542 void
wheel_dec_zoom()4543 wheel_dec_zoom()
4544 {
4545     Window	 root, child;
4546     int		 x1, y1, junk;
4547 
4548     /* don't allow zooming while previewing */
4549     if (preview_in_progress || check_action_on())
4550 	return;
4551 
4552     XQueryPointer(tool_d, canvas_win, &root, &child,
4553 		  &junk, &junk, &x1, &y1, (unsigned int *) &junk);
4554 
4555     if (x1 < 0 || x1 > CANVAS_WD || y1 < 0|| y1 > CANVAS_HT) {
4556 	    x1 = CANVAS_WD / 2;
4557 	    y1 = CANVAS_HT / 2;
4558     }
4559     zoom_focus(x1, y1, dec_zoom);
4560 }
4561 
4562 /* zoom figure to fully fit in canvas */
4563 
4564 void
fit_zoom(ind_sw_info * sw)4565 fit_zoom(ind_sw_info *sw)
4566 {
4567     int		width, height;
4568     double	zoomx, zoomy;
4569 
4570     /* turn off Compose key LED */
4571     setCompLED(0);
4572 
4573     /* don't allow zooming while previewing */
4574     if (preview_in_progress || check_action_on())
4575 	return;
4576 
4577     /* get the figure bounds */
4578     compound_bound(&objects, &objects.nwcorner.x, &objects.nwcorner.y,
4579 			&objects.secorner.x, &objects.secorner.y);
4580     width = objects.secorner.x - objects.nwcorner.x;
4581     height = objects.secorner.y - objects.nwcorner.y;
4582     if (width == 0 && height == 0)
4583 	return;		/* no objects? */
4584 
4585     /* leave a border */
4586     width = 1.05 * width/ZOOM_FACTOR;
4587     height = 1.05 * height/ZOOM_FACTOR;
4588 
4589     if (width != 0)
4590 	zoomx = 1.0 * CANVAS_WD / width;
4591     else
4592 	zoomx = 1e6;
4593     if (height != 0)
4594 	zoomy = 1.0 * CANVAS_HT / height;
4595     else
4596 	zoomy = 1e6;
4597     zoomx = min2(zoomx, zoomy);
4598     zoomx = min2(zoomx, MAX_ZOOM);
4599     if (zoomx < MIN_ZOOM)
4600 	zoomx = MIN_ZOOM;
4601     if (integral_zoom && zoomx > 1.0)
4602 	zoomx = (double) ((int) zoomx);
4603     /* round to 2 decimal places */
4604     display_zoomscale = (double) ((int) (zoomx*100.0))/100.0;
4605     if (display_zoomscale < MIN_ZOOM)
4606 	display_zoomscale = MIN_ZOOM;
4607 
4608     /* keep it on the canvas */
4609     zoomxoff = objects.nwcorner.x - 100/display_zoomscale;
4610     zoomyoff = objects.nwcorner.y - 100/display_zoomscale;
4611     if (!appres.allownegcoords) {
4612 	if (zoomxoff < 0)
4613 	    zoomxoff = 0;
4614 	if (zoomyoff < 0)
4615 	    zoomyoff = 0;
4616     }
4617 
4618     if (display_zoomscale == old_display_zoomscale) {
4619 	/* if the zoom hasn't changed, just make sure it's centered */
4620 	/* fix up the rulers and grid */
4621 	reset_rulers();
4622 	redisplay_canvas();
4623     } else {
4624 	/* update the zoom indicator */
4625 	show_zoom(zoom_sw);
4626     }
4627 }
4628 
4629 void
show_zoom(ind_sw_info * sw)4630 show_zoom(ind_sw_info *sw)
4631 {
4632     /* turn off Compose key LED */
4633     setCompLED(0);
4634 
4635     /* don't allow zooming while previewing */
4636     if (preview_in_progress || check_action_on())
4637 	return;
4638 
4639     if (display_zoomscale < MIN_ZOOM)
4640 	display_zoomscale = MIN_ZOOM;
4641     else if (display_zoomscale > MAX_ZOOM)
4642 	display_zoomscale = MAX_ZOOM;
4643 
4644     /* write the zoom value in the background pixmap */
4645     indbuf[0] = indbuf[1] = indbuf[2] = indbuf[3] = indbuf[4] = '\0';
4646     if (display_zoomscale == (int) display_zoomscale) {
4647 	if (display_zoomscale < 10.0) {
4648 	    sprintf(indbuf, "    %.0f",display_zoomscale);
4649 	} else if (display_zoomscale < 100.0) {
4650 	    sprintf(indbuf, "   %.0f",display_zoomscale);
4651 	} else {
4652 	    sprintf(indbuf, "  %.0f",display_zoomscale);
4653 	}
4654     } else if (display_zoomscale < 10.0) {
4655 	display_zoomscale = (double) ((int) (display_zoomscale*100.0+0.5))/100.0;
4656 	sprintf(indbuf, " %.2f", display_zoomscale);
4657     } else if (display_zoomscale < 100.0) {
4658 	display_zoomscale = (double) ((int) (display_zoomscale*10.0+0.5))/10.0;
4659 	sprintf(indbuf, " %.1f", display_zoomscale);
4660     } else {
4661 	display_zoomscale = (double) ((int) display_zoomscale+0.5);
4662 	sprintf(indbuf, "%.0f",display_zoomscale);
4663     }
4664 
4665     put_msg("Zoom scale %s", indbuf);
4666 
4667     update_string_pixmap(sw, indbuf, sw->sw_width - 35, 24);
4668 
4669     zoomscale=display_zoomscale/ZOOM_FACTOR;
4670 
4671     /* fix up the rulers and grid */
4672     reset_rulers();
4673     /* reload text objects' font structures since we need
4674 	to load larger/smaller fonts */
4675     reload_text_fstructs();
4676     setup_grid();
4677     old_display_zoomscale = display_zoomscale;
4678 }
4679 
4680 /* DEPTH */
4681 
4682 static void
inc_depth(ind_sw_info * sw)4683 inc_depth(ind_sw_info *sw)
4684 {
4685     cur_depth++;
4686     show_depth(sw);
4687 }
4688 
4689 static void
dec_depth(ind_sw_info * sw)4690 dec_depth(ind_sw_info *sw)
4691 {
4692     cur_depth--;
4693     show_depth(sw);
4694 }
4695 
4696 void
show_depth(ind_sw_info * sw)4697 show_depth(ind_sw_info *sw)
4698 {
4699     if (cur_depth < 0)
4700 	cur_depth = 0;
4701     else if (cur_depth > MAX_DEPTH)
4702 	cur_depth = MAX_DEPTH;
4703 
4704     put_msg("Depth %3d", cur_depth);
4705 
4706     /* write the depth in the background pixmap */
4707     indbuf[0] = indbuf[1] = indbuf[2] = indbuf[3] = indbuf[4] = '\0';
4708     sprintf(indbuf, "%3d", cur_depth);
4709     update_string_pixmap(sw, indbuf, sw->sw_width - 22, 20);
4710 }
4711 
4712 /* TEXTSTEP */
4713 
4714 static void
inc_textstep(ind_sw_info * sw)4715 inc_textstep(ind_sw_info *sw)
4716 {
4717     if (cur_textstep >= 10.0) {
4718 	cur_textstep = (int) cur_textstep;	/* round first */
4719 	cur_textstep += 1.0;
4720     } else if (cur_textstep >= 5.0) {
4721 	cur_textstep = ((int)(cur_textstep*2.0+0.01))/2.0;
4722 	cur_textstep += 0.5;
4723     } else if (cur_textstep >= 2.0) {
4724 	cur_textstep = ((int)(cur_textstep*5.0+0.01))/5.0;
4725 	cur_textstep += 0.2;
4726     } else
4727 	cur_textstep += 0.1;
4728     show_textstep(sw);
4729 }
4730 
4731 static void
dec_textstep(ind_sw_info * sw)4732 dec_textstep(ind_sw_info *sw)
4733 {
4734     if (cur_textstep > 10.0) {
4735 	cur_textstep = (int)cur_textstep;	/* round first */
4736 	cur_textstep -= 1.0;
4737     } else if (cur_textstep > 5.0) {
4738 	cur_textstep = ((int)(cur_textstep*2.0+0.01))/2.0;
4739 	cur_textstep -= 0.5;
4740     } else if (cur_textstep > 2.0) {
4741 	cur_textstep = ((int)(cur_textstep*5.0+0.01))/5.0;
4742 	cur_textstep -= 0.2;
4743     } else if (cur_textstep > 0.4)
4744 	cur_textstep -= 0.1;
4745     show_textstep(sw);
4746 }
4747 
4748 /* could make this more generic - but a copy will do for font set JNT */
4749 static void
show_textstep(ind_sw_info * sw)4750 show_textstep(ind_sw_info *sw)
4751 {
4752     if (cur_textstep < (float) MIN_TEXT_STEP)
4753 	cur_textstep = (float) MIN_TEXT_STEP;
4754     else if (cur_textstep > (float) MAX_TEXT_STEP)
4755 	cur_textstep = (float) MAX_TEXT_STEP;
4756 
4757     cur_textstep = round(cur_textstep*10.0)/10.0;
4758     put_msg("Text step %.1f", cur_textstep);
4759     /* write the text step in the background pixmap */
4760     indbuf[0] = indbuf[1] = indbuf[2] = indbuf[3] = indbuf[4] = '\0';
4761     sprintf(indbuf, "%4.1f", cur_textstep);
4762     update_string_pixmap(sw, indbuf, sw->sw_width - 28, 20);
4763 }
4764 
4765 /* call fit_zoom() then dismiss zoom panel */
4766 
4767 static void
zoom_to_fit(Widget w,XtPointer closure,XtPointer call_data)4768 zoom_to_fit(Widget w, XtPointer closure, XtPointer call_data)
4769 {
4770     ind_sw_info *sw = (ind_sw_info *) closure;
4771 
4772     fit_zoom(sw);
4773     nval_panel_dismiss();
4774 }
4775 
4776 /*
4777  * make a pulldown menu with "nent" button entries (PIXMAPS) that call "callback"
4778  * when pressed
4779  */
4780 
4781 void
make_pulldown_menu_images(choice_info * entries,Cardinal nent,Pixmap * images,char ** texts,Widget parent,XtCallbackProc callback)4782 make_pulldown_menu_images(choice_info *entries, Cardinal nent, Pixmap *images, char **texts, Widget parent, XtCallbackProc callback)
4783 {
4784     Widget	    pulldown_menu, entry;
4785     char	    buf[64];
4786     int		    i;
4787 
4788     pulldown_menu = XtCreatePopupShell("menu", simpleMenuWidgetClass, parent,
4789 				  NULL, ZERO);
4790 
4791     for (i = 0; i < nent; i++) {
4792 	FirstArg(XtNleftBitmap, images[i]);	/* image of object */
4793 	NextArg(XtNleftMargin, 32);
4794 	NextArg(XtNvertSpace, 80);		/* height 180% of font */
4795 	NextArg(XtNlabel, texts? texts[i] : "");
4796 	sprintf(buf,"%d",i);
4797 	entry = XtCreateManagedWidget(buf, smeBSBObjectClass, pulldown_menu,
4798 				      Args, ArgCount);
4799 	XtAddCallback(entry, XtNcallback, callback, (XtPointer) &entries[i]);
4800     }
4801 }
4802 
4803 /* set the update switches according to the chosen named style */
4804 
4805 void
tog_selective_update(long unsigned int mask)4806 tog_selective_update(long unsigned int mask)
4807 {
4808     int i;
4809 
4810     for (i = 0; i < NUM_IND_SW; ++i) {
4811 	if (ind_switches[i].updbut == NULL)
4812 		continue;
4813 
4814 	if (ind_switches[i].func & mask)
4815 	  ind_switches[i].update = True;
4816 	else
4817 	  ind_switches[i].update=False;
4818 
4819 	FirstArg(XtNstate, ind_switches[i].update);
4820 	SetValues(ind_switches[i].updbut);
4821     }
4822     put_msg("Update command status SELECTIVELY toggled");
4823     cur_indmask=mask;
4824     cur_updatemask =mask;
4825 }
4826