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 (>K_SPIN_BUTTON (spinner)->entry),
226 "changed", GTK_SIGNAL_FUNC (set_entry_text),
227 (gpointer) key);
228
229 array [n / 2] = >K_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