Workspace clip creation in two steps
[wmaker-crm.git] / WPrefs.app / WPrefs.c
blob2b69b51f80ce993fb0454aef2ee496d158af30bc
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>
25 extern Panel *InitWindowHandling(WMScreen * scr, WMWidget * parent);
27 extern Panel *InitKeyboardSettings(WMScreen * scr, WMWidget * parent);
29 extern Panel *InitMouseSettings(WMScreen * scr, WMWidget * parent);
31 extern Panel *InitKeyboardShortcuts(WMScreen * scr, WMWidget * parent);
33 extern Panel *InitWorkspace(WMScreen * scr, WMWidget * parent);
35 extern Panel *InitFocus(WMScreen * scr, WMWidget * parent);
37 extern Panel *InitPreferences(WMScreen * scr, WMWidget * parent);
39 extern Panel *InitFont(WMScreen * scr, WMWidget * parent);
40 extern Panel *InitFontSimple(WMScreen * scr, WMWidget * parent);
42 extern Panel *InitConfigurations(WMScreen * scr, WMWidget * parent);
44 extern Panel *InitPaths(WMScreen * scr, WMWidget * parent);
46 extern Panel *InitMenu(WMScreen * scr, WMWidget * parent);
48 extern Panel *InitExpert(WMScreen * scr, WMWidget * parent);
50 extern Panel *InitMenuPreferences(WMScreen * scr, WMWidget * parent);
52 extern Panel *InitIcons(WMScreen * scr, WMWidget * parent);
54 extern Panel *InitThemes(WMScreen * scr, WMWidget * parent);
56 extern Panel *InitAppearance(WMScreen * scr, WMWidget * parent);
58 #define ICON_TITLE_FONT "sans serif:pixelsize=9"
59 #define ICON_TITLE_VFONT "sans serif:pixelsize=9:weight=100"
61 #define MAX_SECTIONS 16
63 typedef struct _WPrefs {
64 WMWindow *win;
66 WMScrollView *scrollV;
67 WMFrame *buttonF;
68 WMButton *sectionB[MAX_SECTIONS];
70 int sectionCount;
72 WMButton *saveBtn;
73 WMButton *closeBtn;
74 WMButton *undoBtn;
75 WMButton *undosBtn;
77 WMButton *balloonBtn;
79 WMFrame *banner;
80 WMLabel *nameL;
81 WMLabel *versionL;
82 WMLabel *statusL;
84 Panel *currentPanel;
85 } _WPrefs;
87 static _WPrefs WPrefs;
89 /* system wide defaults dictionary. Read-only */
90 static WMPropList *GlobalDB = NULL;
91 /* user defaults dictionary */
92 static WMPropList *WindowMakerDB = NULL;
93 static char *WindowMakerDBPath = NULL;
95 static Bool TIFFOK = False;
97 #define INITIALIZED_PANEL (1<<0)
99 static void loadConfigurations(WMScreen * scr, WMWindow * mainw);
101 static void savePanelData(Panel * panel);
103 static void prepareForClose();
105 void quit(WMWidget * w, void *data)
107 prepareForClose();
109 exit(0);
112 static void save(WMWidget * w, void *data)
114 int i;
115 WMPropList *p1, *p2;
116 WMPropList *keyList;
117 WMPropList *key;
118 XEvent ev;
120 /* puts("gathering data"); */
121 for (i = 0; i < WPrefs.sectionCount; i++) {
122 PanelRec *rec = WMGetHangedData(WPrefs.sectionB[i]);
123 if ((rec->callbacks.flags & INITIALIZED_PANEL))
124 savePanelData((Panel *) rec);
126 /* puts("compressing data"); */
127 /* compare the user dictionary with the global and remove redundant data */
128 keyList = WMGetPLDictionaryKeys(GlobalDB);
129 /* puts(WMGetPropListDescription(WindowMakerDB, False)); */
130 for (i = 0; i < WMGetPropListItemCount(keyList); i++) {
131 key = WMGetFromPLArray(keyList, i);
133 /* We don't have this value anyway, so no problem.
134 * Probably a new option */
135 p1 = WMGetFromPLDictionary(WindowMakerDB, key);
136 if (!p1)
137 continue;
138 /* The global doesn't have it, so no problem either. */
139 p2 = WMGetFromPLDictionary(GlobalDB, key);
140 if (!p2)
141 continue;
142 /* If both values are the same, don't save. */
143 if (WMIsPropListEqualTo(p1, p2))
144 WMRemoveFromPLDictionary(WindowMakerDB, key);
146 /* puts(WMGetPropListDescription(WindowMakerDB, False)); */
147 WMReleasePropList(keyList);
148 /* puts("storing data"); */
150 WMWritePropListToFile(WindowMakerDB, WindowMakerDBPath);
152 memset(&ev, 0, sizeof(XEvent));
154 ev.xclient.type = ClientMessage;
155 ev.xclient.message_type = XInternAtom(WMScreenDisplay(WMWidgetScreen(w)), "_WINDOWMAKER_COMMAND", False);
156 ev.xclient.window = DefaultRootWindow(WMScreenDisplay(WMWidgetScreen(w)));
157 ev.xclient.format = 8;
158 strncpy(ev.xclient.data.b, "Reconfigure", sizeof(ev.xclient.data.b));
160 XSendEvent(WMScreenDisplay(WMWidgetScreen(w)),
161 DefaultRootWindow(WMScreenDisplay(WMWidgetScreen(w))), False, SubstructureRedirectMask, &ev);
162 XFlush(WMScreenDisplay(WMWidgetScreen(w)));
165 static void undo(WMWidget * w, void *data)
167 PanelRec *rec = (PanelRec *) WPrefs.currentPanel;
169 if (!rec)
170 return;
172 if (rec->callbacks.undoChanges && (rec->callbacks.flags & INITIALIZED_PANEL)) {
173 (*rec->callbacks.undoChanges) (WPrefs.currentPanel);
177 static void undoAll(WMWidget * w, void *data)
179 int i;
181 for (i = 0; i < WPrefs.sectionCount; i++) {
182 PanelRec *rec = WMGetHangedData(WPrefs.sectionB[i]);
184 if (rec->callbacks.undoChanges && (rec->callbacks.flags & INITIALIZED_PANEL))
185 (*rec->callbacks.undoChanges) ((Panel *) rec);
189 static void prepareForClose()
191 int i;
193 for (i = 0; i < WPrefs.sectionCount; i++) {
194 PanelRec *rec = WMGetHangedData(WPrefs.sectionB[i]);
196 if (rec->callbacks.prepareForClose && (rec->callbacks.flags & INITIALIZED_PANEL))
197 (*rec->callbacks.prepareForClose) ((Panel *) rec);
201 void toggleBalloons(WMWidget * w, void *data)
203 WMUserDefaults *udb = WMGetStandardUserDefaults();
204 Bool flag;
206 flag = WMGetButtonSelected(WPrefs.balloonBtn);
208 WMSetBalloonEnabled(WMWidgetScreen(WPrefs.win), flag);
210 WMSetUDBoolForKey(udb, flag, "BalloonHelp");
213 static void createMainWindow(WMScreen * scr)
215 WMScroller *scroller;
216 WMFont *font;
217 char buffer[128];
219 WPrefs.win = WMCreateWindow(scr, "wprefs");
220 WMResizeWidget(WPrefs.win, 520, 390);
221 WMSetWindowTitle(WPrefs.win, _("Window Maker Preferences"));
222 WMSetWindowCloseAction(WPrefs.win, quit, NULL);
223 WMSetWindowMaxSize(WPrefs.win, 520, 390);
224 WMSetWindowMinSize(WPrefs.win, 520, 390);
225 WMSetWindowMiniwindowTitle(WPrefs.win, "Preferences");
227 WPrefs.scrollV = WMCreateScrollView(WPrefs.win);
228 WMResizeWidget(WPrefs.scrollV, 500, 87);
229 WMMoveWidget(WPrefs.scrollV, 10, 10);
230 WMSetScrollViewRelief(WPrefs.scrollV, WRSunken);
231 WMSetScrollViewHasHorizontalScroller(WPrefs.scrollV, True);
232 WMSetScrollViewHasVerticalScroller(WPrefs.scrollV, False);
233 scroller = WMGetScrollViewHorizontalScroller(WPrefs.scrollV);
234 WMSetScrollerArrowsPosition(scroller, WSANone);
236 WPrefs.buttonF = WMCreateFrame(WPrefs.win);
237 WMSetFrameRelief(WPrefs.buttonF, WRFlat);
239 WMSetScrollViewContentView(WPrefs.scrollV, WMWidgetView(WPrefs.buttonF));
241 WPrefs.undosBtn = WMCreateCommandButton(WPrefs.win);
242 WMResizeWidget(WPrefs.undosBtn, 90, 28);
243 WMMoveWidget(WPrefs.undosBtn, 135, 350);
244 WMSetButtonText(WPrefs.undosBtn, _("Revert Page"));
245 WMSetButtonAction(WPrefs.undosBtn, undo, NULL);
247 WPrefs.undoBtn = WMCreateCommandButton(WPrefs.win);
248 WMResizeWidget(WPrefs.undoBtn, 90, 28);
249 WMMoveWidget(WPrefs.undoBtn, 235, 350);
250 WMSetButtonText(WPrefs.undoBtn, _("Revert All"));
251 WMSetButtonAction(WPrefs.undoBtn, undoAll, NULL);
253 WPrefs.saveBtn = WMCreateCommandButton(WPrefs.win);
254 WMResizeWidget(WPrefs.saveBtn, 80, 28);
255 WMMoveWidget(WPrefs.saveBtn, 335, 350);
256 WMSetButtonText(WPrefs.saveBtn, _("Save"));
257 WMSetButtonAction(WPrefs.saveBtn, save, NULL);
259 WPrefs.closeBtn = WMCreateCommandButton(WPrefs.win);
260 WMResizeWidget(WPrefs.closeBtn, 80, 28);
261 WMMoveWidget(WPrefs.closeBtn, 425, 350);
262 WMSetButtonText(WPrefs.closeBtn, _("Close"));
263 WMSetButtonAction(WPrefs.closeBtn, quit, NULL);
265 WPrefs.balloonBtn = WMCreateSwitchButton(WPrefs.win);
266 WMResizeWidget(WPrefs.balloonBtn, 200, 28);
267 WMMoveWidget(WPrefs.balloonBtn, 15, 350);
268 WMSetButtonText(WPrefs.balloonBtn, _("Balloon Help"));
269 WMSetButtonAction(WPrefs.balloonBtn, toggleBalloons, NULL);
271 WMUserDefaults *udb = WMGetStandardUserDefaults();
272 Bool flag = WMGetUDBoolForKey(udb, "BalloonHelp");
274 WMSetButtonSelected(WPrefs.balloonBtn, flag);
275 WMSetBalloonEnabled(scr, flag);
278 /* banner */
279 WPrefs.banner = WMCreateFrame(WPrefs.win);
280 WMResizeWidget(WPrefs.banner, FRAME_WIDTH, FRAME_HEIGHT);
281 WMMoveWidget(WPrefs.banner, FRAME_LEFT, FRAME_TOP);
282 WMSetFrameRelief(WPrefs.banner, WRFlat);
284 font = WMCreateFont(scr, "Lucida Sans,URW Gothic L,Times New Roman,serif"
285 ":bold:pixelsize=26:antialias=true");
286 WPrefs.nameL = WMCreateLabel(WPrefs.banner);
287 WMSetLabelTextAlignment(WPrefs.nameL, WACenter);
288 WMResizeWidget(WPrefs.nameL, FRAME_WIDTH - 20, 60);
289 WMMoveWidget(WPrefs.nameL, 10, 50);
290 WMSetLabelFont(WPrefs.nameL, font);
291 WMSetLabelText(WPrefs.nameL, _("Window Maker Preferences"));
292 WMReleaseFont(font);
294 WPrefs.versionL = WMCreateLabel(WPrefs.banner);
295 WMResizeWidget(WPrefs.versionL, FRAME_WIDTH - 20, 20);
296 WMMoveWidget(WPrefs.versionL, 10, 120);
297 WMSetLabelTextAlignment(WPrefs.versionL, WACenter);
298 sprintf(buffer, _("Version %s"), VERSION);
299 WMSetLabelText(WPrefs.versionL, buffer);
301 WPrefs.statusL = WMCreateLabel(WPrefs.banner);
302 WMResizeWidget(WPrefs.statusL, FRAME_WIDTH - 20, 60);
303 WMMoveWidget(WPrefs.statusL, 10, 150);
304 WMSetLabelTextAlignment(WPrefs.statusL, WACenter);
305 WMSetLabelText(WPrefs.statusL, _("Starting..."));
307 WMMapSubwidgets(WPrefs.win);
309 WMUnmapWidget(WPrefs.undosBtn);
310 WMUnmapWidget(WPrefs.undoBtn);
311 WMUnmapWidget(WPrefs.saveBtn);
314 static void showPanel(Panel * panel)
316 PanelRec *rec = (PanelRec *) panel;
318 if (!(rec->callbacks.flags & INITIALIZED_PANEL)) {
319 (*rec->callbacks.createWidgets) (panel);
320 rec->callbacks.flags |= INITIALIZED_PANEL;
323 WMSetWindowTitle(WPrefs.win, rec->sectionName);
325 if (rec->callbacks.showPanel)
326 (*rec->callbacks.showPanel) (panel);
328 WMMapWidget(rec->box);
331 static void hidePanel(Panel * panel)
333 PanelRec *rec = (PanelRec *) panel;
335 WMUnmapWidget(rec->box);
337 if (rec->callbacks.hidePanel)
338 (*rec->callbacks.hidePanel) (panel);
341 static void savePanelData(Panel * panel)
343 PanelRec *rec = (PanelRec *) panel;
345 if (rec->callbacks.updateDomain) {
346 (*rec->callbacks.updateDomain) (panel);
350 static void changeSection(WMWidget * self, void *data)
352 if (WPrefs.currentPanel == data)
353 return;
355 if (WPrefs.currentPanel == NULL) {
356 WMDestroyWidget(WPrefs.nameL);
357 WMDestroyWidget(WPrefs.versionL);
358 WMDestroyWidget(WPrefs.statusL);
360 WMSetFrameRelief(WPrefs.banner, WRGroove);
362 /* WMMapWidget(WPrefs.undosBtn);
363 WMMapWidget(WPrefs.undoBtn);
365 WMMapWidget(WPrefs.saveBtn);
368 showPanel(data);
370 if (WPrefs.currentPanel)
371 hidePanel(WPrefs.currentPanel);
372 WPrefs.currentPanel = data;
375 char *LocateImage(char *name)
377 char *path;
378 char *tmp = wmalloc(strlen(name) + 8);
380 if (TIFFOK) {
381 sprintf(tmp, "%s.tiff", name);
382 path = WMPathForResourceOfType(tmp, "tiff");
383 } else {
384 sprintf(tmp, "%s.xpm", name);
385 path = WMPathForResourceOfType(tmp, "xpm");
387 wfree(tmp);
388 if (!path) {
389 wwarning(_("could not locate image file %s"), name);
392 return path;
395 static WMPixmap *makeTitledIcon(WMScreen * scr, WMPixmap * icon, char *title1, char *title2)
397 return WMRetainPixmap(icon);
399 #if 0
400 static GC gc = NULL;
401 static XFontStruct *hfont = NULL;
402 static XFontStruct *vfont = NULL;
403 WMPixmap *tmp;
404 Pixmap pix, mask;
405 Display *dpy = WMScreenDisplay(scr);
406 WMColor *black = WMBlackColor(scr);
407 GC fgc;
408 WMSize size = WMGetPixmapSize(icon);
410 tmp = WMCreatePixmap(scr, 60, 60, WMScreenDepth(scr), True);
412 pix = WMGetPixmapXID(tmp);
413 mask = WMGetPixmapMaskXID(tmp);
415 if (gc == NULL) {
416 gc = XCreateGC(dpy, mask, 0, NULL);
418 hfont = XLoadQueryFont(dpy, ICON_TITLE_FONT);
419 vfont = XLoadQueryFont(dpy, ICON_TITLE_VFONT);
422 if (hfont == NULL) {
423 return WMRetainPixmap(icon);
426 XSetForeground(dpy, gc, 0);
427 XFillRectangle(dpy, mask, gc, 0, 0, 60, 60);
429 fgc = WMColorGC(black);
431 XSetForeground(dpy, gc, 1);
433 XCopyArea(dpy, WMGetPixmapXID(icon), pix, fgc, 0, 0, size.width, size.height, 12, 12);
435 if (WMGetPixmapMaskXID(icon) != None)
436 XCopyPlane(dpy, WMGetPixmapMaskXID(icon), mask, gc, 0, 0, size.width, size.height, 12, 12, 1);
437 else
438 XFillRectangle(dpy, mask, gc, 12, 12, 48, 48);
440 if (title1) {
441 XSetFont(dpy, fgc, vfont->fid);
442 XSetFont(dpy, gc, vfont->fid);
444 XDrawString(dpy, pix, fgc, 0, vfont->ascent, title1, strlen(title1));
446 XDrawString(dpy, mask, gc, 0, vfont->ascent, title1, strlen(title1));
449 if (title2) {
450 XSetFont(dpy, fgc, hfont->fid);
451 XSetFont(dpy, gc, hfont->fid);
453 XDrawString(dpy, pix, fgc, (title1 ? 12 : 0), hfont->ascent, title2, strlen(title2));
455 XDrawString(dpy, mask, gc, (title1 ? 12 : 0), hfont->ascent, title2, strlen(title2));
458 return tmp;
459 #endif
462 void SetButtonAlphaImage(WMScreen * scr, WMButton * bPtr, char *file, char *title1, char *title2)
464 WMPixmap *icon;
465 WMPixmap *icon2;
466 RColor color;
467 char *iconPath;
469 iconPath = LocateImage(file);
471 color.red = 0xae;
472 color.green = 0xaa;
473 color.blue = 0xae;
474 color.alpha = 0;
475 if (iconPath) {
476 icon = WMCreateBlendedPixmapFromFile(scr, iconPath, &color);
477 if (!icon)
478 wwarning(_("could not load icon file %s"), iconPath);
479 } else {
480 icon = NULL;
483 if (icon) {
484 icon2 = makeTitledIcon(scr, icon, title1, title2);
485 if (icon)
486 WMReleasePixmap(icon);
487 } else {
488 icon2 = NULL;
491 WMSetButtonImage(bPtr, icon2);
493 if (icon2)
494 WMReleasePixmap(icon2);
496 color.red = 0xff;
497 color.green = 0xff;
498 color.blue = 0xff;
499 color.alpha = 0;
500 if (iconPath) {
501 icon = WMCreateBlendedPixmapFromFile(scr, iconPath, &color);
502 if (!icon)
503 wwarning(_("could not load icon file %s"), iconPath);
504 } else {
505 icon = NULL;
508 WMSetButtonAltImage(bPtr, icon);
510 if (icon)
511 WMReleasePixmap(icon);
513 if (iconPath)
514 wfree(iconPath);
517 void AddSection(Panel * panel, char *iconFile)
519 WMButton *bPtr;
521 assert(WPrefs.sectionCount < MAX_SECTIONS);
523 bPtr = WMCreateCustomButton(WPrefs.buttonF, WBBStateLightMask | WBBStateChangeMask);
524 WMResizeWidget(bPtr, 64, 64);
525 WMMoveWidget(bPtr, WPrefs.sectionCount * 64, 0);
526 WMSetButtonImagePosition(bPtr, WIPImageOnly);
527 WMSetButtonAction(bPtr, changeSection, panel);
528 WMHangData(bPtr, panel);
530 WMSetBalloonTextForView(((PanelRec *) panel)->description, WMWidgetView(bPtr));
533 char *t1, *t2;
535 t1 = wstrdup(((PanelRec *) panel)->sectionName);
536 t2 = strchr(t1, ' ');
537 if (t2) {
538 *t2 = 0;
539 t2++;
541 SetButtonAlphaImage(WMWidgetScreen(bPtr), bPtr, iconFile, t1, t2);
542 wfree(t1);
544 WMMapWidget(bPtr);
546 WPrefs.sectionB[WPrefs.sectionCount] = bPtr;
548 if (WPrefs.sectionCount > 0) {
549 WMGroupButtons(WPrefs.sectionB[0], bPtr);
552 WPrefs.sectionCount++;
554 WMResizeWidget(WPrefs.buttonF, WPrefs.sectionCount * 64, 64);
557 void Initialize(WMScreen * scr)
559 char **list;
560 int i;
561 char *path;
563 list = RSupportedFileFormats();
564 for (i = 0; list[i] != NULL; i++) {
565 if (strcmp(list[i], "TIFF") == 0) {
566 TIFFOK = True;
567 break;
571 if (TIFFOK)
572 path = WMPathForResourceOfType("WPrefs.tiff", NULL);
573 else
574 path = WMPathForResourceOfType("WPrefs.xpm", NULL);
575 if (path) {
576 RImage *tmp;
578 tmp = RLoadImage(WMScreenRContext(scr), path, 0);
579 if (!tmp) {
580 wwarning(_("could not load image file %s:%s"), path, RMessageForError(RErrorCode));
581 } else {
582 WMSetApplicationIconImage(scr, tmp);
583 RReleaseImage(tmp);
585 wfree(path);
588 memset(&WPrefs, 0, sizeof(_WPrefs));
589 createMainWindow(scr);
591 WMRealizeWidget(WPrefs.win);
593 WMSetWindowMiniwindowImage(WPrefs.win, WMGetApplicationIconImage(scr));
595 WMMapWidget(WPrefs.win);
596 XFlush(WMScreenDisplay(scr));
597 WMSetLabelText(WPrefs.statusL, _("Loading Window Maker configuration files..."));
598 XFlush(WMScreenDisplay(scr));
599 loadConfigurations(scr, WPrefs.win);
601 WMSetLabelText(WPrefs.statusL, _("Initializing configuration panels..."));
603 InitFocus(scr, WPrefs.banner);
604 InitWindowHandling(scr, WPrefs.banner);
606 InitMenuPreferences(scr, WPrefs.banner);
607 InitIcons(scr, WPrefs.banner);
608 InitPreferences(scr, WPrefs.banner);
610 InitPaths(scr, WPrefs.banner);
611 InitWorkspace(scr, WPrefs.banner);
612 InitConfigurations(scr, WPrefs.banner);
614 InitMenu(scr, WPrefs.banner);
616 #ifdef not_yet_fully_implemented
617 InitKeyboardSettings(scr, WPrefs.banner);
618 #endif
619 InitKeyboardShortcuts(scr, WPrefs.banner);
620 InitMouseSettings(scr, WPrefs.banner);
622 InitAppearance(scr, WPrefs.banner);
624 InitFontSimple(scr, WPrefs.banner);
626 #ifdef not_yet_fully_implemented
627 InitThemes(scr, WPrefs.banner);
628 #endif
629 InitExpert(scr, WPrefs.banner);
631 WMRealizeWidget(WPrefs.scrollV);
633 WMSetLabelText(WPrefs.statusL, "");
636 WMWindow *GetWindow(Panel * panel)
638 return WPrefs.win;
641 static void loadConfigurations(WMScreen * scr, WMWindow * mainw)
643 WMPropList *db, *gdb;
644 char *path;
645 FILE *file;
646 char buffer[1024];
647 char mbuf[1024];
648 int v1, v2, v3;
650 path = wdefaultspathfordomain("WindowMaker");
651 WindowMakerDBPath = path;
653 db = WMReadPropListFromFile(path);
654 if (db) {
655 if (!WMIsPLDictionary(db)) {
656 WMReleasePropList(db);
657 db = NULL;
658 sprintf(mbuf, _("Window Maker domain (%s) is corrupted!"), path);
659 WMRunAlertPanel(scr, mainw, _("Error"), mbuf, _("OK"), NULL, NULL);
661 } else {
662 sprintf(mbuf, _("Could not load Window Maker domain (%s) from defaults database."), path);
663 WMRunAlertPanel(scr, mainw, _("Error"), mbuf, _("OK"), NULL, NULL);
666 path = getenv("WMAKER_BIN_NAME");
667 if (!path)
668 path = "wmaker";
670 char *command;
672 command = wstrconcat(path, " --version");
673 file = popen(command, "r");
674 wfree(command);
676 if (!file || !fgets(buffer, 1023, file)) {
677 werror(_("could not extract version information from Window Maker"));
678 wfatal(_("Make sure wmaker is in your search path."));
680 WMRunAlertPanel(scr, mainw, _("Error"),
682 ("Could not extract version from Window Maker. Make sure it is correctly installed and is in your PATH environment variable."),
683 _("OK"), NULL, NULL);
684 exit(1);
686 if (file)
687 pclose(file);
689 if (sscanf(buffer, "Window Maker %i.%i.%i", &v1, &v2, &v3) != 3
690 && sscanf(buffer, "WindowMaker %i.%i.%i", &v1, &v2, &v3) != 3) {
691 WMRunAlertPanel(scr, mainw, _("Error"),
692 _("Could not extract version from Window Maker. "
693 "Make sure it is correctly installed and the path "
694 "where it installed is in the PATH environment "
695 "variable."), _("OK"), NULL, NULL);
696 exit(1);
698 if (v1 == 0 && (v2 < 18 || v3 < 0)) {
699 sprintf(mbuf, _("WPrefs only supports Window Maker 0.18.0 or newer.\n"
700 "The version installed is %i.%i.%i\n"), v1, v2, v3);
701 WMRunAlertPanel(scr, mainw, _("Error"), mbuf, _("OK"), NULL, NULL);
702 exit(1);
705 if (v1 > 1 || (v1 == 1 && (v2 > 0))) {
706 sprintf(mbuf,
708 ("Window Maker %i.%i.%i, which is installed in your system, is not fully supported by this version of WPrefs."),
709 v1, v2, v3);
710 WMRunAlertPanel(scr, mainw, _("Warning"), mbuf, _("OK"), NULL, NULL);
714 char *command;
716 command = wstrconcat(path, " --global_defaults_path");
717 file = popen(command, "r");
718 wfree(command);
720 if (!file || !fgets(buffer, 1023, file)) {
721 werror(_("could not run \"%s --global_defaults_path\"."), path);
722 exit(1);
723 } else {
724 char *ptr;
725 ptr = strchr(buffer, '\n');
726 if (ptr)
727 *ptr = 0;
728 strcat(buffer, "/WindowMaker");
731 if (file)
732 pclose(file);
734 gdb = WMReadPropListFromFile(buffer);
736 if (gdb) {
737 if (!WMIsPLDictionary(gdb)) {
738 WMReleasePropList(gdb);
739 gdb = NULL;
740 sprintf(mbuf, _("Window Maker domain (%s) is corrupted!"), buffer);
741 WMRunAlertPanel(scr, mainw, _("Error"), mbuf, _("OK"), NULL, NULL);
743 } else {
744 sprintf(mbuf, _("Could not load global Window Maker domain (%s)."), buffer);
745 WMRunAlertPanel(scr, mainw, _("Error"), mbuf, _("OK"), NULL, NULL);
748 if (!db) {
749 db = WMCreatePLDictionary(NULL, NULL);
751 if (!gdb) {
752 gdb = WMCreatePLDictionary(NULL, NULL);
755 GlobalDB = gdb;
757 WindowMakerDB = db;
760 WMPropList *GetObjectForKey(char *defaultName)
762 WMPropList *object = NULL;
763 WMPropList *key = WMCreatePLString(defaultName);
765 object = WMGetFromPLDictionary(WindowMakerDB, key);
766 if (!object)
767 object = WMGetFromPLDictionary(GlobalDB, key);
769 WMReleasePropList(key);
771 return object;
774 void SetObjectForKey(WMPropList * object, char *defaultName)
776 WMPropList *key = WMCreatePLString(defaultName);
778 WMPutInPLDictionary(WindowMakerDB, key, object);
779 WMReleasePropList(key);
782 void RemoveObjectForKey(char *defaultName)
784 WMPropList *key = WMCreatePLString(defaultName);
786 WMRemoveFromPLDictionary(WindowMakerDB, key);
788 WMReleasePropList(key);
791 char *GetStringForKey(char *defaultName)
793 WMPropList *val;
795 val = GetObjectForKey(defaultName);
797 if (!val)
798 return NULL;
800 if (!WMIsPLString(val))
801 return NULL;
803 return WMGetFromPLString(val);
806 WMPropList *GetArrayForKey(char *defaultName)
808 WMPropList *val;
810 val = GetObjectForKey(defaultName);
812 if (!val)
813 return NULL;
815 if (!WMIsPLArray(val))
816 return NULL;
818 return val;
821 WMPropList *GetDictionaryForKey(char *defaultName)
823 WMPropList *val;
825 val = GetObjectForKey(defaultName);
827 if (!val)
828 return NULL;
830 if (!WMIsPLDictionary(val))
831 return NULL;
833 return val;
836 int GetIntegerForKey(char *defaultName)
838 WMPropList *val;
839 char *str;
840 int value;
842 val = GetObjectForKey(defaultName);
844 if (!val)
845 return 0;
847 if (!WMIsPLString(val))
848 return 0;
850 str = WMGetFromPLString(val);
851 if (!str)
852 return 0;
854 if (sscanf(str, "%i", &value) != 1)
855 return 0;
857 return value;
860 Bool GetBoolForKey(char *defaultName)
862 int value;
863 char *str;
865 str = GetStringForKey(defaultName);
867 if (!str)
868 return False;
870 if (sscanf(str, "%i", &value) == 1 && value != 0)
871 return True;
873 if (strcasecmp(str, "YES") == 0)
874 return True;
876 if (strcasecmp(str, "Y") == 0)
877 return True;
879 return False;
882 void SetIntegerForKey(int value, char *defaultName)
884 WMPropList *object;
885 char buffer[128];
887 sprintf(buffer, "%i", value);
888 object = WMCreatePLString(buffer);
890 SetObjectForKey(object, defaultName);
891 WMReleasePropList(object);
894 void SetStringForKey(char *value, char *defaultName)
896 WMPropList *object;
898 object = WMCreatePLString(value);
900 SetObjectForKey(object, defaultName);
901 WMReleasePropList(object);
904 void SetBoolForKey(Bool value, char *defaultName)
906 static WMPropList *yes = NULL, *no = NULL;
908 if (!yes) {
909 yes = WMCreatePLString("YES");
910 no = WMCreatePLString("NO");
913 SetObjectForKey(value ? yes : no, defaultName);
916 void SetSpeedForKey(int speed, char *defaultName)
918 char *str;
920 switch (speed) {
921 case 0:
922 str = "ultraslow";
923 break;
924 case 1:
925 str = "slow";
926 break;
927 case 2:
928 str = "medium";
929 break;
930 case 3:
931 str = "fast";
932 break;
933 case 4:
934 str = "ultrafast";
935 break;
936 default:
937 str = NULL;
940 if (str)
941 SetStringForKey(str, defaultName);
944 int GetSpeedForKey(char *defaultName)
946 char *str;
947 int i;
949 str = GetStringForKey(defaultName);
950 if (!str)
951 return 2;
953 if (strcasecmp(str, "ultraslow") == 0)
954 i = 0;
955 else if (strcasecmp(str, "slow") == 0)
956 i = 1;
957 else if (strcasecmp(str, "medium") == 0)
958 i = 2;
959 else if (strcasecmp(str, "fast") == 0)
960 i = 3;
961 else if (strcasecmp(str, "ultrafast") == 0)
962 i = 4;
963 else {
964 wwarning(_("bad speed value for option %s; using default Medium"), defaultName);
965 i = 2;
967 return i;