simplified logic of handleMaximize function
[wmaker-crm.git] / WPrefs.app / WPrefs.c
blob6d74409abf560f699cbfff1ebefcc934017be2b9
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 "WPrefs.h"
23 #include <assert.h>
26 #define ICON_TITLE_FONT "sans serif:pixelsize=9"
27 #define ICON_TITLE_VFONT "sans serif:pixelsize=9:weight=100"
29 #define MAX_SECTIONS 16
31 typedef struct _WPrefs {
32 WMWindow *win;
34 WMScrollView *scrollV;
35 WMFrame *buttonF;
36 WMButton *sectionB[MAX_SECTIONS];
38 int sectionCount;
40 WMButton *saveBtn;
41 WMButton *closeBtn;
42 WMButton *undoBtn;
43 WMButton *undosBtn;
45 WMButton *balloonBtn;
47 WMFrame *banner;
48 WMLabel *nameL;
49 WMLabel *versionL;
50 WMLabel *statusL;
52 Panel *currentPanel;
53 } _WPrefs;
55 static _WPrefs WPrefs;
57 /* system wide defaults dictionary. Read-only */
58 static WMPropList *GlobalDB = NULL;
59 /* user defaults dictionary */
60 static WMPropList *WindowMakerDB = NULL;
61 static char *WindowMakerDBPath = NULL;
63 static Bool TIFFOK = False;
65 #define INITIALIZED_PANEL (1<<0)
67 static void loadConfigurations(WMScreen * scr, WMWindow * mainw);
69 static void savePanelData(Panel * panel);
71 static void prepareForClose(void);
73 static void quit(WMWidget *w, void *data)
75 prepareForClose();
77 exit(0);
80 static void save(WMWidget * w, void *data)
82 int i;
83 WMPropList *p1, *p2;
84 WMPropList *keyList;
85 WMPropList *key;
86 XEvent ev;
88 /* puts("gathering data"); */
89 for (i = 0; i < WPrefs.sectionCount; i++) {
90 PanelRec *rec = WMGetHangedData(WPrefs.sectionB[i]);
91 if ((rec->callbacks.flags & INITIALIZED_PANEL))
92 savePanelData((Panel *) rec);
94 /* puts("compressing data"); */
95 /* compare the user dictionary with the global and remove redundant data */
96 keyList = WMGetPLDictionaryKeys(GlobalDB);
97 /* puts(WMGetPropListDescription(WindowMakerDB, False)); */
98 for (i = 0; i < WMGetPropListItemCount(keyList); i++) {
99 key = WMGetFromPLArray(keyList, i);
101 /* We don't have this value anyway, so no problem.
102 * Probably a new option */
103 p1 = WMGetFromPLDictionary(WindowMakerDB, key);
104 if (!p1)
105 continue;
106 /* The global doesn't have it, so no problem either. */
107 p2 = WMGetFromPLDictionary(GlobalDB, key);
108 if (!p2)
109 continue;
110 /* If both values are the same, don't save. */
111 if (WMIsPropListEqualTo(p1, p2))
112 WMRemoveFromPLDictionary(WindowMakerDB, key);
114 /* puts(WMGetPropListDescription(WindowMakerDB, False)); */
115 WMReleasePropList(keyList);
116 /* puts("storing data"); */
118 WMWritePropListToFile(WindowMakerDB, WindowMakerDBPath);
120 memset(&ev, 0, sizeof(XEvent));
122 ev.xclient.type = ClientMessage;
123 ev.xclient.message_type = XInternAtom(WMScreenDisplay(WMWidgetScreen(w)), "_WINDOWMAKER_COMMAND", False);
124 ev.xclient.window = DefaultRootWindow(WMScreenDisplay(WMWidgetScreen(w)));
125 ev.xclient.format = 8;
126 strncpy(ev.xclient.data.b, "Reconfigure", sizeof(ev.xclient.data.b));
128 XSendEvent(WMScreenDisplay(WMWidgetScreen(w)),
129 DefaultRootWindow(WMScreenDisplay(WMWidgetScreen(w))), False, SubstructureRedirectMask, &ev);
130 XFlush(WMScreenDisplay(WMWidgetScreen(w)));
133 static void undo(WMWidget * w, void *data)
135 PanelRec *rec = (PanelRec *) WPrefs.currentPanel;
137 if (!rec)
138 return;
140 if (rec->callbacks.undoChanges && (rec->callbacks.flags & INITIALIZED_PANEL)) {
141 (*rec->callbacks.undoChanges) (WPrefs.currentPanel);
145 static void undoAll(WMWidget * w, void *data)
147 int i;
149 for (i = 0; i < WPrefs.sectionCount; i++) {
150 PanelRec *rec = WMGetHangedData(WPrefs.sectionB[i]);
152 if (rec->callbacks.undoChanges && (rec->callbacks.flags & INITIALIZED_PANEL))
153 (*rec->callbacks.undoChanges) ((Panel *) rec);
157 static void prepareForClose(void)
159 int i;
161 for (i = 0; i < WPrefs.sectionCount; i++) {
162 PanelRec *rec = WMGetHangedData(WPrefs.sectionB[i]);
164 if (rec->callbacks.prepareForClose && (rec->callbacks.flags & INITIALIZED_PANEL))
165 (*rec->callbacks.prepareForClose) ((Panel *) rec);
169 static void toggleBalloons(WMWidget *w, void *data)
171 WMUserDefaults *udb = WMGetStandardUserDefaults();
172 Bool flag;
174 flag = WMGetButtonSelected(WPrefs.balloonBtn);
176 WMSetBalloonEnabled(WMWidgetScreen(WPrefs.win), flag);
178 WMSetUDBoolForKey(udb, flag, "BalloonHelp");
181 static void createMainWindow(WMScreen * scr)
183 WMScroller *scroller;
184 WMFont *font;
185 char buffer[128];
187 WPrefs.win = WMCreateWindow(scr, "wprefs");
188 WMResizeWidget(WPrefs.win, 520, 390);
189 WMSetWindowTitle(WPrefs.win, _("Window Maker Preferences"));
190 WMSetWindowCloseAction(WPrefs.win, quit, NULL);
191 WMSetWindowMaxSize(WPrefs.win, 520, 390);
192 WMSetWindowMinSize(WPrefs.win, 520, 390);
193 WMSetWindowMiniwindowTitle(WPrefs.win, "Preferences");
195 WPrefs.scrollV = WMCreateScrollView(WPrefs.win);
196 WMResizeWidget(WPrefs.scrollV, 500, 87);
197 WMMoveWidget(WPrefs.scrollV, 10, 10);
198 WMSetScrollViewRelief(WPrefs.scrollV, WRSunken);
199 WMSetScrollViewHasHorizontalScroller(WPrefs.scrollV, True);
200 WMSetScrollViewHasVerticalScroller(WPrefs.scrollV, False);
201 scroller = WMGetScrollViewHorizontalScroller(WPrefs.scrollV);
202 WMSetScrollerArrowsPosition(scroller, WSANone);
204 WPrefs.buttonF = WMCreateFrame(WPrefs.win);
205 WMSetFrameRelief(WPrefs.buttonF, WRFlat);
207 WMSetScrollViewContentView(WPrefs.scrollV, WMWidgetView(WPrefs.buttonF));
209 WPrefs.undosBtn = WMCreateCommandButton(WPrefs.win);
210 WMResizeWidget(WPrefs.undosBtn, 90, 28);
211 WMMoveWidget(WPrefs.undosBtn, 135, 350);
212 WMSetButtonText(WPrefs.undosBtn, _("Revert Page"));
213 WMSetButtonAction(WPrefs.undosBtn, undo, NULL);
215 WPrefs.undoBtn = WMCreateCommandButton(WPrefs.win);
216 WMResizeWidget(WPrefs.undoBtn, 90, 28);
217 WMMoveWidget(WPrefs.undoBtn, 235, 350);
218 WMSetButtonText(WPrefs.undoBtn, _("Revert All"));
219 WMSetButtonAction(WPrefs.undoBtn, undoAll, NULL);
221 WPrefs.saveBtn = WMCreateCommandButton(WPrefs.win);
222 WMResizeWidget(WPrefs.saveBtn, 80, 28);
223 WMMoveWidget(WPrefs.saveBtn, 335, 350);
224 WMSetButtonText(WPrefs.saveBtn, _("Save"));
225 WMSetButtonAction(WPrefs.saveBtn, save, NULL);
227 WPrefs.closeBtn = WMCreateCommandButton(WPrefs.win);
228 WMResizeWidget(WPrefs.closeBtn, 80, 28);
229 WMMoveWidget(WPrefs.closeBtn, 425, 350);
230 WMSetButtonText(WPrefs.closeBtn, _("Close"));
231 WMSetButtonAction(WPrefs.closeBtn, quit, NULL);
233 WPrefs.balloonBtn = WMCreateSwitchButton(WPrefs.win);
234 WMResizeWidget(WPrefs.balloonBtn, 200, 28);
235 WMMoveWidget(WPrefs.balloonBtn, 15, 350);
236 WMSetButtonText(WPrefs.balloonBtn, _("Balloon Help"));
237 WMSetButtonAction(WPrefs.balloonBtn, toggleBalloons, NULL);
239 WMUserDefaults *udb = WMGetStandardUserDefaults();
240 Bool flag = WMGetUDBoolForKey(udb, "BalloonHelp");
242 WMSetButtonSelected(WPrefs.balloonBtn, flag);
243 WMSetBalloonEnabled(scr, flag);
246 /* banner */
247 WPrefs.banner = WMCreateFrame(WPrefs.win);
248 WMResizeWidget(WPrefs.banner, FRAME_WIDTH, FRAME_HEIGHT);
249 WMMoveWidget(WPrefs.banner, FRAME_LEFT, FRAME_TOP);
250 WMSetFrameRelief(WPrefs.banner, WRFlat);
252 font = WMCreateFont(scr, "Lucida Sans,URW Gothic L,Times New Roman,serif"
253 ":bold:pixelsize=26:antialias=true");
254 WPrefs.nameL = WMCreateLabel(WPrefs.banner);
255 WMSetLabelTextAlignment(WPrefs.nameL, WACenter);
256 WMResizeWidget(WPrefs.nameL, FRAME_WIDTH - 20, 60);
257 WMMoveWidget(WPrefs.nameL, 10, 50);
258 WMSetLabelFont(WPrefs.nameL, font);
259 WMSetLabelText(WPrefs.nameL, _("Window Maker Preferences"));
260 WMReleaseFont(font);
262 WPrefs.versionL = WMCreateLabel(WPrefs.banner);
263 WMResizeWidget(WPrefs.versionL, FRAME_WIDTH - 20, 20);
264 WMMoveWidget(WPrefs.versionL, 10, 120);
265 WMSetLabelTextAlignment(WPrefs.versionL, WACenter);
266 sprintf(buffer, _("Version %s"), VERSION);
267 WMSetLabelText(WPrefs.versionL, buffer);
269 WPrefs.statusL = WMCreateLabel(WPrefs.banner);
270 WMResizeWidget(WPrefs.statusL, FRAME_WIDTH - 20, 60);
271 WMMoveWidget(WPrefs.statusL, 10, 150);
272 WMSetLabelTextAlignment(WPrefs.statusL, WACenter);
273 WMSetLabelText(WPrefs.statusL, _("Starting..."));
275 WMMapSubwidgets(WPrefs.win);
277 WMUnmapWidget(WPrefs.undosBtn);
278 WMUnmapWidget(WPrefs.undoBtn);
279 WMUnmapWidget(WPrefs.saveBtn);
282 static void showPanel(Panel * panel)
284 PanelRec *rec = (PanelRec *) panel;
286 if (!(rec->callbacks.flags & INITIALIZED_PANEL)) {
287 (*rec->callbacks.createWidgets) (panel);
288 rec->callbacks.flags |= INITIALIZED_PANEL;
291 WMSetWindowTitle(WPrefs.win, rec->sectionName);
293 if (rec->callbacks.showPanel)
294 (*rec->callbacks.showPanel) (panel);
296 WMMapWidget(rec->box);
299 static void hidePanel(Panel * panel)
301 PanelRec *rec = (PanelRec *) panel;
303 WMUnmapWidget(rec->box);
305 if (rec->callbacks.hidePanel)
306 (*rec->callbacks.hidePanel) (panel);
309 static void savePanelData(Panel * panel)
311 PanelRec *rec = (PanelRec *) panel;
313 if (rec->callbacks.updateDomain) {
314 (*rec->callbacks.updateDomain) (panel);
318 static void changeSection(WMWidget * self, void *data)
320 if (WPrefs.currentPanel == data)
321 return;
323 if (WPrefs.currentPanel == NULL) {
324 WMDestroyWidget(WPrefs.nameL);
325 WMDestroyWidget(WPrefs.versionL);
326 WMDestroyWidget(WPrefs.statusL);
328 WMSetFrameRelief(WPrefs.banner, WRGroove);
330 /* WMMapWidget(WPrefs.undosBtn);
331 WMMapWidget(WPrefs.undoBtn);
333 WMMapWidget(WPrefs.saveBtn);
336 showPanel(data);
338 if (WPrefs.currentPanel)
339 hidePanel(WPrefs.currentPanel);
340 WPrefs.currentPanel = data;
343 char *LocateImage(const char *name)
345 char *path;
346 char *tmp = wmalloc(strlen(name) + 8);
348 if (TIFFOK) {
349 sprintf(tmp, "%s.tiff", name);
350 path = WMPathForResourceOfType(tmp, "tiff");
351 } else {
352 sprintf(tmp, "%s.xpm", name);
353 path = WMPathForResourceOfType(tmp, "xpm");
355 wfree(tmp);
356 if (!path) {
357 wwarning(_("could not locate image file %s"), name);
360 return path;
363 void CreateImages(WMScreen *scr, RContext *rc, RImage *xis, const char *file,
364 WMPixmap **icon_normal, WMPixmap **icon_greyed)
366 RImage *icon;
367 char *path;
368 RColor gray = { 0xae, 0xaa, 0xae, 0 };
370 path = LocateImage(file);
371 if (!path)
373 *icon_normal = NULL;
374 if (icon_greyed)
375 *icon_greyed = NULL;
376 return;
379 *icon_normal = WMCreatePixmapFromFile(scr, path);
380 if (!*icon_normal)
382 wwarning(_("could not load icon %s"), path);
383 if (icon_greyed)
384 *icon_greyed = NULL;
385 wfree(path);
386 return;
389 if (!icon_greyed) // Greyed-out version not requested, we are done
391 wfree(path);
392 return;
395 icon = RLoadImage(rc, path, 0);
396 if (!icon)
398 wwarning(_("could not load icon %s"), path);
399 *icon_greyed = NULL;
400 wfree(path);
401 return;
403 RCombineImageWithColor(icon, &gray);
404 if (xis)
406 RCombineImagesWithOpaqueness(icon, xis, 180);
408 *icon_greyed = WMCreatePixmapFromRImage(scr, icon, 127);
409 if (!*icon_greyed)
411 wwarning(_("could not process icon %s: %s"), path, RMessageForError(RErrorCode));
413 RReleaseImage(icon);
414 wfree(path);
418 static WMPixmap *makeTitledIcon(WMScreen * scr, WMPixmap * icon, const char *title1, const char *title2)
420 return WMRetainPixmap(icon);
422 #if 0
423 static GC gc = NULL;
424 static XFontStruct *hfont = NULL;
425 static XFontStruct *vfont = NULL;
426 WMPixmap *tmp;
427 Pixmap pix, mask;
428 Display *dpy = WMScreenDisplay(scr);
429 WMColor *black = WMBlackColor(scr);
430 GC fgc;
431 WMSize size = WMGetPixmapSize(icon);
433 tmp = WMCreatePixmap(scr, 60, 60, WMScreenDepth(scr), True);
435 pix = WMGetPixmapXID(tmp);
436 mask = WMGetPixmapMaskXID(tmp);
438 if (gc == NULL) {
439 gc = XCreateGC(dpy, mask, 0, NULL);
441 hfont = XLoadQueryFont(dpy, ICON_TITLE_FONT);
442 vfont = XLoadQueryFont(dpy, ICON_TITLE_VFONT);
445 if (hfont == NULL) {
446 return WMRetainPixmap(icon);
449 XSetForeground(dpy, gc, 0);
450 XFillRectangle(dpy, mask, gc, 0, 0, 60, 60);
452 fgc = WMColorGC(black);
454 XSetForeground(dpy, gc, 1);
456 XCopyArea(dpy, WMGetPixmapXID(icon), pix, fgc, 0, 0, size.width, size.height, 12, 12);
458 if (WMGetPixmapMaskXID(icon) != None)
459 XCopyPlane(dpy, WMGetPixmapMaskXID(icon), mask, gc, 0, 0, size.width, size.height, 12, 12, 1);
460 else
461 XFillRectangle(dpy, mask, gc, 12, 12, 48, 48);
463 if (title1) {
464 XSetFont(dpy, fgc, vfont->fid);
465 XSetFont(dpy, gc, vfont->fid);
467 XDrawString(dpy, pix, fgc, 0, vfont->ascent, title1, strlen(title1));
469 XDrawString(dpy, mask, gc, 0, vfont->ascent, title1, strlen(title1));
472 if (title2) {
473 XSetFont(dpy, fgc, hfont->fid);
474 XSetFont(dpy, gc, hfont->fid);
476 XDrawString(dpy, pix, fgc, (title1 ? 12 : 0), hfont->ascent, title2, strlen(title2));
478 XDrawString(dpy, mask, gc, (title1 ? 12 : 0), hfont->ascent, title2, strlen(title2));
481 return tmp;
482 #endif
485 void SetButtonAlphaImage(WMScreen * scr, WMButton * bPtr, const char *file, const char *title1, const char *title2)
487 WMPixmap *icon;
488 WMPixmap *icon2;
489 RColor color;
490 char *iconPath;
492 iconPath = LocateImage(file);
494 color.red = 0xae;
495 color.green = 0xaa;
496 color.blue = 0xae;
497 color.alpha = 0;
498 if (iconPath) {
499 icon = WMCreateBlendedPixmapFromFile(scr, iconPath, &color);
500 if (!icon)
501 wwarning(_("could not load icon file %s"), iconPath);
502 } else {
503 icon = NULL;
506 if (icon) {
507 icon2 = makeTitledIcon(scr, icon, title1, title2);
508 if (icon)
509 WMReleasePixmap(icon);
510 } else {
511 icon2 = NULL;
514 WMSetButtonImage(bPtr, icon2);
516 if (icon2)
517 WMReleasePixmap(icon2);
519 color.red = 0xff;
520 color.green = 0xff;
521 color.blue = 0xff;
522 color.alpha = 0;
523 if (iconPath) {
524 icon = WMCreateBlendedPixmapFromFile(scr, iconPath, &color);
525 if (!icon)
526 wwarning(_("could not load icon file %s"), iconPath);
527 } else {
528 icon = NULL;
531 WMSetButtonAltImage(bPtr, icon);
533 if (icon)
534 WMReleasePixmap(icon);
536 if (iconPath)
537 wfree(iconPath);
540 void AddSection(Panel * panel, const char *iconFile)
542 WMButton *bPtr;
544 assert(WPrefs.sectionCount < MAX_SECTIONS);
546 bPtr = WMCreateCustomButton(WPrefs.buttonF, WBBStateLightMask | WBBStateChangeMask);
547 WMResizeWidget(bPtr, 64, 64);
548 WMMoveWidget(bPtr, WPrefs.sectionCount * 64, 0);
549 WMSetButtonImagePosition(bPtr, WIPImageOnly);
550 WMSetButtonAction(bPtr, changeSection, panel);
551 WMHangData(bPtr, panel);
553 WMSetBalloonTextForView(((PanelRec *) panel)->description, WMWidgetView(bPtr));
556 char *t1, *t2;
558 t1 = wstrdup(((PanelRec *) panel)->sectionName);
559 t2 = strchr(t1, ' ');
560 if (t2) {
561 *t2 = 0;
562 t2++;
564 SetButtonAlphaImage(WMWidgetScreen(bPtr), bPtr, iconFile, t1, t2);
565 wfree(t1);
567 WMMapWidget(bPtr);
569 WPrefs.sectionB[WPrefs.sectionCount] = bPtr;
571 if (WPrefs.sectionCount > 0) {
572 WMGroupButtons(WPrefs.sectionB[0], bPtr);
575 WPrefs.sectionCount++;
577 WMResizeWidget(WPrefs.buttonF, WPrefs.sectionCount * 64, 64);
580 void Initialize(WMScreen * scr)
582 char **list;
583 int i;
584 char *path;
586 list = RSupportedFileFormats();
587 for (i = 0; list[i] != NULL; i++) {
588 if (strcmp(list[i], "TIFF") == 0) {
589 TIFFOK = True;
590 break;
594 if (TIFFOK)
595 path = WMPathForResourceOfType("WPrefs.tiff", NULL);
596 else
597 path = WMPathForResourceOfType("WPrefs.xpm", NULL);
598 if (path) {
599 RImage *tmp;
601 tmp = RLoadImage(WMScreenRContext(scr), path, 0);
602 if (!tmp) {
603 wwarning(_("could not load image file %s:%s"), path, RMessageForError(RErrorCode));
604 } else {
605 WMSetApplicationIconImage(scr, tmp);
606 RReleaseImage(tmp);
608 wfree(path);
611 memset(&WPrefs, 0, sizeof(_WPrefs));
612 createMainWindow(scr);
614 WMRealizeWidget(WPrefs.win);
616 WMSetWindowMiniwindowImage(WPrefs.win, WMGetApplicationIconImage(scr));
618 WMMapWidget(WPrefs.win);
619 XFlush(WMScreenDisplay(scr));
620 WMSetLabelText(WPrefs.statusL, _("Loading Window Maker configuration files..."));
621 XFlush(WMScreenDisplay(scr));
622 loadConfigurations(scr, WPrefs.win);
624 WMSetLabelText(WPrefs.statusL, _("Initializing configuration panels..."));
626 InitFocus(scr, WPrefs.banner);
627 InitWindowHandling(scr, WPrefs.banner);
629 InitMenuPreferences(scr, WPrefs.banner);
630 InitIcons(scr, WPrefs.banner);
631 InitPreferences(scr, WPrefs.banner);
633 InitPaths(scr, WPrefs.banner);
634 InitDocks(scr, WPrefs.banner);
635 InitWorkspace(scr, WPrefs.banner);
636 InitConfigurations(scr, WPrefs.banner);
638 InitMenu(scr, WPrefs.banner);
640 #ifdef not_yet_fully_implemented
641 InitKeyboardSettings(scr, WPrefs.banner);
642 #endif
643 InitKeyboardShortcuts(scr, WPrefs.banner);
644 InitMouseSettings(scr, WPrefs.banner);
646 InitAppearance(scr, WPrefs.banner);
648 InitFontSimple(scr, WPrefs.banner);
650 #ifdef not_yet_fully_implemented
651 InitThemes(scr, WPrefs.banner);
652 #endif
653 InitExpert(scr, WPrefs.banner);
655 WMRealizeWidget(WPrefs.scrollV);
657 WMSetLabelText(WPrefs.statusL, "");
660 WMWindow *GetWindow(Panel * panel)
662 return WPrefs.win;
665 static void loadConfigurations(WMScreen * scr, WMWindow * mainw)
667 WMPropList *db, *gdb;
668 char *path;
669 FILE *file;
670 char buffer[1024];
671 char mbuf[1024];
672 int v1, v2, v3;
674 path = wdefaultspathfordomain("WindowMaker");
675 WindowMakerDBPath = path;
677 db = WMReadPropListFromFile(path);
678 if (db) {
679 if (!WMIsPLDictionary(db)) {
680 WMReleasePropList(db);
681 db = NULL;
682 sprintf(mbuf, _("Window Maker domain (%s) is corrupted!"), path);
683 WMRunAlertPanel(scr, mainw, _("Error"), mbuf, _("OK"), NULL, NULL);
685 } else {
686 sprintf(mbuf, _("Could not load Window Maker domain (%s) from defaults database."), path);
687 WMRunAlertPanel(scr, mainw, _("Error"), mbuf, _("OK"), NULL, NULL);
690 path = getenv("WMAKER_BIN_NAME");
691 if (!path)
692 path = "wmaker";
694 char *command;
696 command = wstrconcat(path, " --version");
697 file = popen(command, "r");
698 wfree(command);
700 if (!file || !fgets(buffer, 1023, file)) {
701 werror(_("could not extract version information from Window Maker"));
702 wfatal(_("Make sure wmaker is in your search path."));
704 WMRunAlertPanel(scr, mainw, _("Error"),
706 ("Could not extract version from Window Maker. Make sure it is correctly installed and is in your PATH environment variable."),
707 _("OK"), NULL, NULL);
708 exit(1);
710 if (file)
711 pclose(file);
713 if (sscanf(buffer, "Window Maker %i.%i.%i", &v1, &v2, &v3) != 3
714 && sscanf(buffer, "WindowMaker %i.%i.%i", &v1, &v2, &v3) != 3) {
715 WMRunAlertPanel(scr, mainw, _("Error"),
716 _("Could not extract version from Window Maker. "
717 "Make sure it is correctly installed and the path "
718 "where it installed is in the PATH environment "
719 "variable."), _("OK"), NULL, NULL);
720 exit(1);
722 if (v1 == 0 && (v2 < 18 || v3 < 0)) {
723 sprintf(mbuf, _("WPrefs only supports Window Maker 0.18.0 or newer.\n"
724 "The version installed is %i.%i.%i\n"), v1, v2, v3);
725 WMRunAlertPanel(scr, mainw, _("Error"), mbuf, _("OK"), NULL, NULL);
726 exit(1);
729 if (v1 > 1 || (v1 == 1 && (v2 > 0))) {
730 sprintf(mbuf,
732 ("Window Maker %i.%i.%i, which is installed in your system, is not fully supported by this version of WPrefs."),
733 v1, v2, v3);
734 WMRunAlertPanel(scr, mainw, _("Warning"), mbuf, _("OK"), NULL, NULL);
738 char *command;
740 command = wstrconcat(path, " --global_defaults_path");
741 file = popen(command, "r");
742 wfree(command);
744 if (!file || !fgets(buffer, 1023, file)) {
745 werror(_("could not run \"%s --global_defaults_path\"."), path);
746 exit(1);
747 } else {
748 char *ptr;
749 ptr = strchr(buffer, '\n');
750 if (ptr)
751 *ptr = 0;
752 strcat(buffer, "/WindowMaker");
755 if (file)
756 pclose(file);
758 gdb = WMReadPropListFromFile(buffer);
760 if (gdb) {
761 if (!WMIsPLDictionary(gdb)) {
762 WMReleasePropList(gdb);
763 gdb = NULL;
764 sprintf(mbuf, _("Window Maker domain (%s) is corrupted!"), buffer);
765 WMRunAlertPanel(scr, mainw, _("Error"), mbuf, _("OK"), NULL, NULL);
767 } else {
768 sprintf(mbuf, _("Could not load global Window Maker domain (%s)."), buffer);
769 WMRunAlertPanel(scr, mainw, _("Error"), mbuf, _("OK"), NULL, NULL);
772 if (!db) {
773 db = WMCreatePLDictionary(NULL, NULL);
775 if (!gdb) {
776 gdb = WMCreatePLDictionary(NULL, NULL);
779 GlobalDB = gdb;
781 WindowMakerDB = db;
784 WMPropList *GetObjectForKey(const char *defaultName)
786 WMPropList *object = NULL;
787 WMPropList *key = WMCreatePLString(defaultName);
789 object = WMGetFromPLDictionary(WindowMakerDB, key);
790 if (!object)
791 object = WMGetFromPLDictionary(GlobalDB, key);
793 WMReleasePropList(key);
795 return object;
798 void SetObjectForKey(WMPropList * object, const char *defaultName)
800 WMPropList *key = WMCreatePLString(defaultName);
802 WMPutInPLDictionary(WindowMakerDB, key, object);
803 WMReleasePropList(key);
806 void RemoveObjectForKey(const char *defaultName)
808 WMPropList *key = WMCreatePLString(defaultName);
810 WMRemoveFromPLDictionary(WindowMakerDB, key);
812 WMReleasePropList(key);
815 char *GetStringForKey(const char *defaultName)
817 WMPropList *val;
819 val = GetObjectForKey(defaultName);
821 if (!val)
822 return NULL;
824 if (!WMIsPLString(val))
825 return NULL;
827 return WMGetFromPLString(val);
830 WMPropList *GetArrayForKey(const char *defaultName)
832 WMPropList *val;
834 val = GetObjectForKey(defaultName);
836 if (!val)
837 return NULL;
839 if (!WMIsPLArray(val))
840 return NULL;
842 return val;
845 WMPropList *GetDictionaryForKey(const char *defaultName)
847 WMPropList *val;
849 val = GetObjectForKey(defaultName);
851 if (!val)
852 return NULL;
854 if (!WMIsPLDictionary(val))
855 return NULL;
857 return val;
860 int GetIntegerForKey(const char *defaultName)
862 WMPropList *val;
863 char *str;
864 int value;
866 val = GetObjectForKey(defaultName);
868 if (!val)
869 return 0;
871 if (!WMIsPLString(val))
872 return 0;
874 str = WMGetFromPLString(val);
875 if (!str)
876 return 0;
878 if (sscanf(str, "%i", &value) != 1)
879 return 0;
881 return value;
884 Bool GetBoolForKey(const char *defaultName)
886 int value;
887 char *str;
889 str = GetStringForKey(defaultName);
891 if (!str)
892 return False;
894 if (sscanf(str, "%i", &value) == 1 && value != 0)
895 return True;
897 if (strcasecmp(str, "YES") == 0)
898 return True;
900 if (strcasecmp(str, "Y") == 0)
901 return True;
903 return False;
906 void SetIntegerForKey(int value, const char *defaultName)
908 WMPropList *object;
909 char buffer[128];
911 sprintf(buffer, "%i", value);
912 object = WMCreatePLString(buffer);
914 SetObjectForKey(object, defaultName);
915 WMReleasePropList(object);
918 void SetStringForKey(const char *value, const const char *defaultName)
920 WMPropList *object;
922 object = WMCreatePLString(value);
924 SetObjectForKey(object, defaultName);
925 WMReleasePropList(object);
928 void SetBoolForKey(Bool value, const char *defaultName)
930 static WMPropList *yes = NULL, *no = NULL;
932 if (!yes) {
933 yes = WMCreatePLString("YES");
934 no = WMCreatePLString("NO");
937 SetObjectForKey(value ? yes : no, defaultName);
940 void SetSpeedForKey(int speed, const char *defaultName)
942 char *str;
944 switch (speed) {
945 case 0:
946 str = "ultraslow";
947 break;
948 case 1:
949 str = "slow";
950 break;
951 case 2:
952 str = "medium";
953 break;
954 case 3:
955 str = "fast";
956 break;
957 case 4:
958 str = "ultrafast";
959 break;
960 default:
961 str = NULL;
964 if (str)
965 SetStringForKey(str, defaultName);
968 int GetSpeedForKey(const char *defaultName)
970 char *str;
971 int i;
973 str = GetStringForKey(defaultName);
974 if (!str)
975 return 2;
977 if (strcasecmp(str, "ultraslow") == 0)
978 i = 0;
979 else if (strcasecmp(str, "slow") == 0)
980 i = 1;
981 else if (strcasecmp(str, "medium") == 0)
982 i = 2;
983 else if (strcasecmp(str, "fast") == 0)
984 i = 3;
985 else if (strcasecmp(str, "ultrafast") == 0)
986 i = 4;
987 else {
988 wwarning(_("bad speed value for option %s; using default Medium"), defaultName);
989 i = 2;
991 return i;