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