Update local copy of GPLv2 and FSF address in copyrights
[wmaker-crm.git] / util / getstyle.c
bloba29b1a90cad76dd1f12b00c39cdca413434c853a
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 <unistd.h>
40 #include <WINGs/WUtil.h>
42 #define RETRY( x ) do { \
43 x; \
44 } while (errno == EINTR);
46 #ifndef PATH_MAX
47 #define PATH_MAX 1024
48 #endif
50 #include "../src/wconfig.h"
52 #ifndef GLOBAL_DEFAULTS_SUBDIR
53 #define GLOBAL_DEFAULTS_SUBDIR "WindowMaker"
54 #endif
56 /* table of style related options */
57 static char *options[] = {
58 "TitleJustify",
59 "ClipTitleFont",
60 "WindowTitleFont",
61 "MenuTitleFont",
62 "MenuTextFont",
63 "IconTitleFont",
64 "DisplayFont",
65 "LargeDisplayFont",
66 "WindowTitleExtendSpace",
67 "MenuTitleExtendSpace",
68 "MenuTextExtendSpace",
69 "HighlightColor",
70 "HighlightTextColor",
71 "ClipTitleColor",
72 "CClipTitleColor",
73 "FTitleColor",
74 "PTitleColor",
75 "UTitleColor",
76 "FTitleBack",
77 "PTitleBack",
78 "UTitleBack",
79 "ResizebarBack",
80 "MenuTitleColor",
81 "MenuTextColor",
82 "MenuDisabledColor",
83 "MenuTitleBack",
84 "MenuTextBack",
85 "IconBack",
86 "IconTitleColor",
87 "IconTitleBack",
88 "MenuStyle",
89 "WindowTitleExtendSpace",
90 "MenuTitleExtendSpace",
91 "MenuTextExtendSpace",
92 NULL
95 /* table of theme related options */
96 static char *theme_options[] = {
97 "WorkspaceBack",
98 "NormalCursor",
99 "ArrowCursor",
100 "MoveCursor",
101 "ResizeCursor",
102 "TopLeftResizeCursor",
103 "TopRightResizeCursor",
104 "BottomLeftResizeCursor",
105 "BottomRightResizeCursor",
106 "VerticalResizeCursor",
107 "HorizontalResizeCursor",
108 "WaitCursor",
109 "QuestionCursor",
110 "TextCursor",
111 "SelectCursor",
112 NULL
115 /* table of style related fonts */
117 static char *font_options[] = {
118 "ClipTitleFont",
119 "WindowTitleFont",
120 "MenuTitleFont",
121 "MenuTextFont",
122 "IconTitleFont",
123 "DisplayFont",
124 "LargeDisplayFont",
125 NULL
128 extern char *__progname;
130 WMPropList *PixmapPath = NULL;
132 char *ThemePath = NULL;
134 extern char *convertFont(char *font, Bool keepXLFD);
136 void print_help(int print_usage, int exitval)
138 printf("Usage: %s [-t] [-p] [-h] [-v] [file]\n", __progname);
139 if (print_usage) {
140 puts("Retrieves style/theme configuration and output to FILE or to stdout");
141 puts("");
142 puts(" -h, --help display this help and exit");
143 puts(" -v, --version output version information and exit");
144 puts(" -t, --theme-options output theme related options when producing a style file");
145 puts(" -p, --pack produce output as a theme pack");
147 exit(exitval);
150 void abortar(char *reason)
152 printf("%s: %s\n", __progname, reason);
153 if (ThemePath) {
154 printf("Removing unfinished theme pack\n");
155 (void)wrmdirhier(ThemePath);
157 exit(1);
160 static Bool isFontOption(char *option)
162 int i;
164 for (i = 0; font_options[i] != NULL; i++) {
165 if (strcasecmp(option, font_options[i]) == 0) {
166 return True;
170 return False;
174 * copy a file specified by `file' into `directory'. name stays.
177 * it is more or less assumed that this function will only
178 * copy reasonably-sized files
180 /* XXX: is almost like WINGs/wcolodpanel.c:fetchFile() */
181 void copyFile(char *dir, char *file)
183 FILE *src = NULL, *dst = NULL;
184 size_t nread, nwritten, len;
185 char buf[4096];
186 struct stat st;
187 char *dstpath;
189 /* only to a directory */
190 if (stat(dir, &st) != 0 || !S_ISDIR(st.st_mode))
191 return;
192 /* only copy files */
193 if (stat(file, &st) != 0 || !S_ISREG(st.st_mode))
194 return;
196 len = strlen(dir) + 1 /* / */ + strlen(file) + 1 /* '\0' */;
197 dstpath = wmalloc(len);
198 snprintf(dstpath, len, "%s/%s", dir, basename(file));
199 buf[len] = '\0';
201 RETRY( dst = fopen(dstpath, "wb") )
202 if (dst == NULL) {
203 werror(_("Could not create %s"), dstpath);
204 goto err;
207 RETRY( src = fopen(file, "rb") )
208 if (src == NULL) {
209 werror(_("Could not open %s"), file);
210 goto err;
213 do {
214 RETRY( nread = fread(buf, 1, sizeof(buf), src) )
215 if (ferror(src))
216 break;
218 RETRY( nwritten = fwrite(buf, 1, nread, dst) )
219 if (ferror(dst) || feof(src))
220 break;
222 } while (1);
224 if (ferror(src) || ferror(dst))
225 unlink(dstpath);
227 fchmod(fileno(dst), st.st_mode);
228 fsync(fileno(dst));
229 RETRY( fclose(dst) )
231 err:
232 if (src) {
233 RETRY( fclose(src) )
235 wfree(dstpath);
236 return;
239 void findCopyFile(char *dir, char *file)
241 char *fullPath;
243 fullPath = wfindfileinarray(PixmapPath, file);
244 if (!fullPath) {
245 char buffer[4000];
247 sprintf(buffer, "could not find file %s", file);
248 abortar(buffer);
250 copyFile(dir, fullPath);
251 free(fullPath);
254 void makeThemePack(WMPropList * style, char *themeName)
256 WMPropList *keys;
257 WMPropList *key;
258 WMPropList *value;
259 int i;
260 size_t themeNameLen;
261 char *themeDir, *t;
263 if ((t = wusergnusteppath()) == NULL)
264 return;
265 themeNameLen = strlen(t) + 1 /* / */ + strlen(themeName) + 8 /* ".themed/" */ + 1 /* '\0' */;
266 themeDir = wmalloc(themeNameLen);
267 snprintf(themeDir, themeNameLen, "%s/%s.themed/", t, themeName);
268 ThemePath = themeDir;
269 if (!wmkdirhier(themeDir))
270 return;
272 keys = WMGetPLDictionaryKeys(style);
274 for (i = 0; i < WMGetPropListItemCount(keys); i++) {
275 key = WMGetFromPLArray(keys, i);
277 value = WMGetFromPLDictionary(style, key);
278 if (value && WMIsPLArray(value) && WMGetPropListItemCount(value) > 2) {
279 WMPropList *type;
280 char *t;
282 type = WMGetFromPLArray(value, 0);
283 t = WMGetFromPLString(type);
284 if (t == NULL)
285 continue;
287 if (strcasecmp(t, "tpixmap") == 0 ||
288 strcasecmp(t, "spixmap") == 0 ||
289 strcasecmp(t, "cpixmap") == 0 ||
290 strcasecmp(t, "mpixmap") == 0 ||
291 strcasecmp(t, "tdgradient") == 0 ||
292 strcasecmp(t, "tvgradient") == 0 ||
293 strcasecmp(t, "thgradient") == 0) {
295 WMPropList *file;
296 char *p;
297 char *newPath;
299 file = WMGetFromPLArray(value, 1);
301 p = strrchr(WMGetFromPLString(file), '/');
302 if (p) {
303 copyFile(themeDir, WMGetFromPLString(file));
305 newPath = wstrdup(p + 1);
306 WMDeleteFromPLArray(value, 1);
307 WMInsertInPLArray(value, 1, WMCreatePLString(newPath));
308 free(newPath);
309 } else {
310 findCopyFile(themeDir, WMGetFromPLString(file));
312 } else if (strcasecmp(t, "bitmap") == 0) {
314 WMPropList *file;
315 char *p;
316 char *newPath;
318 file = WMGetFromPLArray(value, 1);
320 p = strrchr(WMGetFromPLString(file), '/');
321 if (p) {
322 copyFile(themeDir, WMGetFromPLString(file));
324 newPath = wstrdup(p + 1);
325 WMDeleteFromPLArray(value, 1);
326 WMInsertInPLArray(value, 1, WMCreatePLString(newPath));
327 free(newPath);
328 } else {
329 findCopyFile(themeDir, WMGetFromPLString(file));
332 file = WMGetFromPLArray(value, 2);
334 p = strrchr(WMGetFromPLString(file), '/');
335 if (p) {
336 copyFile(themeDir, WMGetFromPLString(file));
338 newPath = wstrdup(p + 1);
339 WMDeleteFromPLArray(value, 2);
340 WMInsertInPLArray(value, 2, WMCreatePLString(newPath));
341 free(newPath);
342 } else {
343 findCopyFile(themeDir, WMGetFromPLString(file));
350 int main(int argc, char **argv)
352 WMPropList *prop, *style, *key, *val;
353 char *path, *p;
354 int i, ch, theme_too = 0, make_pack = 0;
355 char *style_file = NULL;
357 struct option longopts[] = {
358 { "pack", no_argument, NULL, 'p' },
359 { "theme-options", no_argument, NULL, 't' },
360 { "version", no_argument, NULL, 'v' },
361 { "help", no_argument, NULL, 'h' },
362 { NULL, 0, NULL, 0 }
365 while ((ch = getopt_long(argc, argv, "ptvh", longopts, NULL)) != -1)
366 switch(ch) {
367 case 'v':
368 printf("%s (Window Maker %s)\n", __progname, VERSION);
369 return 0;
370 /* NOTREACHED */
371 case 'h':
372 print_help(1, 0);
373 /* NOTREACHED */
374 case 'p':
375 make_pack = 1;
376 theme_too = 1;
377 break;
378 case 't':
379 theme_too = 1;
380 case 0:
381 break;
382 default:
383 print_help(0, 1);
384 /* NOTREACHED */
387 argc -= optind;
388 argv += optind;
390 if (argc != 1)
391 print_help(0, 1);
393 style_file = argv[0];
394 while ((p = strchr(style_file, '/')) != NULL)
395 *p = '_';
397 if (style_file && !make_pack) /* what's this? */
398 print_help(0, 1);
400 if (make_pack && !style_file) {
401 printf("%s: you must supply a name for the theme pack\n", __progname);
402 return 1;
405 WMPLSetCaseSensitive(False);
407 path = wdefaultspathfordomain("WindowMaker");
409 prop = WMReadPropListFromFile(path);
410 if (!prop) {
411 printf("%s: could not load WindowMaker configuration file \"%s\".\n", __progname, path);
412 return 1;
415 /* get global value */
416 path = wglobaldefaultspathfordomain("WindowMaker");
418 val = WMReadPropListFromFile(path);
419 if (val) {
420 WMMergePLDictionaries(val, prop, True);
421 WMReleasePropList(prop);
422 prop = val;
425 style = WMCreatePLDictionary(NULL, NULL);
427 for (i = 0; options[i] != NULL; i++) {
428 key = WMCreatePLString(options[i]);
430 val = WMGetFromPLDictionary(prop, key);
431 if (val) {
432 WMRetainPropList(val);
433 if (isFontOption(options[i])) {
434 char *newfont, *oldfont;
436 oldfont = WMGetFromPLString(val);
437 newfont = convertFont(oldfont, False);
438 /* newfont is a reference to old if conversion is not needed */
439 if (newfont != oldfont) {
440 WMReleasePropList(val);
441 val = WMCreatePLString(newfont);
442 wfree(newfont);
445 WMPutInPLDictionary(style, key, val);
446 WMReleasePropList(val);
448 WMReleasePropList(key);
451 val = WMGetFromPLDictionary(prop, WMCreatePLString("PixmapPath"));
452 if (val)
453 PixmapPath = val;
455 if (theme_too) {
456 for (i = 0; theme_options[i] != NULL; i++) {
457 key = WMCreatePLString(theme_options[i]);
459 val = WMGetFromPLDictionary(prop, key);
460 if (val)
461 WMPutInPLDictionary(style, key, val);
465 if (make_pack) {
466 char *path;
468 makeThemePack(style, style_file);
470 path = wmalloc(strlen(ThemePath) + 32);
471 strcpy(path, ThemePath);
472 strcat(path, "/style");
473 WMWritePropListToFile(style, path);
474 wfree(path);
475 } else {
476 if (style_file) {
477 WMWritePropListToFile(style, style_file);
478 } else {
479 puts(WMGetPropListDescription(style, True));
482 return 0;