getstyle: Save theme pack in Themes dir
[wmaker-crm.git] / util / getstyle.c
blob624c0e6eb4ce60dcd7f3273b57339b19b1a48917
1 /* getstyle.c - outputs style related options from WindowMaker to stdout
3 * WindowMaker window manager
5 * Copyright (c) 1997-2003 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 along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #ifdef __GLIBC__
23 #define _GNU_SOURCE /* getopt_long */
24 #endif
26 #include <sys/types.h>
27 #include <sys/stat.h>
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <getopt.h>
32 #include <libgen.h>
33 #include <limits.h>
34 #include <pwd.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <strings.h>
39 #include <unistd.h>
41 #include <WINGs/WUtil.h>
43 #define RETRY( x ) do { \
44 x; \
45 } while (errno == EINTR);
47 #ifndef PATH_MAX
48 #define PATH_MAX 1024
49 #endif
51 #include "../src/wconfig.h"
53 #ifndef GLOBAL_DEFAULTS_SUBDIR
54 #define GLOBAL_DEFAULTS_SUBDIR "WindowMaker"
55 #endif
57 /* table of style related options */
58 static char *options[] = {
59 "TitleJustify",
60 "ClipTitleFont",
61 "WindowTitleFont",
62 "MenuTitleFont",
63 "MenuTextFont",
64 "IconTitleFont",
65 "DisplayFont",
66 "LargeDisplayFont",
67 "WindowTitleExtendSpace",
68 "MenuTitleExtendSpace",
69 "MenuTextExtendSpace",
70 "HighlightColor",
71 "HighlightTextColor",
72 "ClipTitleColor",
73 "CClipTitleColor",
74 "FTitleColor",
75 "PTitleColor",
76 "UTitleColor",
77 "FTitleBack",
78 "PTitleBack",
79 "UTitleBack",
80 "ResizebarBack",
81 "MenuTitleColor",
82 "MenuTextColor",
83 "MenuDisabledColor",
84 "MenuTitleBack",
85 "MenuTextBack",
86 "IconBack",
87 "IconTitleColor",
88 "IconTitleBack",
89 "MenuStyle",
90 "WindowTitleExtendSpace",
91 "MenuTitleExtendSpace",
92 "MenuTextExtendSpace",
93 NULL
96 /* table of theme related options */
97 static char *theme_options[] = {
98 "WorkspaceBack",
99 "NormalCursor",
100 "ArrowCursor",
101 "MoveCursor",
102 "ResizeCursor",
103 "TopLeftResizeCursor",
104 "TopRightResizeCursor",
105 "BottomLeftResizeCursor",
106 "BottomRightResizeCursor",
107 "VerticalResizeCursor",
108 "HorizontalResizeCursor",
109 "WaitCursor",
110 "QuestionCursor",
111 "TextCursor",
112 "SelectCursor",
113 NULL
116 /* table of style related fonts */
118 static char *font_options[] = {
119 "ClipTitleFont",
120 "WindowTitleFont",
121 "MenuTitleFont",
122 "MenuTextFont",
123 "IconTitleFont",
124 "DisplayFont",
125 "LargeDisplayFont",
126 NULL
129 extern char *__progname;
131 WMPropList *PixmapPath = NULL;
133 char *ThemePath = NULL;
135 extern char *convertFont(char *font, Bool keepXLFD);
137 void print_help(int print_usage, int exitval)
139 printf("Usage: %s [-t] [-p] [-h] [-v] [file]\n", __progname);
140 if (print_usage) {
141 puts("Retrieves style/theme configuration and outputs to ~/GNUstep/Library/WindowMaker/Themes/file.themed/style or to stdout");
142 puts("");
143 puts(" -h, --help display this help and exit");
144 puts(" -v, --version output version information and exit");
145 puts(" -t, --theme-options output theme related options when producing a style file");
146 puts(" -p, --pack produce output as a theme pack");
148 exit(exitval);
151 void abortar(char *reason)
153 printf("%s: %s\n", __progname, reason);
154 if (ThemePath) {
155 printf("Removing unfinished theme pack\n");
156 (void)wrmdirhier(ThemePath);
158 exit(1);
161 static Bool isFontOption(char *option)
163 int i;
165 for (i = 0; font_options[i] != NULL; i++) {
166 if (strcasecmp(option, font_options[i]) == 0) {
167 return True;
171 return False;
175 * copy a file specified by `file' into `directory'. name stays.
178 * it is more or less assumed that this function will only
179 * copy reasonably-sized files
181 /* XXX: is almost like WINGs/wcolodpanel.c:fetchFile() */
182 void copyFile(char *dir, char *file)
184 FILE *src = NULL, *dst = NULL;
185 size_t nread, nwritten, len;
186 char buf[4096];
187 struct stat st;
188 char *dstpath;
190 /* only to a directory */
191 if (stat(dir, &st) != 0 || !S_ISDIR(st.st_mode))
192 return;
193 /* only copy files */
194 if (stat(file, &st) != 0 || !S_ISREG(st.st_mode))
195 return;
197 len = strlen(dir) + 1 /* / */ + strlen(file) + 1 /* '\0' */;
198 dstpath = wmalloc(len);
199 snprintf(dstpath, len, "%s/%s", dir, basename(file));
200 buf[len] = '\0';
202 RETRY( dst = fopen(dstpath, "wb") )
203 if (dst == NULL) {
204 werror(_("Could not create %s"), dstpath);
205 goto err;
208 RETRY( src = fopen(file, "rb") )
209 if (src == NULL) {
210 werror(_("Could not open %s"), file);
211 goto err;
214 do {
215 RETRY( nread = fread(buf, 1, sizeof(buf), src) )
216 if (ferror(src))
217 break;
219 RETRY( nwritten = fwrite(buf, 1, nread, dst) )
220 if (ferror(dst) || feof(src) || nread != nwritten)
221 break;
223 } while (1);
225 if (ferror(src) || ferror(dst))
226 unlink(dstpath);
228 fchmod(fileno(dst), st.st_mode);
229 fsync(fileno(dst));
230 RETRY( fclose(dst) )
232 err:
233 if (src) {
234 RETRY( fclose(src) )
236 wfree(dstpath);
237 return;
240 void findCopyFile(char *dir, char *file)
242 char *fullPath;
244 fullPath = wfindfileinarray(PixmapPath, file);
245 if (!fullPath) {
246 char buffer[4000];
248 sprintf(buffer, "could not find file %s", file);
249 abortar(buffer);
251 copyFile(dir, fullPath);
252 free(fullPath);
255 void makeThemePack(WMPropList * style, char *themeName)
257 WMPropList *keys;
258 WMPropList *key;
259 WMPropList *value;
260 int i;
261 size_t themeNameLen;
262 char *themeDir, *t;
264 if ((t = wusergnusteppath()) == NULL)
265 return;
266 themeNameLen = strlen(t) + strlen(themeName) + 50;
267 themeDir = wmalloc(themeNameLen);
268 snprintf(themeDir, themeNameLen, "%s/Library/WindowMaker/Themes/%s.themed/", t, themeName);
269 ThemePath = themeDir;
271 if (!wmkdirhier(themeDir)) {
272 wwarning("Could not make theme dir %s\n", themeDir);
273 return;
276 keys = WMGetPLDictionaryKeys(style);
278 for (i = 0; i < WMGetPropListItemCount(keys); i++) {
279 key = WMGetFromPLArray(keys, i);
281 value = WMGetFromPLDictionary(style, key);
282 if (value && WMIsPLArray(value) && WMGetPropListItemCount(value) > 2) {
283 WMPropList *type;
284 char *t;
286 type = WMGetFromPLArray(value, 0);
287 t = WMGetFromPLString(type);
288 if (t == NULL)
289 continue;
291 if (strcasecmp(t, "tpixmap") == 0 ||
292 strcasecmp(t, "spixmap") == 0 ||
293 strcasecmp(t, "cpixmap") == 0 ||
294 strcasecmp(t, "mpixmap") == 0 ||
295 strcasecmp(t, "tdgradient") == 0 ||
296 strcasecmp(t, "tvgradient") == 0 ||
297 strcasecmp(t, "thgradient") == 0) {
299 WMPropList *file;
300 char *p;
301 char *newPath;
303 file = WMGetFromPLArray(value, 1);
305 p = strrchr(WMGetFromPLString(file), '/');
306 if (p) {
307 copyFile(themeDir, WMGetFromPLString(file));
309 newPath = wstrdup(p + 1);
310 WMDeleteFromPLArray(value, 1);
311 WMInsertInPLArray(value, 1, WMCreatePLString(newPath));
312 free(newPath);
313 } else {
314 findCopyFile(themeDir, WMGetFromPLString(file));
316 } else if (strcasecmp(t, "bitmap") == 0) {
318 WMPropList *file;
319 char *p;
320 char *newPath;
322 file = WMGetFromPLArray(value, 1);
324 p = strrchr(WMGetFromPLString(file), '/');
325 if (p) {
326 copyFile(themeDir, WMGetFromPLString(file));
328 newPath = wstrdup(p + 1);
329 WMDeleteFromPLArray(value, 1);
330 WMInsertInPLArray(value, 1, WMCreatePLString(newPath));
331 free(newPath);
332 } else {
333 findCopyFile(themeDir, WMGetFromPLString(file));
336 file = WMGetFromPLArray(value, 2);
338 p = strrchr(WMGetFromPLString(file), '/');
339 if (p) {
340 copyFile(themeDir, WMGetFromPLString(file));
342 newPath = wstrdup(p + 1);
343 WMDeleteFromPLArray(value, 2);
344 WMInsertInPLArray(value, 2, WMCreatePLString(newPath));
345 free(newPath);
346 } else {
347 findCopyFile(themeDir, WMGetFromPLString(file));
354 int main(int argc, char **argv)
356 WMPropList *prop, *style, *key, *val;
357 char *path, *p;
358 int i, ch, theme_too = 0, make_pack = 0;
359 char *style_file = NULL;
361 struct option longopts[] = {
362 { "pack", no_argument, NULL, 'p' },
363 { "theme-options", no_argument, NULL, 't' },
364 { "version", no_argument, NULL, 'v' },
365 { "help", no_argument, NULL, 'h' },
366 { NULL, 0, NULL, 0 }
369 while ((ch = getopt_long(argc, argv, "ptvh", longopts, NULL)) != -1)
370 switch(ch) {
371 case 'v':
372 printf("%s (Window Maker %s)\n", __progname, VERSION);
373 return 0;
374 /* NOTREACHED */
375 case 'h':
376 print_help(1, 0);
377 /* NOTREACHED */
378 case 'p':
379 make_pack = 1;
380 theme_too = 1;
381 break;
382 case 't':
383 theme_too = 1;
384 case 0:
385 break;
386 default:
387 print_help(0, 1);
388 /* NOTREACHED */
391 /* At most one non-option ARGV-element is accepted (the theme name) */
392 if (argc - optind > 1)
393 print_help(0, 1);
395 if (argc - optind == 1) {
396 style_file = argv[argc - 1];
397 while ((p = strchr(style_file, '/')) != NULL)
398 *p = '_';
401 /* A theme name was given but the option to create it (-p) was not */
402 if (style_file && !make_pack)
403 print_help(0, 1);
405 if (make_pack && !style_file) {
406 printf("%s: you must supply a name for the theme pack\n", __progname);
407 return 1;
410 WMPLSetCaseSensitive(False);
412 path = wdefaultspathfordomain("WindowMaker");
414 prop = WMReadPropListFromFile(path);
415 if (!prop) {
416 printf("%s: could not load WindowMaker configuration file \"%s\".\n", __progname, path);
417 return 1;
420 /* get global value */
421 path = wglobaldefaultspathfordomain("WindowMaker");
423 val = WMReadPropListFromFile(path);
424 if (val) {
425 WMMergePLDictionaries(val, prop, True);
426 WMReleasePropList(prop);
427 prop = val;
430 style = WMCreatePLDictionary(NULL, NULL);
432 for (i = 0; options[i] != NULL; i++) {
433 key = WMCreatePLString(options[i]);
435 val = WMGetFromPLDictionary(prop, key);
436 if (val) {
437 WMRetainPropList(val);
438 if (isFontOption(options[i])) {
439 char *newfont, *oldfont;
441 oldfont = WMGetFromPLString(val);
442 newfont = convertFont(oldfont, False);
443 /* newfont is a reference to old if conversion is not needed */
444 if (newfont != oldfont) {
445 WMReleasePropList(val);
446 val = WMCreatePLString(newfont);
447 wfree(newfont);
450 WMPutInPLDictionary(style, key, val);
451 WMReleasePropList(val);
453 WMReleasePropList(key);
456 val = WMGetFromPLDictionary(prop, WMCreatePLString("PixmapPath"));
457 if (val)
458 PixmapPath = val;
460 if (theme_too) {
461 for (i = 0; theme_options[i] != NULL; i++) {
462 key = WMCreatePLString(theme_options[i]);
464 val = WMGetFromPLDictionary(prop, key);
465 if (val)
466 WMPutInPLDictionary(style, key, val);
470 if (make_pack) {
471 char *path;
473 makeThemePack(style, style_file);
475 path = wmalloc(strlen(ThemePath) + 32);
476 strcpy(path, ThemePath);
477 strcat(path, "/style");
478 WMWritePropListToFile(style, path);
479 wfree(path);
480 } else {
481 if (style_file) {
482 WMWritePropListToFile(style, style_file);
483 } else {
484 puts(WMGetPropListDescription(style, True));
487 return 0;