/* WPrefs.c- main window and other basic stuff * * WPrefs - Window Maker Preferences Program * * Copyright (c) 1998-2003 Alfredo K. Kojima * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include "WPrefs.h" #include #ifdef HAVE_STDNORETURN #include #endif #define ICON_TITLE_FONT "sans serif:pixelsize=9" #define ICON_TITLE_VFONT "sans serif:pixelsize=9:weight=100" #define MAX_SECTIONS 16 typedef struct _WPrefs { WMWindow *win; WMScrollView *scrollV; WMFrame *buttonF; WMButton *sectionB[MAX_SECTIONS]; int sectionCount; WMButton *saveBtn; WMButton *closeBtn; WMButton *undoBtn; WMButton *undosBtn; WMButton *balloonBtn; WMFrame *banner; WMLabel *nameL; WMLabel *versionL; WMLabel *statusL; Panel *currentPanel; } _WPrefs; static _WPrefs WPrefs; /* system wide defaults dictionary. Read-only */ static WMPropList *GlobalDB = NULL; /* user defaults dictionary */ static WMPropList *WindowMakerDB = NULL; static char *WindowMakerDBPath = NULL; static Bool TIFFOK = False; #define INITIALIZED_PANEL (1<<0) static void loadConfigurations(WMScreen * scr, WMWindow * mainw); static void savePanelData(Panel * panel); static void prepareForClose(void); static noreturn void quit(WMWidget *w, void *data) { /* Parameter not used, but tell the compiler that it is ok */ (void) w; (void) data; prepareForClose(); WMReleaseApplication(); exit(0); } static void save(WMWidget * w, void *data) { int i; WMPropList *p1, *p2; WMPropList *keyList; WMPropList *key; XEvent ev; /* Parameter not used, but tell the compiler that it is ok */ (void) data; /* puts("gathering data"); */ for (i = 0; i < WPrefs.sectionCount; i++) { PanelRec *rec = WMGetHangedData(WPrefs.sectionB[i]); if ((rec->callbacks.flags & INITIALIZED_PANEL)) savePanelData((Panel *) rec); } /* puts("compressing data"); */ /* compare the user dictionary with the global and remove redundant data */ keyList = WMGetPLDictionaryKeys(GlobalDB); /* puts(WMGetPropListDescription(WindowMakerDB, False)); */ for (i = 0; i < WMGetPropListItemCount(keyList); i++) { key = WMGetFromPLArray(keyList, i); /* We don't have this value anyway, so no problem. * Probably a new option */ p1 = WMGetFromPLDictionary(WindowMakerDB, key); if (!p1) continue; /* The global doesn't have it, so no problem either. */ p2 = WMGetFromPLDictionary(GlobalDB, key); if (!p2) continue; /* If both values are the same, don't save. */ if (WMIsPropListEqualTo(p1, p2)) WMRemoveFromPLDictionary(WindowMakerDB, key); } /* puts(WMGetPropListDescription(WindowMakerDB, False)); */ WMReleasePropList(keyList); /* puts("storing data"); */ WMWritePropListToFile(WindowMakerDB, WindowMakerDBPath); memset(&ev, 0, sizeof(XEvent)); ev.xclient.type = ClientMessage; ev.xclient.message_type = XInternAtom(WMScreenDisplay(WMWidgetScreen(w)), "_WINDOWMAKER_COMMAND", False); ev.xclient.window = DefaultRootWindow(WMScreenDisplay(WMWidgetScreen(w))); ev.xclient.format = 8; strncpy(ev.xclient.data.b, "Reconfigure", sizeof(ev.xclient.data.b)); XSendEvent(WMScreenDisplay(WMWidgetScreen(w)), DefaultRootWindow(WMScreenDisplay(WMWidgetScreen(w))), False, SubstructureRedirectMask, &ev); XFlush(WMScreenDisplay(WMWidgetScreen(w))); } static void undo(WMWidget * w, void *data) { PanelRec *rec = (PanelRec *) WPrefs.currentPanel; /* Parameter not used, but tell the compiler that it is ok */ (void) w; (void) data; if (!rec) return; if (rec->callbacks.undoChanges && (rec->callbacks.flags & INITIALIZED_PANEL)) { (*rec->callbacks.undoChanges) (WPrefs.currentPanel); } } static void undoAll(WMWidget * w, void *data) { int i; /* Parameter not used, but tell the compiler that it is ok */ (void) w; (void) data; for (i = 0; i < WPrefs.sectionCount; i++) { PanelRec *rec = WMGetHangedData(WPrefs.sectionB[i]); if (rec->callbacks.undoChanges && (rec->callbacks.flags & INITIALIZED_PANEL)) (*rec->callbacks.undoChanges) ((Panel *) rec); } } static void prepareForClose(void) { int i; for (i = 0; i < WPrefs.sectionCount; i++) { PanelRec *rec = WMGetHangedData(WPrefs.sectionB[i]); if (rec->callbacks.prepareForClose && (rec->callbacks.flags & INITIALIZED_PANEL)) (*rec->callbacks.prepareForClose) ((Panel *) rec); } } static void toggleBalloons(WMWidget *w, void *data) { WMUserDefaults *udb = WMGetStandardUserDefaults(); Bool flag; /* Parameter not used, but tell the compiler that it is ok */ (void) w; (void) data; flag = WMGetButtonSelected(WPrefs.balloonBtn); WMSetBalloonEnabled(WMWidgetScreen(WPrefs.win), flag); WMSetUDBoolForKey(udb, flag, "BalloonHelp"); } static void createMainWindow(WMScreen * scr) { WMScroller *scroller; WMFont *font; char buffer[128]; WPrefs.win = WMCreateWindow(scr, "wprefs"); WMResizeWidget(WPrefs.win, 520, 390); WMSetWindowTitle(WPrefs.win, _("Window Maker Preferences")); WMSetWindowCloseAction(WPrefs.win, quit, NULL); WMSetWindowMaxSize(WPrefs.win, 520, 390); WMSetWindowMinSize(WPrefs.win, 520, 390); WMSetWindowMiniwindowTitle(WPrefs.win, "Preferences"); WPrefs.scrollV = WMCreateScrollView(WPrefs.win); WMResizeWidget(WPrefs.scrollV, 500, 87); WMMoveWidget(WPrefs.scrollV, 10, 10); WMSetScrollViewRelief(WPrefs.scrollV, WRSunken); WMSetScrollViewHasHorizontalScroller(WPrefs.scrollV, True); WMSetScrollViewHasVerticalScroller(WPrefs.scrollV, False); scroller = WMGetScrollViewHorizontalScroller(WPrefs.scrollV); WMSetScrollerArrowsPosition(scroller, WSANone); WPrefs.buttonF = WMCreateFrame(WPrefs.win); WMSetFrameRelief(WPrefs.buttonF, WRFlat); WMSetScrollViewContentView(WPrefs.scrollV, WMWidgetView(WPrefs.buttonF)); WPrefs.undosBtn = WMCreateCommandButton(WPrefs.win); WMResizeWidget(WPrefs.undosBtn, 90, 28); WMMoveWidget(WPrefs.undosBtn, 135, 350); WMSetButtonText(WPrefs.undosBtn, _("Revert Page")); WMSetButtonAction(WPrefs.undosBtn, undo, NULL); WPrefs.undoBtn = WMCreateCommandButton(WPrefs.win); WMResizeWidget(WPrefs.undoBtn, 90, 28); WMMoveWidget(WPrefs.undoBtn, 235, 350); WMSetButtonText(WPrefs.undoBtn, _("Revert All")); WMSetButtonAction(WPrefs.undoBtn, undoAll, NULL); WPrefs.saveBtn = WMCreateCommandButton(WPrefs.win); WMResizeWidget(WPrefs.saveBtn, 80, 28); WMMoveWidget(WPrefs.saveBtn, 335, 350); WMSetButtonText(WPrefs.saveBtn, _("Save")); WMSetButtonAction(WPrefs.saveBtn, save, NULL); WPrefs.closeBtn = WMCreateCommandButton(WPrefs.win); WMResizeWidget(WPrefs.closeBtn, 80, 28); WMMoveWidget(WPrefs.closeBtn, 425, 350); WMSetButtonText(WPrefs.closeBtn, _("Close")); WMSetButtonAction(WPrefs.closeBtn, quit, NULL); WPrefs.balloonBtn = WMCreateSwitchButton(WPrefs.win); WMResizeWidget(WPrefs.balloonBtn, 200, 28); WMMoveWidget(WPrefs.balloonBtn, 15, 350); WMSetButtonText(WPrefs.balloonBtn, _("Balloon Help")); WMSetButtonAction(WPrefs.balloonBtn, toggleBalloons, NULL); { WMUserDefaults *udb = WMGetStandardUserDefaults(); Bool flag = WMGetUDBoolForKey(udb, "BalloonHelp"); WMSetButtonSelected(WPrefs.balloonBtn, flag); WMSetBalloonEnabled(scr, flag); } /* banner */ WPrefs.banner = WMCreateFrame(WPrefs.win); WMResizeWidget(WPrefs.banner, FRAME_WIDTH, FRAME_HEIGHT); WMMoveWidget(WPrefs.banner, FRAME_LEFT, FRAME_TOP); WMSetFrameRelief(WPrefs.banner, WRFlat); font = WMCreateFont(scr, "Lucida Sans,URW Gothic L,Times New Roman,serif" ":bold:pixelsize=26:antialias=true"); WPrefs.nameL = WMCreateLabel(WPrefs.banner); WMSetLabelTextAlignment(WPrefs.nameL, WACenter); WMResizeWidget(WPrefs.nameL, FRAME_WIDTH - 20, 60); WMMoveWidget(WPrefs.nameL, 10, 50); WMSetLabelFont(WPrefs.nameL, font); WMSetLabelText(WPrefs.nameL, _("Window Maker Preferences")); WMReleaseFont(font); WPrefs.versionL = WMCreateLabel(WPrefs.banner); WMResizeWidget(WPrefs.versionL, FRAME_WIDTH - 20, 20); WMMoveWidget(WPrefs.versionL, 10, 120); WMSetLabelTextAlignment(WPrefs.versionL, WACenter); sprintf(buffer, _("Version %s"), VERSION); WMSetLabelText(WPrefs.versionL, buffer); WPrefs.statusL = WMCreateLabel(WPrefs.banner); WMResizeWidget(WPrefs.statusL, FRAME_WIDTH - 20, 60); WMMoveWidget(WPrefs.statusL, 10, 150); WMSetLabelTextAlignment(WPrefs.statusL, WACenter); WMSetLabelText(WPrefs.statusL, _("Starting...")); WMMapSubwidgets(WPrefs.win); WMUnmapWidget(WPrefs.undosBtn); WMUnmapWidget(WPrefs.undoBtn); WMUnmapWidget(WPrefs.saveBtn); } static void showPanel(Panel * panel) { PanelRec *rec = (PanelRec *) panel; if (!(rec->callbacks.flags & INITIALIZED_PANEL)) { (*rec->callbacks.createWidgets) (panel); rec->callbacks.flags |= INITIALIZED_PANEL; } WMSetWindowTitle(WPrefs.win, rec->sectionName); if (rec->callbacks.showPanel) (*rec->callbacks.showPanel) (panel); WMMapWidget(rec->box); } static void hidePanel(Panel * panel) { PanelRec *rec = (PanelRec *) panel; WMUnmapWidget(rec->box); if (rec->callbacks.hidePanel) (*rec->callbacks.hidePanel) (panel); } static void savePanelData(Panel * panel) { PanelRec *rec = (PanelRec *) panel; if (rec->callbacks.updateDomain) { (*rec->callbacks.updateDomain) (panel); } } static void changeSection(WMWidget * self, void *data) { /* Parameter not used, but tell the compiler that it is ok */ (void) self; if (WPrefs.currentPanel == data) return; if (WPrefs.currentPanel == NULL) { WMDestroyWidget(WPrefs.nameL); WMDestroyWidget(WPrefs.versionL); WMDestroyWidget(WPrefs.statusL); WMSetFrameRelief(WPrefs.banner, WRGroove); /* WMMapWidget(WPrefs.undosBtn); WMMapWidget(WPrefs.undoBtn); */ WMMapWidget(WPrefs.saveBtn); } showPanel(data); if (WPrefs.currentPanel) hidePanel(WPrefs.currentPanel); WPrefs.currentPanel = data; } char *LocateImage(const char *name) { char *path; char *tmp = wmalloc(strlen(name) + 8); if (TIFFOK) { sprintf(tmp, "%s.tiff", name); path = WMPathForResourceOfType(tmp, "tiff"); } else { sprintf(tmp, "%s.xpm", name); path = WMPathForResourceOfType(tmp, "xpm"); } wfree(tmp); if (!path) { wwarning(_("could not locate image file %s"), name); } return path; } void CreateImages(WMScreen *scr, RContext *rc, RImage *xis, const char *file, WMPixmap **icon_normal, WMPixmap **icon_greyed) { RImage *icon; char *path; RColor gray = { 0xae, 0xaa, 0xae, 0 }; path = LocateImage(file); if (!path) { *icon_normal = NULL; if (icon_greyed) *icon_greyed = NULL; return; } *icon_normal = WMCreatePixmapFromFile(scr, path); if (!*icon_normal) { wwarning(_("could not load icon %s"), path); if (icon_greyed) *icon_greyed = NULL; wfree(path); return; } if (!icon_greyed) // Greyed-out version not requested, we are done { wfree(path); return; } icon = RLoadImage(rc, path, 0); if (!icon) { wwarning(_("could not load icon %s"), path); *icon_greyed = NULL; wfree(path); return; } RCombineImageWithColor(icon, &gray); if (xis) { RCombineImagesWithOpaqueness(icon, xis, 180); } *icon_greyed = WMCreatePixmapFromRImage(scr, icon, 127); if (!*icon_greyed) { wwarning(_("could not process icon %s: %s"), path, RMessageForError(RErrorCode)); } RReleaseImage(icon); wfree(path); } void SetButtonAlphaImage(WMScreen *scr, WMButton *bPtr, const char *file) { WMPixmap *icon; RColor color; char *iconPath; iconPath = LocateImage(file); color.red = 0xae; color.green = 0xaa; color.blue = 0xae; color.alpha = 0; if (iconPath) { icon = WMCreateBlendedPixmapFromFile(scr, iconPath, &color); if (!icon) wwarning(_("could not load icon file %s"), iconPath); } else { icon = NULL; } WMSetButtonImage(bPtr, icon); color.red = 0xff; color.green = 0xff; color.blue = 0xff; color.alpha = 0; if (iconPath) { icon = WMCreateBlendedPixmapFromFile(scr, iconPath, &color); if (!icon) wwarning(_("could not load icon file %s"), iconPath); } else { icon = NULL; } WMSetButtonAltImage(bPtr, icon); if (icon) WMReleasePixmap(icon); if (iconPath) wfree(iconPath); } void AddSection(Panel * panel, const char *iconFile) { WMButton *bPtr; assert(WPrefs.sectionCount < MAX_SECTIONS); bPtr = WMCreateCustomButton(WPrefs.buttonF, WBBStateLightMask | WBBStateChangeMask); WMResizeWidget(bPtr, 64, 64); WMMoveWidget(bPtr, WPrefs.sectionCount * 64, 0); WMSetButtonImagePosition(bPtr, WIPImageOnly); WMSetButtonAction(bPtr, changeSection, panel); WMHangData(bPtr, panel); WMSetBalloonTextForView(((PanelRec *) panel)->description, WMWidgetView(bPtr)); SetButtonAlphaImage(WMWidgetScreen(bPtr), bPtr, iconFile); WMMapWidget(bPtr); WPrefs.sectionB[WPrefs.sectionCount] = bPtr; if (WPrefs.sectionCount > 0) WMGroupButtons(WPrefs.sectionB[0], bPtr); WPrefs.sectionCount++; WMResizeWidget(WPrefs.buttonF, WPrefs.sectionCount * 64, 64); } void Initialize(WMScreen * scr) { char **list; int i; char *path; list = RSupportedFileFormats(); for (i = 0; list[i] != NULL; i++) { if (strcmp(list[i], "TIFF") == 0) { TIFFOK = True; break; } } if (TIFFOK) path = WMPathForResourceOfType("WPrefs.tiff", NULL); else path = WMPathForResourceOfType("WPrefs.xpm", NULL); if (path) { RImage *tmp; tmp = RLoadImage(WMScreenRContext(scr), path, 0); if (!tmp) { wwarning(_("could not load image file %s:%s"), path, RMessageForError(RErrorCode)); } else { WMSetApplicationIconImage(scr, tmp); RReleaseImage(tmp); } wfree(path); } memset(&WPrefs, 0, sizeof(_WPrefs)); createMainWindow(scr); WMRealizeWidget(WPrefs.win); WMSetWindowMiniwindowImage(WPrefs.win, WMGetApplicationIconImage(scr)); WMMapWidget(WPrefs.win); XFlush(WMScreenDisplay(scr)); WMSetLabelText(WPrefs.statusL, _("Loading Window Maker configuration files...")); XFlush(WMScreenDisplay(scr)); loadConfigurations(scr, WPrefs.win); WMSetLabelText(WPrefs.statusL, _("Initializing configuration panels...")); InitFocus(WPrefs.banner); InitWindowHandling(WPrefs.banner); InitMenuPreferences(WPrefs.banner); InitIcons(WPrefs.banner); InitPreferences(WPrefs.banner); InitPaths(WPrefs.banner); InitDocks(WPrefs.banner); InitWorkspace(WPrefs.banner); InitConfigurations(WPrefs.banner); InitMenu(WPrefs.banner); #ifdef not_yet_fully_implemented InitKeyboardSettings(WPrefs.banner); #endif InitKeyboardShortcuts(WPrefs.banner); InitMouseSettings(WPrefs.banner); InitAppearance(WPrefs.banner); InitFontSimple(WPrefs.banner); #ifdef not_yet_fully_implemented InitThemes(WPrefs.banner); #endif InitExpert(WPrefs.banner); WMRealizeWidget(WPrefs.scrollV); WMSetLabelText(WPrefs.statusL, ""); } WMWindow *GetWindow(void) { return WPrefs.win; } static void loadConfigurations(WMScreen * scr, WMWindow * mainw) { WMPropList *db, *gdb; char *path; FILE *file; char buffer[1024]; char mbuf[1024]; int v1, v2, v3; path = wdefaultspathfordomain("WindowMaker"); WindowMakerDBPath = path; db = WMReadPropListFromFile(path); if (db) { if (!WMIsPLDictionary(db)) { WMReleasePropList(db); db = NULL; sprintf(mbuf, _("Window Maker domain (%s) is corrupted!"), path); WMRunAlertPanel(scr, mainw, _("Error"), mbuf, _("OK"), NULL, NULL); } } else { sprintf(mbuf, _("Could not load Window Maker domain (%s) from defaults database."), path); WMRunAlertPanel(scr, mainw, _("Error"), mbuf, _("OK"), NULL, NULL); } path = getenv("WMAKER_BIN_NAME"); if (!path) path = "wmaker"; { char *command; command = wstrconcat(path, " --version"); file = popen(command, "r"); wfree(command); } if (!file || !fgets(buffer, 1023, file)) { werror(_("could not extract version information from Window Maker")); wfatal(_("Make sure wmaker is in your search path.")); WMRunAlertPanel(scr, mainw, _("Error"), _ ("Could not extract version from Window Maker. Make sure it is correctly installed and is in your PATH environment variable."), _("OK"), NULL, NULL); exit(1); } if (file) pclose(file); if (sscanf(buffer, "Window Maker %i.%i.%i", &v1, &v2, &v3) != 3 && sscanf(buffer, "WindowMaker %i.%i.%i", &v1, &v2, &v3) != 3) { WMRunAlertPanel(scr, mainw, _("Error"), _("Could not extract version from Window Maker. " "Make sure it is correctly installed and the path " "where it installed is in the PATH environment " "variable."), _("OK"), NULL, NULL); exit(1); } if (v1 == 0 && (v2 < 18 || v3 < 0)) { sprintf(mbuf, _("WPrefs only supports Window Maker 0.18.0 or newer.\n" "The version installed is %i.%i.%i\n"), v1, v2, v3); WMRunAlertPanel(scr, mainw, _("Error"), mbuf, _("OK"), NULL, NULL); exit(1); } if (v1 > 1 || (v1 == 1 && (v2 > 0))) { sprintf(mbuf, _ ("Window Maker %i.%i.%i, which is installed in your system, is not fully supported by this version of WPrefs."), v1, v2, v3); WMRunAlertPanel(scr, mainw, _("Warning"), mbuf, _("OK"), NULL, NULL); } { char *command; command = wstrconcat(path, " --global_defaults_path"); file = popen(command, "r"); wfree(command); } if (!file || !fgets(buffer, 1023, file)) { werror(_("could not run \"%s --global_defaults_path\"."), path); exit(1); } else { char *ptr; ptr = strchr(buffer, '\n'); if (ptr) *ptr = 0; strcat(buffer, "/WindowMaker"); } if (file) pclose(file); gdb = WMReadPropListFromFile(buffer); if (gdb) { if (!WMIsPLDictionary(gdb)) { WMReleasePropList(gdb); gdb = NULL; sprintf(mbuf, _("Window Maker domain (%s) is corrupted!"), buffer); WMRunAlertPanel(scr, mainw, _("Error"), mbuf, _("OK"), NULL, NULL); } } else { sprintf(mbuf, _("Could not load global Window Maker domain (%s)."), buffer); WMRunAlertPanel(scr, mainw, _("Error"), mbuf, _("OK"), NULL, NULL); } if (!db) { db = WMCreatePLDictionary(NULL, NULL); } if (!gdb) { gdb = WMCreatePLDictionary(NULL, NULL); } GlobalDB = gdb; WindowMakerDB = db; } WMPropList *GetObjectForKey(const char *defaultName) { WMPropList *object = NULL; WMPropList *key = WMCreatePLString(defaultName); object = WMGetFromPLDictionary(WindowMakerDB, key); if (!object) object = WMGetFromPLDictionary(GlobalDB, key); WMReleasePropList(key); return object; } void SetObjectForKey(WMPropList * object, const char *defaultName) { WMPropList *key = WMCreatePLString(defaultName); WMPutInPLDictionary(WindowMakerDB, key, object); WMReleasePropList(key); } void RemoveObjectForKey(const char *defaultName) { WMPropList *key = WMCreatePLString(defaultName); WMRemoveFromPLDictionary(WindowMakerDB, key); WMReleasePropList(key); } char *GetStringForKey(const char *defaultName) { WMPropList *val; val = GetObjectForKey(defaultName); if (!val) return NULL; if (!WMIsPLString(val)) return NULL; return WMGetFromPLString(val); } WMPropList *GetArrayForKey(const char *defaultName) { WMPropList *val; val = GetObjectForKey(defaultName); if (!val) return NULL; if (!WMIsPLArray(val)) return NULL; return val; } WMPropList *GetDictionaryForKey(const char *defaultName) { WMPropList *val; val = GetObjectForKey(defaultName); if (!val) return NULL; if (!WMIsPLDictionary(val)) return NULL; return val; } int GetIntegerForKey(const char *defaultName) { WMPropList *val; char *str; int value; val = GetObjectForKey(defaultName); if (!val) return 0; if (!WMIsPLString(val)) return 0; str = WMGetFromPLString(val); if (!str) return 0; if (sscanf(str, "%i", &value) != 1) return 0; return value; } Bool GetBoolForKey(const char *defaultName) { int value; char *str; str = GetStringForKey(defaultName); if (!str) return False; if (sscanf(str, "%i", &value) == 1 && value != 0) return True; if (strcasecmp(str, "YES") == 0) return True; if (strcasecmp(str, "Y") == 0) return True; return False; } void SetIntegerForKey(int value, const char *defaultName) { WMPropList *object; char buffer[128]; sprintf(buffer, "%i", value); object = WMCreatePLString(buffer); SetObjectForKey(object, defaultName); WMReleasePropList(object); } void SetStringForKey(const char *value, const char *defaultName) { WMPropList *object; object = WMCreatePLString(value); SetObjectForKey(object, defaultName); WMReleasePropList(object); } void SetBoolForKey(Bool value, const char *defaultName) { static WMPropList *yes = NULL, *no = NULL; if (!yes) { yes = WMCreatePLString("YES"); no = WMCreatePLString("NO"); } SetObjectForKey(value ? yes : no, defaultName); } void SetSpeedForKey(int speed, const char *defaultName) { char *str; switch (speed) { case 0: str = "ultraslow"; break; case 1: str = "slow"; break; case 2: str = "medium"; break; case 3: str = "fast"; break; case 4: str = "ultrafast"; break; default: str = NULL; } if (str) SetStringForKey(str, defaultName); } int GetSpeedForKey(const char *defaultName) { char *str; int i; str = GetStringForKey(defaultName); if (!str) return 2; if (strcasecmp(str, "ultraslow") == 0) i = 0; else if (strcasecmp(str, "slow") == 0) i = 1; else if (strcasecmp(str, "medium") == 0) i = 2; else if (strcasecmp(str, "fast") == 0) i = 3; else if (strcasecmp(str, "ultrafast") == 0) i = 4; else { wwarning(_("bad speed value for option %s; using default Medium"), defaultName); i = 2; } return i; }