Change to the linux kernel coding style
[wmaker-crm.git] / WPrefs.app / WPrefs.c
1 /* WPrefs.c- main window and other basic stuff
2  *
3  *  WPrefs - Window Maker Preferences Program
4  *
5  *  Copyright (c) 1998-2003 Alfredo K. Kojima
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20  *  USA.
21  */
22
23 #include "WPrefs.h"
24 #include <assert.h>
25
26 extern Panel *InitWindowHandling(WMScreen * scr, WMWidget * parent);
27
28 extern Panel *InitKeyboardSettings(WMScreen * scr, WMWidget * parent);
29
30 extern Panel *InitMouseSettings(WMScreen * scr, WMWidget * parent);
31
32 extern Panel *InitKeyboardShortcuts(WMScreen * scr, WMWidget * parent);
33
34 extern Panel *InitWorkspace(WMScreen * scr, WMWidget * parent);
35
36 extern Panel *InitFocus(WMScreen * scr, WMWidget * parent);
37
38 extern Panel *InitPreferences(WMScreen * scr, WMWidget * parent);
39
40 extern Panel *InitFont(WMScreen * scr, WMWidget * parent);
41 extern Panel *InitFontSimple(WMScreen * scr, WMWidget * parent);
42
43 extern Panel *InitConfigurations(WMScreen * scr, WMWidget * parent);
44
45 extern Panel *InitPaths(WMScreen * scr, WMWidget * parent);
46
47 extern Panel *InitMenu(WMScreen * scr, WMWidget * parent);
48
49 extern Panel *InitExpert(WMScreen * scr, WMWidget * parent);
50
51 extern Panel *InitMenuPreferences(WMScreen * scr, WMWidget * parent);
52
53 extern Panel *InitIcons(WMScreen * scr, WMWidget * parent);
54
55 extern Panel *InitThemes(WMScreen * scr, WMWidget * parent);
56
57 extern Panel *InitAppearance(WMScreen * scr, WMWidget * parent);
58
59 #define ICON_TITLE_FONT "sans serif:pixelsize=9"
60 #define ICON_TITLE_VFONT "sans serif:pixelsize=9:weight=100"
61
62 #define MAX_SECTIONS 16
63
64 typedef struct _WPrefs {
65         WMWindow *win;
66
67         WMScrollView *scrollV;
68         WMFrame *buttonF;
69         WMButton *sectionB[MAX_SECTIONS];
70
71         int sectionCount;
72
73         WMButton *saveBtn;
74         WMButton *closeBtn;
75         WMButton *undoBtn;
76         WMButton *undosBtn;
77
78         WMButton *balloonBtn;
79
80         WMFrame *banner;
81         WMLabel *nameL;
82         WMLabel *versionL;
83         WMLabel *statusL;
84
85         Panel *currentPanel;
86 } _WPrefs;
87
88 static _WPrefs WPrefs;
89
90 /* system wide defaults dictionary. Read-only */
91 static WMPropList *GlobalDB = NULL;
92 /* user defaults dictionary */
93 static WMPropList *WindowMakerDB = NULL;
94 static char *WindowMakerDBPath = NULL;
95
96 static Bool TIFFOK = False;
97
98 #define INITIALIZED_PANEL       (1<<0)
99
100 static void loadConfigurations(WMScreen * scr, WMWindow * mainw);
101
102 static void savePanelData(Panel * panel);
103
104 static void prepareForClose();
105
106 void quit(WMWidget * w, void *data)
107 {
108         prepareForClose();
109
110         exit(0);
111 }
112
113 static void save(WMWidget * w, void *data)
114 {
115         int i;
116         WMPropList *p1, *p2;
117         WMPropList *keyList;
118         WMPropList *key;
119         char *msg = "Reconfigure";
120         XEvent ev;
121
122         /*    puts("gathering data"); */
123         for (i = 0; i < WPrefs.sectionCount; i++) {
124                 PanelRec *rec = WMGetHangedData(WPrefs.sectionB[i]);
125                 if ((rec->callbacks.flags & INITIALIZED_PANEL))
126                         savePanelData((Panel *) rec);
127         }
128         /*    puts("compressing data"); */
129         /* compare the user dictionary with the global and remove redundant data */
130         keyList = WMGetPLDictionaryKeys(GlobalDB);
131         /*    puts(WMGetPropListDescription(WindowMakerDB, False)); */
132         for (i = 0; i < WMGetPropListItemCount(keyList); i++) {
133                 key = WMGetFromPLArray(keyList, i);
134
135                 /* We don't have this value anyway, so no problem.
136                  * Probably  a new option */
137                 p1 = WMGetFromPLDictionary(WindowMakerDB, key);
138                 if (!p1)
139                         continue;
140                 /* The global doesn't have it, so no problem either. */
141                 p2 = WMGetFromPLDictionary(GlobalDB, key);
142                 if (!p2)
143                         continue;
144                 /* If both values are the same, don't save. */
145                 if (WMIsPropListEqualTo(p1, p2))
146                         WMRemoveFromPLDictionary(WindowMakerDB, key);
147         }
148         /*    puts(WMGetPropListDescription(WindowMakerDB, False)); */
149         WMReleasePropList(keyList);
150         /*    puts("storing data"); */
151
152         WMWritePropListToFile(WindowMakerDB, WindowMakerDBPath, True);
153
154         memset(&ev, 0, sizeof(XEvent));
155
156         ev.xclient.type = ClientMessage;
157         ev.xclient.message_type = XInternAtom(WMScreenDisplay(WMWidgetScreen(w)), "_WINDOWMAKER_COMMAND", False);
158         ev.xclient.window = DefaultRootWindow(WMScreenDisplay(WMWidgetScreen(w)));
159         ev.xclient.format = 8;
160
161         for (i = 0; i <= strlen(msg); i++) {
162                 ev.xclient.data.b[i] = msg[i];
163         }
164         XSendEvent(WMScreenDisplay(WMWidgetScreen(w)),
165                    DefaultRootWindow(WMScreenDisplay(WMWidgetScreen(w))), False, SubstructureRedirectMask, &ev);
166         XFlush(WMScreenDisplay(WMWidgetScreen(w)));
167 }
168
169 static void undo(WMWidget * w, void *data)
170 {
171         PanelRec *rec = (PanelRec *) WPrefs.currentPanel;
172
173         if (!rec)
174                 return;
175
176         if (rec->callbacks.undoChanges && (rec->callbacks.flags & INITIALIZED_PANEL)) {
177                 (*rec->callbacks.undoChanges) (WPrefs.currentPanel);
178         }
179 }
180
181 static void undoAll(WMWidget * w, void *data)
182 {
183         int i;
184
185         for (i = 0; i < WPrefs.sectionCount; i++) {
186                 PanelRec *rec = WMGetHangedData(WPrefs.sectionB[i]);
187
188                 if (rec->callbacks.undoChanges && (rec->callbacks.flags & INITIALIZED_PANEL))
189                         (*rec->callbacks.undoChanges) ((Panel *) rec);
190         }
191 }
192
193 static void prepareForClose()
194 {
195         int i;
196
197         for (i = 0; i < WPrefs.sectionCount; i++) {
198                 PanelRec *rec = WMGetHangedData(WPrefs.sectionB[i]);
199
200                 if (rec->callbacks.prepareForClose && (rec->callbacks.flags & INITIALIZED_PANEL))
201                         (*rec->callbacks.prepareForClose) ((Panel *) rec);
202         }
203 }
204
205 void toggleBalloons(WMWidget * w, void *data)
206 {
207         WMUserDefaults *udb = WMGetStandardUserDefaults();
208         Bool flag;
209
210         flag = WMGetButtonSelected(WPrefs.balloonBtn);
211
212         WMSetBalloonEnabled(WMWidgetScreen(WPrefs.win), flag);
213
214         WMSetUDBoolForKey(udb, flag, "BalloonHelp");
215 }
216
217 static void createMainWindow(WMScreen * scr)
218 {
219         WMScroller *scroller;
220         WMFont *font;
221         char buffer[128];
222
223         WPrefs.win = WMCreateWindow(scr, "wprefs");
224         WMResizeWidget(WPrefs.win, 520, 390);
225         WMSetWindowTitle(WPrefs.win, _("Window Maker Preferences"));
226         WMSetWindowCloseAction(WPrefs.win, quit, NULL);
227         WMSetWindowMaxSize(WPrefs.win, 520, 390);
228         WMSetWindowMinSize(WPrefs.win, 520, 390);
229         WMSetWindowMiniwindowTitle(WPrefs.win, "Preferences");
230
231         WPrefs.scrollV = WMCreateScrollView(WPrefs.win);
232         WMResizeWidget(WPrefs.scrollV, 500, 87);
233         WMMoveWidget(WPrefs.scrollV, 10, 10);
234         WMSetScrollViewRelief(WPrefs.scrollV, WRSunken);
235         WMSetScrollViewHasHorizontalScroller(WPrefs.scrollV, True);
236         WMSetScrollViewHasVerticalScroller(WPrefs.scrollV, False);
237         scroller = WMGetScrollViewHorizontalScroller(WPrefs.scrollV);
238         WMSetScrollerArrowsPosition(scroller, WSANone);
239
240         WPrefs.buttonF = WMCreateFrame(WPrefs.win);
241         WMSetFrameRelief(WPrefs.buttonF, WRFlat);
242
243         WMSetScrollViewContentView(WPrefs.scrollV, WMWidgetView(WPrefs.buttonF));
244
245         WPrefs.undosBtn = WMCreateCommandButton(WPrefs.win);
246         WMResizeWidget(WPrefs.undosBtn, 90, 28);
247         WMMoveWidget(WPrefs.undosBtn, 135, 350);
248         WMSetButtonText(WPrefs.undosBtn, _("Revert Page"));
249         WMSetButtonAction(WPrefs.undosBtn, undo, NULL);
250
251         WPrefs.undoBtn = WMCreateCommandButton(WPrefs.win);
252         WMResizeWidget(WPrefs.undoBtn, 90, 28);
253         WMMoveWidget(WPrefs.undoBtn, 235, 350);
254         WMSetButtonText(WPrefs.undoBtn, _("Revert All"));
255         WMSetButtonAction(WPrefs.undoBtn, undoAll, NULL);
256
257         WPrefs.saveBtn = WMCreateCommandButton(WPrefs.win);
258         WMResizeWidget(WPrefs.saveBtn, 80, 28);
259         WMMoveWidget(WPrefs.saveBtn, 335, 350);
260         WMSetButtonText(WPrefs.saveBtn, _("Save"));
261         WMSetButtonAction(WPrefs.saveBtn, save, NULL);
262
263         WPrefs.closeBtn = WMCreateCommandButton(WPrefs.win);
264         WMResizeWidget(WPrefs.closeBtn, 80, 28);
265         WMMoveWidget(WPrefs.closeBtn, 425, 350);
266         WMSetButtonText(WPrefs.closeBtn, _("Close"));
267         WMSetButtonAction(WPrefs.closeBtn, quit, NULL);
268
269         WPrefs.balloonBtn = WMCreateSwitchButton(WPrefs.win);
270         WMResizeWidget(WPrefs.balloonBtn, 200, 28);
271         WMMoveWidget(WPrefs.balloonBtn, 15, 350);
272         WMSetButtonText(WPrefs.balloonBtn, _("Balloon Help"));
273         WMSetButtonAction(WPrefs.balloonBtn, toggleBalloons, NULL);
274         {
275                 WMUserDefaults *udb = WMGetStandardUserDefaults();
276                 Bool flag = WMGetUDBoolForKey(udb, "BalloonHelp");
277
278                 WMSetButtonSelected(WPrefs.balloonBtn, flag);
279                 WMSetBalloonEnabled(scr, flag);
280         }
281
282         /* banner */
283         WPrefs.banner = WMCreateFrame(WPrefs.win);
284         WMResizeWidget(WPrefs.banner, FRAME_WIDTH, FRAME_HEIGHT);
285         WMMoveWidget(WPrefs.banner, FRAME_LEFT, FRAME_TOP);
286         WMSetFrameRelief(WPrefs.banner, WRFlat);
287
288         font = WMCreateFont(scr, "Lucida Sans,URW Gothic L,Times New Roman,serif"
289                             ":bold:pixelsize=26:antialias=true");
290         WPrefs.nameL = WMCreateLabel(WPrefs.banner);
291         WMSetLabelTextAlignment(WPrefs.nameL, WACenter);
292         WMResizeWidget(WPrefs.nameL, FRAME_WIDTH - 20, 60);
293         WMMoveWidget(WPrefs.nameL, 10, 50);
294         WMSetLabelFont(WPrefs.nameL, font);
295         WMSetLabelText(WPrefs.nameL, _("Window Maker Preferences"));
296         WMReleaseFont(font);
297
298         WPrefs.versionL = WMCreateLabel(WPrefs.banner);
299         WMResizeWidget(WPrefs.versionL, FRAME_WIDTH - 20, 20);
300         WMMoveWidget(WPrefs.versionL, 10, 120);
301         WMSetLabelTextAlignment(WPrefs.versionL, WACenter);
302         sprintf(buffer, _("Version %s"), VERSION);
303         WMSetLabelText(WPrefs.versionL, buffer);
304
305         WPrefs.statusL = WMCreateLabel(WPrefs.banner);
306         WMResizeWidget(WPrefs.statusL, FRAME_WIDTH - 20, 60);
307         WMMoveWidget(WPrefs.statusL, 10, 150);
308         WMSetLabelTextAlignment(WPrefs.statusL, WACenter);
309         WMSetLabelText(WPrefs.statusL, _("Starting..."));
310
311         WMMapSubwidgets(WPrefs.win);
312
313         WMUnmapWidget(WPrefs.undosBtn);
314         WMUnmapWidget(WPrefs.undoBtn);
315         WMUnmapWidget(WPrefs.saveBtn);
316 }
317
318 static void showPanel(Panel * panel)
319 {
320         PanelRec *rec = (PanelRec *) panel;
321
322         if (!(rec->callbacks.flags & INITIALIZED_PANEL)) {
323                 (*rec->callbacks.createWidgets) (panel);
324                 rec->callbacks.flags |= INITIALIZED_PANEL;
325         }
326
327         WMSetWindowTitle(WPrefs.win, rec->sectionName);
328
329         if (rec->callbacks.showPanel)
330                 (*rec->callbacks.showPanel) (panel);
331
332         WMMapWidget(rec->box);
333 }
334
335 static void hidePanel(Panel * panel)
336 {
337         PanelRec *rec = (PanelRec *) panel;
338
339         WMUnmapWidget(rec->box);
340
341         if (rec->callbacks.hidePanel)
342                 (*rec->callbacks.hidePanel) (panel);
343 }
344
345 static void savePanelData(Panel * panel)
346 {
347         PanelRec *rec = (PanelRec *) panel;
348
349         if (rec->callbacks.updateDomain) {
350                 (*rec->callbacks.updateDomain) (panel);
351         }
352 }
353
354 static void changeSection(WMWidget * self, void *data)
355 {
356         if (WPrefs.currentPanel == data)
357                 return;
358
359         if (WPrefs.currentPanel == NULL) {
360                 WMDestroyWidget(WPrefs.nameL);
361                 WMDestroyWidget(WPrefs.versionL);
362                 WMDestroyWidget(WPrefs.statusL);
363
364                 WMSetFrameRelief(WPrefs.banner, WRGroove);
365
366                 /*      WMMapWidget(WPrefs.undosBtn);
367                    WMMapWidget(WPrefs.undoBtn);
368                  */
369                 WMMapWidget(WPrefs.saveBtn);
370         }
371
372         showPanel(data);
373
374         if (WPrefs.currentPanel)
375                 hidePanel(WPrefs.currentPanel);
376         WPrefs.currentPanel = data;
377 }
378
379 char *LocateImage(char *name)
380 {
381         char *path;
382         char *tmp = wmalloc(strlen(name) + 8);
383
384         if (TIFFOK) {
385                 sprintf(tmp, "%s.tiff", name);
386                 path = WMPathForResourceOfType(tmp, "tiff");
387         } else {
388                 sprintf(tmp, "%s.xpm", name);
389                 path = WMPathForResourceOfType(tmp, "xpm");
390         }
391         wfree(tmp);
392         if (!path) {
393                 wwarning(_("could not locate image file %s\n"), name);
394         }
395
396         return path;
397 }
398
399 static WMPixmap *makeTitledIcon(WMScreen * scr, WMPixmap * icon, char *title1, char *title2)
400 {
401         return WMRetainPixmap(icon);
402
403 #if 0
404         static GC gc = NULL;
405         static XFontStruct *hfont = NULL;
406         static XFontStruct *vfont = NULL;
407         WMPixmap *tmp;
408         Pixmap pix, mask;
409         Display *dpy = WMScreenDisplay(scr);
410         WMColor *black = WMBlackColor(scr);
411         GC fgc;
412         WMSize size = WMGetPixmapSize(icon);
413
414         tmp = WMCreatePixmap(scr, 60, 60, WMScreenDepth(scr), True);
415
416         pix = WMGetPixmapXID(tmp);
417         mask = WMGetPixmapMaskXID(tmp);
418
419         if (gc == NULL) {
420                 gc = XCreateGC(dpy, mask, 0, NULL);
421
422                 hfont = XLoadQueryFont(dpy, ICON_TITLE_FONT);
423                 vfont = XLoadQueryFont(dpy, ICON_TITLE_VFONT);
424         }
425
426         if (hfont == NULL) {
427                 return WMRetainPixmap(icon);
428         }
429
430         XSetForeground(dpy, gc, 0);
431         XFillRectangle(dpy, mask, gc, 0, 0, 60, 60);
432
433         fgc = WMColorGC(black);
434
435         XSetForeground(dpy, gc, 1);
436
437         XCopyArea(dpy, WMGetPixmapXID(icon), pix, fgc, 0, 0, size.width, size.height, 12, 12);
438
439         if (WMGetPixmapMaskXID(icon) != None)
440                 XCopyPlane(dpy, WMGetPixmapMaskXID(icon), mask, gc, 0, 0, size.width, size.height, 12, 12, 1);
441         else
442                 XFillRectangle(dpy, mask, gc, 12, 12, 48, 48);
443
444         if (title1) {
445                 XSetFont(dpy, fgc, vfont->fid);
446                 XSetFont(dpy, gc, vfont->fid);
447
448                 XDrawString(dpy, pix, fgc, 0, vfont->ascent, title1, strlen(title1));
449
450                 XDrawString(dpy, mask, gc, 0, vfont->ascent, title1, strlen(title1));
451         }
452
453         if (title2) {
454                 XSetFont(dpy, fgc, hfont->fid);
455                 XSetFont(dpy, gc, hfont->fid);
456
457                 XDrawString(dpy, pix, fgc, (title1 ? 12 : 0), hfont->ascent, title2, strlen(title2));
458
459                 XDrawString(dpy, mask, gc, (title1 ? 12 : 0), hfont->ascent, title2, strlen(title2));
460         }
461
462         return tmp;
463 #endif
464 }
465
466 void SetButtonAlphaImage(WMScreen * scr, WMButton * bPtr, char *file, char *title1, char *title2)
467 {
468         WMPixmap *icon;
469         WMPixmap *icon2;
470         RColor color;
471         char *iconPath;
472
473         iconPath = LocateImage(file);
474
475         color.red = 0xae;
476         color.green = 0xaa;
477         color.blue = 0xae;
478         color.alpha = 0;
479         if (iconPath) {
480                 icon = WMCreateBlendedPixmapFromFile(scr, iconPath, &color);
481                 if (!icon)
482                         wwarning(_("could not load icon file %s"), iconPath);
483         } else {
484                 icon = NULL;
485         }
486
487         if (icon) {
488                 icon2 = makeTitledIcon(scr, icon, title1, title2);
489                 if (icon)
490                         WMReleasePixmap(icon);
491         } else {
492                 icon2 = NULL;
493         }
494
495         WMSetButtonImage(bPtr, icon2);
496
497         if (icon2)
498                 WMReleasePixmap(icon2);
499
500         color.red = 0xff;
501         color.green = 0xff;
502         color.blue = 0xff;
503         color.alpha = 0;
504         if (iconPath) {
505                 icon = WMCreateBlendedPixmapFromFile(scr, iconPath, &color);
506                 if (!icon)
507                         wwarning(_("could not load icon file %s"), iconPath);
508         } else {
509                 icon = NULL;
510         }
511
512         WMSetButtonAltImage(bPtr, icon);
513
514         if (icon)
515                 WMReleasePixmap(icon);
516
517         if (iconPath)
518                 wfree(iconPath);
519 }
520
521 void AddSection(Panel * panel, char *iconFile)
522 {
523         WMButton *bPtr;
524
525         assert(WPrefs.sectionCount < MAX_SECTIONS);
526
527         bPtr = WMCreateCustomButton(WPrefs.buttonF, WBBStateLightMask | WBBStateChangeMask);
528         WMResizeWidget(bPtr, 64, 64);
529         WMMoveWidget(bPtr, WPrefs.sectionCount * 64, 0);
530         WMSetButtonImagePosition(bPtr, WIPImageOnly);
531         WMSetButtonAction(bPtr, changeSection, panel);
532         WMHangData(bPtr, panel);
533
534         WMSetBalloonTextForView(((PanelRec *) panel)->description, WMWidgetView(bPtr));
535
536         {
537                 char *t1, *t2;
538
539                 t1 = wstrdup(((PanelRec *) panel)->sectionName);
540                 t2 = strchr(t1, ' ');
541                 if (t2) {
542                         *t2 = 0;
543                         t2++;
544                 }
545                 SetButtonAlphaImage(WMWidgetScreen(bPtr), bPtr, iconFile, t1, t2);
546                 wfree(t1);
547         }
548         WMMapWidget(bPtr);
549
550         WPrefs.sectionB[WPrefs.sectionCount] = bPtr;
551
552         if (WPrefs.sectionCount > 0) {
553                 WMGroupButtons(WPrefs.sectionB[0], bPtr);
554         }
555
556         WPrefs.sectionCount++;
557
558         WMResizeWidget(WPrefs.buttonF, WPrefs.sectionCount * 64, 64);
559 }
560
561 void Initialize(WMScreen * scr)
562 {
563         char **list;
564         int i;
565         char *path;
566
567         list = RSupportedFileFormats();
568         for (i = 0; list[i] != NULL; i++) {
569                 if (strcmp(list[i], "TIFF") == 0) {
570                         TIFFOK = True;
571                         break;
572                 }
573         }
574
575         if (TIFFOK)
576                 path = WMPathForResourceOfType("WPrefs.tiff", NULL);
577         else
578                 path = WMPathForResourceOfType("WPrefs.xpm", NULL);
579         if (path) {
580                 RImage *tmp;
581
582                 tmp = RLoadImage(WMScreenRContext(scr), path, 0);
583                 if (!tmp) {
584                         wwarning(_("could not load image file %s:%s"), path, RMessageForError(RErrorCode));
585                 } else {
586                         WMSetApplicationIconImage(scr, tmp);
587                         RReleaseImage(tmp);
588                 }
589                 wfree(path);
590         }
591
592         memset(&WPrefs, 0, sizeof(_WPrefs));
593         createMainWindow(scr);
594
595         WMRealizeWidget(WPrefs.win);
596
597         WMSetWindowMiniwindowImage(WPrefs.win, WMGetApplicationIconImage(scr));
598
599         WMMapWidget(WPrefs.win);
600         XFlush(WMScreenDisplay(scr));
601         WMSetLabelText(WPrefs.statusL, _("Loading Window Maker configuration files..."));
602         XFlush(WMScreenDisplay(scr));
603         loadConfigurations(scr, WPrefs.win);
604
605         WMSetLabelText(WPrefs.statusL, _("Initializing configuration panels..."));
606
607         InitFocus(scr, WPrefs.banner);
608         InitWindowHandling(scr, WPrefs.banner);
609
610         InitMenuPreferences(scr, WPrefs.banner);
611         InitIcons(scr, WPrefs.banner);
612         InitPreferences(scr, WPrefs.banner);
613
614         InitPaths(scr, WPrefs.banner);
615         InitWorkspace(scr, WPrefs.banner);
616         InitConfigurations(scr, WPrefs.banner);
617
618         InitMenu(scr, WPrefs.banner);
619
620 #ifdef not_yet_fully_implemented
621         InitKeyboardSettings(scr, WPrefs.banner);
622 #endif
623         InitKeyboardShortcuts(scr, WPrefs.banner);
624         InitMouseSettings(scr, WPrefs.banner);
625
626         InitAppearance(scr, WPrefs.banner);
627
628         InitFontSimple(scr, WPrefs.banner);
629
630 #ifdef not_yet_fully_implemented
631         InitThemes(scr, WPrefs.banner);
632 #endif
633         InitExpert(scr, WPrefs.banner);
634
635         WMRealizeWidget(WPrefs.scrollV);
636
637         WMSetLabelText(WPrefs.statusL, "");
638 }
639
640 WMWindow *GetWindow(Panel * panel)
641 {
642         return WPrefs.win;
643 }
644
645 static void loadConfigurations(WMScreen * scr, WMWindow * mainw)
646 {
647         WMPropList *db, *gdb;
648         char *path;
649         FILE *file;
650         char buffer[1024];
651         char mbuf[1024];
652         int v1, v2, v3;
653
654         path = wdefaultspathfordomain("WindowMaker");
655         WindowMakerDBPath = path;
656
657         db = WMReadPropListFromFile(path);
658         if (db) {
659                 if (!WMIsPLDictionary(db)) {
660                         WMReleasePropList(db);
661                         db = NULL;
662                         sprintf(mbuf, _("Window Maker domain (%s) is corrupted!"), path);
663                         WMRunAlertPanel(scr, mainw, _("Error"), mbuf, _("OK"), NULL, NULL);
664                 }
665         } else {
666                 sprintf(mbuf, _("Could not load Window Maker domain (%s) from defaults database."), path);
667                 WMRunAlertPanel(scr, mainw, _("Error"), mbuf, _("OK"), NULL, NULL);
668         }
669
670         path = getenv("WMAKER_BIN_NAME");
671         if (!path)
672                 path = "wmaker";
673         {
674                 char *command;
675
676                 command = wstrconcat(path, " --version");
677                 file = popen(command, "r");
678                 wfree(command);
679         }
680         if (!file || !fgets(buffer, 1023, file)) {
681                 wsyserror(_("could not extract version information from Window Maker"));
682                 wfatal(_("Make sure wmaker is in your search path."));
683
684                 WMRunAlertPanel(scr, mainw, _("Error"),
685                                 _
686                                 ("Could not extract version from Window Maker. Make sure it is correctly installed and is in your PATH environment variable."),
687                                 _("OK"), NULL, NULL);
688                 exit(1);
689         }
690         if (file)
691                 pclose(file);
692
693         if (sscanf(buffer, "Window Maker %i.%i.%i", &v1, &v2, &v3) != 3
694             && sscanf(buffer, "WindowMaker %i.%i.%i", &v1, &v2, &v3) != 3) {
695                 WMRunAlertPanel(scr, mainw, _("Error"),
696                                 _("Could not extract version from Window Maker. "
697                                   "Make sure it is correctly installed and the path "
698                                   "where it installed is in the PATH environment "
699                                   "variable."), _("OK"), NULL, NULL);
700                 exit(1);
701         }
702         if (v1 == 0 && (v2 < 18 || v3 < 0)) {
703                 sprintf(mbuf, _("WPrefs only supports Window Maker 0.18.0 or newer.\n"
704                                 "The version installed is %i.%i.%i\n"), v1, v2, v3);
705                 WMRunAlertPanel(scr, mainw, _("Error"), mbuf, _("OK"), NULL, NULL);
706                 exit(1);
707
708         }
709         if (v1 > 1 || (v1 == 1 && (v2 > 0))) {
710                 sprintf(mbuf,
711                         _
712                         ("Window Maker %i.%i.%i, which is installed in your system, is not fully supported by this version of WPrefs."),
713                         v1, v2, v3);
714                 WMRunAlertPanel(scr, mainw, _("Warning"), mbuf, _("OK"), NULL, NULL);
715         }
716
717         {
718                 char *command;
719
720                 command = wstrconcat(path, " --global_defaults_path");
721                 file = popen(command, "r");
722                 wfree(command);
723         }
724         if (!file || !fgets(buffer, 1023, file)) {
725                 wsyserror(_("could not run \"%s --global_defaults_path\"."), path);
726                 exit(1);
727         } else {
728                 char *ptr;
729                 ptr = strchr(buffer, '\n');
730                 if (ptr)
731                         *ptr = 0;
732                 strcat(buffer, "/WindowMaker");
733         }
734
735         if (file)
736                 pclose(file);
737
738         gdb = WMReadPropListFromFile(buffer);
739
740         if (gdb) {
741                 if (!WMIsPLDictionary(gdb)) {
742                         WMReleasePropList(gdb);
743                         gdb = NULL;
744                         sprintf(mbuf, _("Window Maker domain (%s) is corrupted!"), buffer);
745                         WMRunAlertPanel(scr, mainw, _("Error"), mbuf, _("OK"), NULL, NULL);
746                 }
747         } else {
748                 sprintf(mbuf, _("Could not load global Window Maker domain (%s)."), buffer);
749                 WMRunAlertPanel(scr, mainw, _("Error"), mbuf, _("OK"), NULL, NULL);
750         }
751
752         if (!db) {
753                 db = WMCreatePLDictionary(NULL, NULL);
754         }
755         if (!gdb) {
756                 gdb = WMCreatePLDictionary(NULL, NULL);
757         }
758
759         GlobalDB = gdb;
760
761         WindowMakerDB = db;
762 }
763
764 WMPropList *GetObjectForKey(char *defaultName)
765 {
766         WMPropList *object = NULL;
767         WMPropList *key = WMCreatePLString(defaultName);
768
769         object = WMGetFromPLDictionary(WindowMakerDB, key);
770         if (!object)
771                 object = WMGetFromPLDictionary(GlobalDB, key);
772
773         WMReleasePropList(key);
774
775         return object;
776 }
777
778 void SetObjectForKey(WMPropList * object, char *defaultName)
779 {
780         WMPropList *key = WMCreatePLString(defaultName);
781
782         WMPutInPLDictionary(WindowMakerDB, key, object);
783         WMReleasePropList(key);
784 }
785
786 void RemoveObjectForKey(char *defaultName)
787 {
788         WMPropList *key = WMCreatePLString(defaultName);
789
790         WMRemoveFromPLDictionary(WindowMakerDB, key);
791
792         WMReleasePropList(key);
793 }
794
795 char *GetStringForKey(char *defaultName)
796 {
797         WMPropList *val;
798
799         val = GetObjectForKey(defaultName);
800
801         if (!val)
802                 return NULL;
803
804         if (!WMIsPLString(val))
805                 return NULL;
806
807         return WMGetFromPLString(val);
808 }
809
810 WMPropList *GetArrayForKey(char *defaultName)
811 {
812         WMPropList *val;
813
814         val = GetObjectForKey(defaultName);
815
816         if (!val)
817                 return NULL;
818
819         if (!WMIsPLArray(val))
820                 return NULL;
821
822         return val;
823 }
824
825 WMPropList *GetDictionaryForKey(char *defaultName)
826 {
827         WMPropList *val;
828
829         val = GetObjectForKey(defaultName);
830
831         if (!val)
832                 return NULL;
833
834         if (!WMIsPLDictionary(val))
835                 return NULL;
836
837         return val;
838 }
839
840 int GetIntegerForKey(char *defaultName)
841 {
842         WMPropList *val;
843         char *str;
844         int value;
845
846         val = GetObjectForKey(defaultName);
847
848         if (!val)
849                 return 0;
850
851         if (!WMIsPLString(val))
852                 return 0;
853
854         str = WMGetFromPLString(val);
855         if (!str)
856                 return 0;
857
858         if (sscanf(str, "%i", &value) != 1)
859                 return 0;
860
861         return value;
862 }
863
864 Bool GetBoolForKey(char *defaultName)
865 {
866         int value;
867         char *str;
868
869         str = GetStringForKey(defaultName);
870
871         if (!str)
872                 return False;
873
874         if (sscanf(str, "%i", &value) == 1 && value != 0)
875                 return True;
876
877         if (strcasecmp(str, "YES") == 0)
878                 return True;
879
880         if (strcasecmp(str, "Y") == 0)
881                 return True;
882
883         return False;
884 }
885
886 void SetIntegerForKey(int value, char *defaultName)
887 {
888         WMPropList *object;
889         char buffer[128];
890
891         sprintf(buffer, "%i", value);
892         object = WMCreatePLString(buffer);
893
894         SetObjectForKey(object, defaultName);
895         WMReleasePropList(object);
896 }
897
898 void SetStringForKey(char *value, char *defaultName)
899 {
900         WMPropList *object;
901
902         object = WMCreatePLString(value);
903
904         SetObjectForKey(object, defaultName);
905         WMReleasePropList(object);
906 }
907
908 void SetBoolForKey(Bool value, char *defaultName)
909 {
910         static WMPropList *yes = NULL, *no = NULL;
911
912         if (!yes) {
913                 yes = WMCreatePLString("YES");
914                 no = WMCreatePLString("NO");
915         }
916
917         SetObjectForKey(value ? yes : no, defaultName);
918 }
919
920 void SetSpeedForKey(int speed, char *defaultName)
921 {
922         char *str;
923
924         switch (speed) {
925         case 0:
926                 str = "ultraslow";
927                 break;
928         case 1:
929                 str = "slow";
930                 break;
931         case 2:
932                 str = "medium";
933                 break;
934         case 3:
935                 str = "fast";
936                 break;
937         case 4:
938                 str = "ultrafast";
939                 break;
940         default:
941                 str = NULL;
942         }
943
944         if (str)
945                 SetStringForKey(str, defaultName);
946 }
947
948 int GetSpeedForKey(char *defaultName)
949 {
950         char *str;
951         int i;
952
953         str = GetStringForKey(defaultName);
954         if (!str)
955                 return 2;
956
957         if (strcasecmp(str, "ultraslow") == 0)
958                 i = 0;
959         else if (strcasecmp(str, "slow") == 0)
960                 i = 1;
961         else if (strcasecmp(str, "medium") == 0)
962                 i = 2;
963         else if (strcasecmp(str, "fast") == 0)
964                 i = 3;
965         else if (strcasecmp(str, "ultrafast") == 0)
966                 i = 4;
967         else {
968                 wwarning(_("bad speed value for option %s\n. Using default Medium"), defaultName);
969                 i = 2;
970         }
971         return i;
972 }