1 /*
2  *  simple.c:		Simple dialog widgets
3  *
4  *  Written by:		Ullrich Hafner
5  *
6  *  Copyright (C) 1999 Ullrich Hafner <hafner@bigfoot.de>
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
21  */
22 
23 /*
24  *  $Date: 2000/09/03 19:22:05 $
25  *  $Author: hafner $
26  *  $Revision: 1.15 $
27  *  $State: Exp $
28  */
29 
30 #include "config.h"
31 
32 #include <stdio.h>
33 #include <stdlib.h>
34 
35 #include <gtk/gtk.h>
36 #include "proplist_t.h"
37 
38 #include "simple.h"
39 #include "dialog.h"
40 #include "menu.h"
41 #include "texture.h"
42 #include "misc.h"
43 #include "window.h"
44 #include "themebrowser.h"
45 
46 #include "error.h"
47 
48 /*******************************************************************************
49 
50 			     global variables
51 
52 *******************************************************************************/
53 
54 extern bool_t	  changed;		/* window.c */
55 extern proplist_t windowmaker;		/* window.c */
56 
57 /*******************************************************************************
58 
59 			     local variables
60 
61 *******************************************************************************/
62 
63 #ifdef HAVE_LIBWMFUN
64 static const char **color_types = NULL;
65 
66 /*******************************************************************************
67 
68 			       prototypes
69 
70 *******************************************************************************/
71 
72 static void
73 color_toggle (GtkWidget *widget, gpointer ptr);
74 static void
75 show_color_buttons (text_color_t *text_color);
76 static void
77 update_text_color (proplist_t key, gpointer ptr, proplist_t value,
78 		   const char *path);
79 #endif /* HAVE_LIBWMFUN */
80 static void
81 set_bool (GtkWidget *widget, gpointer ptr);
82 static void
83 set_ibool (GtkWidget *widget, gpointer ptr);
84 static void
85 append_dialog (GtkWidget *container, GtkWidget *left, GtkWidget *right,
86 	       GtkAttachOptions attach);
87 static void
88 set_string (GtkWidget *widget, gpointer ptr);
89 static void
90 set_int (GtkWidget *widget, gpointer ptr);
91 static void
92 set_entry_text (GtkWidget *widget, gpointer ptr);
93 static void
94 convert_pango_to_fontconfig (const char *pangoname, char *fcname);
95 static void
96 convert_fontconfig_to_pango (const char *fcname, char *pangoname);
97 static void
98 set_fontname (GtkWidget *widget, gpointer ptr);
99 static void
100 fontsel_dialog (GtkWidget *widget, gpointer ptr);
101 static void
102 update_entry (proplist_t key, gpointer ptr, proplist_t value,
103 	      const char *path);
104 static void
105 update_color (proplist_t key, gpointer ptr, proplist_t value,
106 	      const char *path);
107 static void
108 update_boolean (proplist_t key, gpointer ptr, proplist_t value,
109 		const char *path);
110 static void
111 update_iboolean (proplist_t key, gpointer ptr, proplist_t value,
112 		 const char *path);
113 static void
114 update_int (proplist_t key, gpointer ptr, proplist_t value,
115 	    const char *path);
116 
117 /*******************************************************************************
118 
119 			       public code
120 
121 *******************************************************************************/
122 
123 void
boolean_dialog(GtkWidget * table,proplist_t key,proplist_t value,proplist_t info)124 boolean_dialog (GtkWidget *table, proplist_t key, proplist_t value,
125 		proplist_t info)
126 {
127    GtkWidget *label  = gtk_label_new (D_(WMGetFromPLString (info)));
128    GtkWidget *button = gtk_check_button_new ();
129 
130    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
131 				 convert_bool (value));
132    gtk_signal_connect (GTK_OBJECT (button), "toggled",
133 		       GTK_SIGNAL_FUNC (set_bool), (gpointer) key);
134    append_dialog (table, label, button, GTK_SHRINK);
135 
136    connect_update_function (key, button, update_boolean);
137 }
138 
139 void
iboolean_dialog(GtkWidget * table,proplist_t key,proplist_t value,proplist_t info)140 iboolean_dialog (GtkWidget *table, proplist_t key, proplist_t value,
141 		 proplist_t info)
142 {
143    GtkWidget *label  = gtk_label_new (D_(WMGetFromPLString (info)));
144    GtkWidget *button = gtk_check_button_new ();
145 
146    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
147 				 convert_bool (value) ? FALSE : TRUE);
148    gtk_signal_connect (GTK_OBJECT (button), "toggled",
149 		       GTK_SIGNAL_FUNC (set_ibool), (gpointer) key);
150    append_dialog (table, label, button, GTK_SHRINK);
151 
152    connect_update_function (key, button, update_iboolean);
153 }
154 
155 void
string_dialog(GtkWidget * table,proplist_t key,proplist_t value,proplist_t range,proplist_t rinfo,proplist_t info)156 string_dialog (GtkWidget *table, proplist_t key, proplist_t value,
157 	       proplist_t range, proplist_t rinfo, proplist_t info)
158 {
159    GtkWidget	*option_menu;
160    GtkWidget	*label = gtk_label_new (D_(WMGetFromPLString (info)));
161    const char	**values;
162    unsigned	n, current = 0;
163 
164    values = Calloc (WMGetPropListItemCount (range) + 1, sizeof (char *));
165    for (n = 0; n < WMGetPropListItemCount (range); n++)
166    {
167       proplist_t element = WMGetFromPLArray (range, n);
168 
169       if (strcaseeq (WMGetFromPLString (element), WMGetFromPLString (value)))
170 	 current = n;
171       values [n] = WMGetFromPLString (element);
172    }
173    values [n] = NULL;
174 
175    option_menu = generate_option_menu (NULL, NULL, NULL, values,
176 				       values [current], rinfo, set_string, key);
177    append_dialog (table, option_menu, label, GTK_FILL | GTK_SHRINK);
178 
179    {
180       omenudata_t *data = Calloc (1, sizeof (omenudata_t));
181 
182       data->omenu  = GTK_OPTION_MENU (option_menu);
183       data->values = values;
184       connect_update_function (key, data, update_optionmenu);
185    }
186 }
187 
188 void
int_dialog(GtkWidget * table,proplist_t key,proplist_t value,proplist_t range,proplist_t rinfo,proplist_t info)189 int_dialog (GtkWidget *table, proplist_t key, proplist_t value,
190 	    proplist_t range, proplist_t rinfo, proplist_t info)
191 {
192    GtkWidget    *label 	= gtk_label_new (D_(WMGetFromPLString (info)));
193    GtkWidget    *hbox  	= gtk_hbox_new (FALSE, 5);
194    GtkEntry	**array = Calloc (WMGetPropListItemCount (range) / 2 + 1,
195 				  sizeof (GtkEntry *));
196    unsigned	n;
197 
198    for (n = 0; n < WMGetPropListItemCount (range); n += 2)
199    {
200       GtkWidget *spinner;
201       GtkObject *adj;
202       char	*m = WMGetFromPLString (WMGetFromPLArray (range, n));
203       char	*M = WMGetFromPLString (WMGetFromPLArray (range, n + 1));
204       char 	*v;
205 
206       if (WMIsPLArray (value))
207 	 v = WMGetFromPLString (WMGetFromPLArray (value, n / 2));
208       else
209 	 v = WMGetFromPLString (value);
210 
211       adj = gtk_adjustment_new (strtod (v, NULL),
212 				strtod (m, NULL), strtod (M, NULL),
213 				1.0, 5.0, 0.0);
214       spinner = gtk_spin_button_new (GTK_ADJUSTMENT (adj), 0, 0);
215       gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinner), TRUE);
216       gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
217       gtk_widget_show_all (spinner);
218       gtk_object_set_user_data (GTK_OBJECT (adj), (gpointer) spinner);
219       gtk_box_pack_start (GTK_BOX (hbox), spinner, TRUE, TRUE, 0);
220       gtk_object_set_user_data (GTK_OBJECT (spinner),
221 				(gpointer) (spinner + n / 2));
222 
223       gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
224 			  GTK_SIGNAL_FUNC (set_int), (gpointer) key);
225       gtk_signal_connect (GTK_OBJECT (&GTK_SPIN_BUTTON (spinner)->entry),
226 			  "changed", GTK_SIGNAL_FUNC (set_entry_text),
227 			  (gpointer) key);
228 
229       array [n / 2] = &GTK_SPIN_BUTTON (spinner)->entry;
230    }
231    array [n / 2] = NULL;
232 
233    append_dialog (table, hbox, label, GTK_FILL | GTK_SHRINK);
234 
235    connect_update_function (key, array, update_int);
236 }
237 
238 void
text_dialog(GtkWidget * table,proplist_t key,proplist_t value,proplist_t info)239 text_dialog (GtkWidget *table, proplist_t key, proplist_t value,
240 	     proplist_t info)
241 {
242    GtkWidget *entry = gtk_entry_new ();
243    GtkWidget *label = gtk_label_new (D_(WMGetFromPLString (info)));
244 
245    gtk_widget_set_usize (entry, 100, 0);
246    gtk_entry_set_text (GTK_ENTRY (entry), WMGetFromPLString (value));
247    gtk_signal_connect (GTK_OBJECT (entry), "changed",
248 		       GTK_SIGNAL_FUNC (set_entry_text), key);
249    append_dialog (table, entry, label, GTK_FILL | GTK_SHRINK);
250    connect_update_function (key, entry, update_entry);
251 }
252 
253 GtkWidget *
font_dialog(GtkWidget * page,proplist_t key,proplist_t value,proplist_t info)254 font_dialog (GtkWidget *page, proplist_t key, proplist_t value,
255 	     proplist_t info)
256 {
257    GtkWidget *entry  = gtk_entry_new ();
258    GtkWidget *frame  = gtk_frame_new (D_(WMGetFromPLString (info)));
259    GtkWidget *hbox   = gtk_hbox_new (FALSE, 0);
260    GtkWidget *bbox   = gtk_hbutton_box_new ();
261    GtkWidget *button = gtk_button_new_with_label (_("Browse..."));
262 
263    gtk_frame_set_label_align (GTK_FRAME (frame), 0.5, 0.5);
264    gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
265    gtk_container_add (GTK_CONTAINER (frame), hbox);
266 
267    gtk_entry_set_text (GTK_ENTRY (entry), WMGetFromPLString (value));
268    gtk_signal_connect (GTK_OBJECT (entry), "changed",
269 		       GTK_SIGNAL_FUNC (set_entry_text), key);
270    gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 5);
271    gtk_box_pack_start (GTK_BOX (hbox), bbox, FALSE, TRUE, 5);
272    gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, TRUE, 5);
273 
274    gtk_signal_connect (GTK_OBJECT (button), "clicked",
275 		       GTK_SIGNAL_FUNC (fontsel_dialog), (gpointer) entry);
276 
277    gtk_box_pack_end (GTK_BOX (page), frame, TRUE, TRUE, 5);
278    gtk_widget_show_all (frame);
279 
280    connect_update_function (key, entry, update_entry);
281 
282    return frame;
283 }
284 
285 GtkWidget *
color_dialog(GtkWidget * page,proplist_t key,proplist_t value,GtkTooltips * tooltips,proplist_t info,proplist_t title)286 color_dialog (GtkWidget *page, proplist_t key, proplist_t value,
287 	      GtkTooltips *tooltips, proplist_t info, proplist_t title)
288 {
289    GtkWidget *frame;
290    GtkWidget *button = color_button (NULL, key, value, tooltips,
291 				     D_(WMGetFromPLString (info)));
292    GtkWidget *hbox = gtk_hbox_new (TRUE, 0);
293 
294    if (title)
295       frame = gtk_frame_new (D_(WMGetFromPLString (title)));
296    else
297       frame = gtk_frame_new (WMGetFromPLString (key));
298 
299    gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
300    gtk_frame_set_label_align (GTK_FRAME (frame), 0.5, 0.5);
301    gtk_container_add (GTK_CONTAINER (frame), hbox);
302    gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
303 
304    gtk_box_pack_start (GTK_BOX (page), frame, FALSE, TRUE, 5);
305    gtk_widget_show_all (frame);
306 
307    connect_update_function (key,
308 			    gtk_object_get_user_data (GTK_OBJECT (button)),
309 			    update_color);
310 
311    return frame;
312 }
313 
314 #ifdef HAVE_LIBWMFUN
315 GtkWidget *
extended_color_dialog(GtkWidget * page,proplist_t key,proplist_t value,GtkTooltips * tooltips,proplist_t info,proplist_t title)316 extended_color_dialog (GtkWidget *page, proplist_t key, proplist_t value,
317 		       GtkTooltips *tooltips, proplist_t info, proplist_t title)
318 {
319    GtkWidget   	*frame;
320    GtkWidget   	*option_menu;
321    text_color_t *text_color = Calloc (1, sizeof (text_color_t));
322    GtkWidget   	*hbox 	    = gtk_hbox_new (FALSE, 5);
323 
324    gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
325 
326    frame = gtk_frame_new (_("Color of title text"));
327    text_color->key = key;
328 
329    if (!color_types)
330    {
331       color_types = Calloc (TCOLOR_LAST, sizeof (char *));
332 
333       color_types [TCOLOR_SIMPLE]   = _("Solid color");
334       color_types [TCOLOR_COLORSET] = _("Drop shadow");
335       color_types [TCOLOR_LAST]     = NULL;
336    }
337 
338    option_menu = generate_option_menu (NULL, tooltips,
339 				       _("A solid color or a drop shadow."),
340 				       color_types, color_types [0], NULL,
341 				       color_toggle, text_color);
342    text_color->option_menu = option_menu;
343    gtk_frame_set_label_align (GTK_FRAME (frame), 0.5, 0.5);
344    gtk_container_add (GTK_CONTAINER (frame), hbox);
345    gtk_box_pack_start (GTK_BOX (hbox), option_menu, FALSE, FALSE, 0);
346 
347    text_color->solid_color = color_button (NULL, key, NULL, NULL, NULL);
348    gtk_box_pack_start (GTK_BOX (hbox), text_color->solid_color,
349 		       FALSE, TRUE, 0);
350    text_color->color_set [0] = color_button (NULL, key, NULL,
351 					     tooltips, _("Foreground"));
352    gtk_box_pack_start (GTK_BOX (hbox), text_color->color_set [0],
353 		       FALSE, TRUE, 0);
354    text_color->color_set [1] = color_button (NULL, key, NULL,
355 					     tooltips, _("Shadow 1"));
356    gtk_box_pack_start (GTK_BOX (hbox), text_color->color_set [1],
357 		       FALSE, TRUE, 0);
358    text_color->color_set [2] = color_button (NULL, key, NULL,
359 					     tooltips, _("Shadow 2"));
360    gtk_box_pack_start (GTK_BOX (hbox), text_color->color_set [2],
361 		       FALSE, TRUE, 0);
362 
363    gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0);
364    gtk_widget_show_all (frame);
365 
366    show_color_buttons (text_color);
367 
368    connect_update_function (key, text_color, update_text_color);
369 
370    return frame;
371 }
372 #endif /* HAVE_LIBWMFUN */
373 
374 void
update_optionmenu(proplist_t key,gpointer ptr,proplist_t value,const char * path)375 update_optionmenu (proplist_t key, gpointer ptr, proplist_t value,
376 		   const char *path)
377 {
378    omenudata_t *data = (omenudata_t *) ptr;
379 
380    if (WMIsPLString (value))
381       set_option_menu_default (data->omenu, data->values, WMGetFromPLString (value));
382 }
383 
384 bool_t
convert_bool(proplist_t p)385 convert_bool (proplist_t p)
386 /*
387  *  Parse boolean values of WindowMaker file.
388  *
389  *  Return value:
390  *	converted value
391  */
392 {
393    char *val;
394 
395    assert (p && (WMIsPLString (p) || WMIsPLData (p)));
396 
397    val = WMGetFromPLString (p);
398 
399    if (strcaseeq (val, "y") || strcaseeq (val, "yes")
400        || strcaseeq (val, "t") || strcaseeq (val, "true")
401        || strcaseeq (val, "1"))
402       return TRUE;
403    else if (strcaseeq (val, "n") || strcaseeq (val, "no")
404 	    || strcaseeq (val, "f") || strcaseeq (val, "false")
405 	    || strcaseeq (val, "0"))
406       return FALSE;
407    else
408    {
409       warning (_("Undefined boolean value '%s' converted to true."), val);
410       return TRUE;
411    }
412 }
413 
414 /*******************************************************************************
415 
416 			       private code
417 
418 *******************************************************************************/
419 
420 #ifdef HAVE_LIBWMFUN
421 static void
color_toggle(GtkWidget * widget,gpointer ptr)422 color_toggle (GtkWidget *widget, gpointer ptr)
423 {
424    char 	*text 	    = gtk_object_get_user_data (GTK_OBJECT (widget));
425    text_color_t *text_color = (text_color_t *) ptr;
426    proplist_t 	value 	    = WMGetFromPLDictionary (windowmaker, text_color->key);
427 
428    if (text == color_types [TCOLOR_SIMPLE])
429    {
430       if (!WMIsPLString (value))
431       {
432 	 WMPutInPLDictionary (windowmaker, text_color->key,
433 				  WMCreatePLString ("tan"));
434 	 toggle_save (changed = YES, text_color->key);
435 	 show_color_buttons (text_color);
436       }
437    }
438    else
439    {
440       if (!WMIsPLArray (value))
441       {
442 	 proplist_t pl;
443 	 pl = WMCreatePLArray (WMCreatePLString ("function"),
444 				       WMCreatePLString ("libwmfun.so"),
445 				       WMCreatePLString ("drawPlainString"),
446 				       WMCreatePLString ("white"),
447 				       WMCreatePLString ("black"),
448 				       WMCreatePLString ("red"), NULL);
449 
450 	 WMPutInPLDictionary (windowmaker, text_color->key, pl);
451 	 toggle_save (changed = YES, text_color->key);
452 	 show_color_buttons (text_color);
453       }
454    }
455 }
456 
457 static void
show_color_buttons(text_color_t * text_color)458 show_color_buttons (text_color_t *text_color)
459 {
460    proplist_t value = WMGetFromPLDictionary (windowmaker, text_color->key);
461 
462    if (WMIsPLArray (value))		/* check syntax of value */
463    {
464       if (!(WMGetPropListItemCount (value) == 6
465 	    && strcaseeq (WMGetFromPLString (WMGetFromPLArray (value, 0)),
466 			  "function")
467 	    && strncaseeq (WMGetFromPLString (WMGetFromPLArray (value, 1)),
468 			   "libwmfun", strlen ("libwmfun"))
469 	    && strcaseeq (WMGetFromPLString (WMGetFromPLArray (value, 2)),
470 			  "drawPlainString")))
471       {
472 	 proplist_t pl;
473 	 pl = WMCreatePLArray (WMCreatePLString ("function"),
474 				       WMCreatePLString ("libwmfun.so"),
475 				       WMCreatePLString ("drawPlainString"),
476 				       WMCreatePLString ("white"),
477 				       WMCreatePLString ("black"),
478 				       WMCreatePLString ("red"), NULL);
479 
480 	 WMPutInPLDictionary (windowmaker, text_color->key, pl);
481 	 value = pl;
482       }
483       set_option_menu_default (GTK_OPTION_MENU (text_color->option_menu),
484 			       color_types, color_types [TCOLOR_COLORSET]);
485 
486       /*
487        *  Set colors
488        */
489       {
490 	 GtkWidget *preview;
491 
492 	 preview = gtk_object_get_user_data (GTK_OBJECT (text_color->color_set [0]));
493 	 fill_preview (GTK_PREVIEW (preview), WMGetFromPLString (WMGetFromPLArray (value, 3)));
494 	 gtk_object_set_user_data (GTK_OBJECT (preview), WMGetFromPLArray (value, 3));
495 	 preview = gtk_object_get_user_data (GTK_OBJECT (text_color->color_set [1]));
496 	 fill_preview (GTK_PREVIEW (preview), WMGetFromPLString (WMGetFromPLArray (value, 4)));
497 	 gtk_object_set_user_data (GTK_OBJECT (preview), WMGetFromPLArray (value, 4));
498 	 preview = gtk_object_get_user_data (GTK_OBJECT (text_color->color_set [2]));
499 	 fill_preview (GTK_PREVIEW (preview), WMGetFromPLString (WMGetFromPLArray (value, 5)));
500 	 gtk_object_set_user_data (GTK_OBJECT (preview), WMGetFromPLArray (value, 5));
501       }
502       gtk_widget_show (text_color->color_set [0]);
503       gtk_widget_show (text_color->color_set [1]);
504       gtk_widget_show (text_color->color_set [2]);
505       gtk_widget_hide (text_color->solid_color);
506    }
507    else
508    {
509       gtk_widget_hide (text_color->color_set [0]);
510       gtk_widget_hide (text_color->color_set [1]);
511       gtk_widget_hide (text_color->color_set [2]);
512       gtk_widget_show (text_color->solid_color);
513       set_option_menu_default (GTK_OPTION_MENU (text_color->option_menu),
514 			       color_types, color_types [TCOLOR_SIMPLE]);
515       /*
516        *  Set default color
517        */
518       {
519 	 GtkWidget *preview;
520 
521 	 preview = gtk_object_get_user_data (GTK_OBJECT (text_color->solid_color));
522 	 fill_preview (GTK_PREVIEW (preview), WMGetFromPLString (value));
523 	 gtk_object_set_user_data (GTK_OBJECT (preview), value);
524       }
525    }
526 }
527 #endif /* HAVE_LIBWMFUN */
528 
529 static void
append_dialog(GtkWidget * container,GtkWidget * left,GtkWidget * right,GtkAttachOptions attach)530 append_dialog (GtkWidget *container, GtkWidget *left, GtkWidget *right,
531 	       GtkAttachOptions attach)
532 {
533    if (GTK_IS_TABLE (container))
534    {
535       unsigned *number = (unsigned *) gtk_object_get_user_data (GTK_OBJECT (container));
536       unsigned row, col;
537 
538       row  = ++*number;
539       col  = (row % 2) * 2;
540       row /= 2;
541 
542       gtk_table_attach (GTK_TABLE (container), left, col, col + 1, row, row + 1,
543 			GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 0, 0);
544       gtk_table_attach (GTK_TABLE (container), right, col + 1, col + 2, row, row + 1,
545 			attach, attach, 0, 0);
546 
547       gtk_widget_show_all (left);
548       gtk_widget_show_all (right);
549    }
550    else if (GTK_IS_VBOX (container))
551    {
552       GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
553       gtk_container_set_border_width (GTK_CONTAINER (container), 5);
554       gtk_box_pack_start (GTK_BOX (hbox), right, FALSE, FALSE, 0);
555       gtk_box_pack_start (GTK_BOX (hbox), left, FALSE, FALSE, 0);
556       gtk_box_pack_start (GTK_BOX (container), hbox, FALSE, FALSE, 0);
557       gtk_widget_show_all (hbox);
558    }
559 }
560 
561 static void
set_bool(GtkWidget * widget,gpointer ptr)562 set_bool (GtkWidget *widget, gpointer ptr)
563 /*
564  *  Update boolean value.
565  *
566  *  No return value.
567  */
568 {
569    proplist_t key   = (proplist_t) ptr;
570    char       *text = GTK_TOGGLE_BUTTON (widget)->active ? "Yes" : "No";
571    proplist_t pl    = WMCreatePLString (text);
572 
573    WMPutInPLDictionary (windowmaker, key, pl);
574    WMReleasePropList (pl);
575    toggle_save (changed = YES, key);
576 
577    if (strcaseeq (WMGetFromPLString (key), "NewStyle"))
578       check_widgetstyle ();
579 }
580 
581 static void
set_ibool(GtkWidget * widget,gpointer ptr)582 set_ibool (GtkWidget *widget, gpointer ptr)
583 /*
584  *  Update boolean value.
585  *
586  *  No return value.
587  */
588 {
589    proplist_t key  = (proplist_t) ptr;
590    char       *text = GTK_TOGGLE_BUTTON (widget)->active ? "No" : "Yes";
591    proplist_t pl   = WMCreatePLString (text);
592 
593    WMPutInPLDictionary (windowmaker, key, pl);
594    WMReleasePropList (pl);
595    toggle_save (changed = YES, key);
596 
597    if (strcaseeq (WMGetFromPLString (key), "NewStyle"))
598       check_widgetstyle ();
599 }
600 
601 static void
set_string(GtkWidget * widget,gpointer ptr)602 set_string (GtkWidget *widget, gpointer ptr)
603 /*
604  *  Update string value.
605  *
606  *  No return value.
607  */
608 {
609    proplist_t key  = (proplist_t) ptr;
610    char       *text = gtk_object_get_user_data (GTK_OBJECT (widget));
611    proplist_t pl   = WMCreatePLString (text);
612 
613    WMPutInPLDictionary (windowmaker, key, pl);
614    WMReleasePropList (pl);
615    toggle_save (changed = YES, key);
616 }
617 
618 static void
set_int(GtkWidget * widget,gpointer ptr)619 set_int (GtkWidget *widget, gpointer ptr)
620 /*
621  *  Update unsigned value.
622  *
623  *  No return value.
624  */
625 {
626    proplist_t	 key = (proplist_t) ptr;
627    GtkSpinButton *spinner;
628    int		 val;
629    char		 tmp [MAXSTRLEN];
630 
631    spinner = GTK_SPIN_BUTTON (gtk_object_get_user_data (GTK_OBJECT (widget)));
632    val     = gtk_spin_button_get_value_as_int (spinner);
633 
634    sprintf (tmp, "%d", val);
635 
636    if (WMIsPLArray (WMGetFromPLDictionary (windowmaker, key)))
637    {
638       proplist_t array = WMGetFromPLDictionary (windowmaker, key);
639       unsigned	 n;
640 
641       n = (GtkWidget *) gtk_object_get_user_data (GTK_OBJECT (spinner))
642 	  - GTK_WIDGET (spinner);
643       WMDeleteFromPLArray (array, n);
644       WMInsertInPLArray (array, n, WMCreatePLString (tmp));
645    }
646    else
647    {
648       proplist_t pl = WMCreatePLString (tmp);
649       WMPutInPLDictionary (windowmaker, key, pl);
650       WMReleasePropList (pl);
651    }
652 
653    toggle_save (changed = YES, key);
654 }
655 
656 static void
set_entry_text(GtkWidget * widget,gpointer ptr)657 set_entry_text (GtkWidget *widget, gpointer ptr)
658 /*
659  *  Update string value.
660  *
661  *  No return value.
662  */
663 {
664    proplist_t element;
665    proplist_t key   = (proplist_t) ptr;
666    proplist_t array = WMGetFromPLDictionary (windowmaker, key);
667 
668    element = WMCreatePLString ((char *) gtk_entry_get_text (GTK_ENTRY (widget)));
669 
670    if (WMIsPLArray (array))
671    {
672       WMDeleteFromPLArray (array, 1);	/* filename */
673       WMInsertInPLArray (array, 1, element);
674    }
675    else
676    {
677       WMPutInPLDictionary (windowmaker, key, element);
678       WMReleasePropList (element);
679    }
680 
681    toggle_save (changed = YES, key);
682 }
683 
684 static void
fontsel_dialog(GtkWidget * widget,gpointer ptr)685 fontsel_dialog (GtkWidget *widget, gpointer ptr)
686 {
687   static GtkWidget *fontsel = NULL;
688 
689   if (!fontsel)
690   {
691      GtkWidget			*entry;
692      const char			*text;
693      char			*pangotext;
694      GtkFontSelectionDialog	*fs;
695 
696      entry   = GTK_WIDGET (ptr);
697      text    = gtk_entry_get_text (GTK_ENTRY (entry));
698      pangotext = malloc (strlen (text) + 1);
699      fontsel = gtk_font_selection_dialog_new (_("Font selection"));
700      fs	     = GTK_FONT_SELECTION_DIALOG (fontsel);
701 
702      gtk_window_set_position (GTK_WINDOW (fontsel), GTK_WIN_POS_MOUSE);
703      gtk_object_set_user_data (GTK_OBJECT (fontsel), entry);
704      convert_fontconfig_to_pango (text, pangotext);
705      gtk_font_selection_dialog_set_font_name (fs, pangotext);
706      free (pangotext);
707 
708      gtk_object_set_data (GTK_OBJECT (entry), "fontsel", fontsel);
709      gtk_signal_connect (GTK_OBJECT (fontsel), "destroy",
710 			 GTK_SIGNAL_FUNC (gtk_widget_destroyed),
711 			 &fontsel);
712      gtk_signal_connect  (GTK_OBJECT (fs->ok_button), "clicked",
713 			  GTK_SIGNAL_FUNC (set_fontname), fontsel);
714      gtk_signal_connect_object (GTK_OBJECT (fs->ok_button), "clicked",
715 				GTK_SIGNAL_FUNC (gtk_widget_destroy),
716 				GTK_OBJECT (fontsel));
717      gtk_signal_connect_object (GTK_OBJECT (fs->cancel_button), "clicked",
718 				GTK_SIGNAL_FUNC (gtk_widget_destroy),
719 				GTK_OBJECT (fontsel));
720   }
721 
722   if (!GTK_WIDGET_VISIBLE (fontsel))
723      gtk_widget_show (fontsel);
724   else
725      gtk_widget_destroy (fontsel);
726 }
727 
728 struct font_attr_t {
729   int slant;
730   int weight;
731   int width;
732   int size;
733 };
734 
735 /* Function to convert from GTK+ 2's Pango font names to the slightly
736  * different format used by WindowMaker 0.90 (fontconfig?)
737  * fcname must already be allocated and have a length of at least
738  * strlen(pangoname) + 50. */
739 static void
convert_pango_to_fontconfig(const char * pangoname,char * fcname)740 convert_pango_to_fontconfig (const char *pangoname, char *fcname)
741 {
742   const char * posn;
743   char * base;
744   int size;
745   struct font_attr_t attr = { 0, 80, 100, 12 };
746 
747   posn = pangoname + strlen(pangoname) - 1;
748   while (posn > pangoname && isdigit(*posn)) posn--;
749 
750   size = atoi(posn);
751   if (size) attr.size = size;
752 
753   /* check for italic */
754   if (posn - pangoname > 6 && strncmp(posn - 6, "Italic", 6) == 0) {
755     attr.slant = 100;
756     posn -= 7;
757   }
758 
759   /* check for condensed */
760   if (posn - pangoname > 9 && strncmp(posn - 9, "Condensed", 9) == 0) {
761     attr.width = 75;
762     posn -= 10;
763   }
764 
765   /* check for bold */
766   if (posn - pangoname > 9 && strncmp(posn - 9, "Semi-Bold", 9) == 0) {
767     attr.weight = 100;
768     posn -= 10;
769   }
770   else if (posn - pangoname > 4 && strncmp(posn - 4, "Bold", 4) == 0) {
771     attr.weight = 200;
772     posn -= 5;
773   }
774 
775   if (posn > pangoname && *(posn - 1) == ',')
776     posn--;
777 
778   base = malloc(posn - pangoname + 10);
779   strncpy(base, pangoname, posn - pangoname);
780   base[posn - pangoname] = 0;
781 
782   /* Sans and Serif aliases are slightly different in Pango vs. fontconfig */
783   if (strcmp(base, "Sans") == 0)
784     strcpy(base, "sans serif");
785   else if (strcmp(base, "Serif") == 0)
786     strcpy(base, "serif");
787 
788   sprintf(fcname, "%s:slant=%d:weight=%d:width=%d:pixelsize=%d",
789 	  base, attr.slant, attr.weight, attr.width, attr.size);
790   free(base);
791 }
792 
793 /* Function to convert from WindowMaker 0.90's fontconfig font name format
794  * to that used by Pango in GTK+ 2.
795  * pangoname must already be allocated and have a length of at least
796  * strlen(fcname). */
797 static void
convert_fontconfig_to_pango(const char * fcname,char * pangoname)798 convert_fontconfig_to_pango (const char *fcname, char *pangoname)
799 {
800   char * base, * posn, * posn2;
801   char slant[8] = { 0 }, weight[11] = { 0 }, width[11] = { 0 };
802   int size = 12;
803 
804   /* Find the first ':' or ',' and assume this is the end of the font name */
805   posn = strchr(fcname, ':');
806   posn2 = strchr(fcname, ',');
807   if (!posn || posn2 && posn2 < posn)
808     posn = posn2;
809 
810   if (posn) {
811     base = malloc(posn - fcname + 1);
812     strncpy(base, fcname, posn - fcname);
813     base[posn - fcname] = 0;
814   }
815   else {
816     /* maybe XLFD, don't touch */
817     strcpy(pangoname, fcname);
818     return;
819   }
820 
821   /* Sans and Serif aliases are slightly different in Pango vs. fontconfig */
822   if (strcmp(base, "sans serif") == 0)
823     strcpy(base, "Sans");
824   else if (strcmp(base, "serif") == 0)
825     strcpy(base, "Serif");
826 
827   if ((posn = strstr(fcname, ":weight="))) {
828     int wt = atoi(posn + 8);
829     if (wt >= 150)
830       strcpy(weight, "Bold ");
831     else if (wt >= 90)
832       strcpy(weight, "Semi-Bold ");
833   }
834 
835   if ((posn = strstr(fcname, ":bold")))
836     strcpy(weight, "Bold ");
837 
838   if ((posn = strstr(fcname, ":width=")))
839     if (atoi(posn + 7) < 90)
840       strcpy(width, "Condensed ");
841 
842   if ((posn = strstr(fcname, ":slant=")))
843     if (atoi(posn + 7))
844       strcpy(slant, "Italic ");
845 
846   if ((posn = strstr(fcname, ":pixelsize="))) {
847     int sz = atoi(posn + 11);
848     if (sz) size = sz;
849   }
850 
851   sprintf(pangoname, "%s, %s%s%s%d", base, weight, width, slant, size);
852   free(base);
853 }
854 
855 static void
set_fontname(GtkWidget * widget,gpointer ptr)856 set_fontname (GtkWidget *widget, gpointer ptr)
857 {
858    GtkWidget *fontsel = GTK_WIDGET (ptr);
859    GtkWidget *entry   = gtk_object_get_user_data (GTK_OBJECT (fontsel));
860    gchar     *fontname;
861    gchar     *fontconfigname;
862 
863    fontname = gtk_font_selection_dialog_get_font_name (GTK_FONT_SELECTION_DIALOG (fontsel));
864    fontconfigname = malloc(strlen(fontname) + 50);
865    convert_pango_to_fontconfig(fontname, fontconfigname);
866    gtk_entry_set_text (GTK_ENTRY (entry), fontconfigname);
867    free(fontconfigname);
868 }
869 
870 static void
update_entry(proplist_t key,gpointer ptr,proplist_t value,const char * path)871 update_entry (proplist_t key, gpointer ptr, proplist_t value,
872 	      const char *path)
873 {
874    if (WMIsPLString (value))
875       gtk_entry_set_text (GTK_ENTRY (ptr), WMGetFromPLString (value));
876 }
877 
878 static void
update_color(proplist_t key,gpointer ptr,proplist_t value,const char * path)879 update_color (proplist_t key, gpointer ptr, proplist_t value,
880 	      const char *path)
881 {
882    if (WMIsPLString (value))
883    {
884       GtkWidget  *preview  = GTK_WIDGET (ptr);
885       //the below wasn't used; was it supposed to be?
886       //proplist_t oldvalue  = gtk_object_get_user_data (GTK_OBJECT (preview));
887 
888       WMRetainPropList (value);
889       gtk_object_set_user_data (GTK_OBJECT (preview), value);
890       fill_preview (GTK_PREVIEW (preview), WMGetFromPLString (value));
891       WMPutInPLDictionary (windowmaker, key, value);
892       toggle_save (changed = YES, key);
893    }
894 }
895 
896 #ifdef HAVE_LIBWMFUN
897 static void
update_text_color(proplist_t key,gpointer ptr,proplist_t value,const char * path)898 update_text_color (proplist_t key, gpointer ptr, proplist_t value,
899 		   const char *path)
900 {
901    if (WMIsPLString (value) || WMIsPLArray (value))
902    {
903       text_color_t *text_color = (text_color_t *) ptr;
904 
905       WMPutInPLDictionary (windowmaker, key, value);
906       toggle_save (changed = YES, key);
907       show_color_buttons (text_color);
908    }
909 }
910 #endif /* HAVE_LIBWMFUN */
911 
912 static void
update_boolean(proplist_t key,gpointer ptr,proplist_t value,const char * path)913 update_boolean (proplist_t key, gpointer ptr, proplist_t value,
914 		const char *path)
915 {
916    if (WMIsPLString (value))
917    {
918       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ptr),
919 				    convert_bool (value));
920       set_bool (GTK_WIDGET (ptr), key);
921    }
922 }
923 
924 static void
update_iboolean(proplist_t key,gpointer ptr,proplist_t value,const char * path)925 update_iboolean (proplist_t key, gpointer ptr, proplist_t value,
926 		 const char *path)
927 {
928    if (WMIsPLString (value))
929    {
930       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ptr),
931 				    convert_bool (value) ? FALSE : TRUE);
932       set_bool (GTK_WIDGET (ptr), key);
933    }
934 }
935 
936 static void
update_int(proplist_t key,gpointer ptr,proplist_t value,const char * path)937 update_int (proplist_t key, gpointer ptr, proplist_t value,
938 	    const char *path)
939 {
940    GtkEntry **entry = (GtkEntry **) ptr;
941 
942    if (WMIsPLString (value))
943       gtk_entry_set_text (entry [0], WMGetFromPLString (value));
944    else if (WMIsPLArray (value))
945    {
946       unsigned n;
947 
948       for (n = 0; n < WMGetPropListItemCount (value); n++)
949 	 if (entry [n])
950 	    gtk_entry_set_text (entry [n],
951 				WMGetFromPLString (WMGetFromPLArray (value, n)));
952 	 else
953 	    break;
954    }
955 }
956