move dock/icons size adjustments, to fix window placement
[wmaker-crm.git] / WPrefs.app / WPrefs.c
blob7afa42e47e1af7309bf20c5f2e2c3f9699fbcd8f
1 /* WPrefs.c- main window and other basic stuff
3 * WPrefs - Window Maker Preferences Program
5 * Copyright (c) 1998-2003 Alfredo K. Kojima
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.
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.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "config.h"
24 #include "WPrefs.h"
25 #include <assert.h>
27 #ifdef HAVE_STDNORETURN
28 #include <stdnoreturn.h>
29 #endif
32 #define ICON_TITLE_FONT "sans serif:pixelsize=9"
33 #define ICON_TITLE_VFONT "sans serif:pixelsize=9:weight=100"
35 #define MAX_SECTIONS 16
37 typedef struct _WPrefs {
38 WMWindow *win;
40 WMScrollView *scrollV;
41 WMFrame *buttonF;
42 WMButton *sectionB[MAX_SECTIONS];
44 int sectionCount;
46 WMButton *saveBtn;
47 WMButton *closeBtn;
48 WMButton *undoBtn;
49 WMButton *undosBtn;
51 WMButton *balloonBtn;
53 WMFrame *banner;
54 WMLabel *nameL;
55 WMLabel *versionL;
56 WMLabel *statusL;
58 Panel *currentPanel;
59 } _WPrefs;
61 static _WPrefs WPrefs;
63 /* system wide defaults dictionary. Read-only */
64 static WMPropList *GlobalDB = NULL;
65 /* user defaults dictionary */
66 static WMPropList *WindowMakerDB = NULL;
67 static char *WindowMakerDBPath = NULL;
69 static Bool TIFFOK = False;
71 #define INITIALIZED_PANEL (1<<0)
73 static void loadConfigurations(WMScreen * scr, WMWindow * mainw);
75 static void savePanelData(Panel * panel);
77 static void prepareForClose(void);
79 static noreturn void quit(WMWidget *w, void *data)
81 /* Parameter not used, but tell the compiler that it is ok */
82 (void) w;
83 (void) data;
85 prepareForClose();
87 exit(0);
90 static void save(WMWidget * w, void *data)
92 int i;
93 WMPropList *p1, *p2;
94 WMPropList *keyList;
95 WMPropList *key;
96 XEvent ev;
98 /* Parameter not used, but tell the compiler that it is ok */
99 (void) data;
101 /* puts("gathering data"); */
102 for (i = 0; i < WPrefs.sectionCount; i++) {
103 PanelRec *rec = WMGetHangedData(WPrefs.sectionB[i]);
104 if ((rec->callbacks.flags & INITIALIZED_PANEL))
105 savePanelData((Panel *) rec);
107 /* puts("compressing data"); */
108 /* compare the user dictionary with the global and remove redundant data */
109 keyList = WMGetPLDictionaryKeys(GlobalDB);
110 /* puts(WMGetPropListDescription(WindowMakerDB, False)); */
111 for (i = 0; i < WMGetPropListItemCount(keyList); i++) {
112 key = WMGetFromPLArray(keyList, i);
114 /* We don't have this value anyway, so no problem.
115 * Probably a new option */
116 p1 = WMGetFromPLDictionary(WindowMakerDB, key);
117 if (!p1)
118 continue;
119 /* The global doesn't have it, so no problem either. */
120 p2 = WMGetFromPLDictionary(GlobalDB, key);
121 if (!p2)
122 continue;
123 /* If both values are the same, don't save. */
124 if (WMIsPropListEqualTo(p1, p2))
125 WMRemoveFromPLDictionary(WindowMakerDB, key);
127 /* puts(WMGetPropListDescription(WindowMakerDB, False)); */
128 WMReleasePropList(keyList);
129 /* puts("storing data"); */
131 WMWritePropListToFile(WindowMakerDB, WindowMakerDBPath);
133 memset(&ev, 0, sizeof(XEvent));
135 ev.xclient.type = ClientMessage;
136 ev.xclient.message_type = XInternAtom(WMScreenDisplay(WMWidgetScreen(w)), "_WINDOWMAKER_COMMAND", False);
137 ev.xclient.window = DefaultRootWindow(WMScreenDisplay(WMWidgetScreen(w)));
138 ev.xclient.format = 8;
139 strncpy(ev.xclient.data.b, "Reconfigure", sizeof(ev.xclient.data.b));
141 XSendEvent(WMScreenDisplay(WMWidgetScreen(w)),
142 DefaultRootWindow(WMScreenDisplay(WMWidgetScreen(w))), False, SubstructureRedirectMask, &ev);
143 XFlush(WMScreenDisplay(WMWidgetScreen(w)));
146 static void undo(WMWidget * w, void *data)
148 PanelRec *rec = (PanelRec *) WPrefs.currentPanel;
150 /* Parameter not used, but tell the compiler that it is ok */
151 (void) w;
152 (void) data;
154 if (!rec)
155 return;
157 if (rec->callbacks.undoChanges && (rec->callbacks.flags & INITIALIZED_PANEL)) {
158 (*rec->callbacks.undoChanges) (WPrefs.currentPanel);
162 static void undoAll(WMWidget * w, void *data)
164 int i;
166 /* Parameter not used, but tell the compiler that it is ok */
167 (void) w;
168 (void) data;
170 for (i = 0; i < WPrefs.sectionCount; i++) {
171 PanelRec *rec = WMGetHangedData(WPrefs.sectionB[i]);
173 if (rec->callbacks.undoChanges && (rec->callbacks.flags & INITIALIZED_PANEL))
174 (*rec->callbacks.undoChanges) ((Panel *) rec);
178 static void prepareForClose(void)
180 int i;
182 for (i = 0; i < WPrefs.sectionCount; i++) {
183 PanelRec *rec = WMGetHangedData(WPrefs.sectionB[i]);
185 if (rec->callbacks.prepareForClose && (rec->callbacks.flags & INITIALIZED_PANEL))
186 (*rec->callbacks.prepareForClose) ((Panel *) rec);
190 static void toggleBalloons(WMWidget *w, void *data)
192 WMUserDefaults *udb = WMGetStandardUserDefaults();
193 Bool flag;
195 /* Parameter not used, but tell the compiler that it is ok */
196 (void) w;
197 (void) data;
199 flag = WMGetButtonSelected(WPrefs.balloonBtn);
201 WMSetBalloonEnabled(WMWidgetScreen(WPrefs.win), flag);
203 WMSetUDBoolForKey(udb, flag, "BalloonHelp");
206 static void createMainWindow(WMScreen * scr)
208 WMScroller *scroller;
209 WMFont *font;
210 char buffer[128];
212 WPrefs.win = WMCreateWindow(scr, "wprefs");
213 WMResizeWidget(WPrefs.win, 520, 390);
214 WMSetWindowTitle(WPrefs.win, _("Window Maker Preferences"));
215 WMSetWindowCloseAction(WPrefs.win, quit, NULL);
216 WMSetWindowMaxSize(WPrefs.win, 520, 390);
217 WMSetWindowMinSize(WPrefs.win, 520, 390);
218 WMSetWindowMiniwindowTitle(WPrefs.win, "Preferences");
220 WPrefs.scrollV = WMCreateScrollView(WPrefs.win);
221 WMResizeWidget(WPrefs.scrollV, 500, 87);
222 WMMoveWidget(WPrefs.scrollV, 10, 10);
223 WMSetScrollViewRelief(WPrefs.scrollV, WRSunken);
224 WMSetScrollViewHasHorizontalScroller(WPrefs.scrollV, True);
225 WMSetScrollViewHasVerticalScroller(WPrefs.scrollV, False);
226 scroller = WMGetScrollViewHorizontalScroller(WPrefs.scrollV);
227 WMSetScrollerArrowsPosition(scroller, WSANone);
229 WPrefs.buttonF = WMCreateFrame(WPrefs.win);
230 WMSetFrameRelief(WPrefs.buttonF, WRFlat);
232 WMSetScrollViewContentView(WPrefs.scrollV, WMWidgetView(WPrefs.buttonF));
234 WPrefs.undosBtn = WMCreateCommandButton(WPrefs.win);
235 WMResizeWidget(WPrefs.undosBtn, 90, 28);
236 WMMoveWidget(WPrefs.undosBtn, 135, 350);
237 WMSetButtonText(WPrefs.undosBtn, _("Revert Page"));
238 WMSetButtonAction(WPrefs.undosBtn, undo, NULL);
240 WPrefs.undoBtn = WMCreateCommandButton(WPrefs.win);
241 WMResizeWidget(WPrefs.undoBtn, 90, 28);
242 WMMoveWidget(WPrefs.undoBtn, 235, 350);
243 WMSetButtonText(WPrefs.undoBtn, _("Revert All"));
244 WMSetButtonAction(WPrefs.undoBtn, undoAll, NULL);
246 WPrefs.saveBtn = WMCreateCommandButton(WPrefs.win);
247 WMResizeWidget(WPrefs.saveBtn, 80, 28);
248 WMMoveWidget(WPrefs.saveBtn, 335, 350);
249 WMSetButtonText(WPrefs.saveBtn, _("Save"));
250 WMSetButtonAction(WPrefs.saveBtn, save, NULL);
252 WPrefs.closeBtn = WMCreateCommandButton(WPrefs.win);
253 WMResizeWidget(WPrefs.closeBtn, 80, 28);
254 WMMoveWidget(WPrefs.closeBtn, 425, 350);
255 WMSetButtonText(WPrefs.closeBtn, _("Close"));
256 WMSetButtonAction(WPrefs.closeBtn, quit, NULL);
258 WPrefs.balloonBtn = WMCreateSwitchButton(WPrefs.win);
259 WMResizeWidget(WPrefs.balloonBtn, 200, 28);
260 WMMoveWidget(WPrefs.balloonBtn, 15, 350);
261 WMSetButtonText(WPrefs.balloonBtn, _("Balloon Help"));
262 WMSetButtonAction(WPrefs.balloonBtn, toggleBalloons, NULL);
264 WMUserDefaults *udb = WMGetStandardUserDefaults();
265 Bool flag = WMGetUDBoolForKey(udb, "BalloonHelp");
267 WMSetButtonSelected(WPrefs.balloonBtn, flag);
268 WMSetBalloonEnabled(scr, flag);
271 /* banner */
272 WPrefs.banner = WMCreateFrame(WPrefs.win);
273 WMResizeWidget(WPrefs.banner, FRAME_WIDTH, FRAME_HEIGHT);
274 WMMoveWidget(WPrefs.banner, FRAME_LEFT, FRAME_TOP);
275 WMSetFrameRelief(WPrefs.banner, WRFlat);
277 font = WMCreateFont(scr, "Lucida Sans,URW Gothic L,Times New Roman,serif"
278 ":bold:pixelsize=26:antialias=true");
279 WPrefs.nameL = WMCreateLabel(WPrefs.banner);
280 WMSetLabelTextAlignment(WPrefs.nameL, WACenter);
281 WMResizeWidget(WPrefs.nameL, FRAME_WIDTH - 20, 60);
282 WMMoveWidget(WPrefs.nameL, 10, 50);
283 WMSetLabelFont(WPrefs.nameL, font);
284 WMSetLabelText(WPrefs.nameL, _("Window Maker Preferences"));
285 WMReleaseFont(font);
287 WPrefs.versionL = WMCreateLabel(WPrefs.banner);
288 WMResizeWidget(WPrefs.versionL, FRAME_WIDTH - 20, 20);
289 WMMoveWidget(WPrefs.versionL, 10, 120);
290 WMSetLabelTextAlignment(WPrefs.versionL, WACenter);
291 sprintf(buffer, _("Version %s"), VERSION);
292 WMSetLabelText(WPrefs.versionL, buffer);
294 WPrefs.statusL = WMCreateLabel(WPrefs.banner);
295 WMResizeWidget(WPrefs.statusL, FRAME_WIDTH - 20, 60);
296 WMMoveWidget(WPrefs.statusL, 10, 150);
297 WMSetLabelTextAlignment(WPrefs.statusL, WACenter);
298 WMSetLabelText(WPrefs.statusL, _("Starting..."));
300 WMMapSubwidgets(WPrefs.win);
302 WMUnmapWidget(WPrefs.undosBtn);
303 WMUnmapWidget(WPrefs.undoBtn);
304 WMUnmapWidget(WPrefs.saveBtn);
307 static void showPanel(Panel * panel)
309 PanelRec *rec = (PanelRec *) panel;
311 if (!(rec->callbacks.flags & INITIALIZED_PANEL)) {
312 (*rec->callbacks.createWidgets) (panel);
313 rec->callbacks.flags |= INITIALIZED_PANEL;
316 WMSetWindowTitle(WPrefs.win, rec->sectionName);
318 if (rec->callbacks.showPanel)
319 (*rec->callbacks.showPanel) (panel);
321 WMMapWidget(rec->box);
324 static void hidePanel(Panel * panel)
326 PanelRec *rec = (PanelRec *) panel;
328 WMUnmapWidget(rec->box);
330 if (rec->callbacks.hidePanel)
331 (*rec->callbacks.hidePanel) (panel);
334 static void savePanelData(Panel * panel)
336 PanelRec *rec = (PanelRec *) panel;
338 if (rec->callbacks.updateDomain) {
339 (*rec->callbacks.updateDomain) (panel);
343 static void changeSection(WMWidget * self, void *data)
345 /* Parameter not used, but tell the compiler that it is ok */
346 (void) self;
348 if (WPrefs.currentPanel == data)
349 return;
351 if (WPrefs.currentPanel == NULL) {
352 WMDestroyWidget(WPrefs.nameL);
353 WMDestroyWidget(WPrefs.versionL);
354 WMDestroyWidget(WPrefs.statusL);
356 WMSetFrameRelief(WPrefs.banner, WRGroove);
358 /* WMMapWidget(WPrefs.undosBtn);
359 WMMapWidget(WPrefs.undoBtn);
361 WMMapWidget(WPrefs.saveBtn);
364 showPanel(data);
366 if (WPrefs.currentPanel)
367 hidePanel(WPrefs.currentPanel);
368 WPrefs.currentPanel = data;
371 char *LocateImage(const char *name)
373 char *path;
374 char *tmp = wmalloc(strlen(name) + 8);
376 if (TIFFOK) {
377 sprintf(tmp, "%s.tiff", name);
378 path = WMPathForResourceOfType(tmp, "tiff");
379 } else {
380 sprintf(tmp, "%s.xpm", name);
381 path = WMPathForResourceOfType(tmp, "xpm");
383 wfree(tmp);
384 if (!path) {
385 wwarning(_("could not locate image file %s"), name);
388 return path;
391 void CreateImages(WMScreen *scr, RContext *rc, RImage *xis, const char *file,
392 WMPixmap **icon_normal, WMPixmap **icon_greyed)
394 RImage *icon;
395 char *path;
396 RColor gray = { 0xae, 0xaa, 0xae, 0 };
398 path = LocateImage(file);
399 if (!path)
401 *icon_normal = NULL;
402 if (icon_greyed)
403 *icon_greyed = NULL;
404 return;
407 *icon_normal = WMCreatePixmapFromFile(scr, path);
408 if (!*icon_normal)
410 wwarning(_("could not load icon %s"), path);
411 if (icon_greyed)
412 *icon_greyed = NULL;
413 wfree(path);
414 return;
417 if (!icon_greyed) // Greyed-out version not requested, we are done
419 wfree(path);
420 return;
423 icon = RLoadImage(rc, path, 0);
424 if (!icon)
426 wwarning(_("could not load icon %s"), path);
427 *icon_greyed = NULL;
428 wfree(path);
429 return;
431 RCombineImageWithColor(icon, &gray);
432 if (xis)
434 RCombineImagesWithOpaqueness(icon, xis, 180);
436 *icon_greyed = WMCreatePixmapFromRImage(scr, icon, 127);
437 if (!*icon_greyed)
439 wwarning(_("could not process icon %s: %s"), path, RMessageForError(RErrorCode));
441 RReleaseImage(icon);
442 wfree(path);
446 static WMPixmap *makeTitledIcon(WMScreen * scr, WMPixmap * icon, const char *title1, const char *title2)
448 return WMRetainPixmap(icon);
450 #if 0
451 static GC gc = NULL;
452 static XFontStruct *hfont = NULL;
453 static XFontStruct *vfont = NULL;
454 WMPixmap *tmp;
455 Pixmap pix, mask;
456 Display *dpy = WMScreenDisplay(scr);
457 WMColor *black = WMBlackColor(scr);
458 GC fgc;
459 WMSize size = WMGetPixmapSize(icon);
461 tmp = WMCreatePixmap(scr, 60, 60, WMScreenDepth(scr), True);
463 pix = WMGetPixmapXID(tmp);
464 mask = WMGetPixmapMaskXID(tmp);
466 if (gc == NULL) {
467 gc = XCreateGC(dpy, mask, 0, NULL);
469 hfont = XLoadQueryFont(dpy, ICON_TITLE_FONT);
470 vfont = XLoadQueryFont(dpy, ICON_TITLE_VFONT);
473 if (hfont == NULL) {
474 return WMRetainPixmap(icon);
477 XSetForeground(dpy, gc, 0);
478 XFillRectangle(dpy, mask, gc, 0, 0, 60, 60);
480 fgc = WMColorGC(black);
482 XSetForeground(dpy, gc, 1);
484 XCopyArea(dpy, WMGetPixmapXID(icon), pix, fgc, 0, 0, size.width, size.height, 12, 12);
486 if (WMGetPixmapMaskXID(icon) != None)
487 XCopyPlane(dpy, WMGetPixmapMaskXID(icon), mask, gc, 0, 0, size.width, size.height, 12, 12, 1);
488 else
489 XFillRectangle(dpy, mask, gc, 12, 12, 48, 48);
491 if (title1) {
492 XSetFont(dpy, fgc, vfont->fid);
493 XSetFont(dpy, gc, vfont->fid);
495 XDrawString(dpy, pix, fgc, 0, vfont->ascent, title1, strlen(title1));
497 XDrawString(dpy, mask, gc, 0, vfont->ascent, title1, strlen(title1));
500 if (title2) {
501 XSetFont(dpy, fgc, hfont->fid);
502 XSetFont(dpy, gc, hfont->fid);
504 XDrawString(dpy, pix, fgc, (title1 ? 12 : 0), hfont->ascent, title2, strlen(title2));
506 XDrawString(dpy, mask, gc, (title1 ? 12 : 0), hfont->ascent, title2, strlen(title2));
509 return tmp;
510 #endif
513 void SetButtonAlphaImage(WMScreen * scr, WMButton * bPtr, const char *file, const char *title1, const char *title2)
515 WMPixmap *icon;
516 WMPixmap *icon2;
517 RColor color;
518 char *iconPath;
520 iconPath = LocateImage(file);
522 color.red = 0xae;
523 color.green = 0xaa;
524 color.blue = 0xae;
525 color.alpha = 0;
526 if (iconPath) {
527 icon = WMCreateBlendedPixmapFromFile(scr, iconPath, &color);
528 if (!icon)
529 wwarning(_("could not load icon file %s"), iconPath);
530 } else {
531 icon = NULL;
534 if (icon) {
535 icon2 = makeTitledIcon(scr, icon, title1, title2);
536 if (icon)
537 WMReleasePixmap(icon);
538 } else {
539 icon2 = NULL;
542 WMSetButtonImage(bPtr, icon2);
544 if (icon2)
545 WMReleasePixmap(icon2);
547 color.red = 0xff;
548 color.green = 0xff;
549 color.blue = 0xff;
550 color.alpha = 0;
551 if (iconPath) {
552 icon = WMCreateBlendedPixmapFromFile(scr, iconPath, &color);
553 if (!icon)
554 wwarning(_("could not load icon file %s"), iconPath);
555 } else {
556 icon = NULL;
559 WMSetButtonAltImage(bPtr, icon);
561 if (icon)
562 WMReleasePixmap(icon);
564 if (iconPath)
565 wfree(iconPath);
568 void AddSection(Panel * panel, const char *iconFile)
570 WMButton *bPtr;
572 assert(WPrefs.sectionCount < MAX_SECTIONS);
574 bPtr = WMCreateCustomButton(WPrefs.buttonF, WBBStateLightMask | WBBStateChangeMask);
575 WMResizeWidget(bPtr, 64, 64);
576 WMMoveWidget(bPtr, WPrefs.sectionCount * 64, 0);
577 WMSetButtonImagePosition(bPtr, WIPImageOnly);
578 WMSetButtonAction(bPtr, changeSection, panel);
579 WMHangData(bPtr, panel);
581 WMSetBalloonTextForView(((PanelRec *) panel)->description, WMWidgetView(bPtr));
584 char *t1, *t2;
586 t1 = wstrdup(((PanelRec *) panel)->sectionName);
587 t2 = strchr(t1, ' ');
588 if (t2) {
589 *t2 = 0;
590 t2++;
592 SetButtonAlphaImage(WMWidgetScreen(bPtr), bPtr, iconFile, t1, t2);
593 wfree(t1);
595 WMMapWidget(bPtr);
597 WPrefs.sectionB[WPrefs.sectionCount] = bPtr;
599 if (WPrefs.sectionCount > 0) {
600 WMGroupButtons(WPrefs.sectionB[0], bPtr);
603 WPrefs.sectionCount++;
605 WMResizeWidget(WPrefs.buttonF, WPrefs.sectionCount * 64, 64);
608 void Initialize(WMScreen * scr)
610 char **list;
611 int i;
612 char *path;
614 list = RSupportedFileFormats();
615 for (i = 0; list[i] != NULL; i++) {
616 if (strcmp(list[i], "TIFF") == 0) {
617 TIFFOK = True;
618 break;
622 if (TIFFOK)
623 path = WMPathForResourceOfType("WPrefs.tiff", NULL);
624 else
625 path = WMPathForResourceOfType("WPrefs.xpm", NULL);
626 if (path) {
627 RImage *tmp;
629 tmp = RLoadImage(WMScreenRContext(scr), path, 0);
630 if (!tmp) {
631 wwarning(_("could not load image file %s:%s"), path, RMessageForError(RErrorCode));
632 } else {
633 WMSetApplicationIconImage(scr, tmp);
634 RReleaseImage(tmp);
636 wfree(path);
639 memset(&WPrefs, 0, sizeof(_WPrefs));
640 createMainWindow(scr);
642 WMRealizeWidget(WPrefs.win);
644 WMSetWindowMiniwindowImage(WPrefs.win, WMGetApplicationIconImage(scr));
646 WMMapWidget(WPrefs.win);
647 XFlush(WMScreenDisplay(scr));
648 WMSetLabelText(WPrefs.statusL, _("Loading Window Maker configuration files..."));
649 XFlush(WMScreenDisplay(scr));
650 loadConfigurations(scr, WPrefs.win);
652 WMSetLabelText(WPrefs.statusL, _("Initializing configuration panels..."));
654 InitFocus(WPrefs.banner);
655 InitWindowHandling(WPrefs.banner);
657 InitMenuPreferences(WPrefs.banner);
658 InitIcons(WPrefs.banner);
659 InitPreferences(WPrefs.banner);
661 InitPaths(WPrefs.banner);
662 InitDocks(WPrefs.banner);
663 InitWorkspace(WPrefs.banner);
664 InitConfigurations(WPrefs.banner);
666 InitMenu(WPrefs.banner);
668 #ifdef not_yet_fully_implemented
669 InitKeyboardSettings(WPrefs.banner);
670 #endif
671 InitKeyboardShortcuts(WPrefs.banner);
672 InitMouseSettings(WPrefs.banner);
674 InitAppearance(WPrefs.banner);
676 InitFontSimple(WPrefs.banner);
678 #ifdef not_yet_fully_implemented
679 InitThemes(WPrefs.banner);
680 #endif
681 InitExpert(WPrefs.banner);
683 WMRealizeWidget(WPrefs.scrollV);
685 WMSetLabelText(WPrefs.statusL, "");
688 WMWindow *GetWindow(Panel * panel)
690 return WPrefs.win;
693 static void loadConfigurations(WMScreen * scr, WMWindow * mainw)
695 WMPropList *db, *gdb;
696 char *path;
697 FILE *file;
698 char buffer[1024];
699 char mbuf[1024];
700 int v1, v2, v3;
702 path = wdefaultspathfordomain("WindowMaker");
703 WindowMakerDBPath = path;
705 db = WMReadPropListFromFile(path);
706 if (db) {
707 if (!WMIsPLDictionary(db)) {
708 WMReleasePropList(db);
709 db = NULL;
710 sprintf(mbuf, _("Window Maker domain (%s) is corrupted!"), path);
711 WMRunAlertPanel(scr, mainw, _("Error"), mbuf, _("OK"), NULL, NULL);
713 } else {
714 sprintf(mbuf, _("Could not load Window Maker domain (%s) from defaults database."), path);
715 WMRunAlertPanel(scr, mainw, _("Error"), mbuf, _("OK"), NULL, NULL);
718 path = getenv("WMAKER_BIN_NAME");
719 if (!path)
720 path = "wmaker";
722 char *command;
724 command = wstrconcat(path, " --version");
725 file = popen(command, "r");
726 wfree(command);
728 if (!file || !fgets(buffer, 1023, file)) {
729 werror(_("could not extract version information from Window Maker"));
730 wfatal(_("Make sure wmaker is in your search path."));
732 WMRunAlertPanel(scr, mainw, _("Error"),
734 ("Could not extract version from Window Maker. Make sure it is correctly installed and is in your PATH environment variable."),
735 _("OK"), NULL, NULL);
736 exit(1);
738 if (file)
739 pclose(file);
741 if (sscanf(buffer, "Window Maker %i.%i.%i", &v1, &v2, &v3) != 3
742 && sscanf(buffer, "WindowMaker %i.%i.%i", &v1, &v2, &v3) != 3) {
743 WMRunAlertPanel(scr, mainw, _("Error"),
744 _("Could not extract version from Window Maker. "
745 "Make sure it is correctly installed and the path "
746 "where it installed is in the PATH environment "
747 "variable."), _("OK"), NULL, NULL);
748 exit(1);
750 if (v1 == 0 && (v2 < 18 || v3 < 0)) {
751 sprintf(mbuf, _("WPrefs only supports Window Maker 0.18.0 or newer.\n"
752 "The version installed is %i.%i.%i\n"), v1, v2, v3);
753 WMRunAlertPanel(scr, mainw, _("Error"), mbuf, _("OK"), NULL, NULL);
754 exit(1);
757 if (v1 > 1 || (v1 == 1 && (v2 > 0))) {
758 sprintf(mbuf,
760 ("Window Maker %i.%i.%i, which is installed in your system, is not fully supported by this version of WPrefs."),
761 v1, v2, v3);
762 WMRunAlertPanel(scr, mainw, _("Warning"), mbuf, _("OK"), NULL, NULL);
766 char *command;
768 command = wstrconcat(path, " --global_defaults_path");
769 file = popen(command, "r");
770 wfree(command);
772 if (!file || !fgets(buffer, 1023, file)) {
773 werror(_("could not run \"%s --global_defaults_path\"."), path);
774 exit(1);
775 } else {
776 char *ptr;
777 ptr = strchr(buffer, '\n');
778 if (ptr)
779 *ptr = 0;
780 strcat(buffer, "/WindowMaker");
783 if (file)
784 pclose(file);
786 gdb = WMReadPropListFromFile(buffer);
788 if (gdb) {
789 if (!WMIsPLDictionary(gdb)) {
790 WMReleasePropList(gdb);
791 gdb = NULL;
792 sprintf(mbuf, _("Window Maker domain (%s) is corrupted!"), buffer);
793 WMRunAlertPanel(scr, mainw, _("Error"), mbuf, _("OK"), NULL, NULL);
795 } else {
796 sprintf(mbuf, _("Could not load global Window Maker domain (%s)."), buffer);
797 WMRunAlertPanel(scr, mainw, _("Error"), mbuf, _("OK"), NULL, NULL);
800 if (!db) {
801 db = WMCreatePLDictionary(NULL, NULL);
803 if (!gdb) {
804 gdb = WMCreatePLDictionary(NULL, NULL);
807 GlobalDB = gdb;
809 WindowMakerDB = db;
812 WMPropList *GetObjectForKey(const char *defaultName)
814 WMPropList *object = NULL;
815 WMPropList *key = WMCreatePLString(defaultName);
817 object = WMGetFromPLDictionary(WindowMakerDB, key);
818 if (!object)
819 object = WMGetFromPLDictionary(GlobalDB, key);
821 WMReleasePropList(key);
823 return object;
826 void SetObjectForKey(WMPropList * object, const char *defaultName)
828 WMPropList *key = WMCreatePLString(defaultName);
830 WMPutInPLDictionary(WindowMakerDB, key, object);
831 WMReleasePropList(key);
834 void RemoveObjectForKey(const char *defaultName)
836 WMPropList *key = WMCreatePLString(defaultName);
838 WMRemoveFromPLDictionary(WindowMakerDB, key);
840 WMReleasePropList(key);
843 char *GetStringForKey(const char *defaultName)
845 WMPropList *val;
847 val = GetObjectForKey(defaultName);
849 if (!val)
850 return NULL;
852 if (!WMIsPLString(val))
853 return NULL;
855 return WMGetFromPLString(val);
858 WMPropList *GetArrayForKey(const char *defaultName)
860 WMPropList *val;
862 val = GetObjectForKey(defaultName);
864 if (!val)
865 return NULL;
867 if (!WMIsPLArray(val))
868 return NULL;
870 return val;
873 WMPropList *GetDictionaryForKey(const char *defaultName)
875 WMPropList *val;
877 val = GetObjectForKey(defaultName);
879 if (!val)
880 return NULL;
882 if (!WMIsPLDictionary(val))
883 return NULL;
885 return val;
888 int GetIntegerForKey(const char *defaultName)
890 WMPropList *val;
891 char *str;
892 int value;
894 val = GetObjectForKey(defaultName);
896 if (!val)
897 return 0;
899 if (!WMIsPLString(val))
900 return 0;
902 str = WMGetFromPLString(val);
903 if (!str)
904 return 0;
906 if (sscanf(str, "%i", &value) != 1)
907 return 0;
909 return value;
912 Bool GetBoolForKey(const char *defaultName)
914 int value;
915 char *str;
917 str = GetStringForKey(defaultName);
919 if (!str)
920 return False;
922 if (sscanf(str, "%i", &value) == 1 && value != 0)
923 return True;
925 if (strcasecmp(str, "YES") == 0)
926 return True;
928 if (strcasecmp(str, "Y") == 0)
929 return True;
931 return False;
934 void SetIntegerForKey(int value, const char *defaultName)
936 WMPropList *object;
937 char buffer[128];
939 sprintf(buffer, "%i", value);
940 object = WMCreatePLString(buffer);
942 SetObjectForKey(object, defaultName);
943 WMReleasePropList(object);
946 void SetStringForKey(const char *value, const char *defaultName)
948 WMPropList *object;
950 object = WMCreatePLString(value);
952 SetObjectForKey(object, defaultName);
953 WMReleasePropList(object);
956 void SetBoolForKey(Bool value, const char *defaultName)
958 static WMPropList *yes = NULL, *no = NULL;
960 if (!yes) {
961 yes = WMCreatePLString("YES");
962 no = WMCreatePLString("NO");
965 SetObjectForKey(value ? yes : no, defaultName);
968 void SetSpeedForKey(int speed, const char *defaultName)
970 char *str;
972 switch (speed) {
973 case 0:
974 str = "ultraslow";
975 break;
976 case 1:
977 str = "slow";
978 break;
979 case 2:
980 str = "medium";
981 break;
982 case 3:
983 str = "fast";
984 break;
985 case 4:
986 str = "ultrafast";
987 break;
988 default:
989 str = NULL;
992 if (str)
993 SetStringForKey(str, defaultName);
996 int GetSpeedForKey(const char *defaultName)
998 char *str;
999 int i;
1001 str = GetStringForKey(defaultName);
1002 if (!str)
1003 return 2;
1005 if (strcasecmp(str, "ultraslow") == 0)
1006 i = 0;
1007 else if (strcasecmp(str, "slow") == 0)
1008 i = 1;
1009 else if (strcasecmp(str, "medium") == 0)
1010 i = 2;
1011 else if (strcasecmp(str, "fast") == 0)
1012 i = 3;
1013 else if (strcasecmp(str, "ultrafast") == 0)
1014 i = 4;
1015 else {
1016 wwarning(_("bad speed value for option %s; using default Medium"), defaultName);
1017 i = 2;
1019 return i;