/* getstyle.c - outputs style related options from WindowMaker to stdout * * WindowMaker window manager * * Copyright (c) 1997-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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ #define PROG_VERSION "getstyle (Window Maker) 0.6" #include #include #include #include #include #include #include #include #include #ifndef PATH_MAX #define PATH_MAX 1024 #endif #include "../src/wconfig.h" #ifndef GLOBAL_DEFAULTS_SUBDIR #define GLOBAL_DEFAULTS_SUBDIR "WindowMaker" #endif /* table of style related options */ static char *options[] = { "TitleJustify", "ClipTitleFont", "WindowTitleFont", "MenuTitleFont", "MenuTextFont", "IconTitleFont", "DisplayFont", "LargeDisplayFont", "WindowTitleExtendSpace", "MenuTitleExtendSpace", "MenuTextExtendSpace", "HighlightColor", "HighlightTextColor", "ClipTitleColor", "CClipTitleColor", "FTitleColor", "PTitleColor", "UTitleColor", "FTitleBack", "PTitleBack", "UTitleBack", "ResizebarBack", "MenuTitleColor", "MenuTextColor", "MenuDisabledColor", "MenuTitleBack", "MenuTextBack", "IconBack", "IconTitleColor", "IconTitleBack", "MenuStyle", "WindowTitleExtendSpace", "MenuTitleExtendSpace", "MenuTextExtendSpace", NULL }; /* table of theme related options */ static char *theme_options[] = { "WorkspaceBack", "NormalCursor", "ArrowCursor", "MoveCursor", "ResizeCursor", "TopLeftResizeCursor", "TopRightResizeCursor", "BottomLeftResizeCursor", "BottomRightResizeCursor", "VerticalResizeCursor", "HorizontalResizeCursor", "WaitCursor", "QuestionCursor", "TextCursor", "SelectCursor", NULL }; /* table of style related fonts */ static char *font_options[] = { "ClipTitleFont", "WindowTitleFont", "MenuTitleFont", "MenuTextFont", "IconTitleFont", "DisplayFont", "LargeDisplayFont", NULL }; char *ProgName; WMPropList *PixmapPath = NULL; char *ThemePath = NULL; extern char *convertFont(char *font, Bool keepXLFD); void print_help() { printf("Usage: %s [OPTIONS] [FILE]\n", ProgName); puts("Retrieves style/theme configuration and output to FILE or to stdout"); puts(""); puts(" -t, --theme-options output theme related options when producing a style file"); puts(" -p, --pack produce output as a theme pack"); puts(" --help display this help and exit"); puts(" --version output version information and exit"); } char *globalDefaultsPathForDomain(char *domain) { static char path[1024]; sprintf(path, "%s/%s/%s", SYSCONFDIR, GLOBAL_DEFAULTS_SUBDIR, domain); return path; } char *defaultsPathForDomain(char *domain) { static char path[1024]; char *gspath; gspath = getenv("GNUSTEP_USER_ROOT"); if (gspath) { strcpy(path, gspath); strcat(path, "/"); } else { char *home; home = getenv("HOME"); if (!home) { printf("%s:could not get HOME environment variable!\n", ProgName); exit(0); } strcpy(path, home); strcat(path, "/GNUstep/"); } strcat(path, DEFAULTS_DIR); strcat(path, "/"); strcat(path, domain); return path; } void abortar(char *reason) { char buffer[4000]; printf("%s: %s\n", ProgName, reason); if (ThemePath) { printf("Removing unfinished theme pack\n"); sprintf(buffer, "/bin/rm -fr \"%s\"", ThemePath); if (system(buffer) != 0) { printf("%s: could not execute command %s\n", ProgName, buffer); } } exit(1); } char *wgethomedir() { char *home = getenv("HOME"); struct passwd *user; if (home) return home; user = getpwuid(getuid()); if (!user) { char buffer[80]; sprintf(buffer, "could not get password entry for UID %i", getuid()); perror(buffer); return "/"; } if (!user->pw_dir) { return "/"; } else { return user->pw_dir; } } static char *getuserhomedir(char *username) { struct passwd *user; user = getpwnam(username); if (!user) { char buffer[100]; sprintf(buffer, "could not get password entry for user %s", username); perror(buffer); return NULL; } if (!user->pw_dir) { return "/"; } else { return user->pw_dir; } } char *wexpandpath(char *path) { char buffer2[PATH_MAX + 2]; char buffer[PATH_MAX + 2]; int i; memset(buffer, 0, PATH_MAX + 2); if (*path == '~') { char *home; path++; if (*path == '/' || *path == 0) { home = wgethomedir(); strcat(buffer, home); } else { int j; j = 0; while (*path != 0 && *path != '/') { buffer2[j++] = *path; buffer2[j] = 0; path++; } home = getuserhomedir(buffer2); if (!home) return NULL; strcat(buffer, home); } } i = strlen(buffer); while (*path != 0) { char *tmp; if (*path == '$') { int j = 0; path++; /* expand $(HOME) or $HOME style environment variables */ if (*path == '(') { path++; while (*path != 0 && *path != ')') { buffer2[j++] = *(path++); buffer2[j] = 0; } if (*path == ')') path++; tmp = getenv(buffer2); if (!tmp) { buffer[i] = 0; strcat(buffer, "$("); strcat(buffer, buffer2); strcat(buffer, ")"); i += strlen(buffer2) + 3; } else { strcat(buffer, tmp); i += strlen(tmp); } } else { while (*path != 0 && *path != '/') { buffer2[j++] = *(path++); buffer2[j] = 0; } tmp = getenv(buffer2); if (!tmp) { strcat(buffer, "$"); strcat(buffer, buffer2); i += strlen(buffer2) + 1; } else { strcat(buffer, tmp); i += strlen(tmp); } } } else { buffer[i++] = *path; path++; } } return wstrdup(buffer); } char *wfindfileinarray(WMPropList * paths, char *file) { int i; char *path; int len, flen; char *fullpath; if (!file) return NULL; if (*file == '/' || *file == '~' || !paths || !WMIsPLArray(paths) || WMGetPropListItemCount(paths) == 0) { if (access(file, R_OK) < 0) { fullpath = wexpandpath(file); if (!fullpath) return NULL; if (access(fullpath, R_OK) < 0) { free(fullpath); return NULL; } else { return fullpath; } } else { return wstrdup(file); } } flen = strlen(file); for (i = 0; i < WMGetPropListItemCount(paths); i++) { WMPropList *tmp; char *dir; tmp = WMGetFromPLArray(paths, i); if (!WMIsPLString(tmp) || !(dir = WMGetFromPLString(tmp))) continue; len = strlen(dir); path = wmalloc(len + flen + 2); path = memcpy(path, dir, len); path[len] = 0; strcat(path, "/"); strcat(path, file); /* expand tilde */ fullpath = wexpandpath(path); free(path); if (fullpath) { /* check if file is readable */ if (access(fullpath, R_OK) == 0) { return fullpath; } free(fullpath); } } return NULL; } static Bool isFontOption(char *option) { int i; for (i = 0; font_options[i] != NULL; i++) { if (strcasecmp(option, font_options[i]) == 0) { return True; } } return False; } void copyFile(char *dir, char *file) { char buffer[4000]; sprintf(buffer, "/bin/cp \"%s\" \"%s\"", file, dir); if (system(buffer) != 0) { printf("%s: could not copy file %s\n", ProgName, file); } } void findCopyFile(char *dir, char *file) { char *fullPath; fullPath = wfindfileinarray(PixmapPath, file); if (!fullPath) { char buffer[4000]; sprintf(buffer, "could not find file %s", file); abortar(buffer); } copyFile(dir, fullPath); free(fullPath); } char *makeThemePack(WMPropList * style, char *themeName) { WMPropList *keys; WMPropList *key; WMPropList *value; int i; char *themeDir; themeDir = wmalloc(strlen(themeName) + 50); sprintf(themeDir, "%s.themed", themeName); ThemePath = themeDir; { char *tmp; tmp = wmalloc(strlen(themeDir) + 20); sprintf(tmp, "/bin/mkdir \"%s\"", themeDir); if (system(tmp) != 0) { printf ("%s: could not create directory %s. Probably there's already a theme with that name in this directory.\n", ProgName, themeDir); exit(1); } free(tmp); } keys = WMGetPLDictionaryKeys(style); for (i = 0; i < WMGetPropListItemCount(keys); i++) { key = WMGetFromPLArray(keys, i); value = WMGetFromPLDictionary(style, key); if (value && WMIsPLArray(value) && WMGetPropListItemCount(value) > 2) { WMPropList *type; char *t; type = WMGetFromPLArray(value, 0); t = WMGetFromPLString(type); if (t == NULL) continue; if (strcasecmp(t, "tpixmap") == 0 || strcasecmp(t, "spixmap") == 0 || strcasecmp(t, "cpixmap") == 0 || strcasecmp(t, "mpixmap") == 0 || strcasecmp(t, "tdgradient") == 0 || strcasecmp(t, "tvgradient") == 0 || strcasecmp(t, "thgradient") == 0) { WMPropList *file; char *p; char *newPath; file = WMGetFromPLArray(value, 1); p = strrchr(WMGetFromPLString(file), '/'); if (p) { copyFile(themeDir, WMGetFromPLString(file)); newPath = wstrdup(p + 1); WMDeleteFromPLArray(value, 1); WMInsertInPLArray(value, 1, WMCreatePLString(newPath)); free(newPath); } else { findCopyFile(themeDir, WMGetFromPLString(file)); } } else if (strcasecmp(t, "bitmap") == 0) { WMPropList *file; char *p; char *newPath; file = WMGetFromPLArray(value, 1); p = strrchr(WMGetFromPLString(file), '/'); if (p) { copyFile(themeDir, WMGetFromPLString(file)); newPath = wstrdup(p + 1); WMDeleteFromPLArray(value, 1); WMInsertInPLArray(value, 1, WMCreatePLString(newPath)); free(newPath); } else { findCopyFile(themeDir, WMGetFromPLString(file)); } file = WMGetFromPLArray(value, 2); p = strrchr(WMGetFromPLString(file), '/'); if (p) { copyFile(themeDir, WMGetFromPLString(file)); newPath = wstrdup(p + 1); WMDeleteFromPLArray(value, 2); WMInsertInPLArray(value, 2, WMCreatePLString(newPath)); free(newPath); } else { findCopyFile(themeDir, WMGetFromPLString(file)); } } } } return themeDir; } int main(int argc, char **argv) { WMPropList *prop, *style, *key, *val; char *path; int i, theme_too = 0, make_pack = 0; char *style_file = NULL; ProgName = argv[0]; if (argc > 1) { for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-p") == 0 || strcmp(argv[i], "--pack") == 0) { make_pack = 1; theme_too = 1; } else if (strcmp(argv[i], "-t") == 0 || strcmp(argv[i], "--theme-options") == 0) { theme_too++; } else if (strcmp(argv[i], "--help") == 0) { print_help(); exit(0); } else if (strcmp(argv[i], "--version") == 0) { puts(PROG_VERSION); exit(0); } else { if (style_file != NULL) { printf("%s: invalid argument '%s'\n", argv[0], style_file[0] == '-' ? style_file : argv[i]); printf("Try '%s --help' for more information\n", argv[0]); exit(1); } style_file = argv[i]; } } } if (make_pack && !style_file) { printf("%s: you must supply a name for the theme pack\n", ProgName); exit(1); } WMPLSetCaseSensitive(False); path = defaultsPathForDomain("WindowMaker"); prop = WMReadPropListFromFile(path); if (!prop) { printf("%s:could not load WindowMaker configuration file \"%s\".\n", ProgName, path); exit(1); } /* get global value */ path = globalDefaultsPathForDomain("WindowMaker"); val = WMReadPropListFromFile(path); if (val) { WMMergePLDictionaries(val, prop, True); WMReleasePropList(prop); prop = val; } style = WMCreatePLDictionary(NULL, NULL); for (i = 0; options[i] != NULL; i++) { key = WMCreatePLString(options[i]); val = WMGetFromPLDictionary(prop, key); if (val) { WMRetainPropList(val); if (isFontOption(options[i])) { char *newfont, *oldfont; oldfont = WMGetFromPLString(val); newfont = convertFont(oldfont, False); /* newfont is a reference to old if conversion is not needed */ if (newfont != oldfont) { WMReleasePropList(val); val = WMCreatePLString(newfont); wfree(newfont); } } WMPutInPLDictionary(style, key, val); WMReleasePropList(val); } WMReleasePropList(key); } val = WMGetFromPLDictionary(prop, WMCreatePLString("PixmapPath")); if (val) PixmapPath = val; if (theme_too) { for (i = 0; theme_options[i] != NULL; i++) { key = WMCreatePLString(theme_options[i]); val = WMGetFromPLDictionary(prop, key); if (val) WMPutInPLDictionary(style, key, val); } } if (make_pack) { char *path; makeThemePack(style, style_file); path = wmalloc(strlen(ThemePath) + 32); strcpy(path, ThemePath); strcat(path, "/style"); WMWritePropListToFile(style, path); wfree(path); } else { if (style_file) { WMWritePropListToFile(style, style_file); } else { puts(WMGetPropListDescription(style, True)); } } exit(0); }