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
*InitTextureAndColor(WMScreen
*scr
, WMWindow
*win
);
60 extern Panel
*InitAppearance(WMScreen
*scr
, WMWindow
*win
);
64 #define MAX_SECTIONS 16
67 typedef struct _WPrefs
{
70 WMScrollView
*scrollV
;
72 WMButton
*sectionB
[MAX_SECTIONS
];
91 static _WPrefs WPrefs
;
93 /* system wide defaults dictionary. Read-only */
94 static proplist_t GlobalDB
= NULL
;
95 /* user defaults dictionary */
96 static proplist_t WindowMakerDB
= NULL
;
99 static Bool TIFFOK
= False
;
102 #define INITIALIZED_PANEL (1<<0)
107 static void loadConfigurations(WMScreen
*scr
, WMWindow
*mainw
);
109 static void savePanelData(Panel
*panel
);
113 quit(WMWidget
*w
, void *data
)
120 save(WMWidget
*w
, void *data
)
128 /* puts("gathering data");*/
129 for (i
=0; i
<WPrefs
.sectionCount
; i
++) {
130 PanelRec
*rec
= WMGetHangedData(WPrefs
.sectionB
[i
]);
131 if ((rec
->callbacks
.flags
& INITIALIZED_PANEL
))
132 savePanelData((Panel
*)rec
);
134 /* puts("compressing data");*/
135 /* compare the user dictionary with the global and remove redundant data */
136 keyList
= PLGetAllDictionaryKeys(GlobalDB
);
137 /* puts(PLGetDescription(WindowMakerDB));*/
138 for (i
=0; i
<PLGetNumberOfElements(keyList
); i
++) {
139 key
= PLGetArrayElement(keyList
, i
);
141 /* We don't have this value anyway, so no problem.
142 * Probably a new option */
143 p1
= PLGetDictionaryEntry(WindowMakerDB
, key
);
146 /* The global doesn't have it, so no problem either. */
147 p2
= PLGetDictionaryEntry(GlobalDB
, key
);
150 /* If both values are the same, don't save. */
151 if (PLIsEqual(p1
, p2
))
152 PLRemoveDictionaryEntry(WindowMakerDB
, key
);
154 /* puts(PLGetDescription(WindowMakerDB));*/
156 /* puts("storing data");*/
158 PLSave(WindowMakerDB
, YES
);
163 undo(WMWidget
*w
, void *data
)
165 PanelRec
*rec
= (PanelRec
*)WPrefs
.currentPanel
;
170 if (rec
->callbacks
.undoChanges
171 && (rec
->callbacks
.flags
& INITIALIZED_PANEL
)) {
172 (*rec
->callbacks
.undoChanges
)(WPrefs
.currentPanel
);
178 undoAll(WMWidget
*w
, void *data
)
182 for (i
=0; i
<WPrefs
.sectionCount
; i
++) {
183 PanelRec
*rec
= WMGetHangedData(WPrefs
.sectionB
[i
]);
185 if (rec
->callbacks
.undoChanges
186 && (rec
->callbacks
.flags
& INITIALIZED_PANEL
))
187 (*rec
->callbacks
.undoChanges
)((Panel
*)rec
);
193 createMainWindow(WMScreen
*scr
)
195 WMScroller
*scroller
;
199 WPrefs
.win
= WMCreateWindow(scr
, "wprefs");
200 WMResizeWidget(WPrefs
.win
, 520, 390);
201 WMSetWindowTitle(WPrefs
.win
, _("Window Maker Preferences"));
202 WMSetWindowCloseAction(WPrefs
.win
, quit
, NULL
);
203 WMSetWindowMaxSize(WPrefs
.win
, 520, 390);
204 WMSetWindowMinSize(WPrefs
.win
, 520, 390);
205 WMSetWindowMiniwindowTitle(WPrefs
.win
, "Preferences");
206 WMSetWindowMiniwindowImage(WPrefs
.win
, WMGetApplicationIconImage(scr
));
208 WPrefs
.scrollV
= WMCreateScrollView(WPrefs
.win
);
209 WMResizeWidget(WPrefs
.scrollV
, 500, 87);
210 WMMoveWidget(WPrefs
.scrollV
, 10, 10);
211 WMSetScrollViewRelief(WPrefs
.scrollV
, WRSunken
);
212 WMSetScrollViewHasHorizontalScroller(WPrefs
.scrollV
, True
);
213 WMSetScrollViewHasVerticalScroller(WPrefs
.scrollV
, False
);
214 scroller
= WMGetScrollViewHorizontalScroller(WPrefs
.scrollV
);
215 WMSetScrollerArrowsPosition(scroller
, WSANone
);
217 WPrefs
.buttonF
= WMCreateFrame(WPrefs
.win
);
218 WMSetFrameRelief(WPrefs
.buttonF
, WRFlat
);
220 WMSetScrollViewContentView(WPrefs
.scrollV
, WMWidgetView(WPrefs
.buttonF
));
222 WPrefs
.undosBtn
= WMCreateCommandButton(WPrefs
.win
);
223 WMResizeWidget(WPrefs
.undosBtn
, 90, 28);
224 WMMoveWidget(WPrefs
.undosBtn
, 135, 350);
225 WMSetButtonText(WPrefs
.undosBtn
, _("Revert Page"));
226 WMSetButtonAction(WPrefs
.undosBtn
, undo
, NULL
);
228 WPrefs
.undoBtn
= WMCreateCommandButton(WPrefs
.win
);
229 WMResizeWidget(WPrefs
.undoBtn
, 90, 28);
230 WMMoveWidget(WPrefs
.undoBtn
, 235, 350);
231 WMSetButtonText(WPrefs
.undoBtn
, _("Revert All"));
232 WMSetButtonAction(WPrefs
.undoBtn
, undoAll
, NULL
);
234 WPrefs
.saveBtn
= WMCreateCommandButton(WPrefs
.win
);
235 WMResizeWidget(WPrefs
.saveBtn
, 80, 28);
236 WMMoveWidget(WPrefs
.saveBtn
, 335, 350);
237 WMSetButtonText(WPrefs
.saveBtn
, _("Save"));
238 WMSetButtonAction(WPrefs
.saveBtn
, save
, NULL
);
240 WPrefs
.closeBtn
= WMCreateCommandButton(WPrefs
.win
);
241 WMResizeWidget(WPrefs
.closeBtn
, 80, 28);
242 WMMoveWidget(WPrefs
.closeBtn
, 425, 350);
243 WMSetButtonText(WPrefs
.closeBtn
, _("Close"));
244 WMSetButtonAction(WPrefs
.closeBtn
, quit
, NULL
);
247 WPrefs
.banner
= WMCreateFrame(WPrefs
.win
);
248 WMResizeWidget(WPrefs
.banner
, FRAME_WIDTH
, FRAME_HEIGHT
);
249 WMMoveWidget(WPrefs
.banner
, FRAME_LEFT
, FRAME_TOP
);
250 WMSetFrameRelief(WPrefs
.banner
, WRFlat
);
252 font
= WMCreateFont(scr
, "-*-times-bold-r-*-*-24-*-*-*-*-*-*-*");
254 font
= WMBoldSystemFontOfSize(scr
, 24);
255 WPrefs
.nameL
= WMCreateLabel(WPrefs
.banner
);
256 WMSetLabelTextAlignment(WPrefs
.nameL
, WACenter
);
257 WMResizeWidget(WPrefs
.nameL
, FRAME_WIDTH
-20, 30);
258 WMMoveWidget(WPrefs
.nameL
, 10, 25);
259 WMSetLabelFont(WPrefs
.nameL
, font
);
260 WMSetLabelText(WPrefs
.nameL
, "Window Maker Preferences Utility");
263 WPrefs
.versionL
= WMCreateLabel(WPrefs
.banner
);
264 WMResizeWidget(WPrefs
.versionL
, FRAME_WIDTH
-20, 20);
265 WMMoveWidget(WPrefs
.versionL
, 10, 65);
266 WMSetLabelTextAlignment(WPrefs
.versionL
, WACenter
);
267 sprintf(buffer
, _("Version %s for Window Maker %s"), WVERSION
, WMVERSION
);
268 WMSetLabelText(WPrefs
.versionL
, buffer
);
270 WPrefs
.statusL
= WMCreateLabel(WPrefs
.banner
);
271 WMResizeWidget(WPrefs
.statusL
, FRAME_WIDTH
-20, 60);
272 WMMoveWidget(WPrefs
.statusL
, 10, 100);
273 WMSetLabelTextAlignment(WPrefs
.statusL
, WACenter
);
274 WMSetLabelText(WPrefs
.statusL
, _("Starting..."));
276 WPrefs
.creditsL
= WMCreateLabel(WPrefs
.banner
);
277 WMResizeWidget(WPrefs
.creditsL
, FRAME_WIDTH
-20, 60);
278 WMMoveWidget(WPrefs
.creditsL
, 10, FRAME_HEIGHT
-60);
279 WMSetLabelTextAlignment(WPrefs
.creditsL
, WACenter
);
280 WMSetLabelText(WPrefs
.creditsL
, _("Programming/Design: Alfredo K. Kojima\n"
281 "Artwork: Marco van Hylckama Vlieg\n"
282 "More Programming: James Thompson"));
285 WMMapSubwidgets(WPrefs
.win
);
287 WMUnmapWidget(WPrefs
.undosBtn
);
288 WMUnmapWidget(WPrefs
.undoBtn
);
289 WMUnmapWidget(WPrefs
.saveBtn
);
294 showPanel(Panel
*panel
)
296 PanelRec
*rec
= (PanelRec
*)panel
;
298 if (!(rec
->callbacks
.flags
& INITIALIZED_PANEL
)) {
299 (*rec
->callbacks
.createWidgets
)(panel
);
300 rec
->callbacks
.flags
|= INITIALIZED_PANEL
;
303 WMSetWindowTitle(WPrefs
.win
, rec
->sectionName
);
305 WMMapWidget(rec
->frame
);
311 hidePanel(Panel
*panel
)
313 PanelRec
*rec
= (PanelRec
*)panel
;
315 WMUnmapWidget(rec
->frame
);
320 savePanelData(Panel
*panel
)
322 PanelRec
*rec
= (PanelRec
*)panel
;
324 if (rec
->callbacks
.updateDomain
) {
325 (*rec
->callbacks
.updateDomain
)(panel
);
331 changeSection(WMWidget
*self
, void *data
)
334 WMDestroyWidget(WPrefs
.banner
);
335 WPrefs
.banner
= NULL
;
336 /* WMMapWidget(WPrefs.undosBtn);
337 WMMapWidget(WPrefs.undoBtn);
339 WMMapWidget(WPrefs
.saveBtn
);
344 if (WPrefs
.currentPanel
)
345 hidePanel(WPrefs
.currentPanel
);
346 WPrefs
.currentPanel
= data
;
354 LocateImage(char *name
)
357 char *tmp
= wmalloc(strlen(name
)+8);
360 sprintf(tmp
, "%s.tiff", name
);
361 path
= WMPathForResourceOfType(tmp
, "tiff");
363 sprintf(tmp
, "%s.xpm", name
);
364 path
= WMPathForResourceOfType(tmp
, "xpm");
368 wwarning(_("could not locate image file %s\n"), name
);
376 AddSection(Panel
*panel
, char *iconFile
)
383 assert(WPrefs
.sectionCount
< MAX_SECTIONS
);
385 iconPath
= LocateImage(iconFile
);
387 bPtr
= WMCreateCustomButton(WPrefs
.buttonF
, WBBStateLightMask
388 |WBBStateChangeMask
);
389 WMResizeWidget(bPtr
, 64, 64);
390 WMMoveWidget(bPtr
, WPrefs
.sectionCount
*64, 0);
391 WMSetButtonImagePosition(bPtr
, WIPImageOnly
);
392 WMSetButtonAction(bPtr
, changeSection
, panel
);
393 WMHangData(bPtr
, panel
);
400 icon
= WMCreateBlendedPixmapFromFile(WMWidgetScreen(WPrefs
.win
),
403 wwarning(_("could not load icon file %s"), iconPath
);
408 WMSetButtonImage(bPtr
, icon
);
411 WMReleasePixmap(icon
);
418 icon
= WMCreateBlendedPixmapFromFile(WMWidgetScreen(WPrefs
.win
),
421 wwarning(_("could not load icon file %s"), iconPath
);
426 WMSetButtonAltImage(bPtr
, icon
);
429 WMReleasePixmap(icon
);
433 WPrefs
.sectionB
[WPrefs
.sectionCount
] = bPtr
;
435 if (WPrefs
.sectionCount
> 0) {
436 WMGroupButtons(WPrefs
.sectionB
[0], bPtr
);
439 WPrefs
.sectionCount
++;
441 WMResizeWidget(WPrefs
.buttonF
, WPrefs
.sectionCount
*64, 64);
448 Initialize(WMScreen
*scr
)
456 list
= RSupportedFileFormats();
457 for (i
=0; list
[i
]!=NULL
; i
++) {
458 if (strcmp(list
[i
], "TIFF")==0) {
463 RFreeStringList(list
);
466 path
= WMPathForResourceOfType("WPrefs.tiff", NULL
);
468 path
= WMPathForResourceOfType("WPrefs.xpm", NULL
);
472 tmp
= RLoadImage(WMScreenRContext(scr
), path
, 0);
474 wwarning("could not load image file %s:%s", path
,
475 RMessageForError(RErrorCode
));
477 icon
= WMCreatePixmapFromRImage(scr
, tmp
, 0);
480 WMSetApplicationIconImage(scr
, icon
);
481 WMReleasePixmap(icon
);
487 memset(&WPrefs
, 0, sizeof(_WPrefs
));
488 createMainWindow(scr
);
490 WMRealizeWidget(WPrefs
.win
);
491 WMMapWidget(WPrefs
.win
);
492 XFlush(WMScreenDisplay(scr
));
493 WMSetLabelText(WPrefs
.statusL
, _("Loading Window Maker configuration files..."));
494 XFlush(WMScreenDisplay(scr
));
495 loadConfigurations(scr
, WPrefs
.win
);
497 WMSetLabelText(WPrefs
.statusL
, _("Initializing configuration panels..."));
499 InitWindowHandling(scr
, WPrefs
.win
);
500 InitFocus(scr
, WPrefs
.win
);
501 InitMenuPreferences(scr
, WPrefs
.win
);
502 InitIcons(scr
, WPrefs
.win
);
503 InitPreferences(scr
, WPrefs
.win
);
505 InitPaths(scr
, WPrefs
.win
);
506 InitWorkspace(scr
, WPrefs
.win
);
507 InitConfigurations(scr
, WPrefs
.win
);
508 InitMenu(scr
, WPrefs
.win
);
509 #ifdef not_yet_fully_implemented
510 InitKeyboardSettings(scr
, WPrefs
.win
);
512 InitKeyboardShortcuts(scr
, WPrefs
.win
);
513 InitMouseSettings(scr
, WPrefs
.win
);
515 #ifdef not_yet_fully_implemented
516 InitAppearance(scr
, WPrefs
.win
);
517 InitText(scr
, WPrefs
.win
);
518 InitThemes(scr
, WPrefs
.win
);
520 InitExpert(scr
, WPrefs
.win
);
522 WMRealizeWidget(WPrefs
.scrollV
);
524 WMSetLabelText(WPrefs
.statusL
,
525 "WPrefs is free software and is distributed WITHOUT ANY "
526 "WARRANTY under the terms of the GNU General Public License."
527 "Redistribution of the icons in this program separately from the program itself is prohibited.");
533 GetWindow(Panel
*panel
)
540 loadConfigurations(WMScreen
*scr
, WMWindow
*mainw
)
549 path
= wdefaultspathfordomain("WindowMaker");
551 db
= PLGetProplistWithPath(path
);
553 if (!PLIsDictionary(db
)) {
556 sprintf(mbuf
, _("Window Maker domain (%s) is corrupted!"), path
);
557 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
560 sprintf(mbuf
, _("Could not load Window Maker domain (%s) from defaults database."),
562 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
566 file
= popen("wmaker -version", "r");
567 if (!file
|| !fgets(buffer
, 1023, file
)) {
568 wsyserror(_("could not extract version information from Window Maker"));
569 wfatal(_("Make sure wmaker is in your search path."));
571 WMRunAlertPanel(scr
, mainw
, _("Error"),
572 _("Could not extract version from Window Maker. Make sure it is correctly installed and is in your PATH environment variable."),
573 _("OK"), NULL
, NULL
);
579 if (sscanf(buffer
, "Window Maker %i.%i.%i",&v1
,&v2
,&v3
)!=3
580 && sscanf(buffer
, "WindowMaker %i.%i.%i",&v1
,&v2
,&v3
)!=3) {
581 WMRunAlertPanel(scr
, mainw
, _("Error"),
582 _("Could not extract version from Window Maker. Make sure it is correctly installed."),
583 _("OK"), NULL
, NULL
);
586 if (v1
== 0 && (v2
< 18 || v3
< 0)) {
587 sprintf(mbuf
, _("WPrefs only supports Window Maker 0.18.0 or newer.\n"
588 "The version installed is %i.%i.%i\n"), v1
, v2
, v3
);
589 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
593 if (v1
> 1 || (v1
== 1 && (v2
> 0))) {
594 sprintf(mbuf
, _("Window Maker %i.%i.%i, which is installed in your system, is not fully supported by this version of WPrefs."),
596 WMRunAlertPanel(scr
, mainw
, _("Warning"), mbuf
, _("OK"), NULL
, NULL
);
599 file
= popen("wmaker -global_defaults_path", "r");
600 if (!file
|| !fgets(buffer
, 1023, file
)) {
601 wsyserror(_("could not run \"wmaker -global_defaults_path\"."));
607 gdb
= PLGetProplistWithPath(buffer
);
609 if (!PLIsDictionary(gdb
)) {
612 sprintf(mbuf
, _("Window Maker domain (%s) is corrupted!"), buffer
);
613 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
616 sprintf(mbuf
, _("Could not load global Window Maker domain (%s)."),
618 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
622 db
= PLMakeDictionaryFromEntries(NULL
, NULL
, NULL
);
625 gdb
= PLMakeDictionaryFromEntries(NULL
, NULL
, NULL
);
635 GetObjectForKey(char *defaultName
)
637 proplist_t object
= NULL
;
638 proplist_t key
= PLMakeString(defaultName
);
640 object
= PLGetDictionaryEntry(WindowMakerDB
, key
);
642 object
= PLGetDictionaryEntry(GlobalDB
, key
);
651 SetObjectForKey(proplist_t object
, char *defaultName
)
653 proplist_t key
= PLMakeString(defaultName
);
655 PLInsertDictionaryEntry(WindowMakerDB
, key
, object
);
661 RemoveObjectForKey(char *defaultName
)
663 proplist_t key
= PLMakeString(defaultName
);
665 PLRemoveDictionaryEntry(WindowMakerDB
, key
);
672 GetStringForKey(char *defaultName
)
676 val
= GetObjectForKey(defaultName
);
681 if (!PLIsString(val
))
684 return PLGetString(val
);
690 GetArrayForKey(char *defaultName
)
694 val
= GetObjectForKey(defaultName
);
707 GetDictionaryForKey(char *defaultName
)
711 val
= GetObjectForKey(defaultName
);
716 if (!PLIsDictionary(val
))
724 GetIntegerForKey(char *defaultName
)
730 val
= GetObjectForKey(defaultName
);
735 if (!PLIsString(val
))
738 str
= PLGetString(val
);
742 if (sscanf(str
, "%i", &value
)!=1)
750 GetBoolForKey(char *defaultName
)
755 str
= GetStringForKey(defaultName
);
760 if (sscanf(str
, "%i", &value
)==1 && value
!=0)
763 if (strcasecmp(str
, "YES")==0)
766 if (strcasecmp(str
, "Y")==0)
774 SetIntegerForKey(int value
, char *defaultName
)
779 sprintf(buffer
, "%i", value
);
780 object
= PLMakeString(buffer
);
782 SetObjectForKey(object
, defaultName
);
789 SetStringForKey(char *value
, char *defaultName
)
793 object
= PLMakeString(value
);
795 SetObjectForKey(object
, defaultName
);
801 SetBoolForKey(Bool value
, char *defaultName
)
803 static proplist_t yes
= NULL
, no
= NULL
;
806 yes
= PLMakeString("YES");
807 no
= PLMakeString("NO");
810 SetObjectForKey(value
? yes
: no
, defaultName
);
815 SetSpeedForKey(int speed
, char *defaultName
)
840 SetStringForKey(str
, defaultName
);
845 GetSpeedForKey(char *defaultName
)
850 str
= GetStringForKey(defaultName
);
851 if (strcasecmp(str
, "ultraslow")==0)
853 else if (strcasecmp(str
, "slow")==0)
855 else if (strcasecmp(str
, "medium")==0)
857 else if (strcasecmp(str
, "fast")==0)
859 else if (strcasecmp(str
, "ultrafast")==0)
862 wwarning(_("bad speed value for option %s\n. Using default Medium"),