1 /* WPrefs.c- main window and other basic stuff
3 * WPrefs - WindowMaker 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
, _("WindowMaker 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
, "WindowMaker 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 WindowMaker %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, 40);
273 WMMoveWidget(WPrefs
.creditsL
, 10, FRAME_HEIGHT
-40);
274 WMSetLabelTextAlignment(WPrefs
.creditsL
, WACenter
);
275 WMSetLabelText(WPrefs
.creditsL
, _("Programming/Design: Alfredo K. Kojima\n"
276 "Artwork: Marco van Hylckama Vlieg"));
279 WMMapSubwidgets(WPrefs
.win
);
281 WMUnmapWidget(WPrefs
.undosBtn
);
282 WMUnmapWidget(WPrefs
.undoBtn
);
283 WMUnmapWidget(WPrefs
.saveBtn
);
288 showPanel(Panel
*panel
)
290 PanelRec
*rec
= (PanelRec
*)panel
;
292 if (!(rec
->callbacks
.flags
& INITIALIZED_PANEL
)) {
293 (*rec
->callbacks
.createWidgets
)(panel
);
294 rec
->callbacks
.flags
|= INITIALIZED_PANEL
;
297 WMSetWindowTitle(WPrefs
.win
, rec
->sectionName
);
299 WMMapWidget(rec
->frame
);
305 hidePanel(Panel
*panel
)
307 PanelRec
*rec
= (PanelRec
*)panel
;
309 WMUnmapWidget(rec
->frame
);
314 savePanelData(Panel
*panel
)
316 PanelRec
*rec
= (PanelRec
*)panel
;
318 if (rec
->callbacks
.updateDomain
) {
319 (*rec
->callbacks
.updateDomain
)(panel
);
325 changeSection(WMWidget
*self
, void *data
)
328 WMDestroyWidget(WPrefs
.banner
);
329 WPrefs
.banner
= NULL
;
330 /* WMMapWidget(WPrefs.undosBtn);
331 WMMapWidget(WPrefs.undoBtn);
333 WMMapWidget(WPrefs
.saveBtn
);
338 if (WPrefs
.currentPanel
)
339 hidePanel(WPrefs
.currentPanel
);
340 WPrefs
.currentPanel
= data
;
348 LocateImage(char *name
)
351 char *tmp
= wmalloc(strlen(name
)+8);
354 sprintf(tmp
, "%s.tiff", name
);
355 path
= WMPathForResourceOfType(tmp
, "tiff");
357 sprintf(tmp
, "%s.xpm", name
);
358 path
= WMPathForResourceOfType(tmp
, "xpm");
362 wwarning(_("could not locate image file %s\n"), name
);
370 AddSection(Panel
*panel
, char *iconFile
)
377 assert(WPrefs
.sectionCount
< MAX_SECTIONS
);
379 iconPath
= LocateImage(iconFile
);
381 bPtr
= WMCreateCustomButton(WPrefs
.buttonF
, WBBStateLightMask
382 |WBBStateChangeMask
);
383 WMResizeWidget(bPtr
, 64, 64);
384 WMMoveWidget(bPtr
, WPrefs
.sectionCount
*64, 0);
385 WMSetButtonImagePosition(bPtr
, WIPImageOnly
);
386 WMSetButtonAction(bPtr
, changeSection
, panel
);
387 WMHangData(bPtr
, panel
);
394 icon
= WMCreateBlendedPixmapFromFile(WMWidgetScreen(WPrefs
.win
),
397 wwarning(_("could not load icon file %s"), iconPath
);
402 WMSetButtonImage(bPtr
, icon
);
405 WMReleasePixmap(icon
);
412 icon
= WMCreateBlendedPixmapFromFile(WMWidgetScreen(WPrefs
.win
),
415 wwarning(_("could not load icon file %s"), iconPath
);
420 WMSetButtonAltImage(bPtr
, icon
);
423 WMReleasePixmap(icon
);
427 WPrefs
.sectionB
[WPrefs
.sectionCount
] = bPtr
;
429 if (WPrefs
.sectionCount
> 0) {
430 WMGroupButtons(WPrefs
.sectionB
[0], bPtr
);
433 WPrefs
.sectionCount
++;
435 WMResizeWidget(WPrefs
.buttonF
, WPrefs
.sectionCount
*64, 64);
442 Initialize(WMScreen
*scr
)
450 list
= RSupportedFileFormats();
451 for (i
=0; list
[i
]!=NULL
; i
++) {
452 if (strcmp(list
[i
], "TIFF")==0) {
457 RFreeStringList(list
);
460 path
= WMPathForResourceOfType("WPrefs.tiff", NULL
);
462 path
= WMPathForResourceOfType("WPrefs.xpm", NULL
);
466 tmp
= RLoadImage(WMScreenRContext(scr
), path
, 0);
468 wwarning("could not load image file %s:%s", path
, RErrorString
);
470 icon
= WMCreatePixmapFromRImage(scr
, tmp
, 0);
473 WMSetApplicationIconImage(scr
, icon
);
474 WMReleasePixmap(icon
);
480 memset(&WPrefs
, 0, sizeof(_WPrefs
));
481 createMainWindow(scr
);
483 WMRealizeWidget(WPrefs
.win
);
484 WMMapWidget(WPrefs
.win
);
485 XFlush(WMScreenDisplay(scr
));
486 WMSetLabelText(WPrefs
.statusL
, _("Loading WindowMaker configuration files..."));
487 XFlush(WMScreenDisplay(scr
));
488 loadConfigurations(scr
, WPrefs
.win
);
490 WMSetLabelText(WPrefs
.statusL
, _("Initializing configuration panels..."));
492 InitWindowHandling(scr
, WPrefs
.win
);
493 InitFocus(scr
, WPrefs
.win
);
494 InitMenuPreferences(scr
, WPrefs
.win
);
495 InitIcons(scr
, WPrefs
.win
);
496 InitPreferences(scr
, WPrefs
.win
);
498 InitPaths(scr
, WPrefs
.win
);
499 InitWorkspace(scr
, WPrefs
.win
);
500 InitConfigurations(scr
, WPrefs
.win
);
501 InitMenu(scr
, WPrefs
.win
);
502 #ifdef not_yet_fully_implemented
503 InitKeyboardSettings(scr
, WPrefs
.win
);
505 InitKeyboardShortcuts(scr
, WPrefs
.win
);
506 InitMouseSettings(scr
, WPrefs
.win
);
507 #ifdef not_yet_fully_implemented
508 InitTextureAndColor(scr
, WPrefs
.win
);
509 InitText(scr
, WPrefs
.win
);
511 InitExpert(scr
, WPrefs
.win
);
513 WMRealizeWidget(WPrefs
.scrollV
);
515 WMSetLabelText(WPrefs
.statusL
, "This program is still under development. Backup your ~/GNUstep/Defaults directory, before using it.");
520 GetWindow(Panel
*panel
)
527 loadConfigurations(WMScreen
*scr
, WMWindow
*mainw
)
536 path
= wdefaultspathfordomain("WindowMaker");
538 db
= PLGetProplistWithPath(path
);
540 if (!PLIsDictionary(db
)) {
543 sprintf(mbuf
, _("WindowMaker domain (%s) is corrupted!"), path
);
544 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
547 sprintf(mbuf
, _("Could not load WindowMaker domain (%s) from defaults database."),
549 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
553 file
= popen("wmaker -version", "r");
554 if (!file
|| !fgets(buffer
, 1023, file
)) {
555 wsyserror(_("could not extract version information from WindowMaker"));
556 wfatal(_("Make sure WindowMaker is in your search path."));
558 WMRunAlertPanel(scr
, mainw
, _("Error"),
559 _("Could not extract version from WindowMaker. Make sure it is correctly installed."),
560 _("OK"), NULL
, NULL
);
566 if (sscanf(buffer
, "WindowMaker %i.%i.%i",&v1
,&v2
,&v3
)!=3) {
567 WMRunAlertPanel(scr
, mainw
, _("Error"),
568 _("Could not extract version from WindowMaker. Make sure it is correctly installed."),
569 _("OK"), NULL
, NULL
);
572 if (v1
== 0 && (v2
< 18 || v3
< 0)) {
573 sprintf(mbuf
, _("WPrefs only supports WindowMaker 0.18.0 or newer.\n"
574 "The version installed is %i.%i.%i\n"), v1
, v2
, v3
);
575 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
579 if (v1
> 1 || (v1
== 1 && (v2
> 0))) {
580 sprintf(mbuf
, _("WindowMaker %i.%i.%i, which is installed in your system, is not fully supported by this version of WPrefs."),
582 WMRunAlertPanel(scr
, mainw
, _("Warning"), mbuf
, _("OK"), NULL
, NULL
);
585 file
= popen("wmaker -global_defaults_path", "r");
586 if (!file
|| !fgets(buffer
, 1023, file
)) {
587 wsyserror(_("could not run \"wmaker -global_defaults_path\"."));
593 gdb
= PLGetProplistWithPath(buffer
);
595 if (!PLIsDictionary(gdb
)) {
598 sprintf(mbuf
, _("WindowMaker domain (%s) is corrupted!"), buffer
);
599 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
602 sprintf(mbuf
, _("Could not load global WindowMaker domain (%s)."),
604 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
608 db
= PLMakeDictionaryFromEntries(NULL
, NULL
, NULL
);
611 gdb
= PLMakeDictionaryFromEntries(NULL
, NULL
, NULL
);
621 GetObjectForKey(char *defaultName
)
623 proplist_t object
= NULL
;
624 proplist_t key
= PLMakeString(defaultName
);
626 object
= PLGetDictionaryEntry(WindowMakerDB
, key
);
628 object
= PLGetDictionaryEntry(GlobalDB
, key
);
637 SetObjectForKey(proplist_t object
, char *defaultName
)
639 proplist_t key
= PLMakeString(defaultName
);
641 PLInsertDictionaryEntry(WindowMakerDB
, key
, object
);
647 RemoveObjectForKey(char *defaultName
)
649 proplist_t key
= PLMakeString(defaultName
);
651 PLRemoveDictionaryEntry(WindowMakerDB
, key
);
658 GetStringForKey(char *defaultName
)
662 val
= GetObjectForKey(defaultName
);
667 if (!PLIsString(val
))
670 return PLGetString(val
);
676 GetArrayForKey(char *defaultName
)
680 val
= GetObjectForKey(defaultName
);
693 GetDictionaryForKey(char *defaultName
)
697 val
= GetObjectForKey(defaultName
);
702 if (!PLIsDictionary(val
))
710 GetIntegerForKey(char *defaultName
)
716 val
= GetObjectForKey(defaultName
);
721 if (!PLIsString(val
))
724 str
= PLGetString(val
);
728 if (sscanf(str
, "%i", &value
)!=1)
736 GetBoolForKey(char *defaultName
)
741 str
= GetStringForKey(defaultName
);
746 if (sscanf(str
, "%i", &value
)==1 && value
!=0)
749 if (strcasecmp(str
, "YES")==0)
752 if (strcasecmp(str
, "Y")==0)
760 SetIntegerForKey(int value
, char *defaultName
)
765 sprintf(buffer
, "%i", value
);
766 object
= PLMakeString(buffer
);
768 SetObjectForKey(object
, defaultName
);
775 SetStringForKey(char *value
, char *defaultName
)
779 object
= PLMakeString(value
);
781 SetObjectForKey(object
, defaultName
);
787 SetBoolForKey(Bool value
, char *defaultName
)
789 static proplist_t yes
= NULL
, no
= NULL
;
792 yes
= PLMakeString("YES");
793 no
= PLMakeString("NO");
796 SetObjectForKey(value
? yes
: no
, defaultName
);
801 SetSpeedForKey(int speed
, char *defaultName
)
826 SetStringForKey(str
, defaultName
);
831 GetSpeedForKey(char *defaultName
)
836 str
= GetStringForKey(defaultName
);
837 if (strcasecmp(str
, "ultraslow")==0)
839 else if (strcasecmp(str
, "slow")==0)
841 else if (strcasecmp(str
, "medium")==0)
843 else if (strcasecmp(str
, "fast")==0)
845 else if (strcasecmp(str
, "ultrafast")==0)
848 wwarning(_("bad speed value for option %s\n. Using default Medium"),