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
);
521 #ifdef not_yet_fully_implemented
522 InitAppearance(scr
, WPrefs
.win
);
524 InitText(scr
, WPrefs
.win
);
525 InitThemes(scr
, WPrefs
.win
);
527 InitExpert(scr
, WPrefs
.win
);
529 WMRealizeWidget(WPrefs
.scrollV
);
531 WMSetLabelText(WPrefs
.statusL
,
532 _("WPrefs is free software and is distributed WITHOUT ANY\n"
533 "WARRANTY under the terms of the GNU General Public License.\n"
534 "The icons in this program are licensed through the\n"
535 "OpenContent License."));
540 GetWindow(Panel
*panel
)
547 loadConfigurations(WMScreen
*scr
, WMWindow
*mainw
)
556 path
= wdefaultspathfordomain("WindowMaker");
558 db
= PLGetProplistWithPath(path
);
560 if (!PLIsDictionary(db
)) {
563 sprintf(mbuf
, _("Window Maker domain (%s) is corrupted!"), path
);
564 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
567 sprintf(mbuf
, _("Could not load Window Maker domain (%s) from defaults database."),
569 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
573 file
= popen("wmaker --version", "r");
574 if (!file
|| !fgets(buffer
, 1023, file
)) {
575 wsyserror(_("could not extract version information from Window Maker"));
576 wfatal(_("Make sure wmaker is in your search path."));
578 WMRunAlertPanel(scr
, mainw
, _("Error"),
579 _("Could not extract version from Window Maker. Make sure it is correctly installed and is in your PATH environment variable."),
580 _("OK"), NULL
, NULL
);
586 if (sscanf(buffer
, "Window Maker %i.%i.%i",&v1
,&v2
,&v3
)!=3
587 && sscanf(buffer
, "WindowMaker %i.%i.%i",&v1
,&v2
,&v3
)!=3) {
588 WMRunAlertPanel(scr
, mainw
, _("Error"),
589 _("Could not extract version from Window Maker. "
590 "Make sure it is correctly installed and the path "
591 "where it installed is in the PATH environment "
592 "variable."), _("OK"), NULL
, NULL
);
595 if (v1
== 0 && (v2
< 18 || v3
< 0)) {
596 sprintf(mbuf
, _("WPrefs only supports Window Maker 0.18.0 or newer.\n"
597 "The version installed is %i.%i.%i\n"), v1
, v2
, v3
);
598 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
602 if (v1
> 1 || (v1
== 1 && (v2
> 0))) {
603 sprintf(mbuf
, _("Window Maker %i.%i.%i, which is installed in your system, is not fully supported by this version of WPrefs."),
605 WMRunAlertPanel(scr
, mainw
, _("Warning"), mbuf
, _("OK"), NULL
, NULL
);
608 file
= popen("wmaker --global_defaults_path", "r");
609 if (!file
|| !fgets(buffer
, 1023, file
)) {
610 wsyserror(_("could not run \"wmaker --global_defaults_path\"."));
614 ptr
= strchr(buffer
, '\n');
617 strcat(buffer
, "/WindowMaker");
623 gdb
= PLGetProplistWithPath(buffer
);
625 if (!PLIsDictionary(gdb
)) {
628 sprintf(mbuf
, _("Window Maker domain (%s) is corrupted!"), buffer
);
629 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
632 sprintf(mbuf
, _("Could not load global Window Maker domain (%s)."),
634 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
638 db
= PLMakeDictionaryFromEntries(NULL
, NULL
, NULL
);
641 gdb
= PLMakeDictionaryFromEntries(NULL
, NULL
, NULL
);
651 GetObjectForKey(char *defaultName
)
653 proplist_t object
= NULL
;
654 proplist_t key
= PLMakeString(defaultName
);
656 object
= PLGetDictionaryEntry(WindowMakerDB
, key
);
658 object
= PLGetDictionaryEntry(GlobalDB
, key
);
667 SetObjectForKey(proplist_t object
, char *defaultName
)
669 proplist_t key
= PLMakeString(defaultName
);
671 PLInsertDictionaryEntry(WindowMakerDB
, key
, object
);
677 RemoveObjectForKey(char *defaultName
)
679 proplist_t key
= PLMakeString(defaultName
);
681 PLRemoveDictionaryEntry(WindowMakerDB
, key
);
688 GetStringForKey(char *defaultName
)
692 val
= GetObjectForKey(defaultName
);
697 if (!PLIsString(val
))
700 return PLGetString(val
);
706 GetArrayForKey(char *defaultName
)
710 val
= GetObjectForKey(defaultName
);
723 GetDictionaryForKey(char *defaultName
)
727 val
= GetObjectForKey(defaultName
);
732 if (!PLIsDictionary(val
))
740 GetIntegerForKey(char *defaultName
)
746 val
= GetObjectForKey(defaultName
);
751 if (!PLIsString(val
))
754 str
= PLGetString(val
);
758 if (sscanf(str
, "%i", &value
)!=1)
766 GetBoolForKey(char *defaultName
)
771 str
= GetStringForKey(defaultName
);
776 if (sscanf(str
, "%i", &value
)==1 && value
!=0)
779 if (strcasecmp(str
, "YES")==0)
782 if (strcasecmp(str
, "Y")==0)
790 SetIntegerForKey(int value
, char *defaultName
)
795 sprintf(buffer
, "%i", value
);
796 object
= PLMakeString(buffer
);
798 SetObjectForKey(object
, defaultName
);
805 SetStringForKey(char *value
, char *defaultName
)
809 object
= PLMakeString(value
);
811 SetObjectForKey(object
, defaultName
);
817 SetBoolForKey(Bool value
, char *defaultName
)
819 static proplist_t yes
= NULL
, no
= NULL
;
822 yes
= PLMakeString("YES");
823 no
= PLMakeString("NO");
826 SetObjectForKey(value
? yes
: no
, defaultName
);
831 SetSpeedForKey(int speed
, char *defaultName
)
856 SetStringForKey(str
, defaultName
);
861 GetSpeedForKey(char *defaultName
)
866 str
= GetStringForKey(defaultName
);
870 if (strcasecmp(str
, "ultraslow")==0)
872 else if (strcasecmp(str
, "slow")==0)
874 else if (strcasecmp(str
, "medium")==0)
876 else if (strcasecmp(str
, "fast")==0)
878 else if (strcasecmp(str
, "ultrafast")==0)
881 wwarning(_("bad speed value for option %s\n. Using default Medium"),