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
*InitTextureAndColor(WMScreen
*scr
, WMWindow
*win
);
44 extern Panel
*InitText(WMScreen
*scr
, WMWindow
*win
);
46 extern Panel
*InitConfigurations(WMScreen
*scr
, WMWindow
*win
);
48 extern Panel
*InitPaths(WMScreen
*scr
, WMWindow
*win
);
50 extern Panel
*InitMenu(WMScreen
*scr
, WMWindow
*win
);
52 extern Panel
*InitExpert(WMScreen
*scr
, WMWindow
*win
);
54 extern Panel
*InitMenuPreferences(WMScreen
*scr
, WMWindow
*win
);
56 extern Panel
*InitIcons(WMScreen
*scr
, WMWindow
*win
);
59 #define MAX_SECTIONS 16
62 typedef struct _WPrefs
{
65 WMScrollView
*scrollV
;
67 WMButton
*sectionB
[MAX_SECTIONS
];
86 static _WPrefs WPrefs
;
88 /* system wide defaults dictionary. Read-only */
89 static proplist_t GlobalDB
= NULL
;
90 /* user defaults dictionary */
91 static proplist_t WindowMakerDB
= NULL
;
94 static Bool TIFFOK
= False
;
97 #define INITIALIZED_PANEL (1<<0)
102 static void loadConfigurations(WMScreen
*scr
, WMWindow
*mainw
);
104 static void savePanelData(Panel
*panel
);
108 quit(WMWidget
*w
, void *data
)
115 save(WMWidget
*w
, void *data
)
123 /* puts("gathering data");*/
124 for (i
=0; i
<WPrefs
.sectionCount
; i
++) {
125 PanelRec
*rec
= WMGetHangedData(WPrefs
.sectionB
[i
]);
126 if ((rec
->callbacks
.flags
& INITIALIZED_PANEL
))
127 savePanelData((Panel
*)rec
);
129 /* puts("compressing data");*/
130 /* compare the user dictionary with the global and remove redundant data */
131 keyList
= PLGetAllDictionaryKeys(GlobalDB
);
132 /* puts(PLGetDescription(WindowMakerDB));*/
133 for (i
=0; i
<PLGetNumberOfElements(keyList
); i
++) {
134 key
= PLGetArrayElement(keyList
, i
);
136 /* We don't have this value anyway, so no problem.
137 * Probably a new option */
138 p1
= PLGetDictionaryEntry(WindowMakerDB
, key
);
141 /* The global doesn't have it, so no problem either. */
142 p2
= PLGetDictionaryEntry(GlobalDB
, key
);
145 /* If both values are the same, don't save. */
146 if (PLIsEqual(p1
, p2
))
147 PLRemoveDictionaryEntry(WindowMakerDB
, key
);
149 /* puts(PLGetDescription(WindowMakerDB));*/
151 /* puts("storing data");*/
153 PLSave(WindowMakerDB
, YES
);
158 undo(WMWidget
*w
, void *data
)
160 PanelRec
*rec
= (PanelRec
*)WPrefs
.currentPanel
;
165 if (rec
->callbacks
.undoChanges
166 && (rec
->callbacks
.flags
& INITIALIZED_PANEL
)) {
167 (*rec
->callbacks
.undoChanges
)(WPrefs
.currentPanel
);
173 undoAll(WMWidget
*w
, void *data
)
177 for (i
=0; i
<WPrefs
.sectionCount
; i
++) {
178 PanelRec
*rec
= WMGetHangedData(WPrefs
.sectionB
[i
]);
180 if (rec
->callbacks
.undoChanges
181 && (rec
->callbacks
.flags
& INITIALIZED_PANEL
))
182 (*rec
->callbacks
.undoChanges
)((Panel
*)rec
);
188 createMainWindow(WMScreen
*scr
)
190 WMScroller
*scroller
;
194 WPrefs
.win
= WMCreateWindow(scr
, "wprefs");
195 WMResizeWidget(WPrefs
.win
, 520, 390);
196 WMSetWindowTitle(WPrefs
.win
, _("Window Maker Preferences"));
197 WMSetWindowCloseAction(WPrefs
.win
, quit
, NULL
);
198 WMSetWindowMaxSize(WPrefs
.win
, 520, 390);
199 WMSetWindowMinSize(WPrefs
.win
, 520, 390);
200 WMSetWindowMiniwindowTitle(WPrefs
.win
, "Preferences");
201 WMSetWindowMiniwindowImage(WPrefs
.win
, WMGetApplicationIconImage(scr
));
203 WPrefs
.scrollV
= WMCreateScrollView(WPrefs
.win
);
204 WMResizeWidget(WPrefs
.scrollV
, 500, 87);
205 WMMoveWidget(WPrefs
.scrollV
, 10, 10);
206 WMSetScrollViewRelief(WPrefs
.scrollV
, WRSunken
);
207 WMSetScrollViewHasHorizontalScroller(WPrefs
.scrollV
, True
);
208 WMSetScrollViewHasVerticalScroller(WPrefs
.scrollV
, False
);
209 scroller
= WMGetScrollViewHorizontalScroller(WPrefs
.scrollV
);
210 WMSetScrollerArrowsPosition(scroller
, WSANone
);
212 WPrefs
.buttonF
= WMCreateFrame(WPrefs
.win
);
213 WMSetFrameRelief(WPrefs
.buttonF
, WRFlat
);
215 WMSetScrollViewContentView(WPrefs
.scrollV
, WMWidgetView(WPrefs
.buttonF
));
217 WPrefs
.undosBtn
= WMCreateCommandButton(WPrefs
.win
);
218 WMResizeWidget(WPrefs
.undosBtn
, 90, 28);
219 WMMoveWidget(WPrefs
.undosBtn
, 135, 350);
220 WMSetButtonText(WPrefs
.undosBtn
, _("Revert Page"));
221 WMSetButtonAction(WPrefs
.undosBtn
, undo
, NULL
);
223 WPrefs
.undoBtn
= WMCreateCommandButton(WPrefs
.win
);
224 WMResizeWidget(WPrefs
.undoBtn
, 90, 28);
225 WMMoveWidget(WPrefs
.undoBtn
, 235, 350);
226 WMSetButtonText(WPrefs
.undoBtn
, _("Revert All"));
227 WMSetButtonAction(WPrefs
.undoBtn
, undoAll
, NULL
);
229 WPrefs
.saveBtn
= WMCreateCommandButton(WPrefs
.win
);
230 WMResizeWidget(WPrefs
.saveBtn
, 80, 28);
231 WMMoveWidget(WPrefs
.saveBtn
, 335, 350);
232 WMSetButtonText(WPrefs
.saveBtn
, _("Save"));
233 WMSetButtonAction(WPrefs
.saveBtn
, save
, NULL
);
235 WPrefs
.closeBtn
= WMCreateCommandButton(WPrefs
.win
);
236 WMResizeWidget(WPrefs
.closeBtn
, 80, 28);
237 WMMoveWidget(WPrefs
.closeBtn
, 425, 350);
238 WMSetButtonText(WPrefs
.closeBtn
, _("Close"));
239 WMSetButtonAction(WPrefs
.closeBtn
, quit
, NULL
);
242 WPrefs
.banner
= WMCreateFrame(WPrefs
.win
);
243 WMResizeWidget(WPrefs
.banner
, FRAME_WIDTH
, FRAME_HEIGHT
);
244 WMMoveWidget(WPrefs
.banner
, FRAME_LEFT
, FRAME_TOP
);
245 WMSetFrameRelief(WPrefs
.banner
, WRFlat
);
247 font
= WMCreateFont(scr
, "-*-times-bold-r-*-*-24-*-*-*-*-*-*-*");
249 font
= WMBoldSystemFontOfSize(scr
, 24);
250 WPrefs
.nameL
= WMCreateLabel(WPrefs
.banner
);
251 WMSetLabelTextAlignment(WPrefs
.nameL
, WACenter
);
252 WMResizeWidget(WPrefs
.nameL
, FRAME_WIDTH
-20, 30);
253 WMMoveWidget(WPrefs
.nameL
, 10, 25);
254 WMSetLabelFont(WPrefs
.nameL
, font
);
255 WMSetLabelText(WPrefs
.nameL
, "Window Maker Preferences Utility");
258 WPrefs
.versionL
= WMCreateLabel(WPrefs
.banner
);
259 WMResizeWidget(WPrefs
.versionL
, FRAME_WIDTH
-20, 20);
260 WMMoveWidget(WPrefs
.versionL
, 10, 65);
261 WMSetLabelTextAlignment(WPrefs
.versionL
, WACenter
);
262 sprintf(buffer
, _("Version %s for Window Maker %s"), WVERSION
, WMVERSION
);
263 WMSetLabelText(WPrefs
.versionL
, buffer
);
265 WPrefs
.statusL
= WMCreateLabel(WPrefs
.banner
);
266 WMResizeWidget(WPrefs
.statusL
, FRAME_WIDTH
-20, 60);
267 WMMoveWidget(WPrefs
.statusL
, 10, 100);
268 WMSetLabelTextAlignment(WPrefs
.statusL
, WACenter
);
269 WMSetLabelText(WPrefs
.statusL
, _("Starting..."));
271 WPrefs
.creditsL
= WMCreateLabel(WPrefs
.banner
);
272 WMResizeWidget(WPrefs
.creditsL
, FRAME_WIDTH
-20, 60);
273 WMMoveWidget(WPrefs
.creditsL
, 10, FRAME_HEIGHT
-60);
274 WMSetLabelTextAlignment(WPrefs
.creditsL
, WACenter
);
275 WMSetLabelText(WPrefs
.creditsL
, _("Programming/Design: Alfredo K. Kojima\n"
276 "Artwork: Marco van Hylckama Vlieg\n"
277 "More Programming: James Thompson"));
280 WMMapSubwidgets(WPrefs
.win
);
282 WMUnmapWidget(WPrefs
.undosBtn
);
283 WMUnmapWidget(WPrefs
.undoBtn
);
284 WMUnmapWidget(WPrefs
.saveBtn
);
289 showPanel(Panel
*panel
)
291 PanelRec
*rec
= (PanelRec
*)panel
;
293 if (!(rec
->callbacks
.flags
& INITIALIZED_PANEL
)) {
294 (*rec
->callbacks
.createWidgets
)(panel
);
295 rec
->callbacks
.flags
|= INITIALIZED_PANEL
;
298 WMSetWindowTitle(WPrefs
.win
, rec
->sectionName
);
300 WMMapWidget(rec
->frame
);
306 hidePanel(Panel
*panel
)
308 PanelRec
*rec
= (PanelRec
*)panel
;
310 WMUnmapWidget(rec
->frame
);
315 savePanelData(Panel
*panel
)
317 PanelRec
*rec
= (PanelRec
*)panel
;
319 if (rec
->callbacks
.updateDomain
) {
320 (*rec
->callbacks
.updateDomain
)(panel
);
326 changeSection(WMWidget
*self
, void *data
)
329 WMDestroyWidget(WPrefs
.banner
);
330 WPrefs
.banner
= NULL
;
331 /* WMMapWidget(WPrefs.undosBtn);
332 WMMapWidget(WPrefs.undoBtn);
334 WMMapWidget(WPrefs
.saveBtn
);
339 if (WPrefs
.currentPanel
)
340 hidePanel(WPrefs
.currentPanel
);
341 WPrefs
.currentPanel
= data
;
349 LocateImage(char *name
)
352 char *tmp
= wmalloc(strlen(name
)+8);
355 sprintf(tmp
, "%s.tiff", name
);
356 path
= WMPathForResourceOfType(tmp
, "tiff");
358 sprintf(tmp
, "%s.xpm", name
);
359 path
= WMPathForResourceOfType(tmp
, "xpm");
363 wwarning(_("could not locate image file %s\n"), name
);
371 AddSection(Panel
*panel
, char *iconFile
)
378 assert(WPrefs
.sectionCount
< MAX_SECTIONS
);
380 iconPath
= LocateImage(iconFile
);
382 bPtr
= WMCreateCustomButton(WPrefs
.buttonF
, WBBStateLightMask
383 |WBBStateChangeMask
);
384 WMResizeWidget(bPtr
, 64, 64);
385 WMMoveWidget(bPtr
, WPrefs
.sectionCount
*64, 0);
386 WMSetButtonImagePosition(bPtr
, WIPImageOnly
);
387 WMSetButtonAction(bPtr
, changeSection
, panel
);
388 WMHangData(bPtr
, panel
);
395 icon
= WMCreateBlendedPixmapFromFile(WMWidgetScreen(WPrefs
.win
),
398 wwarning(_("could not load icon file %s"), iconPath
);
403 WMSetButtonImage(bPtr
, icon
);
406 WMReleasePixmap(icon
);
413 icon
= WMCreateBlendedPixmapFromFile(WMWidgetScreen(WPrefs
.win
),
416 wwarning(_("could not load icon file %s"), iconPath
);
421 WMSetButtonAltImage(bPtr
, icon
);
424 WMReleasePixmap(icon
);
428 WPrefs
.sectionB
[WPrefs
.sectionCount
] = bPtr
;
430 if (WPrefs
.sectionCount
> 0) {
431 WMGroupButtons(WPrefs
.sectionB
[0], bPtr
);
434 WPrefs
.sectionCount
++;
436 WMResizeWidget(WPrefs
.buttonF
, WPrefs
.sectionCount
*64, 64);
443 Initialize(WMScreen
*scr
)
451 list
= RSupportedFileFormats();
452 for (i
=0; list
[i
]!=NULL
; i
++) {
453 if (strcmp(list
[i
], "TIFF")==0) {
458 RFreeStringList(list
);
461 path
= WMPathForResourceOfType("WPrefs.tiff", NULL
);
463 path
= WMPathForResourceOfType("WPrefs.xpm", NULL
);
467 tmp
= RLoadImage(WMScreenRContext(scr
), path
, 0);
469 wwarning("could not load image file %s:%s", path
,
470 RMessageForError(RErrorCode
));
472 icon
= WMCreatePixmapFromRImage(scr
, tmp
, 0);
475 WMSetApplicationIconImage(scr
, icon
);
476 WMReleasePixmap(icon
);
482 memset(&WPrefs
, 0, sizeof(_WPrefs
));
483 createMainWindow(scr
);
485 WMRealizeWidget(WPrefs
.win
);
486 WMMapWidget(WPrefs
.win
);
487 XFlush(WMScreenDisplay(scr
));
488 WMSetLabelText(WPrefs
.statusL
, _("Loading Window Maker configuration files..."));
489 XFlush(WMScreenDisplay(scr
));
490 loadConfigurations(scr
, WPrefs
.win
);
492 WMSetLabelText(WPrefs
.statusL
, _("Initializing configuration panels..."));
494 InitWindowHandling(scr
, WPrefs
.win
);
495 InitFocus(scr
, WPrefs
.win
);
496 InitMenuPreferences(scr
, WPrefs
.win
);
497 InitIcons(scr
, WPrefs
.win
);
498 InitPreferences(scr
, WPrefs
.win
);
500 InitPaths(scr
, WPrefs
.win
);
501 InitWorkspace(scr
, WPrefs
.win
);
502 InitConfigurations(scr
, WPrefs
.win
);
503 InitMenu(scr
, WPrefs
.win
);
504 #ifdef not_yet_fully_implemented
505 InitKeyboardSettings(scr
, WPrefs
.win
);
507 InitKeyboardShortcuts(scr
, WPrefs
.win
);
508 InitMouseSettings(scr
, WPrefs
.win
);
509 #ifdef not_yet_fully_implemented
510 InitTextureAndColor(scr
, WPrefs
.win
);
511 InitText(scr
, WPrefs
.win
);
513 InitExpert(scr
, WPrefs
.win
);
515 WMRealizeWidget(WPrefs
.scrollV
);
517 WMSetLabelText(WPrefs
.statusL
, "This program is still under development. Backup your ~/GNUstep/Defaults directory, before using it.");
522 GetWindow(Panel
*panel
)
529 loadConfigurations(WMScreen
*scr
, WMWindow
*mainw
)
538 path
= wdefaultspathfordomain("WindowMaker");
540 db
= PLGetProplistWithPath(path
);
542 if (!PLIsDictionary(db
)) {
545 sprintf(mbuf
, _("Window Maker domain (%s) is corrupted!"), path
);
546 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
549 sprintf(mbuf
, _("Could not load Window Maker domain (%s) from defaults database."),
551 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
555 file
= popen("wmaker -version", "r");
556 if (!file
|| !fgets(buffer
, 1023, file
)) {
557 wsyserror(_("could not extract version information from Window Maker"));
558 wfatal(_("Make sure Window Maker is in your search path."));
560 WMRunAlertPanel(scr
, mainw
, _("Error"),
561 _("Could not extract version from Window Maker. Make sure it is correctly installed."),
562 _("OK"), NULL
, NULL
);
568 if (sscanf(buffer
, "Window Maker %i.%i.%i",&v1
,&v2
,&v3
)!=3
569 && sscanf(buffer
, "WindowMaker %i.%i.%i",&v1
,&v2
,&v3
)!=3) {
570 WMRunAlertPanel(scr
, mainw
, _("Error"),
571 _("Could not extract version from Window Maker. Make sure it is correctly installed."),
572 _("OK"), NULL
, NULL
);
575 if (v1
== 0 && (v2
< 18 || v3
< 0)) {
576 sprintf(mbuf
, _("WPrefs only supports Window Maker 0.18.0 or newer.\n"
577 "The version installed is %i.%i.%i\n"), v1
, v2
, v3
);
578 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
582 if (v1
> 1 || (v1
== 1 && (v2
> 0))) {
583 sprintf(mbuf
, _("Window Maker %i.%i.%i, which is installed in your system, is not fully supported by this version of WPrefs."),
585 WMRunAlertPanel(scr
, mainw
, _("Warning"), mbuf
, _("OK"), NULL
, NULL
);
588 file
= popen("wmaker -global_defaults_path", "r");
589 if (!file
|| !fgets(buffer
, 1023, file
)) {
590 wsyserror(_("could not run \"wmaker -global_defaults_path\"."));
596 gdb
= PLGetProplistWithPath(buffer
);
598 if (!PLIsDictionary(gdb
)) {
601 sprintf(mbuf
, _("Window Maker domain (%s) is corrupted!"), buffer
);
602 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
605 sprintf(mbuf
, _("Could not load global Window Maker domain (%s)."),
607 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
611 db
= PLMakeDictionaryFromEntries(NULL
, NULL
, NULL
);
614 gdb
= PLMakeDictionaryFromEntries(NULL
, NULL
, NULL
);
624 GetObjectForKey(char *defaultName
)
626 proplist_t object
= NULL
;
627 proplist_t key
= PLMakeString(defaultName
);
629 object
= PLGetDictionaryEntry(WindowMakerDB
, key
);
631 object
= PLGetDictionaryEntry(GlobalDB
, key
);
640 SetObjectForKey(proplist_t object
, char *defaultName
)
642 proplist_t key
= PLMakeString(defaultName
);
644 PLInsertDictionaryEntry(WindowMakerDB
, key
, object
);
650 RemoveObjectForKey(char *defaultName
)
652 proplist_t key
= PLMakeString(defaultName
);
654 PLRemoveDictionaryEntry(WindowMakerDB
, key
);
661 GetStringForKey(char *defaultName
)
665 val
= GetObjectForKey(defaultName
);
670 if (!PLIsString(val
))
673 return PLGetString(val
);
679 GetArrayForKey(char *defaultName
)
683 val
= GetObjectForKey(defaultName
);
696 GetDictionaryForKey(char *defaultName
)
700 val
= GetObjectForKey(defaultName
);
705 if (!PLIsDictionary(val
))
713 GetIntegerForKey(char *defaultName
)
719 val
= GetObjectForKey(defaultName
);
724 if (!PLIsString(val
))
727 str
= PLGetString(val
);
731 if (sscanf(str
, "%i", &value
)!=1)
739 GetBoolForKey(char *defaultName
)
744 str
= GetStringForKey(defaultName
);
749 if (sscanf(str
, "%i", &value
)==1 && value
!=0)
752 if (strcasecmp(str
, "YES")==0)
755 if (strcasecmp(str
, "Y")==0)
763 SetIntegerForKey(int value
, char *defaultName
)
768 sprintf(buffer
, "%i", value
);
769 object
= PLMakeString(buffer
);
771 SetObjectForKey(object
, defaultName
);
778 SetStringForKey(char *value
, char *defaultName
)
782 object
= PLMakeString(value
);
784 SetObjectForKey(object
, defaultName
);
790 SetBoolForKey(Bool value
, char *defaultName
)
792 static proplist_t yes
= NULL
, no
= NULL
;
795 yes
= PLMakeString("YES");
796 no
= PLMakeString("NO");
799 SetObjectForKey(value
? yes
: no
, defaultName
);
804 SetSpeedForKey(int speed
, char *defaultName
)
829 SetStringForKey(str
, defaultName
);
834 GetSpeedForKey(char *defaultName
)
839 str
= GetStringForKey(defaultName
);
840 if (strcasecmp(str
, "ultraslow")==0)
842 else if (strcasecmp(str
, "slow")==0)
844 else if (strcasecmp(str
, "medium")==0)
846 else if (strcasecmp(str
, "fast")==0)
848 else if (strcasecmp(str
, "ultrafast")==0)
851 wwarning(_("bad speed value for option %s\n. Using default Medium"),