1 /* WPrefs.c- main window and other basic stuff
3 * WPrefs - Window Maker Preferences Program
5 * Copyright (c) 1998 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
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
28 extern Panel
*InitWindowHandling(WMScreen
*scr
, WMWindow
*win
);
30 extern Panel
*InitKeyboardSettings(WMScreen
*scr
, WMWindow
*win
);
32 extern Panel
*InitMouseSettings(WMScreen
*scr
, WMWindow
*win
);
34 extern Panel
*InitKeyboardShortcuts(WMScreen
*scr
, WMWindow
*win
);
36 extern Panel
*InitWorkspace(WMScreen
*scr
, WMWindow
*win
);
38 extern Panel
*InitFocus(WMScreen
*scr
, WMWindow
*win
);
40 extern Panel
*InitPreferences(WMScreen
*scr
, WMWindow
*win
);
42 extern Panel
*InitText(WMScreen
*scr
, WMWindow
*win
);
44 extern Panel
*InitConfigurations(WMScreen
*scr
, WMWindow
*win
);
46 extern Panel
*InitPaths(WMScreen
*scr
, WMWindow
*win
);
48 extern Panel
*InitMenu(WMScreen
*scr
, WMWindow
*win
);
50 extern Panel
*InitExpert(WMScreen
*scr
, WMWindow
*win
);
52 extern Panel
*InitMenuPreferences(WMScreen
*scr
, WMWindow
*win
);
54 extern Panel
*InitIcons(WMScreen
*scr
, WMWindow
*win
);
56 extern Panel
*InitThemes(WMScreen
*scr
, WMWindow
*win
);
58 extern Panel
*InitAppearance(WMScreen
*scr
, WMWindow
*win
);
62 #define MAX_SECTIONS 16
65 typedef struct _WPrefs
{
68 WMScrollView
*scrollV
;
70 WMButton
*sectionB
[MAX_SECTIONS
];
89 static _WPrefs WPrefs
;
91 /* system wide defaults dictionary. Read-only */
92 static proplist_t GlobalDB
= NULL
;
93 /* user defaults dictionary */
94 static proplist_t WindowMakerDB
= NULL
;
97 static Bool TIFFOK
= False
;
100 #define INITIALIZED_PANEL (1<<0)
105 static void loadConfigurations(WMScreen
*scr
, WMWindow
*mainw
);
107 static void savePanelData(Panel
*panel
);
109 static void prepareForClose();
112 quit(WMWidget
*w
, void *data
)
121 save(WMWidget
*w
, void *data
)
129 /* puts("gathering data");*/
130 for (i
=0; i
<WPrefs
.sectionCount
; i
++) {
131 PanelRec
*rec
= WMGetHangedData(WPrefs
.sectionB
[i
]);
132 if ((rec
->callbacks
.flags
& INITIALIZED_PANEL
))
133 savePanelData((Panel
*)rec
);
135 /* puts("compressing data");*/
136 /* compare the user dictionary with the global and remove redundant data */
137 keyList
= PLGetAllDictionaryKeys(GlobalDB
);
138 /* puts(PLGetDescription(WindowMakerDB));*/
139 for (i
=0; i
<PLGetNumberOfElements(keyList
); i
++) {
140 key
= PLGetArrayElement(keyList
, i
);
142 /* We don't have this value anyway, so no problem.
143 * Probably a new option */
144 p1
= PLGetDictionaryEntry(WindowMakerDB
, key
);
147 /* The global doesn't have it, so no problem either. */
148 p2
= PLGetDictionaryEntry(GlobalDB
, key
);
151 /* If both values are the same, don't save. */
152 if (PLIsEqual(p1
, p2
))
153 PLRemoveDictionaryEntry(WindowMakerDB
, key
);
155 /* puts(PLGetDescription(WindowMakerDB));*/
157 /* puts("storing data");*/
159 PLSave(WindowMakerDB
, YES
);
165 undo(WMWidget
*w
, void *data
)
167 PanelRec
*rec
= (PanelRec
*)WPrefs
.currentPanel
;
172 if (rec
->callbacks
.undoChanges
173 && (rec
->callbacks
.flags
& INITIALIZED_PANEL
)) {
174 (*rec
->callbacks
.undoChanges
)(WPrefs
.currentPanel
);
180 undoAll(WMWidget
*w
, void *data
)
184 for (i
=0; i
<WPrefs
.sectionCount
; i
++) {
185 PanelRec
*rec
= WMGetHangedData(WPrefs
.sectionB
[i
]);
187 if (rec
->callbacks
.undoChanges
188 && (rec
->callbacks
.flags
& INITIALIZED_PANEL
))
189 (*rec
->callbacks
.undoChanges
)((Panel
*)rec
);
200 for (i
=0; i
<WPrefs
.sectionCount
; i
++) {
201 PanelRec
*rec
= WMGetHangedData(WPrefs
.sectionB
[i
]);
203 if (rec
->callbacks
.prepareForClose
204 && (rec
->callbacks
.flags
& INITIALIZED_PANEL
))
205 (*rec
->callbacks
.prepareForClose
)((Panel
*)rec
);
212 createMainWindow(WMScreen
*scr
)
214 WMScroller
*scroller
;
218 WPrefs
.win
= WMCreateWindow(scr
, "wprefs");
219 WMResizeWidget(WPrefs
.win
, 520, 390);
220 WMSetWindowTitle(WPrefs
.win
, _("Window Maker Preferences"));
221 WMSetWindowCloseAction(WPrefs
.win
, quit
, NULL
);
222 WMSetWindowMaxSize(WPrefs
.win
, 520, 390);
223 WMSetWindowMinSize(WPrefs
.win
, 520, 390);
224 WMSetWindowMiniwindowTitle(WPrefs
.win
, "Preferences");
225 WMSetWindowMiniwindowImage(WPrefs
.win
, WMGetApplicationIconImage(scr
));
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
);
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
, "-*-times-bold-r-*-*-24-*-*-*-*-*-*-*,"
272 "-*-fixed-medium-r-normal-*-24-*");
274 font
= WMBoldSystemFontOfSize(scr
, 24);
275 WPrefs
.nameL
= WMCreateLabel(WPrefs
.banner
);
276 WMSetLabelTextAlignment(WPrefs
.nameL
, WACenter
);
277 WMResizeWidget(WPrefs
.nameL
, FRAME_WIDTH
-20, 30);
278 WMMoveWidget(WPrefs
.nameL
, 10, 25);
279 WMSetLabelFont(WPrefs
.nameL
, font
);
280 WMSetLabelText(WPrefs
.nameL
, _("Window Maker Preferences Utility"));
283 WPrefs
.versionL
= WMCreateLabel(WPrefs
.banner
);
284 WMResizeWidget(WPrefs
.versionL
, FRAME_WIDTH
-20, 20);
285 WMMoveWidget(WPrefs
.versionL
, 10, 65);
286 WMSetLabelTextAlignment(WPrefs
.versionL
, WACenter
);
287 sprintf(buffer
, _("Version %s for Window Maker %s"), WVERSION
, WMVERSION
);
288 WMSetLabelText(WPrefs
.versionL
, buffer
);
290 WPrefs
.statusL
= WMCreateLabel(WPrefs
.banner
);
291 WMResizeWidget(WPrefs
.statusL
, FRAME_WIDTH
-20, 60);
292 WMMoveWidget(WPrefs
.statusL
, 10, 100);
293 WMSetLabelTextAlignment(WPrefs
.statusL
, WACenter
);
294 WMSetLabelText(WPrefs
.statusL
, _("Starting..."));
296 WPrefs
.creditsL
= WMCreateLabel(WPrefs
.banner
);
297 WMResizeWidget(WPrefs
.creditsL
, FRAME_WIDTH
-20, 60);
298 WMMoveWidget(WPrefs
.creditsL
, 10, FRAME_HEIGHT
-60);
299 WMSetLabelTextAlignment(WPrefs
.creditsL
, WACenter
);
300 WMSetLabelText(WPrefs
.creditsL
, _("Programming/Design: Alfredo K. Kojima\n"
301 "Artwork: Marco van Hylckama Vlieg\n"
302 "More Programming: James Thompson"));
305 WMMapSubwidgets(WPrefs
.win
);
307 WMUnmapWidget(WPrefs
.undosBtn
);
308 WMUnmapWidget(WPrefs
.undoBtn
);
309 WMUnmapWidget(WPrefs
.saveBtn
);
314 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 WMMapWidget(rec
->frame
);
331 hidePanel(Panel
*panel
)
333 PanelRec
*rec
= (PanelRec
*)panel
;
335 WMUnmapWidget(rec
->frame
);
340 savePanelData(Panel
*panel
)
342 PanelRec
*rec
= (PanelRec
*)panel
;
344 if (rec
->callbacks
.updateDomain
) {
345 (*rec
->callbacks
.updateDomain
)(panel
);
351 changeSection(WMWidget
*self
, void *data
)
354 WMDestroyWidget(WPrefs
.banner
);
355 WPrefs
.banner
= NULL
;
356 /* WMMapWidget(WPrefs.undosBtn);
357 WMMapWidget(WPrefs.undoBtn);
359 WMMapWidget(WPrefs
.saveBtn
);
364 if (WPrefs
.currentPanel
)
365 hidePanel(WPrefs
.currentPanel
);
366 WPrefs
.currentPanel
= data
;
374 LocateImage(char *name
)
377 char *tmp
= wmalloc(strlen(name
)+8);
380 sprintf(tmp
, "%s.tiff", name
);
381 path
= WMPathForResourceOfType(tmp
, "tiff");
383 sprintf(tmp
, "%s.xpm", name
);
384 path
= WMPathForResourceOfType(tmp
, "xpm");
388 wwarning(_("could not locate image file %s\n"), name
);
396 SetButtonAlphaImage(WMScreen
*scr
, WMButton
*bPtr
, char *file
)
402 iconPath
= LocateImage(file
);
409 icon
= WMCreateBlendedPixmapFromFile(scr
, iconPath
, &color
);
411 wwarning(_("could not load icon file %s"), iconPath
);
416 WMSetButtonImage(bPtr
, icon
);
419 WMReleasePixmap(icon
);
426 icon
= WMCreateBlendedPixmapFromFile(scr
, iconPath
, &color
);
428 wwarning(_("could not load icon file %s"), iconPath
);
433 WMSetButtonAltImage(bPtr
, icon
);
436 WMReleasePixmap(icon
);
444 AddSection(Panel
*panel
, char *iconFile
)
448 assert(WPrefs
.sectionCount
< MAX_SECTIONS
);
451 bPtr
= WMCreateCustomButton(WPrefs
.buttonF
, WBBStateLightMask
452 |WBBStateChangeMask
);
453 WMResizeWidget(bPtr
, 64, 64);
454 WMMoveWidget(bPtr
, WPrefs
.sectionCount
*64, 0);
455 WMSetButtonImagePosition(bPtr
, WIPImageOnly
);
456 WMSetButtonAction(bPtr
, changeSection
, panel
);
457 WMHangData(bPtr
, panel
);
459 SetButtonAlphaImage(WMWidgetScreen(bPtr
), bPtr
, iconFile
);
463 WPrefs
.sectionB
[WPrefs
.sectionCount
] = bPtr
;
465 if (WPrefs
.sectionCount
> 0) {
466 WMGroupButtons(WPrefs
.sectionB
[0], bPtr
);
469 WPrefs
.sectionCount
++;
471 WMResizeWidget(WPrefs
.buttonF
, WPrefs
.sectionCount
*64, 64);
476 Initialize(WMScreen
*scr
)
484 list
= RSupportedFileFormats();
485 for (i
=0; list
[i
]!=NULL
; i
++) {
486 if (strcmp(list
[i
], "TIFF")==0) {
493 path
= WMPathForResourceOfType("WPrefs.tiff", NULL
);
495 path
= WMPathForResourceOfType("WPrefs.xpm", NULL
);
499 tmp
= RLoadImage(WMScreenRContext(scr
), path
, 0);
501 wwarning(_("could not load image file %s:%s"), path
,
502 RMessageForError(RErrorCode
));
504 icon
= WMCreatePixmapFromRImage(scr
, tmp
, 0);
507 WMSetApplicationIconImage(scr
, icon
);
508 WMReleasePixmap(icon
);
514 memset(&WPrefs
, 0, sizeof(_WPrefs
));
515 createMainWindow(scr
);
517 WMRealizeWidget(WPrefs
.win
);
518 WMMapWidget(WPrefs
.win
);
519 XFlush(WMScreenDisplay(scr
));
520 WMSetLabelText(WPrefs
.statusL
, _("Loading Window Maker configuration files..."));
521 XFlush(WMScreenDisplay(scr
));
522 loadConfigurations(scr
, WPrefs
.win
);
524 WMSetLabelText(WPrefs
.statusL
, _("Initializing configuration panels..."));
526 InitWindowHandling(scr
, WPrefs
.win
);
527 InitFocus(scr
, WPrefs
.win
);
528 InitMenuPreferences(scr
, WPrefs
.win
);
529 InitIcons(scr
, WPrefs
.win
);
530 InitPreferences(scr
, WPrefs
.win
);
532 InitPaths(scr
, WPrefs
.win
);
533 InitWorkspace(scr
, WPrefs
.win
);
534 InitConfigurations(scr
, WPrefs
.win
);
536 InitMenu(scr
, WPrefs
.win
);
538 #ifdef not_yet_fully_implemented
539 InitKeyboardSettings(scr
, WPrefs
.win
);
541 InitKeyboardShortcuts(scr
, WPrefs
.win
);
542 InitMouseSettings(scr
, WPrefs
.win
);
544 InitAppearance(scr
, WPrefs
.win
);
545 #ifdef not_yet_fully_implemented
547 InitText(scr
, WPrefs
.win
);
548 InitThemes(scr
, WPrefs
.win
);
550 InitExpert(scr
, WPrefs
.win
);
552 WMRealizeWidget(WPrefs
.scrollV
);
554 WMSetLabelText(WPrefs
.statusL
,
555 _("WPrefs is free software and is distributed WITHOUT ANY\n"
556 "WARRANTY under the terms of the GNU General Public License.\n"
557 "The icons in this program are licensed through the\n"
558 "OpenContent License."));
563 GetWindow(Panel
*panel
)
570 loadConfigurations(WMScreen
*scr
, WMWindow
*mainw
)
579 path
= wdefaultspathfordomain("WindowMaker");
581 db
= PLGetProplistWithPath(path
);
583 if (!PLIsDictionary(db
)) {
586 sprintf(mbuf
, _("Window Maker domain (%s) is corrupted!"), path
);
587 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
590 sprintf(mbuf
, _("Could not load Window Maker domain (%s) from defaults database."),
592 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
596 file
= popen("wmaker --version", "r");
597 if (!file
|| !fgets(buffer
, 1023, file
)) {
598 wsyserror(_("could not extract version information from Window Maker"));
599 wfatal(_("Make sure wmaker is in your search path."));
601 WMRunAlertPanel(scr
, mainw
, _("Error"),
602 _("Could not extract version from Window Maker. Make sure it is correctly installed and is in your PATH environment variable."),
603 _("OK"), NULL
, NULL
);
609 if (sscanf(buffer
, "Window Maker %i.%i.%i",&v1
,&v2
,&v3
)!=3
610 && sscanf(buffer
, "WindowMaker %i.%i.%i",&v1
,&v2
,&v3
)!=3) {
611 WMRunAlertPanel(scr
, mainw
, _("Error"),
612 _("Could not extract version from Window Maker. "
613 "Make sure it is correctly installed and the path "
614 "where it installed is in the PATH environment "
615 "variable."), _("OK"), NULL
, NULL
);
618 if (v1
== 0 && (v2
< 18 || v3
< 0)) {
619 sprintf(mbuf
, _("WPrefs only supports Window Maker 0.18.0 or newer.\n"
620 "The version installed is %i.%i.%i\n"), v1
, v2
, v3
);
621 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
625 if (v1
> 1 || (v1
== 1 && (v2
> 0))) {
626 sprintf(mbuf
, _("Window Maker %i.%i.%i, which is installed in your system, is not fully supported by this version of WPrefs."),
628 WMRunAlertPanel(scr
, mainw
, _("Warning"), mbuf
, _("OK"), NULL
, NULL
);
631 file
= popen("wmaker --global_defaults_path", "r");
632 if (!file
|| !fgets(buffer
, 1023, file
)) {
633 wsyserror(_("could not run \"wmaker --global_defaults_path\"."));
637 ptr
= strchr(buffer
, '\n');
640 strcat(buffer
, "/WindowMaker");
646 gdb
= PLGetProplistWithPath(buffer
);
648 if (!PLIsDictionary(gdb
)) {
651 sprintf(mbuf
, _("Window Maker domain (%s) is corrupted!"), buffer
);
652 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
655 sprintf(mbuf
, _("Could not load global Window Maker domain (%s)."),
657 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
661 db
= PLMakeDictionaryFromEntries(NULL
, NULL
, NULL
);
664 gdb
= PLMakeDictionaryFromEntries(NULL
, NULL
, NULL
);
674 GetObjectForKey(char *defaultName
)
676 proplist_t object
= NULL
;
677 proplist_t key
= PLMakeString(defaultName
);
679 object
= PLGetDictionaryEntry(WindowMakerDB
, key
);
681 object
= PLGetDictionaryEntry(GlobalDB
, key
);
690 SetObjectForKey(proplist_t object
, char *defaultName
)
692 proplist_t key
= PLMakeString(defaultName
);
694 PLInsertDictionaryEntry(WindowMakerDB
, key
, object
);
700 RemoveObjectForKey(char *defaultName
)
702 proplist_t key
= PLMakeString(defaultName
);
704 PLRemoveDictionaryEntry(WindowMakerDB
, key
);
711 GetStringForKey(char *defaultName
)
715 val
= GetObjectForKey(defaultName
);
720 if (!PLIsString(val
))
723 return PLGetString(val
);
729 GetArrayForKey(char *defaultName
)
733 val
= GetObjectForKey(defaultName
);
746 GetDictionaryForKey(char *defaultName
)
750 val
= GetObjectForKey(defaultName
);
755 if (!PLIsDictionary(val
))
763 GetIntegerForKey(char *defaultName
)
769 val
= GetObjectForKey(defaultName
);
774 if (!PLIsString(val
))
777 str
= PLGetString(val
);
781 if (sscanf(str
, "%i", &value
)!=1)
789 GetBoolForKey(char *defaultName
)
794 str
= GetStringForKey(defaultName
);
799 if (sscanf(str
, "%i", &value
)==1 && value
!=0)
802 if (strcasecmp(str
, "YES")==0)
805 if (strcasecmp(str
, "Y")==0)
813 SetIntegerForKey(int value
, char *defaultName
)
818 sprintf(buffer
, "%i", value
);
819 object
= PLMakeString(buffer
);
821 SetObjectForKey(object
, defaultName
);
828 SetStringForKey(char *value
, char *defaultName
)
832 object
= PLMakeString(value
);
834 SetObjectForKey(object
, defaultName
);
840 SetBoolForKey(Bool value
, char *defaultName
)
842 static proplist_t yes
= NULL
, no
= NULL
;
845 yes
= PLMakeString("YES");
846 no
= PLMakeString("NO");
849 SetObjectForKey(value
? yes
: no
, defaultName
);
854 SetSpeedForKey(int speed
, char *defaultName
)
879 SetStringForKey(str
, defaultName
);
884 GetSpeedForKey(char *defaultName
)
889 str
= GetStringForKey(defaultName
);
893 if (strcasecmp(str
, "ultraslow")==0)
895 else if (strcasecmp(str
, "slow")==0)
897 else if (strcasecmp(str
, "medium")==0)
899 else if (strcasecmp(str
, "fast")==0)
901 else if (strcasecmp(str
, "ultrafast")==0)
904 wwarning(_("bad speed value for option %s\n. Using default Medium"),