/* 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" /* 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 }; #define DEFAULT_FONT "sans-serif:pixelsize=12" char *ProgName; WMPropList *PixmapPath = NULL; char *ThemePath = NULL; 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/WindowMaker/%s", SYSCONFDIR, 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; } static int countChar(char *str, char c) { int count = 0; if (!str) return 0; for (; *str!=0; str++) { if (*str == c) { count++; } } return count; } typedef struct str { char *str; int len; } str; #define XLFD_TOKENS 14 static str* getXLFDTokens(char *xlfd) { static str tokens[XLFD_TOKENS]; int i, len, size; char *ptr; if (!xlfd || countChar(xlfd, '-')0; i++) { size = strspn(ptr, "-"); ptr += size; len -= size; if (len <= 0) break; size = strcspn(ptr, "-"); if (size==0) break; tokens[i].str = ptr; tokens[i].len = size; ptr += size; len -= size; } return tokens; } static int strToInt(str *token) { int res=0, pos, c; if (token->len==0 || token->str[0]=='*') { return -1; } else { for (res=0, pos=0; poslen; pos++) { c = token->str[pos] - '0'; if (c<0 || c>9) break; res = res*10 + c; } } return res; } static char* mapSlantToName(str *slant) { if (slant->len==0 || slant->str[0]=='*') return "roman"; switch(slant->str[0]) { case 'i': return "italic"; case 'o': return "oblique"; case 'r': default: return "roman"; } } char* xlfdToFc(char *xlfd) { str *tokens, *family, *weight, *slant; char *name, buf[512]; int size, pixelsize; tokens = getXLFDTokens(xlfd); if (!tokens) return wstrdup(DEFAULT_FONT); family = &(tokens[1]); weight = &(tokens[2]); slant = &(tokens[3]); if (family->len==0 || family->str[0]=='*') return wstrdup(DEFAULT_FONT); sprintf(buf, "%.*s", family->len, family->str); name = wstrdup(buf); pixelsize = strToInt(&tokens[6]); size = strToInt(&tokens[7]); if (size<=0 && pixelsize<=0) { name = wstrappend(name, ":pixelsize=12"); } else if (pixelsize>0) { /* if pixelsize is present size will be ignored so we skip it */ sprintf(buf, ":pixelsize=%d", pixelsize); name = wstrappend(name, buf); } else { sprintf(buf, "-%d", size/10); name = wstrappend(name, buf); } if (weight->len>0 && weight->str[0]!='*') { sprintf(buf, ":weight=%.*s", weight->len, weight->str); name = wstrappend(name, buf); } if (slant->len>0 && slant->str[0]!='*') { sprintf(buf, ":slant=%s", mapSlantToName(slant)); name = wstrappend(name, buf); } name = wstrappend(name, ":xlfd="); name = wstrappend(name, xlfd); return name; } /* return converted font (if conversion is needed) else the original font */ static char* convertFont(char *font) { if (font[0]=='-') { if (!strchr(font, ',')) { return xlfdToFc(font); } else { wwarning("fontsets are not supported. replaced " "with default %s", DEFAULT_FONT); return wstrdup(DEFAULT_FONT); } } else { return font; } } 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, "coould 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