1 /*
2  * FIG : Facility for Interactive Generation of figures
3  * This file Copyright (c) 2002 Stephane Mancini
4  *
5  * Any party obtaining a copy of these files is granted, free of charge, a
6  * full and unrestricted irrevocable, world-wide, paid up, royalty-free,
7  * nonexclusive right and license to deal in this software and documentation
8  * files (the "Software"), including without limitation the rights to use,
9  * copy, modify, merge, publish, distribute, sublicense and/or sell copies of
10  * the Software, and to permit persons who receive copies from any such
11  * party to do so, with the only requirement being that the above copyright
12  * and this permission notice remain intact.
13  *
14  */
15 
16 #include "fig.h"
17 #include "figx.h"
18 #include "resources.h"
19 #include "object.h"
20 #include "mode.h"
21 #include "paintop.h"
22 #include "d_text.h"
23 #include "e_edit.h"
24 #include "e_update.h"
25 #include "u_draw.h"
26 #include "u_fonts.h"
27 #include "w_drawprim.h"
28 #include "w_file.h"
29 #include "w_fontbits.h"
30 #include "w_indpanel.h"
31 #include "w_color.h"
32 #include "w_listwidget.h"
33 #include "w_mousefun.h"
34 #include "w_msgpanel.h"
35 #include "w_setup.h"
36 #include "w_style.h"
37 #include "w_util.h"
38 #include "w_zoom.h"
39 
40 #include "w_modepanel.h"
41 
42 /* EXPORTS */
43 
44 void	popup_manage_style_panel(void);
45 void	close_style(Widget w, XButtonEvent *ev);
46 Boolean	style_dirty_flag = False;
47 
48 /* LOCALS */
49 
50 static Style_family current_family_set[MAX_STYLE_FAMILY_SET];
51 int     current_family = -1, current_style = -1;
52 Widget  style_popup, style_main_form, style_main_label;
53 Widget  style_family_form, style_style_form;
54 Widget  style_family_label, style_family_list_viewport,
55 	style_family_choice_label, style_family_list, style_family_name,
56 	style_add_family, style_delete_family;
57 Widget  style_style_label, style_style_list_viewport,
58 	style_style_choice_label, style_style_list, style_style_name,
59 	style_add_style, style_delete_style;
60 Widget  style_save_style, style_load_style, style_close_style;
61 char   *family_text[MAX_STYLE_FAMILY_SET + 1];
62 char   *style_text[MAX_STYLE_FAMILY + 1];
63 
64 DeclareStaticArgs (20);
65 
66 Element style_reference[] = {
67     "depth", Tint, "", &cur_depth, I_DEPTH,
68     "text_step", Tfloat, NULL, &cur_textstep, I_TEXTSTEP,
69     "font_size", Tint, NULL, &cur_fontsize, I_FONTSIZE,
70     "font", Tint, NULL, &cur_latex_font, I_FONT,
71     "font_ps", Tint, NULL, &cur_ps_font, I_FONT,
72     "font_latex", Tint, NULL, &cur_latex_font, I_FONT,
73     "text_flags", Tint, NULL, &cur_textflags, I_FONT | I_TEXTFLAGS,
74     "text_just", Tint, NULL, &cur_textjust, I_TEXTJUST,
75     "line_width", Tint, NULL, &cur_linewidth, I_LINEWIDTH,
76     "line_style", Tint, NULL, &cur_linestyle, I_LINESTYLE,
77     "join_style", Tint, NULL, &cur_joinstyle, I_JOINSTYLE,
78     "cap_style", Tint, NULL, &cur_capstyle, I_CAPSTYLE,
79     "dash_length", Tfloat, NULL, &cur_dashlength, I_CAPSTYLE,
80     "dot_gap", Tfloat, NULL, &cur_dotgap, I_CAPSTYLE,
81     "pen_color", TColor, NULL, &cur_pencolor, I_PEN_COLOR,
82     "fill_color", TColor, NULL, &cur_fillcolor, I_FILL_COLOR,
83     "box_radius", Tint, NULL, &cur_boxradius, I_BOXRADIUS,
84     "fill_style", Tint, NULL, &cur_fillstyle, I_FILLSTYLE,
85     "arrow_mode", Tint, NULL, &cur_arrowmode, I_ARROWMODE,
86     "arrow_type", Tint, NULL, &cur_arrowtype, I_ARROWTYPE,
87     "arrow_width", Tfloat, NULL, &cur_arrowwidth, I_ARROWSIZE,
88     "arrow_height", Tfloat, NULL, &cur_arrowheight, I_ARROWSIZE,
89     "arrow_thick", Tfloat, NULL, &cur_arrowthick, I_ARROWSIZE,
90     "arrow_mult_width", Tfloat, NULL, &cur_arrow_multwidth, I_ARROWSIZE,
91     "arrow_mult_height", Tfloat, NULL, &cur_arrow_multheight, I_ARROWSIZE,
92     "arrow_mult_thick", Tfloat, NULL, &cur_arrow_multthick, I_ARROWSIZE,
93     "arc_type", Tint, NULL, &cur_arctype, I_ARCTYPE,
94     "ellipse_text_angle", Tfloat, NULL, &cur_elltextangle, I_ELLTEXTANGLE,
95     NULL, 0, NULL, NULL, 0
96 };
97 
98 
99 
100 void
construct_style(Style * style,unsigned long flag)101 construct_style (Style * style, unsigned long flag)
102 {
103     int     i = 0, j = 0;
104 
105     while (style_reference[i].name != NULL) {
106 	if (flag & style_reference[i].flag) {
107 	    style->element[j].name = style_reference[i].name;
108 	    style->element[j].type = style_reference[i].type;
109 	    style->element[j].toset = style_reference[i].toset;
110 	    style->element[j].flag = style_reference[i].flag;
111 	    switch (style_reference[i].type) {
112 		case Tint:
113 		    style->element[j].value = malloc (sizeof (int));
114 		    *((int *) style->element[j].value) =
115 			*((int *) style_reference[i].toset);
116 		    break;
117 		case Tfloat:
118 		    style->element[j].value = malloc (sizeof (float));
119 		    *((float *) style->element[j].value) =
120 			*((float *) style_reference[i].toset);
121 		    break;
122 		case TColor:
123 		    style->element[j].value = malloc (sizeof (int));
124 		    *((int *) style->element[j].value) =
125 			*((int *) style_reference[i].toset);
126 		    break;
127 	    }
128 	    j++;
129 	}
130 	i++;
131     }
132     if (j < MAX_STYLE_ELEMENT)
133 	style->element[j].name = NULL;
134 }
135 
136 unsigned long
set_style(Style * style)137 set_style (Style * style)
138 {
139     int     i = 0;
140     unsigned long flag = 0;
141 
142     while (style->element[i].name != NULL) {
143 	flag = flag | style->element[i].flag;
144 	switch (style->element[i].type) {
145 	    case Tint:
146 		*((int *) style->element[i].toset) = *((int *) style->element[i].value);
147 		break;
148 	    case Tfloat:
149 		*((float *) style->element[i].toset) =
150 		    *((float *) style->element[i].value);
151 		break;
152 	    case TColor:
153 		*((int *) style->element[i].toset) = *((int *) style->element[i].value);
154 		break;
155 	}
156 	i++;
157     }
158     return flag;
159 }
160 
161 static int indent;
162 
print_indent(FILE * file)163 void print_indent (FILE * file)
164 {
165     int     i;
166 
167     for (i = 0; i < indent; i++)
168 	fprintf (file, " ");
169 }
170 
171 void
print_style(FILE * file,Style * style)172 print_style (FILE * file, Style * style)
173 {
174     int     i = 0;
175 
176     print_indent (file);
177     fprintf (file, "%s [\n", style[i].name);
178     indent += 2;
179     while (style->element[i].name != NULL) {
180 	print_indent (file);
181 	fprintf (file, "%s : ", style->element[i].name);
182 	switch (style->element[i].type) {
183 	    case Tint:
184 		fprintf (file, "%d\n", *((int *) style->element[i].value));
185 		break;
186 	    case Tfloat:
187 		fprintf (file, "%f\n", *((float *) style->element[i].value));
188 		break;
189 	    case TColor:
190 		fprintf (file, "%d\n", *((int *) style->element[i].value));
191 		break;
192 	}
193 	i++;
194     }
195     indent -= 2;
196     print_indent (file);
197     fprintf (file, "]\n");
198 }
199 
200 void
print_style_family(FILE * file,Style_family * family)201 print_style_family (FILE * file, Style_family * family)
202 {
203     int     i = 0;
204 
205     print_indent (file);
206     fprintf (file, "%s {\n", family->name);
207     indent += 2;
208     while (family->style[i].name != NULL) {
209 	print_style (file, &family->style[i]);
210 	i++;
211     }
212     indent -= 2;
213     print_indent (file);
214     fprintf (file, "}\n");
215 }
216 
217 void
print_family_set(FILE * file,Style_family * family)218 print_family_set (FILE * file, Style_family * family)
219 {
220     int     i = 0;
221 
222     indent = 0;
223     while (family[i].name != NULL) {
224 	print_style_family (file, &family[i]);
225 	i++;
226     }
227 }
228 
229 /* return the next non-blank line */
230 
231 char   *
get_nstyle_line(char * string,int buflen,FILE * file)232 get_nstyle_line (char *string, int buflen, FILE * file)
233 {
234     int     i;
235 
236     while (1) {
237 	if (fgets (string, buflen, file) == NULL)
238 	    return NULL;
239 	if (strlen (string) == 1)
240 	    continue;		/* empty (except for newline) - read next */
241 	for (i = strlen (string); i >= 0; i--)
242 	    if (string[i] != '\t' && string[i] != ' ')
243 		return string;	/* found at least one non-blank char */
244     }
245 }
246 
247 /* remove leading and trailing blanks */
248 
249 void
trim(char * string)250 trim (char *string)
251 {
252     int     i, j, k, len;
253 
254     len = strlen (string);
255     for (i = 0; i < len; i++)
256 	if (string[i] != ' ')
257 	    break;
258     for (j = strlen (string) - 1; j > i; j--)
259 	if (string[j] != ' ')
260 	    break;
261     if (j)
262 	string[j + 1] = '\0';
263     /* now move string left if i>0 */
264     if (i)
265 	for (k = 0; k <= j; i++, k++)
266 	    string[k] = string[i];
267 }
268 
269 /* parse a single style */
270 int
parse_style(Style * style,FILE * file)271 parse_style (Style * style, FILE * file)
272 {
273     int     i = 0, j = 0;
274     char    name[256], value[256], string[256];
275     long    pos;
276 
277     pos = ftell (file);
278     if (get_nstyle_line (string, 256, file) == NULL)
279 	return 1;
280     if ((sscanf (string, "%[^[^\n] [", name) != 1) || string[0] == '}') {
281 	fseek (file, pos, 0);
282 	return 1;
283     }
284     /* remove leading and trailing blanks */
285     trim (name);
286     style->name = strdup (name);
287     if (get_nstyle_line (string, 256, file) == NULL)
288 	return 1;
289     while (string[0] != ']' &&
290 	   i < MAX_STYLE_ELEMENT && sscanf (string, "%s : %s", name, value) == 2) {
291 	while (style_reference[j].name != NULL && strcmp (style_reference[j].name, name))
292 	    j++;
293 	if (style_reference[j].name != NULL) {
294 	    style->element[i].name = style_reference[j].name;
295 	    style->element[i].type = style_reference[j].type;
296 	    style->element[i].toset = style_reference[j].toset;
297 	    style->element[i].flag = style_reference[j].flag;
298 	    switch (style->element[i].type) {
299 		case Tint:
300 		    style->element[i].value = malloc (sizeof (int));
301 		    *((int *) style->element[i].value) = atoi (value);
302 		    break;
303 
304 		case Tfloat:
305 		    style->element[i].value = malloc (sizeof (float));
306 		    *((float *) style->element[i].value) = atof (value);
307 		    break;
308 
309 		case TColor:
310 		    style->element[i].value = malloc (sizeof (int));
311 		    *((int *) style->element[i].value) = atoi (value);
312 		    break;
313 	    }
314 	    i++;
315 	}
316 	if (get_nstyle_line (string, 256, file) == NULL)
317 	    return 1;
318     }
319     style->element[i].name = NULL;
320     return 0;
321 }
322 
323 int
parse_family_style(Style_family * family,FILE * file)324 parse_family_style (Style_family * family, FILE * file)
325 {
326     int     i = 0, r;
327     char    name[256], string[256];
328 
329     if (get_nstyle_line (string, 256, file) == NULL)
330 	return EOF;
331 
332     r = sscanf (string, "%[^{^\n] {", name);
333     /* remove leading and trailing blanks */
334     trim (name);
335     family->name = strdup (name);
336     while (i < MAX_STYLE_FAMILY && !parse_style (&family->style[i], file)) {
337 	i++;
338     }
339     if (get_nstyle_line (string, 256, file) == NULL)
340 	return 1;
341     if (string[0] != '}') {
342 	i = 0;
343 	return 1;
344     }
345     if (i < MAX_STYLE_FAMILY)
346 	family->style[i].name = NULL;
347     return 0;
348 }
349 
350 void
parse_family_set(Style_family * family,FILE * file)351 parse_family_set (Style_family * family, FILE * file)
352 {
353     int     i = 0, ok;
354 
355     while ((ok = parse_family_style (&family[i], file)) == 0)
356 	i++;
357     if (ok == 1)
358 	i = 0;
359     if (i < MAX_STYLE_FAMILY_SET)
360 	family[i].name = NULL;
361 }
362 
363 void
load_family_set(Style_family * family)364 load_family_set (Style_family * family)
365 {
366     FILE   *file;
367     char    name[PATH_MAX];
368 
369     strcpy (name, xfigrc_name);
370     strcat (name, "style");
371     if ((file = fopen (name, "r")) != NULL) {
372 	parse_family_set (family, file);
373 	fclose (file);
374     }
375     else {
376 	family[0].name = NULL;
377     }
378     /* clear dirty flag */
379     style_dirty_flag = False;
380 }
381 
382 void
save_family_set(Style_family * family)383 save_family_set (Style_family * family)
384 {
385     FILE   *file;
386     char    name[PATH_MAX];
387 
388     strcpy (name, xfigrc_name);
389     strcat (name, "style");
390     file = fopen (name, "w");
391     print_family_set (file, family);
392     fclose (file);
393     /* clear dirty flag */
394     style_dirty_flag = False;
395 }
396 
397 /* the name should not contain blanks */
398 int
add_family_to_family_set(Style_family * family,char * name)399 add_family_to_family_set (Style_family * family, char *name)
400 {
401     int     i, ok;
402 
403     /* search if the family already exists */
404     i = 0;
405     while (i < MAX_STYLE_FAMILY_SET &&
406 	   family[i].name != NULL && (ok = (strcmp (family[i].name, name) != 0)))
407 	i++;
408 
409     if ((i < MAX_STYLE_FAMILY_SET) && (family[i].name == NULL)) {
410 	family[i].name = strdup (name);
411 	family[i].style[0].name = NULL;
412 	if (i + 1 < MAX_STYLE_FAMILY_SET)
413 	    family[i + 1].name = NULL;
414 	/* set dirty flag */
415 	style_dirty_flag = True;
416     }
417     return i;
418 }
419 
420 Boolean
add_style_to_family(Style_family * family,int * iii,int * jjj,char * family_name,char * style_name,unsigned long flag)421 add_style_to_family (Style_family * family,
422 		     int *iii, int *jjj,
423 		     char *family_name, char *style_name, unsigned long flag)
424 {
425     int		i, j, ok;
426     Boolean	status;
427 
428     i = add_family_to_family_set (family, family_name);
429     j = 0;
430     while (j < MAX_STYLE_FAMILY &&
431 	   family[i].style[j].name != NULL &&
432 	   (ok = (strcmp (family[i].style[j].name, style_name) != 0)))
433 	j++;
434 
435     if (j < MAX_STYLE_FAMILY) {
436 	if (family[i].style[j].name == NULL) {
437 	    family[i].style[j].name = strdup (style_name);
438 	    family[i].style[j].element[0].name = NULL;
439 	    if (j + 1 < MAX_STYLE_FAMILY)
440 		family[i].style[j + 1].name = NULL;
441 	    /* set dirty flag */
442 	    style_dirty_flag = True;
443 	}
444 	construct_style (&family[i].style[j], flag);
445 	*iii = i;
446 	*jjj = j;
447 	status = True;
448     } else {
449 	*iii = -1;
450 	*jjj = -1;
451 	status = False;
452     }
453     return status;
454 }
455 
delete_family_from_family_set(Style_family * family,char * name)456 void delete_family_from_family_set (Style_family * family, char *name)
457 {
458     int		i, ii, j, k, ok;
459 
460     /* search if the family  exists */
461     i = 0;
462     while (i < MAX_STYLE_FAMILY_SET &&
463 	   family[i].name != NULL && (ok = (strcmp (family[i].name, name) != 0)))
464 	i++;
465     /* it exists */
466     if (!ok) {
467 	free (family[i].name);
468 	j = 0;
469 	while (j < MAX_STYLE_FAMILY && family[i].style[j].name != NULL) {
470 	    free (family[i].style[j].name);
471 	    k = 0;
472 	    while (family[i].style[j].element[k].name != NULL) {
473 		free (family[i].style[j].element[k].value);
474 		k++;
475 	    }
476 	    j++;
477 	}
478 	for (ii = i + 1; ii < MAX_STYLE_FAMILY_SET && family[ii].name != NULL; ii++) {
479 	    family[ii - 1].name = family[ii].name;
480 	    j = 0;
481 	    while (j < MAX_STYLE_FAMILY && family[ii].style[j].name != NULL) {
482 		family[ii - 1].style[j].name = family[ii].style[j].name;
483 		k = 0;
484 		while (family[ii].style[j].element[k].name != NULL) {
485 		    family[ii - 1].style[j].element[k] = family[ii].style[j].element[k];
486 		    k++;
487 		}
488 		family[ii - 1].style[j].element[k].name = NULL;
489 		j++;
490 	    }
491 	    family[ii - 1].style[j].name = NULL;
492 	}
493 	family[ii - 1].name = NULL;
494 	/* set dirty flag */
495 	style_dirty_flag = True;
496     }
497 }
498 
delete_style_from_family(Style_family * family,char * family_name,char * style_name)499 void delete_style_from_family (Style_family * family, char *family_name, char *style_name)
500 {
501     int     i, j, jj, k, ok;
502 
503     /* search the family */
504     i = 0;
505     while (i < MAX_STYLE_FAMILY_SET &&
506 	   family[i].name != NULL && (ok = (strcmp (family[i].name, family_name) != 0)))
507 	i++;
508     /* it exists */
509     if (!ok) {
510 	/* search the style */
511 	j = 0;
512 	while (j < MAX_STYLE_FAMILY &&
513 	       family[i].style[j].name != NULL &&
514 	       (ok = (strcmp (family[i].style[j].name, style_name) != 0)))
515 	    j++;
516 	if (!ok) {
517 	    free (family[i].style[j].name);
518 	    k = 0;
519 	    while (family[i].style[j].element[k].name != NULL) {
520 		free (family[i].style[j].element[k].value);
521 		k++;
522 	    }
523 	    for (jj = j + 1;
524 		 jj < MAX_STYLE_FAMILY && family[i].style[jj].name != NULL; jj++) {
525 		family[i].style[jj - 1].name = family[i].style[jj].name;
526 		k = 0;
527 		while (family[i].style[jj].element[k].name != NULL) {
528 		    family[i].style[jj - 1].element[k] = family[i].style[jj].element[k];
529 		    k++;
530 		}
531 		family[i].style[jj].element[k].name = NULL;
532 	    }
533 	    family[i].style[jj - 1].name = NULL;
534 	    /* set dirty flag */
535 	    style_dirty_flag = True;
536 	}
537     }
538 }
539 
540 static void
build_family_text(Style_family * family)541 build_family_text (Style_family * family)
542 {
543     int     i = 0;
544 
545     while (i < MAX_STYLE_FAMILY_SET && family[i].name != NULL) {
546 	family_text[i] = family[i].name;
547 	i++;
548     }
549     family_text[i] = NULL;
550 }
551 
552 static void
build_style_text(Style_family * family,int f)553 build_style_text (Style_family * family, int f)
554 {
555     int     i = 0;
556 
557     if (f >= 0) {
558 	while (i < MAX_STYLE_FAMILY && family[f].style[i].name != NULL) {
559 	    style_text[i] = family[f].style[i].name;
560 	    i++;
561 	}
562 	style_text[i] = NULL;
563     }
564     else
565 	style_text[0] = NULL;
566 }
567 
568 static void
style_update(void)569 style_update (void)
570 {
571     build_family_text (current_family_set);
572     build_style_text (current_family_set, current_family);
573     XawListChange (style_family_list, family_text, 0, 0, True);
574     XawListChange (style_style_list, style_text, 0, 0, True);
575     if (current_family >= 0)
576 	panel_set_value (style_family_name, family_text[current_family]);
577     else
578 	panel_set_value (style_family_name, "");
579 
580     if (current_style >= 0)
581 	panel_set_value (style_style_name, style_text[current_style]);
582     else
583 	panel_set_value (style_style_name, "");
584 }
585 
586 static void
family_select(Widget w,XtPointer closure,XtPointer call_data)587 family_select (Widget w, XtPointer closure, XtPointer call_data)
588 {
589 
590     XawListReturnStruct *ret_struct = (XawListReturnStruct *) call_data;
591 
592     if (ret_struct == 0)
593 	return;
594     current_family = ret_struct->list_index;
595     current_style = -1;
596     style_update ();
597 }
598 
599 static void
style_select(Widget w,XtPointer closure,XtPointer call_data)600 style_select (Widget w, XtPointer closure, XtPointer call_data)
601 {
602     XawListReturnStruct *ret_struct = (XawListReturnStruct *) call_data;
603 
604     if (ret_struct == 0)
605 	return;
606     current_style = ret_struct->list_index;
607     style_update ();
608     cur_updatemask = set_style (&current_family_set[current_family].style[current_style]);
609 
610     tog_selective_update (cur_updatemask);
611     update_current_settings ();
612 }
613 
614 void
add_family(Widget w,XButtonEvent * ev)615 add_family (Widget w, XButtonEvent *ev)
616 {
617     char   *fval;
618 
619     FirstArg (XtNstring, &fval);
620     GetValues (style_family_name);
621     if (strlen (fval)) {
622 	current_family = add_family_to_family_set (current_family_set, fval);
623 	current_style = -1;
624 	style_update ();
625     }
626 }
627 
628 void
delete_family(Widget w,XButtonEvent * ev)629 delete_family (Widget w, XButtonEvent *ev)
630 {
631     char   *fval;
632 
633     FirstArg (XtNstring, &fval);
634     GetValues (style_family_name);
635     if (strlen (fval)) {
636 	delete_family_from_family_set (current_family_set, fval);
637 	current_family = -1;
638 	current_style = -1;
639 	style_update ();
640     }
641 }
642 
643 void
add_style(Widget w,XButtonEvent * ev)644 add_style (Widget w, XButtonEvent *ev)
645 {
646     char   *fval, *sval, ftemp[256], stemp[256];
647 
648     FirstArg (XtNstring, &fval);
649     GetValues (style_family_name);
650     strcpy (ftemp, fval);
651     FirstArg (XtNstring, &sval);
652     GetValues (style_style_name);
653     strcpy (stemp, sval);
654     if (strlen (ftemp) && strlen (stemp)) {
655 	if (!add_style_to_family (current_family_set,
656 			     &current_family, &current_style,
657 			     ftemp, stemp, cur_updatemask))
658 	    file_msg("Sorry, no more room available in this family : use a new one");
659 	style_update ();
660     }
661 }
662 
663 
664 
665 void
delete_style(Widget w,XButtonEvent * ev)666 delete_style (Widget w, XButtonEvent *ev)
667 {
668     char   *fval, *sval;
669 
670     FirstArg (XtNstring, &fval);
671     GetValues (style_family_name);
672     FirstArg (XtNstring, &sval);
673     GetValues (style_style_name);
674     if (strlen (fval) && strlen (sval)) {
675 	delete_style_from_family (current_family_set, fval, sval);
676 	current_style = -1;
677 	style_update ();
678     }
679 }
680 
681 void
save_style(Widget w,XButtonEvent * ev)682 save_style (Widget w, XButtonEvent *ev)
683 {
684     save_family_set (current_family_set);
685 }
686 
687 void
load_style(Widget w,XButtonEvent * ev)688 load_style (Widget w, XButtonEvent *ev)
689 {
690     load_family_set (current_family_set);
691     current_family = current_style = -1;
692     style_update ();
693 }
694 
695 int
confirm_close_style(void)696 confirm_close_style (void)
697 {
698     int      status;
699 
700     if (style_dirty_flag) {
701 	status = popup_query(QUERY_YESNOCAN, "Do you wish to save the changes you made to the styles?");
702 	if (status == RESULT_YES)
703 	    save_style((Widget) 0, (XButtonEvent *) 0);
704 	return status;
705     }
706     return RESULT_YES;
707 }
708 
709 void
close_style(Widget w,XButtonEvent * ev)710 close_style (Widget w, XButtonEvent *ev)
711 {
712     if (confirm_close_style() == RESULT_CANCEL)
713 	return;
714     XtPopdown (style_popup);
715 }
716 
717 static String style_family_list_translations = "<Btn1Down>,<Btn1Up>: Set()Notify()\n\
718 	 <Btn1Up>(2): family_select()\n\
719 	 <Key>Escape: CloseStyle()\n\
720 	 <Key>Return: family_select()\n";
721 
722 static String style_family_name_translations = "<Key>Escape: CloseStyle()\n\
723 	 <Key>Return: add_family()\n";
724 
725 static String style_style_list_translations = "<Btn1Down>,<Btn1Up>: Set()Notify()\n\
726 	 <Btn1Up>(2): style_select()\n\
727 	 <Key>Escape: CloseStyle()\n\
728 	 <Key>Return: style_select()\n";
729 
730 static String style_style_name_translations = "<Key>Escape: CloseStyle()\n\
731 	 <Key>Return: add_style()\n";
732 
733 static String style_translations = "<Message>WM_PROTOCOLS: CloseStyle()\n\
734 	 <Key>Escape: CloseStyle()\n";
735 
736 static XtActionsRec style_actions[] = {
737     "ShowNamedStyles", (XtActionProc) popup_manage_style_panel,
738     "add_family", (XtActionProc) add_family,
739     "delete_family", (XtActionProc) delete_family,
740     "add_style", (XtActionProc) add_style,
741     "delete_style", (XtActionProc) delete_style,
742     "family_select", (XtActionProc) family_select,
743     "style_select", (XtActionProc) style_select,
744     "CloseStyle", (XtActionProc) close_style
745 };
746 
747 /**********************************/
748 /* create the style manager panel */
749 /**********************************/
750 
751 void
init_manage_style_panel(void)752 init_manage_style_panel (void)
753 {
754     load_family_set (current_family_set);
755     FirstArg (XtNtitle, "Xfig: Manage Styles");
756     NextArg (XtNcolormap, tool_cm);
757 
758     style_popup = XtCreatePopupShell ("style_manage_panel",
759 				      transientShellWidgetClass, tool, Args, ArgCount);
760 
761     XtOverrideTranslations (style_popup, XtParseTranslationTable (style_translations));
762     FirstArg (XtNborderWidth, 0);
763 
764     style_main_form = XtCreateManagedWidget ("style_main_form",
765 					     formWidgetClass, style_popup,
766 					     Args, ArgCount);
767     XtOverrideTranslations (style_main_form,
768 			    XtParseTranslationTable (style_translations));
769 
770     /* label for title - "Manage Styles" */
771     FirstArg (XtNlabel, "Manage Styles");
772     NextArg (XtNborderWidth, 0);
773     style_main_label =
774 	XtCreateManagedWidget ("style_main_label", labelWidgetClass,
775 			       style_main_form, Args, ArgCount);
776 
777     /* frame for Family stuff */
778 
779     FirstArg (XtNborderWidth, 1);
780     NextArg (XtNfromVert, style_main_label);
781     style_family_form = XtCreateManagedWidget ("style_family_form",
782 					       formWidgetClass,
783 					       style_main_form, Args, ArgCount);
784     /* Put family stuff */
785     FirstArg (XtNlabel, "Family");
786     NextArg (XtNborderWidth, 0);
787     style_family_label =
788 	XtCreateManagedWidget ("style_family_label", labelWidgetClass,
789 			       style_family_form, Args, ArgCount);
790 
791     FirstArg (XtNallowVert, True);
792     NextArg (XtNfromHoriz, style_family_label);
793     NextArg (XtNborderWidth, INTERNAL_BW);
794     NextArg (XtNwidth, 180);
795     NextArg (XtNheight, 100);
796     NextArg (XtNtop, XtChainBottom);
797     NextArg (XtNbottom, XtChainBottom);
798     NextArg (XtNleft, XtChainLeft);
799     NextArg (XtNright, XtChainRight);
800     style_family_list_viewport =
801 	XtCreateManagedWidget ("style_family_list_viewport",
802 			       viewportWidgetClass, style_family_form, Args, ArgCount);
803     FirstArg (XtNlist, family_text);
804     NextArg (XtNforceColumns, True);
805     NextArg (XtNdefaultColumns, 1);
806     NextArg (XtNallowVert, True);
807     style_family_list =
808 	XtCreateManagedWidget ("family_list", figListWidgetClass,
809 			       style_family_list_viewport, Args, ArgCount);
810 
811     XawListChange (style_family_list, family_text, 0, 0, True);
812     XtAddCallback (style_family_list, XtNcallback, family_select, (XtPointer) NULL);
813     XtAugmentTranslations (style_family_list,
814 			   XtParseTranslationTable (style_family_list_translations));
815 
816     FirstArg (XtNlabel, "Choice");
817     NextArg (XtNfromVert, style_family_list_viewport);
818     NextArg (XtNborderWidth, 0);
819     style_family_choice_label =
820 	XtCreateManagedWidget ("family_choice_label", labelWidgetClass,
821 			       style_family_form, Args, ArgCount);
822     FirstArg (XtNeditType, XawtextEdit);
823     NextArg (XtNfromVert, style_family_list_viewport);
824     NextArg (XtNfromHoriz, style_family_choice_label);
825     NextArg (XtNwidth, 180);
826     NextArg (XtNheight, 30);
827     NextArg (XtNstring, "\0");
828     NextArg (XtNscrollHorizontal, XawtextScrollWhenNeeded);
829     style_family_name = XtCreateManagedWidget ("style_family_name",
830 					       asciiTextWidgetClass,
831 					       style_family_form, Args, ArgCount);
832     XtOverrideTranslations (style_family_name,
833 			    XtParseTranslationTable (style_family_name_translations));
834 
835     FirstArg (XtNlabel, "Add");
836     NextArg (XtNfromVert, style_family_name);
837     style_add_family =
838 	XtCreateManagedWidget ("style_add_family", commandWidgetClass,
839 			       style_family_form, Args, ArgCount);
840     XtAddCallback (style_add_family, XtNcallback, (XtCallbackProc) add_family,
841 		   (XtPointer) NULL);
842 
843     FirstArg (XtNlabel, "Delete");
844     NextArg (XtNfromVert, style_family_name);
845     NextArg (XtNfromHoriz, style_add_family);
846     style_delete_family = XtCreateManagedWidget ("style_delete_family",
847 						 commandWidgetClass,
848 						 style_family_form, Args, ArgCount);
849     XtAddCallback (style_delete_family, XtNcallback,
850 		   (XtCallbackProc) delete_family, (XtPointer) NULL);
851 
852 
853     /* frame for Style stuff inside family frame */
854 
855     FirstArg (XtNborderWidth, 1);
856     NextArg (XtNfromVert, style_add_family);
857     style_style_form = XtCreateManagedWidget ("style_style_form",
858 					      formWidgetClass,
859 					      style_family_form, Args, ArgCount);
860     FirstArg (XtNlabel, "Style ");
861     NextArg (XtNborderWidth, 0);
862     style_style_label =
863 	XtCreateManagedWidget ("style_style_label", labelWidgetClass,
864 			       style_style_form, Args, ArgCount);
865     FirstArg (XtNallowVert, True);
866     NextArg (XtNfromHoriz, style_style_label);
867     NextArg (XtNborderWidth, INTERNAL_BW);
868     NextArg (XtNwidth, 180);
869     NextArg (XtNheight, 100);
870     NextArg (XtNtop, XtChainBottom);
871     NextArg (XtNbottom, XtChainBottom);
872     NextArg (XtNleft, XtChainLeft);
873     NextArg (XtNright, XtChainRight);
874     style_style_list_viewport =
875 	XtCreateManagedWidget ("style_family_list_viewport",
876 			       viewportWidgetClass, style_style_form, Args, ArgCount);
877 
878 
879     FirstArg (XtNlist, style_text);
880     NextArg (XtNforceColumns, True);
881     NextArg (XtNdefaultColumns, 1);
882     style_style_list =
883 	XtCreateManagedWidget ("style_list", figListWidgetClass,
884 			       style_style_list_viewport, Args, ArgCount);
885 
886     XawListChange (style_style_list, style_text, 0, 0, True);
887     XtAddCallback (style_style_list, XtNcallback, style_select, (XtPointer) NULL);
888     XtAugmentTranslations (style_style_list,
889 			   XtParseTranslationTable (style_style_list_translations));
890 
891 
892     FirstArg (XtNlabel, "Choice");
893     NextArg (XtNfromVert, style_style_list_viewport);
894     NextArg (XtNborderWidth, 0);
895     style_style_choice_label =
896 	XtCreateManagedWidget ("style_choice_label", labelWidgetClass,
897 			       style_style_form, Args, ArgCount);
898     FirstArg (XtNeditType, XawtextEdit);
899     NextArg (XtNfromVert, style_style_list_viewport);
900     NextArg (XtNfromHoriz, style_style_choice_label);
901     NextArg (XtNwidth, 180);
902     NextArg (XtNheight, 30);
903     NextArg (XtNstring, "\0");
904     NextArg (XtNscrollHorizontal, XawtextScrollWhenNeeded);
905     style_style_name = XtCreateManagedWidget ("style_style_name",
906 					      asciiTextWidgetClass,
907 					      style_style_form, Args, ArgCount);
908     XtOverrideTranslations (style_style_name,
909 			    XtParseTranslationTable (style_style_name_translations));
910 
911     FirstArg (XtNlabel, "Add");
912     NextArg (XtNfromVert, style_style_name);
913     style_add_style =
914 	XtCreateManagedWidget ("style_add_family", commandWidgetClass,
915 			       style_style_form, Args, ArgCount);
916     XtAddCallback (style_add_style, XtNcallback, (XtCallbackProc) add_style,
917 		   (XtPointer) NULL);
918 
919     FirstArg (XtNlabel, "Delete");
920     NextArg (XtNfromVert, style_style_name);
921     NextArg (XtNfromHoriz, style_add_style);
922     style_delete_style = XtCreateManagedWidget ("style_delete_family",
923 						commandWidgetClass,
924 						style_style_form, Args, ArgCount);
925     XtAddCallback (style_delete_style, XtNcallback,
926 		   (XtCallbackProc) delete_style, (XtPointer) NULL);
927 
928     /* overall save/load/close buttons */
929 
930     FirstArg (XtNlabel, "Save settings");
931     NextArg (XtNfromVert, style_family_form);
932     style_save_style = XtCreateManagedWidget ("style_save",
933 					      commandWidgetClass,
934 					      style_main_form, Args, ArgCount);
935     XtAddCallback (style_save_style, XtNcallback, (XtCallbackProc) save_style,
936 		   (XtPointer) NULL);
937 
938     FirstArg (XtNlabel, "Reload settings");
939     NextArg (XtNfromVert, style_family_form);
940     NextArg (XtNfromHoriz, style_save_style);
941     style_load_style = XtCreateManagedWidget ("style_load",
942 					      commandWidgetClass,
943 					      style_main_form, Args, ArgCount);
944     XtAddCallback (style_load_style, XtNcallback, (XtCallbackProc) load_style,
945 		   (XtPointer) NULL);
946 
947     FirstArg (XtNlabel, "Close");
948     NextArg (XtNfromHoriz, style_load_style);
949     NextArg (XtNfromVert, style_family_form);
950     style_close_style = XtCreateManagedWidget ("style_close",
951 					       commandWidgetClass,
952 					       style_main_form, Args, ArgCount);
953     XtAddCallback (style_close_style, XtNcallback,
954 		   (XtCallbackProc) close_style, (XtPointer) NULL);
955 
956     style_update ();
957 }
958 
959 void
add_style_actions(void)960 add_style_actions(void)
961 {
962     XtAppAddActions (tool_app, style_actions, XtNumber (style_actions));
963 }
964 
965 /* now that the main tool has been created we can position (although it
966    is not popped up yet) the style panel */
967 
968 void
setup_manage_style_panel(void)969 setup_manage_style_panel (void)
970 {
971     Position x_val, y_val;
972     Dimension width, height;
973 
974     FirstArg (XtNwidth, &width);
975     NextArg (XtNheight, &height);
976     GetValues (tool);
977     /* position the popup 1/6 in from left and 1/4 down from top */
978     XtTranslateCoords (tool, (Position) (width / 6), (Position) (height / 4),
979 		       &x_val, &y_val);
980 
981     FirstArg (XtNx, x_val);
982     NextArg (XtNy, y_val);
983     SetValues (style_popup);
984 }
985 
986 void
popup_manage_style_panel(void)987 popup_manage_style_panel (void)
988 {
989     /* first make sure we're in update mode */
990     change_mode (&update_ic);
991     /* use GrabNone so user can choose styles while drawing */
992     XtPopup (style_popup, XtGrabNone);
993     (void) XSetWMProtocols (tool_d, XtWindow (style_popup), &wm_delete_window, 1);
994 }
995