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
);
111 quit(WMWidget
*w
, void *data
)
118 save(WMWidget
*w
, void *data
)
126 /* puts("gathering data");*/
127 for (i
=0; i
<WPrefs
.sectionCount
; i
++) {
128 PanelRec
*rec
= WMGetHangedData(WPrefs
.sectionB
[i
]);
129 if ((rec
->callbacks
.flags
& INITIALIZED_PANEL
))
130 savePanelData((Panel
*)rec
);
132 /* puts("compressing data");*/
133 /* compare the user dictionary with the global and remove redundant data */
134 keyList
= PLGetAllDictionaryKeys(GlobalDB
);
135 /* puts(PLGetDescription(WindowMakerDB));*/
136 for (i
=0; i
<PLGetNumberOfElements(keyList
); i
++) {
137 key
= PLGetArrayElement(keyList
, i
);
139 /* We don't have this value anyway, so no problem.
140 * Probably a new option */
141 p1
= PLGetDictionaryEntry(WindowMakerDB
, key
);
144 /* The global doesn't have it, so no problem either. */
145 p2
= PLGetDictionaryEntry(GlobalDB
, key
);
148 /* If both values are the same, don't save. */
149 if (PLIsEqual(p1
, p2
))
150 PLRemoveDictionaryEntry(WindowMakerDB
, key
);
152 /* puts(PLGetDescription(WindowMakerDB));*/
154 /* puts("storing data");*/
156 PLSave(WindowMakerDB
, YES
);
161 undo(WMWidget
*w
, void *data
)
163 PanelRec
*rec
= (PanelRec
*)WPrefs
.currentPanel
;
168 if (rec
->callbacks
.undoChanges
169 && (rec
->callbacks
.flags
& INITIALIZED_PANEL
)) {
170 (*rec
->callbacks
.undoChanges
)(WPrefs
.currentPanel
);
176 undoAll(WMWidget
*w
, void *data
)
180 for (i
=0; i
<WPrefs
.sectionCount
; i
++) {
181 PanelRec
*rec
= WMGetHangedData(WPrefs
.sectionB
[i
]);
183 if (rec
->callbacks
.undoChanges
184 && (rec
->callbacks
.flags
& INITIALIZED_PANEL
))
185 (*rec
->callbacks
.undoChanges
)((Panel
*)rec
);
191 createMainWindow(WMScreen
*scr
)
193 WMScroller
*scroller
;
197 WPrefs
.win
= WMCreateWindow(scr
, "wprefs");
198 WMResizeWidget(WPrefs
.win
, 520, 390);
199 WMSetWindowTitle(WPrefs
.win
, _("Window Maker Preferences"));
200 WMSetWindowCloseAction(WPrefs
.win
, quit
, NULL
);
201 WMSetWindowMaxSize(WPrefs
.win
, 520, 390);
202 WMSetWindowMinSize(WPrefs
.win
, 520, 390);
203 WMSetWindowMiniwindowTitle(WPrefs
.win
, "Preferences");
204 WMSetWindowMiniwindowImage(WPrefs
.win
, WMGetApplicationIconImage(scr
));
206 WPrefs
.scrollV
= WMCreateScrollView(WPrefs
.win
);
207 WMResizeWidget(WPrefs
.scrollV
, 500, 87);
208 WMMoveWidget(WPrefs
.scrollV
, 10, 10);
209 WMSetScrollViewRelief(WPrefs
.scrollV
, WRSunken
);
210 WMSetScrollViewHasHorizontalScroller(WPrefs
.scrollV
, True
);
211 WMSetScrollViewHasVerticalScroller(WPrefs
.scrollV
, False
);
212 scroller
= WMGetScrollViewHorizontalScroller(WPrefs
.scrollV
);
213 WMSetScrollerArrowsPosition(scroller
, WSANone
);
215 WPrefs
.buttonF
= WMCreateFrame(WPrefs
.win
);
216 WMSetFrameRelief(WPrefs
.buttonF
, WRFlat
);
218 WMSetScrollViewContentView(WPrefs
.scrollV
, WMWidgetView(WPrefs
.buttonF
));
220 WPrefs
.undosBtn
= WMCreateCommandButton(WPrefs
.win
);
221 WMResizeWidget(WPrefs
.undosBtn
, 90, 28);
222 WMMoveWidget(WPrefs
.undosBtn
, 135, 350);
223 WMSetButtonText(WPrefs
.undosBtn
, _("Revert Page"));
224 WMSetButtonAction(WPrefs
.undosBtn
, undo
, NULL
);
226 WPrefs
.undoBtn
= WMCreateCommandButton(WPrefs
.win
);
227 WMResizeWidget(WPrefs
.undoBtn
, 90, 28);
228 WMMoveWidget(WPrefs
.undoBtn
, 235, 350);
229 WMSetButtonText(WPrefs
.undoBtn
, _("Revert All"));
230 WMSetButtonAction(WPrefs
.undoBtn
, undoAll
, NULL
);
232 WPrefs
.saveBtn
= WMCreateCommandButton(WPrefs
.win
);
233 WMResizeWidget(WPrefs
.saveBtn
, 80, 28);
234 WMMoveWidget(WPrefs
.saveBtn
, 335, 350);
235 WMSetButtonText(WPrefs
.saveBtn
, _("Save"));
236 WMSetButtonAction(WPrefs
.saveBtn
, save
, NULL
);
238 WPrefs
.closeBtn
= WMCreateCommandButton(WPrefs
.win
);
239 WMResizeWidget(WPrefs
.closeBtn
, 80, 28);
240 WMMoveWidget(WPrefs
.closeBtn
, 425, 350);
241 WMSetButtonText(WPrefs
.closeBtn
, _("Close"));
242 WMSetButtonAction(WPrefs
.closeBtn
, quit
, NULL
);
245 WPrefs
.banner
= WMCreateFrame(WPrefs
.win
);
246 WMResizeWidget(WPrefs
.banner
, FRAME_WIDTH
, FRAME_HEIGHT
);
247 WMMoveWidget(WPrefs
.banner
, FRAME_LEFT
, FRAME_TOP
);
248 WMSetFrameRelief(WPrefs
.banner
, WRFlat
);
250 font
= WMCreateFont(scr
, "-*-times-bold-r-*-*-24-*-*-*-*-*-*-*");
252 font
= WMBoldSystemFontOfSize(scr
, 24);
253 WPrefs
.nameL
= WMCreateLabel(WPrefs
.banner
);
254 WMSetLabelTextAlignment(WPrefs
.nameL
, WACenter
);
255 WMResizeWidget(WPrefs
.nameL
, FRAME_WIDTH
-20, 30);
256 WMMoveWidget(WPrefs
.nameL
, 10, 25);
257 WMSetLabelFont(WPrefs
.nameL
, font
);
258 WMSetLabelText(WPrefs
.nameL
, _("Window Maker Preferences Utility"));
261 WPrefs
.versionL
= WMCreateLabel(WPrefs
.banner
);
262 WMResizeWidget(WPrefs
.versionL
, FRAME_WIDTH
-20, 20);
263 WMMoveWidget(WPrefs
.versionL
, 10, 65);
264 WMSetLabelTextAlignment(WPrefs
.versionL
, WACenter
);
265 sprintf(buffer
, _("Version %s for Window Maker %s"), WVERSION
, WMVERSION
);
266 WMSetLabelText(WPrefs
.versionL
, buffer
);
268 WPrefs
.statusL
= WMCreateLabel(WPrefs
.banner
);
269 WMResizeWidget(WPrefs
.statusL
, FRAME_WIDTH
-20, 60);
270 WMMoveWidget(WPrefs
.statusL
, 10, 100);
271 WMSetLabelTextAlignment(WPrefs
.statusL
, WACenter
);
272 WMSetLabelText(WPrefs
.statusL
, _("Starting..."));
274 WPrefs
.creditsL
= WMCreateLabel(WPrefs
.banner
);
275 WMResizeWidget(WPrefs
.creditsL
, FRAME_WIDTH
-20, 60);
276 WMMoveWidget(WPrefs
.creditsL
, 10, FRAME_HEIGHT
-60);
277 WMSetLabelTextAlignment(WPrefs
.creditsL
, WACenter
);
278 WMSetLabelText(WPrefs
.creditsL
, _("Programming/Design: Alfredo K. Kojima\n"
279 "Artwork: Marco van Hylckama Vlieg\n"
280 "More Programming: James Thompson"));
283 WMMapSubwidgets(WPrefs
.win
);
285 WMUnmapWidget(WPrefs
.undosBtn
);
286 WMUnmapWidget(WPrefs
.undoBtn
);
287 WMUnmapWidget(WPrefs
.saveBtn
);
292 showPanel(Panel
*panel
)
294 PanelRec
*rec
= (PanelRec
*)panel
;
296 if (!(rec
->callbacks
.flags
& INITIALIZED_PANEL
)) {
297 (*rec
->callbacks
.createWidgets
)(panel
);
298 rec
->callbacks
.flags
|= INITIALIZED_PANEL
;
301 WMSetWindowTitle(WPrefs
.win
, rec
->sectionName
);
303 WMMapWidget(rec
->frame
);
309 hidePanel(Panel
*panel
)
311 PanelRec
*rec
= (PanelRec
*)panel
;
313 WMUnmapWidget(rec
->frame
);
318 savePanelData(Panel
*panel
)
320 PanelRec
*rec
= (PanelRec
*)panel
;
322 if (rec
->callbacks
.updateDomain
) {
323 (*rec
->callbacks
.updateDomain
)(panel
);
329 changeSection(WMWidget
*self
, void *data
)
332 WMDestroyWidget(WPrefs
.banner
);
333 WPrefs
.banner
= NULL
;
334 /* WMMapWidget(WPrefs.undosBtn);
335 WMMapWidget(WPrefs.undoBtn);
337 WMMapWidget(WPrefs
.saveBtn
);
342 if (WPrefs
.currentPanel
)
343 hidePanel(WPrefs
.currentPanel
);
344 WPrefs
.currentPanel
= data
;
352 LocateImage(char *name
)
355 char *tmp
= wmalloc(strlen(name
)+8);
358 sprintf(tmp
, "%s.tiff", name
);
359 path
= WMPathForResourceOfType(tmp
, "tiff");
361 sprintf(tmp
, "%s.xpm", name
);
362 path
= WMPathForResourceOfType(tmp
, "xpm");
366 wwarning(_("could not locate image file %s\n"), name
);
374 SetButtonAlphaImage(WMScreen
*scr
, WMButton
*bPtr
, char *file
)
380 iconPath
= LocateImage(file
);
387 icon
= WMCreateBlendedPixmapFromFile(scr
, iconPath
, &color
);
389 wwarning(_("could not load icon file %s"), iconPath
);
394 WMSetButtonImage(bPtr
, icon
);
397 WMReleasePixmap(icon
);
404 icon
= WMCreateBlendedPixmapFromFile(scr
, iconPath
, &color
);
406 wwarning(_("could not load icon file %s"), iconPath
);
411 WMSetButtonAltImage(bPtr
, icon
);
414 WMReleasePixmap(icon
);
422 AddSection(Panel
*panel
, char *iconFile
)
426 assert(WPrefs
.sectionCount
< MAX_SECTIONS
);
429 bPtr
= WMCreateCustomButton(WPrefs
.buttonF
, WBBStateLightMask
430 |WBBStateChangeMask
);
431 WMResizeWidget(bPtr
, 64, 64);
432 WMMoveWidget(bPtr
, WPrefs
.sectionCount
*64, 0);
433 WMSetButtonImagePosition(bPtr
, WIPImageOnly
);
434 WMSetButtonAction(bPtr
, changeSection
, panel
);
435 WMHangData(bPtr
, panel
);
437 SetButtonAlphaImage(WMWidgetScreen(bPtr
), bPtr
, iconFile
);
441 WPrefs
.sectionB
[WPrefs
.sectionCount
] = bPtr
;
443 if (WPrefs
.sectionCount
> 0) {
444 WMGroupButtons(WPrefs
.sectionB
[0], bPtr
);
447 WPrefs
.sectionCount
++;
449 WMResizeWidget(WPrefs
.buttonF
, WPrefs
.sectionCount
*64, 64);
454 Initialize(WMScreen
*scr
)
462 list
= RSupportedFileFormats();
463 for (i
=0; list
[i
]!=NULL
; i
++) {
464 if (strcmp(list
[i
], "TIFF")==0) {
471 path
= WMPathForResourceOfType("WPrefs.tiff", NULL
);
473 path
= WMPathForResourceOfType("WPrefs.xpm", NULL
);
477 tmp
= RLoadImage(WMScreenRContext(scr
), path
, 0);
479 wwarning(_("could not load image file %s:%s"), path
,
480 RMessageForError(RErrorCode
));
482 icon
= WMCreatePixmapFromRImage(scr
, tmp
, 0);
485 WMSetApplicationIconImage(scr
, icon
);
486 WMReleasePixmap(icon
);
492 memset(&WPrefs
, 0, sizeof(_WPrefs
));
493 createMainWindow(scr
);
495 WMRealizeWidget(WPrefs
.win
);
496 WMMapWidget(WPrefs
.win
);
497 XFlush(WMScreenDisplay(scr
));
498 WMSetLabelText(WPrefs
.statusL
, _("Loading Window Maker configuration files..."));
499 XFlush(WMScreenDisplay(scr
));
500 loadConfigurations(scr
, WPrefs
.win
);
502 WMSetLabelText(WPrefs
.statusL
, _("Initializing configuration panels..."));
504 InitWindowHandling(scr
, WPrefs
.win
);
505 InitFocus(scr
, WPrefs
.win
);
506 InitMenuPreferences(scr
, WPrefs
.win
);
507 InitIcons(scr
, WPrefs
.win
);
508 InitPreferences(scr
, WPrefs
.win
);
510 InitPaths(scr
, WPrefs
.win
);
511 InitWorkspace(scr
, WPrefs
.win
);
512 InitConfigurations(scr
, WPrefs
.win
);
514 InitMenu(scr
, WPrefs
.win
);
516 #ifdef not_yet_fully_implemented
517 InitKeyboardSettings(scr
, WPrefs
.win
);
519 InitKeyboardShortcuts(scr
, WPrefs
.win
);
520 InitMouseSettings(scr
, WPrefs
.win
);
522 InitAppearance(scr
, WPrefs
.win
);
523 #ifdef not_yet_fully_implemented
525 InitText(scr
, WPrefs
.win
);
526 InitThemes(scr
, WPrefs
.win
);
528 InitExpert(scr
, WPrefs
.win
);
530 WMRealizeWidget(WPrefs
.scrollV
);
532 WMSetLabelText(WPrefs
.statusL
,
533 _("WPrefs is free software and is distributed WITHOUT ANY\n"
534 "WARRANTY under the terms of the GNU General Public License.\n"
535 "The icons in this program are licensed through the\n"
536 "OpenContent License."));
541 GetWindow(Panel
*panel
)
548 loadConfigurations(WMScreen
*scr
, WMWindow
*mainw
)
557 path
= wdefaultspathfordomain("WindowMaker");
559 db
= PLGetProplistWithPath(path
);
561 if (!PLIsDictionary(db
)) {
564 sprintf(mbuf
, _("Window Maker domain (%s) is corrupted!"), path
);
565 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
568 sprintf(mbuf
, _("Could not load Window Maker domain (%s) from defaults database."),
570 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
574 file
= popen("wmaker --version", "r");
575 if (!file
|| !fgets(buffer
, 1023, file
)) {
576 wsyserror(_("could not extract version information from Window Maker"));
577 wfatal(_("Make sure wmaker is in your search path."));
579 WMRunAlertPanel(scr
, mainw
, _("Error"),
580 _("Could not extract version from Window Maker. Make sure it is correctly installed and is in your PATH environment variable."),
581 _("OK"), NULL
, NULL
);
587 if (sscanf(buffer
, "Window Maker %i.%i.%i",&v1
,&v2
,&v3
)!=3
588 && sscanf(buffer
, "WindowMaker %i.%i.%i",&v1
,&v2
,&v3
)!=3) {
589 WMRunAlertPanel(scr
, mainw
, _("Error"),
590 _("Could not extract version from Window Maker. "
591 "Make sure it is correctly installed and the path "
592 "where it installed is in the PATH environment "
593 "variable."), _("OK"), NULL
, NULL
);
596 if (v1
== 0 && (v2
< 18 || v3
< 0)) {
597 sprintf(mbuf
, _("WPrefs only supports Window Maker 0.18.0 or newer.\n"
598 "The version installed is %i.%i.%i\n"), v1
, v2
, v3
);
599 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
603 if (v1
> 1 || (v1
== 1 && (v2
> 0))) {
604 sprintf(mbuf
, _("Window Maker %i.%i.%i, which is installed in your system, is not fully supported by this version of WPrefs."),
606 WMRunAlertPanel(scr
, mainw
, _("Warning"), mbuf
, _("OK"), NULL
, NULL
);
609 file
= popen("wmaker --global_defaults_path", "r");
610 if (!file
|| !fgets(buffer
, 1023, file
)) {
611 wsyserror(_("could not run \"wmaker --global_defaults_path\"."));
615 ptr
= strchr(buffer
, '\n');
618 strcat(buffer
, "/WindowMaker");
624 gdb
= PLGetProplistWithPath(buffer
);
626 if (!PLIsDictionary(gdb
)) {
629 sprintf(mbuf
, _("Window Maker domain (%s) is corrupted!"), buffer
);
630 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
633 sprintf(mbuf
, _("Could not load global Window Maker domain (%s)."),
635 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
639 db
= PLMakeDictionaryFromEntries(NULL
, NULL
, NULL
);
642 gdb
= PLMakeDictionaryFromEntries(NULL
, NULL
, NULL
);
652 GetObjectForKey(char *defaultName
)
654 proplist_t object
= NULL
;
655 proplist_t key
= PLMakeString(defaultName
);
657 object
= PLGetDictionaryEntry(WindowMakerDB
, key
);
659 object
= PLGetDictionaryEntry(GlobalDB
, key
);
668 SetObjectForKey(proplist_t object
, char *defaultName
)
670 proplist_t key
= PLMakeString(defaultName
);
672 PLInsertDictionaryEntry(WindowMakerDB
, key
, object
);
678 RemoveObjectForKey(char *defaultName
)
680 proplist_t key
= PLMakeString(defaultName
);
682 PLRemoveDictionaryEntry(WindowMakerDB
, key
);
689 GetStringForKey(char *defaultName
)
693 val
= GetObjectForKey(defaultName
);
698 if (!PLIsString(val
))
701 return PLGetString(val
);
707 GetArrayForKey(char *defaultName
)
711 val
= GetObjectForKey(defaultName
);
724 GetDictionaryForKey(char *defaultName
)
728 val
= GetObjectForKey(defaultName
);
733 if (!PLIsDictionary(val
))
741 GetIntegerForKey(char *defaultName
)
747 val
= GetObjectForKey(defaultName
);
752 if (!PLIsString(val
))
755 str
= PLGetString(val
);
759 if (sscanf(str
, "%i", &value
)!=1)
767 GetBoolForKey(char *defaultName
)
772 str
= GetStringForKey(defaultName
);
777 if (sscanf(str
, "%i", &value
)==1 && value
!=0)
780 if (strcasecmp(str
, "YES")==0)
783 if (strcasecmp(str
, "Y")==0)
791 SetIntegerForKey(int value
, char *defaultName
)
796 sprintf(buffer
, "%i", value
);
797 object
= PLMakeString(buffer
);
799 SetObjectForKey(object
, defaultName
);
806 SetStringForKey(char *value
, char *defaultName
)
810 object
= PLMakeString(value
);
812 SetObjectForKey(object
, defaultName
);
818 SetBoolForKey(Bool value
, char *defaultName
)
820 static proplist_t yes
= NULL
, no
= NULL
;
823 yes
= PLMakeString("YES");
824 no
= PLMakeString("NO");
827 SetObjectForKey(value
? yes
: no
, defaultName
);
832 SetSpeedForKey(int speed
, char *defaultName
)
857 SetStringForKey(str
, defaultName
);
862 GetSpeedForKey(char *defaultName
)
867 str
= GetStringForKey(defaultName
);
871 if (strcasecmp(str
, "ultraslow")==0)
873 else if (strcasecmp(str
, "slow")==0)
875 else if (strcasecmp(str
, "medium")==0)
877 else if (strcasecmp(str
, "fast")==0)
879 else if (strcasecmp(str
, "ultrafast")==0)
882 wwarning(_("bad speed value for option %s\n. Using default Medium"),