1 /*
2 * window.c: GTK stuff
3 *
4 * Written by: Ullrich Hafner
5 *
6 * Copyright (C) 1998 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 /*
25 * $Date: 2000/09/03 19:22:06 $
26 * $Author: hafner $
27 * $Revision: 1.123 $
28 * $State: Exp $
29 */
30
31 #include "config.h"
32
33 #if HAVE_STDLIB_H
34 # include <stdlib.h>
35 #endif /* not HAVE_STDLIB_H */
36 #if HAVE_STRING_H
37 # include <string.h>
38 #else /* not HAVE_STRING_H */
39 # include <strings.h>
40 #endif /* not HAVE_STRING_H */
41 #if HAVE_SYS_STAT_H
42 # include <sys/stat.h>
43 #endif /* HAVE_SYS_STAT_H */
44
45 #include <stdio.h>
46 #include <gtk/gtk.h>
47 #include "proplist_t.h"
48
49 /* unistd.h defines _POSIX_VERSION on POSIX.1 systems. */
50 #if defined(HAVE_DIRENT_H) || defined(_POSIX_VERSION)
51 # include <dirent.h>
52 # define NLENGTH(dirent) (strlen ((dirent)->d_name))
53 #else
54 # define dirent direct
55 # define NLENGTH(dirent) ((dirent)->d_namlen)
56 # ifdef HAVE_SYS_NDIR_H
57 # include <sys/ndir.h>
58 # endif /* HAVE_SYS_NDIR_H */
59 # ifdef HAVE_SYS_DIR_H
60 # include <sys/dir.h>
61 # endif /* HAVE_SYS_DIR_H */
62 # ifdef HAVE_NDIR_H
63 # include <ndir.h>
64 # endif /* HAVE_NDIR_H */
65 #endif /* not (HAVE_DIRENT_H or _POSIX_VERSION) */
66
67 #ifdef HAVE_IMLIB
68 #include <gdk_imlib.h>
69 #endif /* HAVE_IMLIB */
70
71 #include "window.h"
72 #include "icons.h"
73 #include "misc.h"
74 #include "dialog.h"
75 #include "texture.h"
76 #include "keys.h"
77 #include "menu.h"
78 #include "shortcuts.h"
79 #include "rootmenu.h"
80 #include "simple.h"
81 #include "path.h"
82 #include "themebrowser.h"
83 #include "rimage.h"
84
85 #include "error.h"
86
87 /*****************************************************************************
88
89 global variables
90
91 *****************************************************************************/
92
93 bool_t changed = NO;
94 bool_t use_imlib = NO;
95 GtkWidget *main_window = NULL;
96 GdkColor *background = NULL;
97 GtkTooltips *tooltips = NULL;
98 proplist_t windowmaker = NULL;
99 proplist_t wmconfig = NULL;
100
101 extern char *orig_wmaker_fname;
102 extern proplist_t plist_changed;
103 extern proplist_t pl_yes;
104
105 GtkWidget *widgetstyle_item = NULL;
106
107 /*****************************************************************************
108
109 prototypes
110
111 *****************************************************************************/
112
113 void
114 update (gpointer ptr, proplist_t value);
115 static GtkWidget *
116 create_page (GtkNotebook *notebook, const char *name, const char *pixmap_name,
117 bool_t horizontal);
118 static void
119 quit_and_save_popup (char *question,
120 void (*yes_function) (GtkWidget *, gpointer),
121 gpointer dataptr);
122 static void
123 switch_subentries (GtkWidget *widget, gpointer ptr);
124 static void
125 init_option_menu (gpointer data, gpointer user_data);
126 static void
127 appearance_container (proplist_t type, proplist_t thispanel,
128 GList **options, GtkWidget *box);
129 static int
130 compare_fn (const void * p1, const void * p2);
131
132 typedef struct { char * name; char * intlname; } names_t;
133
134 /*****************************************************************************
135
136 public code
137
138 *****************************************************************************/
139
140 void
root_window(const char * conffile,const node * sections,int sections_restriction_type,bool_t noinet,GtkWidget * logwindow,proplist_t wmc,proplist_t panel,proplist_t wmlist)141 root_window (const char *conffile, const node *sections,
142 int sections_restriction_type, bool_t noinet,
143 GtkWidget *logwindow, proplist_t wmc,
144 proplist_t panel, proplist_t wmlist)
145 /*
146 * Create root window and call the event loop of GTK
147 *
148 * No return value.
149 */
150 {
151 GtkWidget *box1;
152 GtkWidget *notebook;
153 #ifndef FREEBSD_SYSTEM
154 GtkWidget *progress_window = NULL;
155 GtkWidget *progress_label = NULL;
156 GtkWidget *progress_bar = NULL;
157 #endif /* not FREEBSD_SYSTEM */
158 GtkWidget *toolbar;
159 proplist_t plinfo = WMCreatePLString ("Info");
160 proplist_t pltype = WMCreatePLString ("Type");
161 proplist_t plicon = WMCreatePLString ("Icon");
162 proplist_t pltitle = WMCreatePLString ("Title");
163 proplist_t plwidget = WMCreatePLString ("Widget");
164 proplist_t plcolor = WMCreatePLString ("Colorbox");
165 proplist_t plfont = WMCreatePLString ("Fontbox");
166 proplist_t pltexture = WMCreatePLString ("Texturebox");
167 proplist_t plgrp = WMCreatePLString ("Group");
168 proplist_t plrange = WMCreatePLString ("Range");
169 proplist_t plrinfo = WMCreatePLString ("RangeInfo");
170 GList *options = NULL;
171 bool_t section_found = NO;
172 GtkWidget *iconbox = gtk_hbox_new (FALSE, 0);
173 char *section = NULL; /* will point to something if only
174 one section will be shown*/
175
176
177 #if defined(PREVIEWS) && !defined(CONVERT)
178 init_wraster_lib ();
179 #endif /* defined(PREVIEWS) && !defined(CONVERT) */
180
181 windowmaker = wmlist;
182 wmconfig = wmc;
183
184 if (sections_restriction_type == 1 && sections && !sections->next)
185 section = sections->name;
186
187 /*
188 * Progress bar window (only if not on FreeBSD and section is not given)
189 */
190 #ifndef FREEBSD_SYSTEM
191 if (!section)
192 {
193 GtkWidget *vbox;
194
195 progress_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
196 gtk_window_set_title (GTK_WINDOW (progress_window),
197 PACKAGE " " VERSION " init ...");
198
199 gtk_container_set_border_width (GTK_CONTAINER (progress_window), 10);
200 gtk_signal_connect (GTK_OBJECT (progress_window), "delete_event",
201 GTK_SIGNAL_FUNC (gtk_true), NULL);
202 gtk_widget_set_usize (progress_window, 250, -1);
203
204 vbox = gtk_vbox_new (FALSE, 0);
205 gtk_container_add (GTK_CONTAINER (progress_window), vbox);
206
207 progress_label = gtk_label_new ("");
208 gtk_box_pack_start (GTK_BOX (vbox), progress_label, FALSE, TRUE, 0);
209
210 {
211 GtkAdjustment *adj;
212
213 adj = (GtkAdjustment *) gtk_adjustment_new (0, 1, 300, 0, 0, 0);
214
215 progress_bar = gtk_progress_bar_new_with_adjustment (adj);
216 gtk_progress_set_format_string (GTK_PROGRESS (progress_bar), "[%p%%]");
217 gtk_progress_set_show_text (GTK_PROGRESS (progress_bar), YES);
218 }
219
220 gtk_box_pack_start (GTK_BOX (vbox), progress_bar, FALSE, TRUE, 0);
221 gtk_widget_show_all (progress_window);
222 }
223 #endif /* not FREEBSD_SYSTEM */
224
225 /*
226 * Fallback if libwraster is not (correctly) installed
227 */
228 #ifdef HAVE_IMLIB
229 {
230 GdkVisual *gdkvisual;
231 GdkColormap *gdkcmap;
232
233 gdk_imlib_init ();
234 gdkvisual = gdk_imlib_get_visual ();
235 gdkcmap = gdk_imlib_get_colormap ();
236
237 if (gdkvisual && gdkcmap)
238 {
239 gtk_widget_push_visual (gdkvisual);
240 gtk_widget_push_colormap (gdkcmap);
241 use_imlib = YES;
242 }
243 else
244 use_imlib = NO;
245 }
246 #endif /* HAVE_IMLIB */
247
248 gtk_widget_push_visual (gdk_rgb_get_visual ());
249 gtk_widget_push_colormap (gdk_rgb_get_cmap ());
250
251 /*
252 * Main window
253 */
254 main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
255 gtk_signal_connect (GTK_OBJECT (main_window), "delete_event",
256 GTK_SIGNAL_FUNC (quit), NULL);
257 gtk_widget_realize (main_window);
258 background = &main_window->style->bg [GTK_STATE_NORMAL];
259
260 init_pixmaps ();
261
262 while (gtk_events_pending()) /* FreeBSD workaround */
263 gtk_main_iteration();
264
265 box1 = gtk_vbox_new (FALSE, 0);
266 gtk_container_add (GTK_CONTAINER (main_window), box1);
267 tooltips = gtk_tooltips_new ();
268 gtk_widget_show (box1);
269
270 while (gtk_events_pending()) /* FreeBSD workaround */
271 gtk_main_iteration();
272
273 /*
274 * Menu and toolbox
275 */
276 gtk_box_pack_start (GTK_BOX(box1),
277 make_menubar (logwindow, section == NULL, noinet),
278 FALSE, TRUE, 0);
279 if (section)
280 {
281 gtk_box_pack_start (GTK_BOX(box1), iconbox, FALSE, TRUE, 0);
282 gtk_box_pack_start (GTK_BOX(iconbox), toolbar = make_toolbar (noinet),
283 FALSE, TRUE, 0);
284 }
285 else
286 gtk_box_pack_start (GTK_BOX(box1), toolbar = make_toolbar (noinet),
287 FALSE, TRUE, 0);
288
289 while (gtk_events_pending()) /* FreeBSD workaround */
290 gtk_main_iteration();
291
292 /*
293 * Notebook for all different wmakerconf sections
294 */
295 notebook = gtk_notebook_new ();
296 gtk_notebook_set_homogeneous_tabs (GTK_NOTEBOOK (notebook), FALSE);
297 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), TRUE);
298 gtk_notebook_set_scrollable (GTK_NOTEBOOK (notebook), TRUE);
299 gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_LEFT);
300 gtk_box_pack_start (GTK_BOX (box1), notebook, TRUE, TRUE, 0);
301 gtk_container_set_border_width (GTK_CONTAINER (notebook), section ? 5 : 10);
302 gtk_widget_show_all (notebook);
303
304 while (gtk_events_pending()) /* FreeBSD workaround */
305 gtk_main_iteration();
306
307 /*
308 * Generate notebook page for every section.
309 * Section information is extracted from config file 'WMWmakerconf'.
310 */
311 {
312 proplist_t tab_orig = WMGetPLDictionaryKeys (panel);
313 proplist_t tab = WMCreatePLArray (NULL);
314 names_t *tab_s;
315 unsigned n;
316 int size = WMGetPropListItemCount (tab_orig);
317
318 /* Sort the tabs alphabetically by the current translation.
319 * (OK, technically this isn't quite correct since the compare
320 * function is strcmp and the text ought to be UTF-8...)
321 * Unfortunately libWINGs provides no convenient way to do this. */
322 tab_s = malloc (size * sizeof (names_t));
323 for (n = 0; n < size; n++) {
324 proplist_t thispanel = WMGetFromPLArray (tab_orig, n);
325 proplist_t entry = WMGetFromPLDictionary (panel, thispanel);
326 proplist_t info = WMGetFromPLDictionary (entry, plinfo);
327
328 tab_s[n].name = WMGetFromPLString (thispanel);
329 tab_s[n].intlname = D_(WMGetFromPLString(info));
330 }
331 qsort (tab_s, size, sizeof (names_t), compare_fn);
332 for (n = 0; n < size; n++)
333 WMAddToPLArray (tab, WMCreatePLString (tab_s[n].name));
334 free (tab_s);
335 WMReleasePropList (tab_orig);
336
337 for (n = 0; n < size; n++)
338 {
339 proplist_t thispanel = WMGetFromPLArray (tab, n);
340 proplist_t entry = WMGetFromPLDictionary (panel, thispanel);
341 proplist_t info = WMGetFromPLDictionary (entry, plinfo);
342 proplist_t icon = WMGetFromPLDictionary (entry, plicon);
343 proplist_t type = WMGetFromPLDictionary (entry, pltype);
344 GtkWidget *page;
345
346 if (!icon || !info || !WMIsPLString (info) || !WMIsPLString (icon))
347 error (_("'%s': parse error."), conffile);
348
349 /*
350 * Check whether the current section is allowed
351 */
352 {
353 char *thissecname = WMGetFromPLString (thispanel);
354 const node *cur;
355 bool_t matches;
356
357 for (cur = sections, matches = NO; cur && !matches; cur = cur->next)
358 if (strcaseeq (thissecname, cur->name))
359 matches = YES;
360
361 if (sections &&
362 ((matches && sections_restriction_type==NO)
363 || (!matches && sections_restriction_type==YES)))
364 continue;
365 /* we are here since this section is allowed */
366 section_found = TRUE;
367 }
368
369 /*
370 * Create new notbook page (use icon given in WMWmakerconf)
371 */
372 {
373 char *path = g_strconcat (PKGDATADIR, "/", WMGetFromPLString (icon), NULL);
374
375 page = create_page (GTK_NOTEBOOK (notebook), D_(WMGetFromPLString (info)),
376 path, TRUE);
377 Free (path);
378 }
379
380 while (gtk_events_pending()) /* FreeBSD workaround */
381 gtk_main_iteration();
382
383 /*
384 * Create container for config widgets
385 */
386 {
387 GtkWidget *box = gtk_vbox_new (FALSE, 5);
388
389 gtk_widget_show (box);
390
391 while (gtk_events_pending()) /* FreeBSD workaround */
392 gtk_main_iteration();
393
394 /*
395 * Use different layout if section is given:
396 * Notebook border and tabs are invisible, section icon is
397 * shown in the top right corner.
398 */
399 if (section)
400 {
401 GdkPixmap *pixmap;
402 GdkBitmap *mask;
403 GtkWidget *image;
404 GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
405 char *path = g_strconcat (PKGDATADIR, "/",
406 WMGetFromPLString (icon), NULL);
407
408 pixmap = gdk_pixmap_create_from_xpm (main_window->window, &mask,
409 background, path);
410 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), FALSE);
411 gtk_notebook_set_show_border (GTK_NOTEBOOK (notebook), FALSE);
412 image = gtk_pixmap_new (pixmap, mask);
413 gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
414 gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, TRUE, 0);
415 gtk_box_pack_end (GTK_BOX(iconbox), hbox, FALSE, TRUE, 0);
416 gtk_widget_show_all (iconbox);
417 }
418 /*
419 * Config sections (except for Appearance) are
420 * surrounded by a frame.
421 */
422 if (!strcaseeq (WMGetFromPLString (thispanel), "Appearance")
423 && !strcaseeq (WMGetFromPLString (thispanel), "Paths"))
424 {
425 GtkWidget *frame;
426
427 frame = gtk_frame_new (section ? D_(WMGetFromPLString (info)) : NULL);
428 gtk_frame_set_label_align (GTK_FRAME (frame), 0.5, 0.5);
429 gtk_frame_set_shadow_type (GTK_FRAME (frame),
430 GTK_SHADOW_ETCHED_IN);
431 gtk_container_set_border_width (GTK_CONTAINER (frame), 5);
432 gtk_container_add (GTK_CONTAINER (frame), box);
433
434 gtk_container_add (GTK_CONTAINER (page), frame);
435 }
436 else
437 gtk_container_add (GTK_CONTAINER (page), box);
438
439 gtk_widget_show_all (page);
440
441 while (gtk_events_pending()) /* FreeBSD workaround */
442 gtk_main_iteration();
443
444 /*
445 * Generate special containers for Menu, Themes and Appearance
446 */
447 if (strcaseeq (WMGetFromPLString (thispanel), "Menu") &&
448 (!section || strcaseeq (section, "Menu")))
449 box = rootmenu_dialog (box, tooltips);
450 if (strcaseeq (WMGetFromPLString (thispanel), "Themes") &&
451 (!section || strcaseeq (section, "Themes")))
452 box = theme_browser (box, section != NULL);
453 if (strcaseeq (WMGetFromPLString (thispanel), "Appearance") &&
454 (!section || strcaseeq (section, "Appearance")))
455 appearance_container (type, thispanel, &options, box);
456
457 /*
458 * Store container widget of current panel
459 */
460 {
461 proplist_t data;
462 data = WMCreatePLDataWithBytes ((unsigned char *) &box, sizeof (GtkWidget *));
463 WMPutInPLDictionary (entry, plwidget, data);
464 WMReleasePropList (data);
465 }
466 }
467 }
468 WMReleasePropList (tab);
469 }
470
471 if (!section_found)
472 error (_("No sections to show!"));
473
474 while (gtk_events_pending()) /* FreeBSD workaround */
475 gtk_main_iteration();
476
477 /*
478 * Add config widget for each defined Window Maker attribute
479 */
480 {
481 proplist_t all_keys = WMGetPLDictionaryKeys (wmconfig);
482 unsigned melem = WMGetPropListItemCount (all_keys);
483 unsigned n;
484
485 for (n = 0; n < melem; n++)
486 {
487 proplist_t key = WMGetFromPLArray (all_keys, n);
488 proplist_t value = WMGetFromPLDictionary (windowmaker, key);
489 proplist_t keydef = WMGetFromPLDictionary (wmconfig, key);
490 proplist_t group = WMGetFromPLDictionary (keydef, plgrp);
491 proplist_t title = WMGetFromPLDictionary (keydef, pltitle);
492 proplist_t range;
493 proplist_t info;
494 proplist_t rinfo;
495 GtkWidget *page_box;
496 char *name;
497 char *type;
498 proplist_t ptype;
499 proplist_t pentry;
500
501 if (strcaseeq (WMGetFromPLString (group), "None"))
502 continue;
503
504 #ifndef FREEBSD_SYSTEM
505 /*
506 * Update of progress bar window
507 */
508 if (!section)
509 {
510 gtk_label_set_text (GTK_LABEL (progress_label), WMGetFromPLString (key));
511 gtk_progress_bar_update (GTK_PROGRESS_BAR (progress_bar),
512 n / (double) melem);
513 gtk_widget_draw (progress_window, NULL);
514 }
515 #endif /* not FREEBSD_SYSTEM */
516
517 while (gtk_events_pending())
518 gtk_main_iteration();
519
520 range = WMGetFromPLDictionary (keydef, plrange);
521 rinfo = WMGetFromPLDictionary (keydef, plrinfo);
522 info = WMGetFromPLDictionary (keydef, plinfo);
523 name = WMGetFromPLString (key);
524 type = WMGetFromPLString (WMGetFromPLDictionary (keydef, pltype));
525
526 /*
527 * We need attributes of actived sections only
528 */
529 {
530 char *thissecname = WMGetFromPLString (group);
531 const node* cur;
532 bool_t matches;
533
534 for(cur = sections, matches = NO; cur && !matches; cur = cur->next)
535 if (strncaseeq(thissecname,cur->name,cur->length))
536 matches = YES;
537
538 if (sections &&
539 ((matches && sections_restriction_type==NO)
540 || (!matches && sections_restriction_type==YES)))
541 continue;
542 /* we are here since this section is allowed */
543 section_found = TRUE;
544 }
545
546 /*
547 * Get main group and corresponding container
548 */
549 {
550 char *pos;
551 proplist_t pgroup;
552 proplist_t pbox;
553 char *groupname = g_strdup (WMGetFromPLString (group));
554
555 if ((pos = strchr (groupname, '/')))
556 *pos = 0;
557
558 pgroup = WMCreatePLString (groupname);
559 pentry = WMGetFromPLDictionary (panel, pgroup);
560 pbox = WMGetFromPLDictionary (pentry, plwidget);
561 ptype = WMGetFromPLDictionary (pentry, pltype);
562 WMReleasePropList (pgroup);
563
564 if (!pentry || !pbox || !ptype)
565 continue;
566
567 if (WMIsPLDictionary (ptype)) /* get sub entry */
568 {
569 char *subname = pos + 1;
570
571 if ((pos = strchr (subname, '/')))
572 *pos = 0;
573
574 pgroup = WMCreatePLString (subname);
575 pentry = WMGetFromPLDictionary (ptype, pgroup);
576 ptype = WMGetFromPLDictionary (pentry, pltype);
577 WMReleasePropList (pgroup);
578
579 if (WMIsPLDictionary (ptype) && pos) /* get sub sub entry */
580 {
581 pgroup = WMCreatePLString (pos + 1);
582 pentry = WMGetFromPLDictionary (ptype, pgroup);
583 WMReleasePropList (pgroup);
584 if (strcaseeq (type, "Color") || strcaseeq (type, "TextColor") )
585 pbox = WMGetFromPLDictionary (pentry, plcolor);
586 else if (strcaseeq (type, "Font"))
587 pbox = WMGetFromPLDictionary (pentry, plfont);
588 else if (strcaseeq (type, "Texture"))
589 pbox = WMGetFromPLDictionary (pentry, pltexture);
590 else
591 pbox = WMGetFromPLDictionary (pentry, plwidget);
592 }
593 else
594 {
595 if (strcaseeq (type, "Color") || strcaseeq (type, "TextColor"))
596 pbox = WMGetFromPLDictionary (pentry, plcolor);
597 else if (strcaseeq (type, "Font"))
598 pbox = WMGetFromPLDictionary (pentry, plfont);
599 else if (strcaseeq (type, "Texture"))
600 pbox = WMGetFromPLDictionary (pentry, pltexture);
601 else
602 pbox = WMGetFromPLDictionary (pentry, plwidget);
603 }
604 page_box = * (GtkWidget **) WMGetPLDataBytes (pbox);
605 {
606 GtkWidget *frame;
607 frame = gtk_object_get_user_data (GTK_OBJECT (page_box));
608
609 if (frame && GTK_IS_WIDGET (frame)
610 && !GTK_WIDGET_VISIBLE (frame))
611 gtk_widget_show_all (frame);
612 }
613 }
614 else
615 page_box = * (GtkWidget **) WMGetPLDataBytes (pbox);
616
617 Free (groupname);
618 }
619
620 while (gtk_events_pending())
621 gtk_main_iteration();
622
623 /*
624 * Use different dialogs for different attribute types
625 */
626 if (strcaseeq ("Bool", type))
627 {
628 boolean_dialog (page_box, key, value, title);
629 }
630 else if (strcaseeq ("IBool", type))
631 {
632 iboolean_dialog (page_box, key, value, title);
633 }
634 else if (strcaseeq ("String", type)
635 && !strcaseeq ("ModifierKey", WMGetFromPLString (key)))
636 {
637 string_dialog (page_box, key, value, range, rinfo, title);
638 }
639 else if (strcaseeq ("Int", type))
640 {
641 int_dialog (page_box, key, value, range, rinfo, title);
642 }
643 else if (strcaseeq ("Text", type))
644 {
645 text_dialog (page_box, key, value, title);
646 }
647 else if (strcaseeq ("Font", type) || strcaseeq ("Color", type)
648 || strcaseeq ("TextColor", type)
649 || strcaseeq ("Texture", type))
650 {
651 GtkWidget *widget;
652 proplist_t data;
653
654 if (strcaseeq ("Font", type))
655 widget = font_dialog (page_box, key, value, info);
656 else if (strcaseeq ("Texture", type))
657 {
658 GtkWidget *box = NULL;
659 proplist_t fontbox = WMGetFromPLDictionary (pentry, plfont);
660
661 if (fontbox)
662 box = * (GtkWidget **) WMGetPLDataBytes (fontbox);
663 widget = texture_dialog (page_box, box, key);
664 }
665 #ifdef HAVE_LIBWMFUN
666 else if (strcaseeq ("TextColor", type))
667 widget = extended_color_dialog (page_box, key, value, tooltips,
668 info, title);
669 #endif /* HAVE_LIBWMFUN */
670 else
671 widget = color_dialog (page_box, key, value, tooltips,
672 info, title);
673
674 data = WMCreatePLDataWithBytes ((unsigned char *) &widget, sizeof (GtkWidget *));
675 WMPutInPLDictionary (keydef, plwidget, data);
676 WMReleasePropList (data);
677
678 if (WMIsPLDictionary (ptype)) /* subsubbox */
679 gtk_widget_hide (widget);
680 }
681 else if (strcaseeq ("Key", type))
682 {
683 add_shortcut (page_box, key);
684 }
685 else if (strcaseeq ("Pathlist", type))
686 {
687 if (!streq (WMGetFromPLString (key), "ThemePath"))
688 path_dialog (page_box, key, value, tooltips, info);
689 }
690 }
691 WMReleasePropList (all_keys);
692 }
693
694 gtk_widget_set_usize (main_window,
695 min (gdk_screen_width () - 64,
696 790 - (section ? 150 : 0)),
697 min (gdk_screen_height () - 64, 600));
698
699 while (gtk_events_pending())
700 gtk_main_iteration();
701
702 toggle_save (changed = NO, NULL);
703 #ifndef FREEBSD_SYSTEM
704 if (!section)
705 gtk_widget_destroy (progress_window);
706 #endif /* not FREEBSD_SYSTEM */
707
708 WMReleasePropList (plinfo);
709 WMReleasePropList (pltype);
710 WMReleasePropList (plicon);
711 WMReleasePropList (plwidget);
712 WMReleasePropList (plcolor);
713 WMReleasePropList (plfont);
714 WMReleasePropList (pltexture);
715 WMReleasePropList (plrange);
716 WMReleasePropList (plgrp);
717 WMReleasePropList (pltitle);
718
719 g_list_foreach (options, init_option_menu, NULL);
720 g_list_free (options);
721
722 while (gtk_events_pending())
723 gtk_main_iteration();
724
725 check_widgetstyle ();
726 #ifdef GETSTYLE
727 get_theme_attributes ();
728 #endif /* GETSTYLE */
729
730 while (gtk_events_pending())
731 gtk_main_iteration();
732
733 gtk_widget_show (main_window);
734
735 {
736 char *path = g_strconcat (g_get_home_dir (), "/.wmakerconf", NULL);
737 DIR *dir;
738
739 if (!(dir = opendir (path)))
740 {
741 dialog_popup (DIALOG_INFO, generate_previews, NULL,
742 _("Directory $HOME/.wmakerconf does not exist yet.\n"
743 "This directory is used to store the previews of all "
744 "images.\nShould I generate this directory and the "
745 "image previews now?"));
746 }
747 else
748 closedir (dir);
749 }
750
751 gtk_main ();
752 gtk_widget_destroy (main_window);
753 cleanup_textures ();
754 #ifdef GETSTYLE
755 cleanup_themes ();
756 #endif /* GETSTYLE */
757 }
758
759 void
check_widgetstyle(void)760 check_widgetstyle (void)
761 {
762 proplist_t plnewstyle = WMCreatePLString ("NewStyle");
763 proplist_t value = WMGetFromPLDictionary (windowmaker, plnewstyle);
764
765 if (widgetstyle_item)
766 gtk_widget_set_sensitive (widgetstyle_item, !convert_bool (value));
767
768 WMReleasePropList (plnewstyle);
769 }
770
771 char *
get_pixmap_path(const char * name)772 get_pixmap_path (const char *name)
773 /*
774 * Guess filename of pixmap 'name'.
775 * Cycle through list of available paths or use absolute path
776 * if name [0] == '/' or '~'.
777 *
778 * Return value:
779 * string with pixmap path on success
780 * NULL if pixmap not found
781 */
782 {
783 if (name [0] == '/' || name [0] == '~') /* absolute path ? */
784 {
785 FILE *file;
786 char *path = expand_tilde (name);
787
788 file = fopen (path, "r");
789 if (!file)
790 {
791 Free (path);
792 return NULL;
793 }
794 else
795 {
796 fclose (file);
797 return path;
798 }
799 }
800 else
801 {
802 unsigned n;
803 char *found = NULL;
804 proplist_t plpath = WMCreatePLString ("PixmapPath");
805 proplist_t pixmap_path = WMGetFromPLDictionary (windowmaker, plpath);
806
807 WMReleasePropList (plpath);
808
809 for (n = 0; n < WMGetPropListItemCount (pixmap_path) && !found; n++)
810 {
811 FILE *file;
812 char *path = expand_tilde (WMGetFromPLString (WMGetFromPLArray (pixmap_path,
813 n)));
814 char *filename = g_strconcat (path, "/", name, NULL);
815
816 Free (path);
817 file = fopen (filename, "r");
818 if (file)
819 {
820 found = filename;
821 fclose (file);
822 }
823 else
824 Free (filename);
825 }
826 return found;
827 }
828 }
829
830 GtkWidget *
make_pixmap(const char * name,int width,int height,GtkWidget * pw)831 make_pixmap (const char *name, int width, int height, GtkWidget *pw)
832 /*
833 * Genearate a new pixmap widget with pixmap 'name' of maximum size
834 * 'max_width' x 'max_height'. If 'pw' is already valid (i.e., != NULL)
835 * just replace the pixmap of the widget.
836 *
837 * Return value:
838 * new or changed pixmap widget
839 */
840 {
841 char *path = get_pixmap_path (name);
842
843 if (!path)
844 {
845 dialog_popup (DIALOG_ERROR, NULL, NULL,
846 _("Can't find pixmap\n'%s`\nin PixmapPath. Please update\n"
847 "your PixmapPath attribute."), name);
848 return make_pixmap (PKGDATADIR "/black.xpm", width, height, pw);
849 }
850
851 #if defined(PREVIEWS) && !defined(CONVERT)
852
853 if (!pw && width > 0 && height > 0)
854 pw = make_image (PKGDATADIR "/black.xpm", width, height, pw);
855 pw = make_image (path, width, height, pw);
856
857 #else /* not PREVIEWS or CONVERT */
858
859 #ifdef HAVE_STAT
860 /*
861 * Don't load large XPM (may cause trouble with imlib)
862 */
863 {
864 struct stat buffer;
865
866 if (strstr (path, ".xpm") && stat (path, &buffer) == 0
867 && buffer.st_size > 65000) /* image too large */
868 {
869 Free (path);
870 return make_pixmap (PKGDATADIR "/black.xpm", width, height, pw);
871 }
872 }
873 #endif /* HAVE_STAT */
874
875 {
876 GdkBitmap *mask = NULL;
877 GdkPixmap *pixmap = NULL;
878
879 #ifdef HAVE_IMLIB
880 if (use_imlib)
881 {
882 GdkImlibImage *image;
883
884 image = gdk_imlib_load_image (path);
885 if (image)
886 {
887 if (width <= 0)
888 width = image->rgb_width;
889 if (height <= 0)
890 height = image->rgb_height;
891 if (image->rgb_width > width || image->rgb_height > height)
892 {
893 if (height * image->rgb_width > width * image->rgb_height)
894 height = width * image->rgb_height / image->rgb_width;
895 else
896 width = height * image->rgb_width / image->rgb_height;
897 }
898 gdk_imlib_render (image, max (width, 22), max (height, 22));
899 pixmap = gdk_imlib_move_image (image);
900 mask = gdk_imlib_move_mask (image);
901 if (strchr (g_path_get_basename (path), '.')) /* don't cache x-of-day */
902 gdk_imlib_destroy_image (image);
903 else
904 gdk_imlib_kill_image (image);
905 }
906 }
907 else
908 #else /* not HAVE_IMLIB */
909 pixmap
910 = gdk_pixmap_create_from_xpm (main_window->window, &mask,
911 background, PKGDATADIR "/black.xpm");
912 #endif /* not HAVE_IMLIB */
913 if (!pixmap) /* pixmap not found or unknown format */
914 {
915 static bool_t error_message = NO;
916
917 if (!error_message)
918 {
919 dialog_popup (DIALOG_ERROR, NULL, NULL,
920 _("Unable to display pixmap\n'%s`\n"
921 "(format not supported).\n"
922 "See stderr for subsequent messages."), path);
923 error_message = YES;
924 }
925 else
926 warning (_("Can't display pixmap '%s`."), path);
927 Free (path);
928 return make_pixmap (PKGDATADIR "/black.xpm", width, height, pw);
929 }
930 Free (path);
931 if (pw)
932 gtk_pixmap_set (GTK_PIXMAP (pw), pixmap, mask);
933 else
934 {
935 pw = gtk_pixmap_new (pixmap, mask);
936 gtk_widget_show (pw);
937 }
938 }
939 #endif /* not PREVIEWS or CONVERT */
940
941 return pw;
942 }
943
944 gint
quit(GtkWidget * widget,gpointer ptr)945 quit (GtkWidget *widget, gpointer ptr)
946 /*
947 * Return from gtk_main () loop, i.e. leave the application.
948 * Before quitting ask for confirmation.
949 *
950 * No return value.
951 */
952 {
953 if (changed || rootmenu_changed ())
954 {
955 quit_and_save_popup (_("Some values are modified.\n"
956 "Do you want to save them before quitting?"),
957 save_config_file, (gpointer) "quit");
958 return TRUE;
959 }
960 else
961 {
962 gtk_main_quit ();
963 return TRUE; /* do not delete window */
964 }
965 }
966
967 static void
quit_and_save_popup(char * question,void (* save_function)(GtkWidget *,gpointer),gpointer dataptr)968 quit_and_save_popup (char *question,
969 void (*save_function) (GtkWidget *, gpointer),
970 gpointer dataptr)
971 /*
972 * Popup dialog to ensure that current process is not killed until
973 * user confirmation.
974 * 'question' is the text to be displayed.
975 * 'save_function' is called in case user confirms saving.
976 * 'dataptr' argument is passed to 'save_function'.
977 *
978 * No return value.
979 */
980 {
981 GtkWidget *hbox;
982 GtkWidget *window, *button;
983
984 window = gtk_dialog_new ();
985 gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_MOUSE);
986 gtk_window_set_title (GTK_WINDOW (window), _("Save before quitting?"));
987 gtk_widget_realize (window);
988
989 gtk_signal_connect (GTK_OBJECT (window), "delete_event",
990 GTK_SIGNAL_FUNC (gtk_false), NULL);
991 gtk_signal_connect_object (GTK_OBJECT (window), "destroy",
992 GTK_SIGNAL_FUNC (gtk_widget_destroy),
993 GTK_OBJECT (window));
994
995 hbox = gtk_hbox_new (FALSE, 5);
996 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), hbox,
997 FALSE, FALSE, 0);
998 gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
999
1000 gtk_box_pack_start (GTK_BOX (hbox),
1001 gtk_pixmap_new (p_array [P_INFO].pixmap,
1002 p_array [P_INFO].mask),
1003 TRUE, FALSE, 5);
1004
1005 gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (question), TRUE, TRUE, 5);
1006
1007 button = gtk_button_new_with_label (_("Yes"));
1008 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button,
1009 TRUE, TRUE, 10);
1010 GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
1011 gtk_widget_grab_default (button);
1012 gtk_signal_connect (GTK_OBJECT (button), "clicked",
1013 GTK_SIGNAL_FUNC (save_function), dataptr);
1014 gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
1015 (GtkSignalFunc) gtk_widget_destroy,
1016 GTK_OBJECT (window));
1017
1018 button = gtk_button_new_with_label (_("No"));
1019 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button,
1020 TRUE, TRUE, 10);
1021 gtk_signal_connect (GTK_OBJECT (button), "clicked",
1022 GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
1023
1024 button = gtk_button_new_with_label (_("Cancel"));
1025 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button,
1026 TRUE, TRUE, 10);
1027 gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
1028 (GtkSignalFunc) gtk_widget_destroy,
1029 GTK_OBJECT (window));
1030
1031 gtk_widget_show_all (window);
1032 }
1033
1034 void
save_config_file(GtkWidget * widget,gpointer ptr)1035 save_config_file (GtkWidget *widget, gpointer ptr)
1036 /*
1037 * Save 'WindowMaker' file if attributes have been changed.
1038 *
1039 * No return value.
1040 *
1041 * Side effects:
1042 * 'changed' is set to FALSE
1043 */
1044 {
1045 if (!save_rootmenu ())
1046 return;
1047
1048 if (changed)
1049 {
1050 proplist_t newwm = WMCreatePLDictionary (NULL, NULL, NULL);
1051
1052 /*
1053 * Compare user attributes with system attributes
1054 */
1055 {
1056 proplist_t all_keys = WMGetPLDictionaryKeys (windowmaker) ;
1057 unsigned n;
1058
1059 for (n = 0; n < WMGetPropListItemCount (all_keys); n++)
1060 {
1061 proplist_t user;
1062 proplist_t key = WMGetFromPLArray (all_keys, n);
1063
1064 user = WMGetFromPLDictionary (windowmaker, key);
1065
1066 if (WMGetFromPLDictionary (plist_changed, key))
1067 WMPutInPLDictionary (newwm, key, WMDeepCopyPropList (user));
1068 }
1069 WMReleasePropList (all_keys);
1070 }
1071
1072 if (WMWritePropListToFile (newwm, orig_wmaker_fname))
1073 {
1074 changed = NO;
1075 message (_("Window Maker config file '%s' saved."),
1076 orig_wmaker_fname);
1077 }
1078 else
1079 {
1080 dialog_popup (DIALOG_ERROR, NULL, NULL,
1081 _("Can't write to Window Maker file\n`%s'."),
1082 orig_wmaker_fname);
1083 return;
1084 }
1085 WMReleasePropList (newwm);
1086 }
1087
1088 enable_revert ();
1089 toggle_save (FALSE, NULL);
1090
1091 if (ptr && streq (ptr, "quit"))
1092 gtk_main_quit ();
1093 }
1094
1095 /*****************************************************************************
1096
1097 private code
1098
1099 *****************************************************************************/
1100
1101 static int
compare_fn(const void * p1,const void * p2)1102 compare_fn (const void *p1, const void *p2)
1103 { return strcmp(((names_t *)p1)->intlname, ((names_t *)p2)->intlname); }
1104
1105 static void
appearance_container(proplist_t type,proplist_t thispanel,GList ** options,GtkWidget * box)1106 appearance_container (proplist_t type, proplist_t thispanel,
1107 GList **options, GtkWidget *box)
1108 /*
1109 * Gererate sub-containers for each appearance sub-panel.
1110 */
1111 {
1112 proplist_t subentries = WMGetPLDictionaryKeys (type);
1113 GtkWidget *subbook = gtk_notebook_new ();
1114 proplist_t plinfo = WMCreatePLString ("Info");
1115 proplist_t plfont = WMCreatePLString ("Fontbox");
1116 proplist_t pltexture = WMCreatePLString ("Texturebox");
1117 proplist_t plcolor = WMCreatePLString ("Colorbox");
1118 proplist_t plwidget = WMCreatePLString ("Widget");
1119 proplist_t pltype = WMCreatePLString ("Type");
1120 proplist_t plicon = WMCreatePLString ("Icon");
1121 unsigned i;
1122
1123 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (subbook), TRUE);
1124 gtk_notebook_set_scrollable (GTK_NOTEBOOK (subbook), TRUE);
1125 gtk_notebook_set_tab_pos (GTK_NOTEBOOK (subbook), GTK_POS_TOP);
1126 gtk_notebook_set_homogeneous_tabs (GTK_NOTEBOOK (subbook), TRUE);
1127 gtk_box_pack_start (GTK_BOX (box), subbook, TRUE, TRUE, 0);
1128 gtk_container_set_border_width (GTK_CONTAINER (subbook), 10);
1129 gtk_widget_show_all (subbook);
1130
1131 while (gtk_events_pending())
1132 gtk_main_iteration();
1133
1134 for (i = 0; i < WMGetPropListItemCount (subentries); i++)
1135 {
1136 GtkWidget *subpage;
1137 proplist_t thissub = WMGetFromPLArray (subentries, i);
1138 proplist_t subentry = WMGetFromPLDictionary (type, thissub);
1139 proplist_t subinfo = WMGetFromPLDictionary (subentry, plinfo);
1140 proplist_t subicon = WMGetFromPLDictionary (subentry, plicon);
1141 proplist_t subtype = WMGetFromPLDictionary (subentry, pltype);
1142 char *path = NULL;
1143
1144 if (subicon && WMIsPLString (subicon)) /* subsubsections ? */
1145 path = g_strconcat (PKGDATADIR, "/",
1146 WMGetFromPLString (subicon), NULL);
1147 subpage = create_page (GTK_NOTEBOOK (subbook),
1148 D_(WMGetFromPLString (subinfo)), path, FALSE);
1149 if (path)
1150 Free (path);
1151
1152 {
1153 proplist_t data;
1154
1155 data = WMCreatePLDataWithBytes ((unsigned char *) &subpage,
1156 sizeof (GtkWidget *));
1157 WMPutInPLDictionary (subentry, plwidget, data);
1158 WMReleasePropList (data);
1159 }
1160
1161
1162 while (gtk_events_pending())
1163 gtk_main_iteration();
1164
1165 /*
1166 * Add subboxes for color, texture and font
1167 */
1168 {
1169 GtkWidget *vbox = gtk_vbox_new (FALSE, 0);
1170 GtkWidget *nw_hbox = gtk_hbox_new (FALSE, 0);
1171 GtkWidget *color_frame = gtk_hbox_new (FALSE, 0);
1172 GtkWidget *texture_frame = gtk_hbox_new (FALSE, 0);
1173 GtkWidget *color_box = gtk_hbox_new (FALSE, 0);
1174 GtkWidget *texture_box = gtk_vbox_new (FALSE, 0);
1175 GtkWidget *hbox;
1176 proplist_t color_data;
1177 proplist_t texture_data;
1178 proplist_t font_data;
1179
1180 gtk_container_add (GTK_CONTAINER (subpage), vbox);
1181
1182 /*
1183 * Overall boxes
1184 */
1185 gtk_box_pack_start (GTK_BOX (vbox), nw_hbox,
1186 FALSE, TRUE, 5);
1187 hbox = gtk_hbox_new (FALSE, 0);
1188 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
1189 gtk_box_pack_start (GTK_BOX (hbox), color_frame,
1190 TRUE, TRUE, 5);
1191 hbox = gtk_hbox_new (FALSE, 0);
1192 gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 5);
1193 gtk_box_pack_start (GTK_BOX (hbox), texture_frame,
1194 TRUE, TRUE, 5);
1195 while (gtk_events_pending())
1196 gtk_main_iteration();
1197
1198 /*
1199 * Color box
1200 */
1201 {
1202 GtkWidget *frame = gtk_frame_new (_("Colors"));
1203 GtkWidget *box = color_box;
1204
1205 gtk_box_pack_start (GTK_BOX (color_frame), frame,
1206 TRUE, TRUE, 0);
1207 gtk_frame_set_label_align (GTK_FRAME (frame), 0.5, 0.5);
1208 gtk_container_add (GTK_CONTAINER (frame), box);
1209 gtk_container_set_border_width (GTK_CONTAINER (box), 5);
1210 color_data = WMCreatePLDataWithBytes ((unsigned char *) &box,
1211 sizeof (GtkWidget *));
1212 gtk_object_set_user_data (GTK_OBJECT (box),
1213 color_frame);
1214 }
1215 while (gtk_events_pending())
1216 gtk_main_iteration();
1217 /*
1218 * Texture box
1219 */
1220 {
1221 GtkWidget *frame = gtk_frame_new (_("Texture"));
1222 GtkWidget *box = texture_box;
1223
1224 gtk_box_pack_start (GTK_BOX (texture_frame), frame,
1225 TRUE, TRUE, 0);
1226 gtk_frame_set_label_align (GTK_FRAME (frame), 0.5, 0.5);
1227 gtk_container_add (GTK_CONTAINER (frame), box);
1228 texture_data = WMCreatePLDataWithBytes ((unsigned char *) &box,
1229 sizeof (GtkWidget *));
1230 gtk_object_set_user_data (GTK_OBJECT (box),
1231 texture_frame);
1232 }
1233 /*
1234 * Font box
1235 */
1236 {
1237 font_data = WMCreatePLDataWithBytes ((unsigned char *) &nw_hbox,
1238 sizeof (GtkWidget *));
1239 }
1240 gtk_widget_show_all (subpage);
1241 gtk_widget_hide (color_frame);
1242 gtk_widget_hide (texture_frame);
1243
1244 while (gtk_events_pending())
1245 gtk_main_iteration();
1246
1247 /*
1248 * Make option box with subsubsections and subboxes
1249 * for color, texture and font
1250 */
1251 if (subtype && WMIsPLDictionary (subtype))
1252 {
1253 proplist_t ssentries = WMGetPLDictionaryKeys (subtype);
1254 unsigned k;
1255 char *path;
1256 GtkWidget *option_menu = gtk_option_menu_new ();
1257 GtkWidget *menu = gtk_menu_new ();
1258
1259 path = g_strconcat (WMGetFromPLString (thispanel), "/",
1260 WMGetFromPLString (thissub), NULL);
1261
1262 for (k = 0; k < WMGetPropListItemCount (ssentries); k++)
1263 {
1264 proplist_t thisss;
1265 proplist_t ssentry;
1266 proplist_t ssinfo;
1267 GtkWidget *menu_item;
1268
1269 thisss = WMGetFromPLArray (ssentries, k);
1270 ssentry = WMGetFromPLDictionary (subtype, thisss);
1271 ssinfo = WMGetFromPLDictionary (ssentry, plinfo);
1272 menu_item = gtk_menu_item_new_with_label (D_(WMGetFromPLString (ssinfo)));
1273 gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
1274 GTK_SIGNAL_FUNC (switch_subentries),
1275 path);
1276 gtk_object_set_user_data (GTK_OBJECT (menu_item),
1277 (gpointer) WMGetFromPLString (thisss));
1278 gtk_menu_append (GTK_MENU (menu), menu_item);
1279 gtk_widget_show (menu_item);
1280
1281 WMPutInPLDictionary (ssentry, plcolor,
1282 color_data);
1283 WMPutInPLDictionary (ssentry, pltexture,
1284 texture_data);
1285 WMPutInPLDictionary (ssentry, plfont,
1286 font_data);
1287 if (strcaseeq (WMGetFromPLString (thisss), "Widget"))
1288 widgetstyle_item = menu_item;
1289 }
1290 gtk_option_menu_set_menu (GTK_OPTION_MENU (option_menu),
1291 menu);
1292 gtk_option_menu_set_history (GTK_OPTION_MENU (option_menu), 0);
1293 gtk_widget_show (option_menu);
1294 *options = g_list_append (*options, option_menu);
1295
1296 while (gtk_events_pending())
1297 gtk_main_iteration();
1298
1299 {
1300 GtkWidget *frame;
1301 GtkWidget *box = gtk_hbox_new (TRUE, 0);
1302
1303 frame = gtk_frame_new (D_(WMGetFromPLString (subinfo)));
1304 gtk_frame_set_label_align (GTK_FRAME (frame),
1305 0.5, 0.5);
1306 gtk_container_set_border_width (GTK_CONTAINER (box), 5);
1307 gtk_container_add (GTK_CONTAINER (frame), box);
1308 gtk_box_pack_start (GTK_BOX (box), option_menu,
1309 TRUE, TRUE, 0);
1310 gtk_box_pack_start (GTK_BOX (nw_hbox), frame,
1311 FALSE, TRUE, 5);
1312 gtk_widget_show_all (frame);
1313 }
1314
1315 while (gtk_events_pending())
1316 gtk_main_iteration();
1317
1318 }
1319 else
1320 {
1321 WMPutInPLDictionary (subentry, plcolor,
1322 color_data);
1323 WMPutInPLDictionary (subentry, pltexture,
1324 texture_data);
1325 WMPutInPLDictionary (subentry, plfont,
1326 font_data);
1327 }
1328 WMReleasePropList (color_data);
1329 WMReleasePropList (texture_data);
1330 WMReleasePropList (font_data);
1331 }
1332 }
1333 WMReleasePropList (subentries);
1334 WMReleasePropList (plinfo);
1335 WMReleasePropList (pltype);
1336 WMReleasePropList (plicon);
1337 WMReleasePropList (plwidget);
1338 WMReleasePropList (plcolor);
1339 WMReleasePropList (plfont);
1340 WMReleasePropList (pltexture);
1341 }
1342
1343 static void
init_option_menu(gpointer data,gpointer user_data)1344 init_option_menu (gpointer data, gpointer user_data)
1345 {
1346 GtkOptionMenu *omenu = GTK_OPTION_MENU (data);
1347 GtkMenu *menu = GTK_MENU (gtk_option_menu_get_menu (omenu));
1348 GtkWidget *item = gtk_menu_get_active (menu);
1349
1350 if (item)
1351 gtk_menu_item_activate (GTK_MENU_ITEM (item));
1352 }
1353
1354 static GtkWidget *
create_page(GtkNotebook * notebook,const char * name,const char * pixmap_name,bool_t horizontal)1355 create_page (GtkNotebook *notebook, const char *name, const char *pixmap_name,
1356 bool_t horizontal)
1357 /*
1358 * Create a new group notebook page and append it to the given 'notebook'.
1359 * 'name' is the notebook label and 'pm' is the pixmap identifier.
1360 *
1361 * Return value:
1362 * container of label and pixmap
1363 */
1364 {
1365 GtkWidget *vbox = gtk_vbox_new (FALSE, 5);
1366 GtkWidget *label_box = NULL;
1367 GtkWidget *scrolled = NULL;
1368
1369 if (name || pixmap_name)
1370 {
1371 label_box = horizontal ? gtk_hbox_new (FALSE, 5) : gtk_vbox_new (FALSE, 0);
1372 gtk_container_set_border_width (GTK_CONTAINER (label_box),
1373 horizontal ? 0 : 5);
1374 if (pixmap_name)
1375 {
1376 GdkPixmap *pixmap;
1377 GdkBitmap *mask;
1378
1379 pixmap = gdk_pixmap_create_from_xpm (main_window->window, &mask,
1380 background, pixmap_name);
1381 if (pixmap)
1382 gtk_box_pack_start (GTK_BOX (label_box),
1383 gtk_pixmap_new (pixmap, mask), FALSE, TRUE, 0);
1384 }
1385 if (name)
1386 gtk_box_pack_start (GTK_BOX (label_box), gtk_label_new (name),
1387 TRUE, TRUE, 0);
1388 gtk_widget_show_all (label_box);
1389 }
1390
1391 scrolled = gtk_scrolled_window_new (NULL, NULL);
1392 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
1393 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1394 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled),
1395 vbox);
1396 gtk_notebook_append_page_menu (notebook, scrolled, label_box, NULL);
1397 gtk_widget_show_all (scrolled);
1398
1399 return vbox;
1400 }
1401
1402 static void
switch_subentries(GtkWidget * widget,gpointer ptr)1403 switch_subentries (GtkWidget *widget, gpointer ptr)
1404 /*
1405 * Show only widgets of chosen subsubentry
1406 */
1407 {
1408 unsigned n;
1409 proplist_t all_keys = WMGetPLDictionaryKeys (wmconfig);
1410 proplist_t plgrp = WMCreatePLString ("Group");
1411 proplist_t plwidget = WMCreatePLString ("Widget");
1412 char *text = gtk_object_get_user_data (GTK_OBJECT (widget));
1413 char *prefix = (char *) ptr;
1414 char *path = g_strconcat (prefix, "/", text, NULL);
1415
1416 for (n = 0; n < WMGetPropListItemCount (all_keys); n++)
1417 {
1418 proplist_t key = WMGetFromPLArray (all_keys, n);
1419 proplist_t keydef = WMGetFromPLDictionary (wmconfig, key);
1420 proplist_t data = WMGetFromPLDictionary (keydef, plwidget);
1421
1422 if (data)
1423 {
1424 proplist_t group = WMGetFromPLDictionary (keydef, plgrp);
1425 GtkWidget *widget = * (GtkWidget **) WMGetPLDataBytes (data);
1426
1427 if (strcaseeq (path, WMGetFromPLString (group)))
1428 gtk_widget_show (widget);
1429 else
1430 {
1431 char *right = strrchr (path, '/');
1432
1433 /* g_strncasecmp: only in GTK+1.1.x */
1434 {
1435 char *str1 = g_strdup (path);
1436 char *str2 = g_strdup (WMGetFromPLString (group));
1437
1438 str1 [right - path] = 0;
1439 str2 [right - path] = 0;
1440
1441 if (g_strcasecmp (str1, str2) == 0)
1442 gtk_widget_hide (widget);
1443 Free (str1);
1444 Free (str2);
1445 }
1446 }
1447 }
1448 }
1449 WMReleasePropList (plwidget);
1450 WMReleasePropList (plgrp);
1451 }
1452
1453