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) {
465 path
= WMPathForResourceOfType("WPrefs.tiff", NULL
);
467 path
= WMPathForResourceOfType("WPrefs.xpm", NULL
);
471 tmp
= RLoadImage(WMScreenRContext(scr
), path
, 0);
473 wwarning(_("could not load image file %s:%s"), path
,
474 RMessageForError(RErrorCode
));
476 icon
= WMCreatePixmapFromRImage(scr
, tmp
, 0);
479 WMSetApplicationIconImage(scr
, icon
);
480 WMReleasePixmap(icon
);
486 memset(&WPrefs
, 0, sizeof(_WPrefs
));
487 createMainWindow(scr
);
489 WMRealizeWidget(WPrefs
.win
);
490 WMMapWidget(WPrefs
.win
);
491 XFlush(WMScreenDisplay(scr
));
492 WMSetLabelText(WPrefs
.statusL
, _("Loading Window Maker configuration files..."));
493 XFlush(WMScreenDisplay(scr
));
494 loadConfigurations(scr
, WPrefs
.win
);
496 WMSetLabelText(WPrefs
.statusL
, _("Initializing configuration panels..."));
498 InitWindowHandling(scr
, WPrefs
.win
);
499 InitFocus(scr
, WPrefs
.win
);
500 InitMenuPreferences(scr
, WPrefs
.win
);
501 InitIcons(scr
, WPrefs
.win
);
502 InitPreferences(scr
, WPrefs
.win
);
504 InitPaths(scr
, WPrefs
.win
);
505 InitWorkspace(scr
, WPrefs
.win
);
506 InitConfigurations(scr
, WPrefs
.win
);
508 InitMenu(scr
, WPrefs
.win
);
510 #ifdef not_yet_fully_implemented
511 InitKeyboardSettings(scr
, WPrefs
.win
);
513 InitKeyboardShortcuts(scr
, WPrefs
.win
);
514 InitMouseSettings(scr
, WPrefs
.win
);
516 #ifdef not_yet_fully_implemented
517 InitAppearance(scr
, WPrefs
.win
);
518 InitText(scr
, WPrefs
.win
);
519 InitThemes(scr
, WPrefs
.win
);
521 InitExpert(scr
, WPrefs
.win
);
523 WMRealizeWidget(WPrefs
.scrollV
);
525 WMSetLabelText(WPrefs
.statusL
,
526 _("WPrefs is free software and is distributed WITHOUT ANY\n"
527 "WARRANTY under the terms of the GNU General Public License.\n"
528 "The icons in this program are licensed through the\n"
529 "OpenContent License."));
534 GetWindow(Panel
*panel
)
541 loadConfigurations(WMScreen
*scr
, WMWindow
*mainw
)
550 path
= wdefaultspathfordomain("WindowMaker");
552 db
= PLGetProplistWithPath(path
);
554 if (!PLIsDictionary(db
)) {
557 sprintf(mbuf
, _("Window Maker domain (%s) is corrupted!"), path
);
558 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
561 sprintf(mbuf
, _("Could not load Window Maker domain (%s) from defaults database."),
563 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
567 file
= popen("wmaker --version", "r");
568 if (!file
|| !fgets(buffer
, 1023, file
)) {
569 wsyserror(_("could not extract version information from Window Maker"));
570 wfatal(_("Make sure wmaker is in your search path."));
572 WMRunAlertPanel(scr
, mainw
, _("Error"),
573 _("Could not extract version from Window Maker. Make sure it is correctly installed and is in your PATH environment variable."),
574 _("OK"), NULL
, NULL
);
580 if (sscanf(buffer
, "Window Maker %i.%i.%i",&v1
,&v2
,&v3
)!=3
581 && sscanf(buffer
, "WindowMaker %i.%i.%i",&v1
,&v2
,&v3
)!=3) {
582 WMRunAlertPanel(scr
, mainw
, _("Error"),
583 _("Could not extract version from Window Maker. "
584 "Make sure it is correctly installed and the path "
585 "where it installed is in the PATH environment "
586 "variable."), _("OK"), NULL
, NULL
);
589 if (v1
== 0 && (v2
< 18 || v3
< 0)) {
590 sprintf(mbuf
, _("WPrefs only supports Window Maker 0.18.0 or newer.\n"
591 "The version installed is %i.%i.%i\n"), v1
, v2
, v3
);
592 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
596 if (v1
> 1 || (v1
== 1 && (v2
> 0))) {
597 sprintf(mbuf
, _("Window Maker %i.%i.%i, which is installed in your system, is not fully supported by this version of WPrefs."),
599 WMRunAlertPanel(scr
, mainw
, _("Warning"), mbuf
, _("OK"), NULL
, NULL
);
602 file
= popen("wmaker --global_defaults_path", "r");
603 if (!file
|| !fgets(buffer
, 1023, file
)) {
604 wsyserror(_("could not run \"wmaker --global_defaults_path\"."));
608 ptr
= strchr(buffer
, '\n');
611 strcat(buffer
, "/WindowMaker");
617 gdb
= PLGetProplistWithPath(buffer
);
619 if (!PLIsDictionary(gdb
)) {
622 sprintf(mbuf
, _("Window Maker domain (%s) is corrupted!"), buffer
);
623 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
626 sprintf(mbuf
, _("Could not load global Window Maker domain (%s)."),
628 WMRunAlertPanel(scr
, mainw
, _("Error"), mbuf
, _("OK"), NULL
, NULL
);
632 db
= PLMakeDictionaryFromEntries(NULL
, NULL
, NULL
);
635 gdb
= PLMakeDictionaryFromEntries(NULL
, NULL
, NULL
);
645 GetObjectForKey(char *defaultName
)
647 proplist_t object
= NULL
;
648 proplist_t key
= PLMakeString(defaultName
);
650 object
= PLGetDictionaryEntry(WindowMakerDB
, key
);
652 object
= PLGetDictionaryEntry(GlobalDB
, key
);
661 SetObjectForKey(proplist_t object
, char *defaultName
)
663 proplist_t key
= PLMakeString(defaultName
);
665 PLInsertDictionaryEntry(WindowMakerDB
, key
, object
);
671 RemoveObjectForKey(char *defaultName
)
673 proplist_t key
= PLMakeString(defaultName
);
675 PLRemoveDictionaryEntry(WindowMakerDB
, key
);
682 GetStringForKey(char *defaultName
)
686 val
= GetObjectForKey(defaultName
);
691 if (!PLIsString(val
))
694 return PLGetString(val
);
700 GetArrayForKey(char *defaultName
)
704 val
= GetObjectForKey(defaultName
);
717 GetDictionaryForKey(char *defaultName
)
721 val
= GetObjectForKey(defaultName
);
726 if (!PLIsDictionary(val
))
734 GetIntegerForKey(char *defaultName
)
740 val
= GetObjectForKey(defaultName
);
745 if (!PLIsString(val
))
748 str
= PLGetString(val
);
752 if (sscanf(str
, "%i", &value
)!=1)
760 GetBoolForKey(char *defaultName
)
765 str
= GetStringForKey(defaultName
);
770 if (sscanf(str
, "%i", &value
)==1 && value
!=0)
773 if (strcasecmp(str
, "YES")==0)
776 if (strcasecmp(str
, "Y")==0)
784 SetIntegerForKey(int value
, char *defaultName
)
789 sprintf(buffer
, "%i", value
);
790 object
= PLMakeString(buffer
);
792 SetObjectForKey(object
, defaultName
);
799 SetStringForKey(char *value
, char *defaultName
)
803 object
= PLMakeString(value
);
805 SetObjectForKey(object
, defaultName
);
811 SetBoolForKey(Bool value
, char *defaultName
)
813 static proplist_t yes
= NULL
, no
= NULL
;
816 yes
= PLMakeString("YES");
817 no
= PLMakeString("NO");
820 SetObjectForKey(value
? yes
: no
, defaultName
);
825 SetSpeedForKey(int speed
, char *defaultName
)
850 SetStringForKey(str
, defaultName
);
855 GetSpeedForKey(char *defaultName
)
860 str
= GetStringForKey(defaultName
);
864 if (strcasecmp(str
, "ultraslow")==0)
866 else if (strcasecmp(str
, "slow")==0)
868 else if (strcasecmp(str
, "medium")==0)
870 else if (strcasecmp(str
, "fast")==0)
872 else if (strcasecmp(str
, "ultrafast")==0)
875 wwarning(_("bad speed value for option %s\n. Using default Medium"),