WPrefs: Use the macro 'wlengthof' to get the number of element in an array
[wmaker-crm.git] / WPrefs.app / WPrefs.c
blob8f223bc8386e65d98987aaa7fc57ba5a97a1b77c
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 /* Parameter not used, but tell the compiler that it is ok */
76 (void) w;
77 (void) data;
79 prepareForClose();
81 exit(0);
84 static void save(WMWidget * w, void *data)
86 int i;
87 WMPropList *p1, *p2;
88 WMPropList *keyList;
89 WMPropList *key;
90 XEvent ev;
92 /* Parameter not used, but tell the compiler that it is ok */
93 (void) data;
95 /* puts("gathering data"); */
96 for (i = 0; i < WPrefs.sectionCount; i++) {
97 PanelRec *rec = WMGetHangedData(WPrefs.sectionB[i]);
98 if ((rec->callbacks.flags & INITIALIZED_PANEL))
99 savePanelData((Panel *) rec);
101 /* puts("compressing data"); */
102 /* compare the user dictionary with the global and remove redundant data */
103 keyList = WMGetPLDictionaryKeys(GlobalDB);
104 /* puts(WMGetPropListDescription(WindowMakerDB, False)); */
105 for (i = 0; i < WMGetPropListItemCount(keyList); i++) {
106 key = WMGetFromPLArray(keyList, i);
108 /* We don't have this value anyway, so no problem.
109 * Probably a new option */
110 p1 = WMGetFromPLDictionary(WindowMakerDB, key);
111 if (!p1)
112 continue;
113 /* The global doesn't have it, so no problem either. */
114 p2 = WMGetFromPLDictionary(GlobalDB, key);
115 if (!p2)
116 continue;
117 /* If both values are the same, don't save. */
118 if (WMIsPropListEqualTo(p1, p2))
119 WMRemoveFromPLDictionary(WindowMakerDB, key);
121 /* puts(WMGetPropListDescription(WindowMakerDB, False)); */
122 WMReleasePropList(keyList);
123 /* puts("storing data"); */
125 WMWritePropListToFile(WindowMakerDB, WindowMakerDBPath);
127 memset(&ev, 0, sizeof(XEvent));
129 ev.xclient.type = ClientMessage;
130 ev.xclient.message_type = XInternAtom(WMScreenDisplay(WMWidgetScreen(w)), "_WINDOWMAKER_COMMAND", False);
131 ev.xclient.window = DefaultRootWindow(WMScreenDisplay(WMWidgetScreen(w)));
132 ev.xclient.format = 8;
133 strncpy(ev.xclient.data.b, "Reconfigure", sizeof(ev.xclient.data.b));
135 XSendEvent(WMScreenDisplay(WMWidgetScreen(w)),
136 DefaultRootWindow(WMScreenDisplay(WMWidgetScreen(w))), False, SubstructureRedirectMask, &ev);
137 XFlush(WMScreenDisplay(WMWidgetScreen(w)));
140 static void undo(WMWidget * w, void *data)
142 PanelRec *rec = (PanelRec *) WPrefs.currentPanel;
144 /* Parameter not used, but tell the compiler that it is ok */
145 (void) w;
146 (void) data;
148 if (!rec)
149 return;
151 if (rec->callbacks.undoChanges && (rec->callbacks.flags & INITIALIZED_PANEL)) {
152 (*rec->callbacks.undoChanges) (WPrefs.currentPanel);
156 static void undoAll(WMWidget * w, void *data)
158 int i;
160 /* Parameter not used, but tell the compiler that it is ok */
161 (void) w;
162 (void) data;
164 for (i = 0; i < WPrefs.sectionCount; i++) {
165 PanelRec *rec = WMGetHangedData(WPrefs.sectionB[i]);
167 if (rec->callbacks.undoChanges && (rec->callbacks.flags & INITIALIZED_PANEL))
168 (*rec->callbacks.undoChanges) ((Panel *) rec);
172 static void prepareForClose(void)
174 int i;
176 for (i = 0; i < WPrefs.sectionCount; i++) {
177 PanelRec *rec = WMGetHangedData(WPrefs.sectionB[i]);
179 if (rec->callbacks.prepareForClose && (rec->callbacks.flags & INITIALIZED_PANEL))
180 (*rec->callbacks.prepareForClose) ((Panel *) rec);
184 static void toggleBalloons(WMWidget *w, void *data)
186 WMUserDefaults *udb = WMGetStandardUserDefaults();
187 Bool flag;
189 /* Parameter not used, but tell the compiler that it is ok */
190 (void) w;
191 (void) data;
193 flag = WMGetButtonSelected(WPrefs.balloonBtn);
195 WMSetBalloonEnabled(WMWidgetScreen(WPrefs.win), flag);
197 WMSetUDBoolForKey(udb, flag, "BalloonHelp");
200 static void createMainWindow(WMScreen * scr)
202 WMScroller *scroller;
203 WMFont *font;
204 char buffer[128];
206 WPrefs.win = WMCreateWindow(scr, "wprefs");
207 WMResizeWidget(WPrefs.win, 520, 390);
208 WMSetWindowTitle(WPrefs.win, _("Window Maker Preferences"));
209 WMSetWindowCloseAction(WPrefs.win, quit, NULL);
210 WMSetWindowMaxSize(WPrefs.win, 520, 390);
211 WMSetWindowMinSize(WPrefs.win, 520, 390);
212 WMSetWindowMiniwindowTitle(WPrefs.win, "Preferences");
214 WPrefs.scrollV = WMCreateScrollView(WPrefs.win);
215 WMResizeWidget(WPrefs.scrollV, 500, 87);
216 WMMoveWidget(WPrefs.scrollV, 10, 10);
217 WMSetScrollViewRelief(WPrefs.scrollV, WRSunken);
218 WMSetScrollViewHasHorizontalScroller(WPrefs.scrollV, True);
219 WMSetScrollViewHasVerticalScroller(WPrefs.scrollV, False);
220 scroller = WMGetScrollViewHorizontalScroller(WPrefs.scrollV);
221 WMSetScrollerArrowsPosition(scroller, WSANone);
223 WPrefs.buttonF = WMCreateFrame(WPrefs.win);
224 WMSetFrameRelief(WPrefs.buttonF, WRFlat);
226 WMSetScrollViewContentView(WPrefs.scrollV, WMWidgetView(WPrefs.buttonF));
228 WPrefs.undosBtn = WMCreateCommandButton(WPrefs.win);
229 WMResizeWidget(WPrefs.undosBtn, 90, 28);
230 WMMoveWidget(WPrefs.undosBtn, 135, 350);
231 WMSetButtonText(WPrefs.undosBtn, _("Revert Page"));
232 WMSetButtonAction(WPrefs.undosBtn, undo, NULL);
234 WPrefs.undoBtn = WMCreateCommandButton(WPrefs.win);
235 WMResizeWidget(WPrefs.undoBtn, 90, 28);
236 WMMoveWidget(WPrefs.undoBtn, 235, 350);
237 WMSetButtonText(WPrefs.undoBtn, _("Revert All"));
238 WMSetButtonAction(WPrefs.undoBtn, undoAll, NULL);
240 WPrefs.saveBtn = WMCreateCommandButton(WPrefs.win);
241 WMResizeWidget(WPrefs.saveBtn, 80, 28);
242 WMMoveWidget(WPrefs.saveBtn, 335, 350);
243 WMSetButtonText(WPrefs.saveBtn, _("Save"));
244 WMSetButtonAction(WPrefs.saveBtn, save, NULL);
246 WPrefs.closeBtn = WMCreateCommandButton(WPrefs.win);
247 WMResizeWidget(WPrefs.closeBtn, 80, 28);
248 WMMoveWidget(WPrefs.closeBtn, 425, 350);
249 WMSetButtonText(WPrefs.closeBtn, _("Close"));
250 WMSetButtonAction(WPrefs.closeBtn, quit, NULL);
252 WPrefs.balloonBtn = WMCreateSwitchButton(WPrefs.win);
253 WMResizeWidget(WPrefs.balloonBtn, 200, 28);
254 WMMoveWidget(WPrefs.balloonBtn, 15, 350);
255 WMSetButtonText(WPrefs.balloonBtn, _("Balloon Help"));
256 WMSetButtonAction(WPrefs.balloonBtn, toggleBalloons, NULL);
258 WMUserDefaults *udb = WMGetStandardUserDefaults();
259 Bool flag = WMGetUDBoolForKey(udb, "BalloonHelp");
261 WMSetButtonSelected(WPrefs.balloonBtn, flag);
262 WMSetBalloonEnabled(scr, flag);
265 /* banner */
266 WPrefs.banner = WMCreateFrame(WPrefs.win);
267 WMResizeWidget(WPrefs.banner, FRAME_WIDTH, FRAME_HEIGHT);
268 WMMoveWidget(WPrefs.banner, FRAME_LEFT, FRAME_TOP);
269 WMSetFrameRelief(WPrefs.banner, WRFlat);
271 font = WMCreateFont(scr, "Lucida Sans,URW Gothic L,Times New Roman,serif"
272 ":bold:pixelsize=26:antialias=true");
273 WPrefs.nameL = WMCreateLabel(WPrefs.banner);
274 WMSetLabelTextAlignment(WPrefs.nameL, WACenter);
275 WMResizeWidget(WPrefs.nameL, FRAME_WIDTH - 20, 60);
276 WMMoveWidget(WPrefs.nameL, 10, 50);
277 WMSetLabelFont(WPrefs.nameL, font);
278 WMSetLabelText(WPrefs.nameL, _("Window Maker Preferences"));
279 WMReleaseFont(font);
281 WPrefs.versionL = WMCreateLabel(WPrefs.banner);
282 WMResizeWidget(WPrefs.versionL, FRAME_WIDTH - 20, 20);
283 WMMoveWidget(WPrefs.versionL, 10, 120);
284 WMSetLabelTextAlignment(WPrefs.versionL, WACenter);
285 sprintf(buffer, _("Version %s"), VERSION);
286 WMSetLabelText(WPrefs.versionL, buffer);
288 WPrefs.statusL = WMCreateLabel(WPrefs.banner);
289 WMResizeWidget(WPrefs.statusL, FRAME_WIDTH - 20, 60);
290 WMMoveWidget(WPrefs.statusL, 10, 150);
291 WMSetLabelTextAlignment(WPrefs.statusL, WACenter);
292 WMSetLabelText(WPrefs.statusL, _("Starting..."));
294 WMMapSubwidgets(WPrefs.win);
296 WMUnmapWidget(WPrefs.undosBtn);
297 WMUnmapWidget(WPrefs.undoBtn);
298 WMUnmapWidget(WPrefs.saveBtn);
301 static void showPanel(Panel * panel)
303 PanelRec *rec = (PanelRec *) panel;
305 if (!(rec->callbacks.flags & INITIALIZED_PANEL)) {
306 (*rec->callbacks.createWidgets) (panel);
307 rec->callbacks.flags |= INITIALIZED_PANEL;
310 WMSetWindowTitle(WPrefs.win, rec->sectionName);
312 if (rec->callbacks.showPanel)
313 (*rec->callbacks.showPanel) (panel);
315 WMMapWidget(rec->box);
318 static void hidePanel(Panel * panel)
320 PanelRec *rec = (PanelRec *) panel;
322 WMUnmapWidget(rec->box);
324 if (rec->callbacks.hidePanel)
325 (*rec->callbacks.hidePanel) (panel);
328 static void savePanelData(Panel * panel)
330 PanelRec *rec = (PanelRec *) panel;
332 if (rec->callbacks.updateDomain) {
333 (*rec->callbacks.updateDomain) (panel);
337 static void changeSection(WMWidget * self, void *data)
339 /* Parameter not used, but tell the compiler that it is ok */
340 (void) self;
342 if (WPrefs.currentPanel == data)
343 return;
345 if (WPrefs.currentPanel == NULL) {
346 WMDestroyWidget(WPrefs.nameL);
347 WMDestroyWidget(WPrefs.versionL);
348 WMDestroyWidget(WPrefs.statusL);
350 WMSetFrameRelief(WPrefs.banner, WRGroove);
352 /* WMMapWidget(WPrefs.undosBtn);
353 WMMapWidget(WPrefs.undoBtn);
355 WMMapWidget(WPrefs.saveBtn);
358 showPanel(data);
360 if (WPrefs.currentPanel)
361 hidePanel(WPrefs.currentPanel);
362 WPrefs.currentPanel = data;
365 char *LocateImage(const char *name)
367 char *path;
368 char *tmp = wmalloc(strlen(name) + 8);
370 if (TIFFOK) {
371 sprintf(tmp, "%s.tiff", name);
372 path = WMPathForResourceOfType(tmp, "tiff");
373 } else {
374 sprintf(tmp, "%s.xpm", name);
375 path = WMPathForResourceOfType(tmp, "xpm");
377 wfree(tmp);
378 if (!path) {
379 wwarning(_("could not locate image file %s"), name);
382 return path;
385 void CreateImages(WMScreen *scr, RContext *rc, RImage *xis, const char *file,
386 WMPixmap **icon_normal, WMPixmap **icon_greyed)
388 RImage *icon;
389 char *path;
390 RColor gray = { 0xae, 0xaa, 0xae, 0 };
392 path = LocateImage(file);
393 if (!path)
395 *icon_normal = NULL;
396 if (icon_greyed)
397 *icon_greyed = NULL;
398 return;
401 *icon_normal = WMCreatePixmapFromFile(scr, path);
402 if (!*icon_normal)
404 wwarning(_("could not load icon %s"), path);
405 if (icon_greyed)
406 *icon_greyed = NULL;
407 wfree(path);
408 return;
411 if (!icon_greyed) // Greyed-out version not requested, we are done
413 wfree(path);
414 return;
417 icon = RLoadImage(rc, path, 0);
418 if (!icon)
420 wwarning(_("could not load icon %s"), path);
421 *icon_greyed = NULL;
422 wfree(path);
423 return;
425 RCombineImageWithColor(icon, &gray);
426 if (xis)
428 RCombineImagesWithOpaqueness(icon, xis, 180);
430 *icon_greyed = WMCreatePixmapFromRImage(scr, icon, 127);
431 if (!*icon_greyed)
433 wwarning(_("could not process icon %s: %s"), path, RMessageForError(RErrorCode));
435 RReleaseImage(icon);
436 wfree(path);
440 static WMPixmap *makeTitledIcon(WMScreen * scr, WMPixmap * icon, const char *title1, const char *title2)
442 return WMRetainPixmap(icon);
444 #if 0
445 static GC gc = NULL;
446 static XFontStruct *hfont = NULL;
447 static XFontStruct *vfont = NULL;
448 WMPixmap *tmp;
449 Pixmap pix, mask;
450 Display *dpy = WMScreenDisplay(scr);
451 WMColor *black = WMBlackColor(scr);
452 GC fgc;
453 WMSize size = WMGetPixmapSize(icon);
455 tmp = WMCreatePixmap(scr, 60, 60, WMScreenDepth(scr), True);
457 pix = WMGetPixmapXID(tmp);
458 mask = WMGetPixmapMaskXID(tmp);
460 if (gc == NULL) {
461 gc = XCreateGC(dpy, mask, 0, NULL);
463 hfont = XLoadQueryFont(dpy, ICON_TITLE_FONT);
464 vfont = XLoadQueryFont(dpy, ICON_TITLE_VFONT);
467 if (hfont == NULL) {
468 return WMRetainPixmap(icon);
471 XSetForeground(dpy, gc, 0);
472 XFillRectangle(dpy, mask, gc, 0, 0, 60, 60);
474 fgc = WMColorGC(black);
476 XSetForeground(dpy, gc, 1);
478 XCopyArea(dpy, WMGetPixmapXID(icon), pix, fgc, 0, 0, size.width, size.height, 12, 12);
480 if (WMGetPixmapMaskXID(icon) != None)
481 XCopyPlane(dpy, WMGetPixmapMaskXID(icon), mask, gc, 0, 0, size.width, size.height, 12, 12, 1);
482 else
483 XFillRectangle(dpy, mask, gc, 12, 12, 48, 48);
485 if (title1) {
486 XSetFont(dpy, fgc, vfont->fid);
487 XSetFont(dpy, gc, vfont->fid);
489 XDrawString(dpy, pix, fgc, 0, vfont->ascent, title1, strlen(title1));
491 XDrawString(dpy, mask, gc, 0, vfont->ascent, title1, strlen(title1));
494 if (title2) {
495 XSetFont(dpy, fgc, hfont->fid);
496 XSetFont(dpy, gc, hfont->fid);
498 XDrawString(dpy, pix, fgc, (title1 ? 12 : 0), hfont->ascent, title2, strlen(title2));
500 XDrawString(dpy, mask, gc, (title1 ? 12 : 0), hfont->ascent, title2, strlen(title2));
503 return tmp;
504 #endif
507 void SetButtonAlphaImage(WMScreen * scr, WMButton * bPtr, const char *file, const char *title1, const char *title2)
509 WMPixmap *icon;
510 WMPixmap *icon2;
511 RColor color;
512 char *iconPath;
514 iconPath = LocateImage(file);
516 color.red = 0xae;
517 color.green = 0xaa;
518 color.blue = 0xae;
519 color.alpha = 0;
520 if (iconPath) {
521 icon = WMCreateBlendedPixmapFromFile(scr, iconPath, &color);
522 if (!icon)
523 wwarning(_("could not load icon file %s"), iconPath);
524 } else {
525 icon = NULL;
528 if (icon) {
529 icon2 = makeTitledIcon(scr, icon, title1, title2);
530 if (icon)
531 WMReleasePixmap(icon);
532 } else {
533 icon2 = NULL;
536 WMSetButtonImage(bPtr, icon2);
538 if (icon2)
539 WMReleasePixmap(icon2);
541 color.red = 0xff;
542 color.green = 0xff;
543 color.blue = 0xff;
544 color.alpha = 0;
545 if (iconPath) {
546 icon = WMCreateBlendedPixmapFromFile(scr, iconPath, &color);
547 if (!icon)
548 wwarning(_("could not load icon file %s"), iconPath);
549 } else {
550 icon = NULL;
553 WMSetButtonAltImage(bPtr, icon);
555 if (icon)
556 WMReleasePixmap(icon);
558 if (iconPath)
559 wfree(iconPath);
562 void AddSection(Panel * panel, const char *iconFile)
564 WMButton *bPtr;
566 assert(WPrefs.sectionCount < MAX_SECTIONS);
568 bPtr = WMCreateCustomButton(WPrefs.buttonF, WBBStateLightMask | WBBStateChangeMask);
569 WMResizeWidget(bPtr, 64, 64);
570 WMMoveWidget(bPtr, WPrefs.sectionCount * 64, 0);
571 WMSetButtonImagePosition(bPtr, WIPImageOnly);
572 WMSetButtonAction(bPtr, changeSection, panel);
573 WMHangData(bPtr, panel);
575 WMSetBalloonTextForView(((PanelRec *) panel)->description, WMWidgetView(bPtr));
578 char *t1, *t2;
580 t1 = wstrdup(((PanelRec *) panel)->sectionName);
581 t2 = strchr(t1, ' ');
582 if (t2) {
583 *t2 = 0;
584 t2++;
586 SetButtonAlphaImage(WMWidgetScreen(bPtr), bPtr, iconFile, t1, t2);
587 wfree(t1);
589 WMMapWidget(bPtr);
591 WPrefs.sectionB[WPrefs.sectionCount] = bPtr;
593 if (WPrefs.sectionCount > 0) {
594 WMGroupButtons(WPrefs.sectionB[0], bPtr);
597 WPrefs.sectionCount++;
599 WMResizeWidget(WPrefs.buttonF, WPrefs.sectionCount * 64, 64);
602 void Initialize(WMScreen * scr)
604 char **list;
605 int i;
606 char *path;
608 list = RSupportedFileFormats();
609 for (i = 0; list[i] != NULL; i++) {
610 if (strcmp(list[i], "TIFF") == 0) {
611 TIFFOK = True;
612 break;
616 if (TIFFOK)
617 path = WMPathForResourceOfType("WPrefs.tiff", NULL);
618 else
619 path = WMPathForResourceOfType("WPrefs.xpm", NULL);
620 if (path) {
621 RImage *tmp;
623 tmp = RLoadImage(WMScreenRContext(scr), path, 0);
624 if (!tmp) {
625 wwarning(_("could not load image file %s:%s"), path, RMessageForError(RErrorCode));
626 } else {
627 WMSetApplicationIconImage(scr, tmp);
628 RReleaseImage(tmp);
630 wfree(path);
633 memset(&WPrefs, 0, sizeof(_WPrefs));
634 createMainWindow(scr);
636 WMRealizeWidget(WPrefs.win);
638 WMSetWindowMiniwindowImage(WPrefs.win, WMGetApplicationIconImage(scr));
640 WMMapWidget(WPrefs.win);
641 XFlush(WMScreenDisplay(scr));
642 WMSetLabelText(WPrefs.statusL, _("Loading Window Maker configuration files..."));
643 XFlush(WMScreenDisplay(scr));
644 loadConfigurations(scr, WPrefs.win);
646 WMSetLabelText(WPrefs.statusL, _("Initializing configuration panels..."));
648 InitFocus(WPrefs.banner);
649 InitWindowHandling(WPrefs.banner);
651 InitMenuPreferences(WPrefs.banner);
652 InitIcons(WPrefs.banner);
653 InitPreferences(WPrefs.banner);
655 InitPaths(WPrefs.banner);
656 InitDocks(WPrefs.banner);
657 InitWorkspace(WPrefs.banner);
658 InitConfigurations(WPrefs.banner);
660 InitMenu(WPrefs.banner);
662 #ifdef not_yet_fully_implemented
663 InitKeyboardSettings(WPrefs.banner);
664 #endif
665 InitKeyboardShortcuts(WPrefs.banner);
666 InitMouseSettings(WPrefs.banner);
668 InitAppearance(WPrefs.banner);
670 InitFontSimple(WPrefs.banner);
672 #ifdef not_yet_fully_implemented
673 InitThemes(WPrefs.banner);
674 #endif
675 InitExpert(WPrefs.banner);
677 WMRealizeWidget(WPrefs.scrollV);
679 WMSetLabelText(WPrefs.statusL, "");
682 WMWindow *GetWindow(Panel * panel)
684 return WPrefs.win;
687 static void loadConfigurations(WMScreen * scr, WMWindow * mainw)
689 WMPropList *db, *gdb;
690 char *path;
691 FILE *file;
692 char buffer[1024];
693 char mbuf[1024];
694 int v1, v2, v3;
696 path = wdefaultspathfordomain("WindowMaker");
697 WindowMakerDBPath = path;
699 db = WMReadPropListFromFile(path);
700 if (db) {
701 if (!WMIsPLDictionary(db)) {
702 WMReleasePropList(db);
703 db = NULL;
704 sprintf(mbuf, _("Window Maker domain (%s) is corrupted!"), path);
705 WMRunAlertPanel(scr, mainw, _("Error"), mbuf, _("OK"), NULL, NULL);
707 } else {
708 sprintf(mbuf, _("Could not load Window Maker domain (%s) from defaults database."), path);
709 WMRunAlertPanel(scr, mainw, _("Error"), mbuf, _("OK"), NULL, NULL);
712 path = getenv("WMAKER_BIN_NAME");
713 if (!path)
714 path = "wmaker";
716 char *command;
718 command = wstrconcat(path, " --version");
719 file = popen(command, "r");
720 wfree(command);
722 if (!file || !fgets(buffer, 1023, file)) {
723 werror(_("could not extract version information from Window Maker"));
724 wfatal(_("Make sure wmaker is in your search path."));
726 WMRunAlertPanel(scr, mainw, _("Error"),
728 ("Could not extract version from Window Maker. Make sure it is correctly installed and is in your PATH environment variable."),
729 _("OK"), NULL, NULL);
730 exit(1);
732 if (file)
733 pclose(file);
735 if (sscanf(buffer, "Window Maker %i.%i.%i", &v1, &v2, &v3) != 3
736 && sscanf(buffer, "WindowMaker %i.%i.%i", &v1, &v2, &v3) != 3) {
737 WMRunAlertPanel(scr, mainw, _("Error"),
738 _("Could not extract version from Window Maker. "
739 "Make sure it is correctly installed and the path "
740 "where it installed is in the PATH environment "
741 "variable."), _("OK"), NULL, NULL);
742 exit(1);
744 if (v1 == 0 && (v2 < 18 || v3 < 0)) {
745 sprintf(mbuf, _("WPrefs only supports Window Maker 0.18.0 or newer.\n"
746 "The version installed is %i.%i.%i\n"), v1, v2, v3);
747 WMRunAlertPanel(scr, mainw, _("Error"), mbuf, _("OK"), NULL, NULL);
748 exit(1);
751 if (v1 > 1 || (v1 == 1 && (v2 > 0))) {
752 sprintf(mbuf,
754 ("Window Maker %i.%i.%i, which is installed in your system, is not fully supported by this version of WPrefs."),
755 v1, v2, v3);
756 WMRunAlertPanel(scr, mainw, _("Warning"), mbuf, _("OK"), NULL, NULL);
760 char *command;
762 command = wstrconcat(path, " --global_defaults_path");
763 file = popen(command, "r");
764 wfree(command);
766 if (!file || !fgets(buffer, 1023, file)) {
767 werror(_("could not run \"%s --global_defaults_path\"."), path);
768 exit(1);
769 } else {
770 char *ptr;
771 ptr = strchr(buffer, '\n');
772 if (ptr)
773 *ptr = 0;
774 strcat(buffer, "/WindowMaker");
777 if (file)
778 pclose(file);
780 gdb = WMReadPropListFromFile(buffer);
782 if (gdb) {
783 if (!WMIsPLDictionary(gdb)) {
784 WMReleasePropList(gdb);
785 gdb = NULL;
786 sprintf(mbuf, _("Window Maker domain (%s) is corrupted!"), buffer);
787 WMRunAlertPanel(scr, mainw, _("Error"), mbuf, _("OK"), NULL, NULL);
789 } else {
790 sprintf(mbuf, _("Could not load global Window Maker domain (%s)."), buffer);
791 WMRunAlertPanel(scr, mainw, _("Error"), mbuf, _("OK"), NULL, NULL);
794 if (!db) {
795 db = WMCreatePLDictionary(NULL, NULL);
797 if (!gdb) {
798 gdb = WMCreatePLDictionary(NULL, NULL);
801 GlobalDB = gdb;
803 WindowMakerDB = db;
806 WMPropList *GetObjectForKey(const char *defaultName)
808 WMPropList *object = NULL;
809 WMPropList *key = WMCreatePLString(defaultName);
811 object = WMGetFromPLDictionary(WindowMakerDB, key);
812 if (!object)
813 object = WMGetFromPLDictionary(GlobalDB, key);
815 WMReleasePropList(key);
817 return object;
820 void SetObjectForKey(WMPropList * object, const char *defaultName)
822 WMPropList *key = WMCreatePLString(defaultName);
824 WMPutInPLDictionary(WindowMakerDB, key, object);
825 WMReleasePropList(key);
828 void RemoveObjectForKey(const char *defaultName)
830 WMPropList *key = WMCreatePLString(defaultName);
832 WMRemoveFromPLDictionary(WindowMakerDB, key);
834 WMReleasePropList(key);
837 char *GetStringForKey(const char *defaultName)
839 WMPropList *val;
841 val = GetObjectForKey(defaultName);
843 if (!val)
844 return NULL;
846 if (!WMIsPLString(val))
847 return NULL;
849 return WMGetFromPLString(val);
852 WMPropList *GetArrayForKey(const char *defaultName)
854 WMPropList *val;
856 val = GetObjectForKey(defaultName);
858 if (!val)
859 return NULL;
861 if (!WMIsPLArray(val))
862 return NULL;
864 return val;
867 WMPropList *GetDictionaryForKey(const char *defaultName)
869 WMPropList *val;
871 val = GetObjectForKey(defaultName);
873 if (!val)
874 return NULL;
876 if (!WMIsPLDictionary(val))
877 return NULL;
879 return val;
882 int GetIntegerForKey(const char *defaultName)
884 WMPropList *val;
885 char *str;
886 int value;
888 val = GetObjectForKey(defaultName);
890 if (!val)
891 return 0;
893 if (!WMIsPLString(val))
894 return 0;
896 str = WMGetFromPLString(val);
897 if (!str)
898 return 0;
900 if (sscanf(str, "%i", &value) != 1)
901 return 0;
903 return value;
906 Bool GetBoolForKey(const char *defaultName)
908 int value;
909 char *str;
911 str = GetStringForKey(defaultName);
913 if (!str)
914 return False;
916 if (sscanf(str, "%i", &value) == 1 && value != 0)
917 return True;
919 if (strcasecmp(str, "YES") == 0)
920 return True;
922 if (strcasecmp(str, "Y") == 0)
923 return True;
925 return False;
928 void SetIntegerForKey(int value, const char *defaultName)
930 WMPropList *object;
931 char buffer[128];
933 sprintf(buffer, "%i", value);
934 object = WMCreatePLString(buffer);
936 SetObjectForKey(object, defaultName);
937 WMReleasePropList(object);
940 void SetStringForKey(const char *value, const char *defaultName)
942 WMPropList *object;
944 object = WMCreatePLString(value);
946 SetObjectForKey(object, defaultName);
947 WMReleasePropList(object);
950 void SetBoolForKey(Bool value, const char *defaultName)
952 static WMPropList *yes = NULL, *no = NULL;
954 if (!yes) {
955 yes = WMCreatePLString("YES");
956 no = WMCreatePLString("NO");
959 SetObjectForKey(value ? yes : no, defaultName);
962 void SetSpeedForKey(int speed, const char *defaultName)
964 char *str;
966 switch (speed) {
967 case 0:
968 str = "ultraslow";
969 break;
970 case 1:
971 str = "slow";
972 break;
973 case 2:
974 str = "medium";
975 break;
976 case 3:
977 str = "fast";
978 break;
979 case 4:
980 str = "ultrafast";
981 break;
982 default:
983 str = NULL;
986 if (str)
987 SetStringForKey(str, defaultName);
990 int GetSpeedForKey(const char *defaultName)
992 char *str;
993 int i;
995 str = GetStringForKey(defaultName);
996 if (!str)
997 return 2;
999 if (strcasecmp(str, "ultraslow") == 0)
1000 i = 0;
1001 else if (strcasecmp(str, "slow") == 0)
1002 i = 1;
1003 else if (strcasecmp(str, "medium") == 0)
1004 i = 2;
1005 else if (strcasecmp(str, "fast") == 0)
1006 i = 3;
1007 else if (strcasecmp(str, "ultrafast") == 0)
1008 i = 4;
1009 else {
1010 wwarning(_("bad speed value for option %s; using default Medium"), defaultName);
1011 i = 2;
1013 return i;