Add GLOBAL_DEFAULTS_SUBDIR and fix a syntax error in wmlib/Makefile.am
[wmaker-crm.git] / util / getstyle.c
blob87924ad9315f773d83be3cfa8ab451c0abaa6096
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
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20 * USA.
23 #define PROG_VERSION "getstyle (Window Maker) 0.6"
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <string.h>
30 #include <pwd.h>
31 #include <limits.h>
32 #include <assert.h>
33 #include <WINGs/WUtil.h>
35 #ifndef PATH_MAX
36 #define PATH_MAX 1024
37 #endif
39 #include "../src/wconfig.h"
41 #ifndef GLOBAL_DEFAULTS_SUBDIR
42 #define GLOBAL_DEFAULTS_SUBDIR "WindowMaker"
43 #endif
45 /* table of style related options */
46 static char *options[] = {
47 "TitleJustify",
48 "ClipTitleFont",
49 "WindowTitleFont",
50 "MenuTitleFont",
51 "MenuTextFont",
52 "IconTitleFont",
53 "DisplayFont",
54 "LargeDisplayFont",
55 "WindowTitleExtendSpace",
56 "MenuTitleExtendSpace",
57 "MenuTextExtendSpace",
58 "HighlightColor",
59 "HighlightTextColor",
60 "ClipTitleColor",
61 "CClipTitleColor",
62 "FTitleColor",
63 "PTitleColor",
64 "UTitleColor",
65 "FTitleBack",
66 "PTitleBack",
67 "UTitleBack",
68 "ResizebarBack",
69 "MenuTitleColor",
70 "MenuTextColor",
71 "MenuDisabledColor",
72 "MenuTitleBack",
73 "MenuTextBack",
74 "IconBack",
75 "IconTitleColor",
76 "IconTitleBack",
77 "MenuStyle",
78 "WindowTitleExtendSpace",
79 "MenuTitleExtendSpace",
80 "MenuTextExtendSpace",
81 NULL
84 /* table of theme related options */
85 static char *theme_options[] = {
86 "WorkspaceBack",
87 "NormalCursor",
88 "ArrowCursor",
89 "MoveCursor",
90 "ResizeCursor",
91 "TopLeftResizeCursor",
92 "TopRightResizeCursor",
93 "BottomLeftResizeCursor",
94 "BottomRightResizeCursor",
95 "VerticalResizeCursor",
96 "HorizontalResizeCursor",
97 "WaitCursor",
98 "QuestionCursor",
99 "TextCursor",
100 "SelectCursor",
101 NULL
104 /* table of style related fonts */
106 static char *font_options[] = {
107 "ClipTitleFont",
108 "WindowTitleFont",
109 "MenuTitleFont",
110 "MenuTextFont",
111 "IconTitleFont",
112 "DisplayFont",
113 "LargeDisplayFont",
114 NULL
117 char *ProgName;
119 WMPropList *PixmapPath = NULL;
121 char *ThemePath = NULL;
123 extern char *convertFont(char *font, Bool keepXLFD);
125 void print_help()
127 printf("Usage: %s [OPTIONS] [FILE]\n", ProgName);
128 puts("Retrieves style/theme configuration and output to FILE or to stdout");
129 puts("");
130 puts(" -t, --theme-options output theme related options when producing a style file");
131 puts(" -p, --pack produce output as a theme pack");
132 puts(" --help display this help and exit");
133 puts(" --version output version information and exit");
136 char *globalDefaultsPathForDomain(char *domain)
138 static char path[1024];
140 sprintf(path, "%s/%s/%s", SYSCONFDIR, GLOBAL_DEFAULTS_SUBDIR, domain);
142 return path;
145 char *defaultsPathForDomain(char *domain)
147 static char path[1024];
148 char *gspath;
150 gspath = getenv("GNUSTEP_USER_ROOT");
151 if (gspath) {
152 strcpy(path, gspath);
153 strcat(path, "/");
154 } else {
155 char *home;
157 home = getenv("HOME");
158 if (!home) {
159 printf("%s:could not get HOME environment variable!\n", ProgName);
160 exit(0);
162 strcpy(path, home);
163 strcat(path, "/GNUstep/");
165 strcat(path, DEFAULTS_DIR);
166 strcat(path, "/");
167 strcat(path, domain);
169 return path;
172 void abortar(char *reason)
174 char buffer[4000];
176 printf("%s: %s\n", ProgName, reason);
178 if (ThemePath) {
179 printf("Removing unfinished theme pack\n");
180 sprintf(buffer, "/bin/rm -fr \"%s\"", ThemePath);
182 if (system(buffer) != 0) {
183 printf("%s: could not execute command %s\n", ProgName, buffer);
186 exit(1);
189 char *wgethomedir()
191 char *home = getenv("HOME");
192 struct passwd *user;
194 if (home)
195 return home;
197 user = getpwuid(getuid());
198 if (!user) {
199 char buffer[80];
201 sprintf(buffer, "could not get password entry for UID %i", getuid());
202 perror(buffer);
203 return "/";
205 if (!user->pw_dir) {
206 return "/";
207 } else {
208 return user->pw_dir;
212 static char *getuserhomedir(char *username)
214 struct passwd *user;
216 user = getpwnam(username);
217 if (!user) {
218 char buffer[100];
220 sprintf(buffer, "could not get password entry for user %s", username);
221 perror(buffer);
222 return NULL;
224 if (!user->pw_dir) {
225 return "/";
226 } else {
227 return user->pw_dir;
231 char *wexpandpath(char *path)
233 char buffer2[PATH_MAX + 2];
234 char buffer[PATH_MAX + 2];
235 int i;
237 memset(buffer, 0, PATH_MAX + 2);
239 if (*path == '~') {
240 char *home;
242 path++;
243 if (*path == '/' || *path == 0) {
244 home = wgethomedir();
245 strcat(buffer, home);
246 } else {
247 int j;
248 j = 0;
249 while (*path != 0 && *path != '/') {
250 buffer2[j++] = *path;
251 buffer2[j] = 0;
252 path++;
254 home = getuserhomedir(buffer2);
255 if (!home)
256 return NULL;
257 strcat(buffer, home);
261 i = strlen(buffer);
263 while (*path != 0) {
264 char *tmp;
266 if (*path == '$') {
267 int j = 0;
268 path++;
269 /* expand $(HOME) or $HOME style environment variables */
270 if (*path == '(') {
271 path++;
272 while (*path != 0 && *path != ')') {
273 buffer2[j++] = *(path++);
274 buffer2[j] = 0;
276 if (*path == ')')
277 path++;
278 tmp = getenv(buffer2);
279 if (!tmp) {
280 buffer[i] = 0;
281 strcat(buffer, "$(");
282 strcat(buffer, buffer2);
283 strcat(buffer, ")");
284 i += strlen(buffer2) + 3;
285 } else {
286 strcat(buffer, tmp);
287 i += strlen(tmp);
289 } else {
290 while (*path != 0 && *path != '/') {
291 buffer2[j++] = *(path++);
292 buffer2[j] = 0;
294 tmp = getenv(buffer2);
295 if (!tmp) {
296 strcat(buffer, "$");
297 strcat(buffer, buffer2);
298 i += strlen(buffer2) + 1;
299 } else {
300 strcat(buffer, tmp);
301 i += strlen(tmp);
304 } else {
305 buffer[i++] = *path;
306 path++;
310 return wstrdup(buffer);
313 char *wfindfileinarray(WMPropList * paths, char *file)
315 int i;
316 char *path;
317 int len, flen;
318 char *fullpath;
320 if (!file)
321 return NULL;
323 if (*file == '/' || *file == '~' || !paths || !WMIsPLArray(paths)
324 || WMGetPropListItemCount(paths) == 0) {
325 if (access(file, R_OK) < 0) {
326 fullpath = wexpandpath(file);
327 if (!fullpath)
328 return NULL;
330 if (access(fullpath, R_OK) < 0) {
331 free(fullpath);
332 return NULL;
333 } else {
334 return fullpath;
336 } else {
337 return wstrdup(file);
341 flen = strlen(file);
342 for (i = 0; i < WMGetPropListItemCount(paths); i++) {
343 WMPropList *tmp;
344 char *dir;
346 tmp = WMGetFromPLArray(paths, i);
347 if (!WMIsPLString(tmp) || !(dir = WMGetFromPLString(tmp)))
348 continue;
350 len = strlen(dir);
351 path = wmalloc(len + flen + 2);
352 path = memcpy(path, dir, len);
353 path[len] = 0;
354 strcat(path, "/");
355 strcat(path, file);
356 /* expand tilde */
357 fullpath = wexpandpath(path);
358 free(path);
359 if (fullpath) {
360 /* check if file is readable */
361 if (access(fullpath, R_OK) == 0) {
362 return fullpath;
364 free(fullpath);
367 return NULL;
370 static Bool isFontOption(char *option)
372 int i;
374 for (i = 0; font_options[i] != NULL; i++) {
375 if (strcasecmp(option, font_options[i]) == 0) {
376 return True;
380 return False;
383 void copyFile(char *dir, char *file)
385 char buffer[4000];
387 sprintf(buffer, "/bin/cp \"%s\" \"%s\"", file, dir);
388 if (system(buffer) != 0) {
389 printf("%s: could not copy file %s\n", ProgName, file);
393 void findCopyFile(char *dir, char *file)
395 char *fullPath;
397 fullPath = wfindfileinarray(PixmapPath, file);
398 if (!fullPath) {
399 char buffer[4000];
401 sprintf(buffer, "could not find file %s", file);
402 abortar(buffer);
404 copyFile(dir, fullPath);
405 free(fullPath);
408 char *makeThemePack(WMPropList * style, char *themeName)
410 WMPropList *keys;
411 WMPropList *key;
412 WMPropList *value;
413 int i;
414 char *themeDir;
416 themeDir = wmalloc(strlen(themeName) + 50);
417 sprintf(themeDir, "%s.themed", themeName);
418 ThemePath = themeDir;
420 char *tmp;
422 tmp = wmalloc(strlen(themeDir) + 20);
423 sprintf(tmp, "/bin/mkdir \"%s\"", themeDir);
424 if (system(tmp) != 0) {
425 printf
426 ("%s: could not create directory %s. Probably there's already a theme with that name in this directory.\n",
427 ProgName, themeDir);
428 exit(1);
430 free(tmp);
432 keys = WMGetPLDictionaryKeys(style);
434 for (i = 0; i < WMGetPropListItemCount(keys); i++) {
435 key = WMGetFromPLArray(keys, i);
437 value = WMGetFromPLDictionary(style, key);
438 if (value && WMIsPLArray(value) && WMGetPropListItemCount(value) > 2) {
439 WMPropList *type;
440 char *t;
442 type = WMGetFromPLArray(value, 0);
443 t = WMGetFromPLString(type);
444 if (t == NULL)
445 continue;
447 if (strcasecmp(t, "tpixmap") == 0
448 || strcasecmp(t, "spixmap") == 0
449 || strcasecmp(t, "cpixmap") == 0
450 || strcasecmp(t, "mpixmap") == 0
451 || strcasecmp(t, "tdgradient") == 0
452 || strcasecmp(t, "tvgradient") == 0 || strcasecmp(t, "thgradient") == 0) {
453 WMPropList *file;
454 char *p;
455 char *newPath;
457 file = WMGetFromPLArray(value, 1);
459 p = strrchr(WMGetFromPLString(file), '/');
460 if (p) {
461 copyFile(themeDir, WMGetFromPLString(file));
463 newPath = wstrdup(p + 1);
464 WMDeleteFromPLArray(value, 1);
465 WMInsertInPLArray(value, 1, WMCreatePLString(newPath));
466 free(newPath);
467 } else {
468 findCopyFile(themeDir, WMGetFromPLString(file));
470 } else if (strcasecmp(t, "bitmap") == 0) {
471 WMPropList *file;
472 char *p;
473 char *newPath;
475 file = WMGetFromPLArray(value, 1);
477 p = strrchr(WMGetFromPLString(file), '/');
478 if (p) {
479 copyFile(themeDir, WMGetFromPLString(file));
481 newPath = wstrdup(p + 1);
482 WMDeleteFromPLArray(value, 1);
483 WMInsertInPLArray(value, 1, WMCreatePLString(newPath));
484 free(newPath);
485 } else {
486 findCopyFile(themeDir, WMGetFromPLString(file));
489 file = WMGetFromPLArray(value, 2);
491 p = strrchr(WMGetFromPLString(file), '/');
492 if (p) {
493 copyFile(themeDir, WMGetFromPLString(file));
495 newPath = wstrdup(p + 1);
496 WMDeleteFromPLArray(value, 2);
497 WMInsertInPLArray(value, 2, WMCreatePLString(newPath));
498 free(newPath);
499 } else {
500 findCopyFile(themeDir, WMGetFromPLString(file));
506 return themeDir;
509 int main(int argc, char **argv)
511 WMPropList *prop, *style, *key, *val;
512 char *path;
513 int i, theme_too = 0, make_pack = 0;
514 char *style_file = NULL;
516 ProgName = argv[0];
518 if (argc > 1) {
519 for (i = 1; i < argc; i++) {
520 if (strcmp(argv[i], "-p") == 0 || strcmp(argv[i], "--pack") == 0) {
521 make_pack = 1;
522 theme_too = 1;
523 } else if (strcmp(argv[i], "-t") == 0 || strcmp(argv[i], "--theme-options") == 0) {
524 theme_too++;
525 } else if (strcmp(argv[i], "--help") == 0) {
526 print_help();
527 exit(0);
528 } else if (strcmp(argv[i], "--version") == 0) {
529 puts(PROG_VERSION);
530 exit(0);
531 } else {
532 if (style_file != NULL) {
533 printf("%s: invalid argument '%s'\n", argv[0],
534 style_file[0] == '-' ? style_file : argv[i]);
535 printf("Try '%s --help' for more information\n", argv[0]);
536 exit(1);
538 style_file = argv[i];
543 if (make_pack && !style_file) {
544 printf("%s: you must supply a name for the theme pack\n", ProgName);
545 exit(1);
548 WMPLSetCaseSensitive(False);
550 path = defaultsPathForDomain("WindowMaker");
552 prop = WMReadPropListFromFile(path);
553 if (!prop) {
554 printf("%s:could not load WindowMaker configuration file \"%s\".\n", ProgName, path);
555 exit(1);
558 /* get global value */
559 path = globalDefaultsPathForDomain("WindowMaker");
560 val = WMReadPropListFromFile(path);
561 if (val) {
562 WMMergePLDictionaries(val, prop, True);
563 WMReleasePropList(prop);
564 prop = val;
567 style = WMCreatePLDictionary(NULL, NULL);
569 for (i = 0; options[i] != NULL; i++) {
570 key = WMCreatePLString(options[i]);
572 val = WMGetFromPLDictionary(prop, key);
573 if (val) {
574 WMRetainPropList(val);
575 if (isFontOption(options[i])) {
576 char *newfont, *oldfont;
578 oldfont = WMGetFromPLString(val);
579 newfont = convertFont(oldfont, False);
580 /* newfont is a reference to old if conversion is not needed */
581 if (newfont != oldfont) {
582 WMReleasePropList(val);
583 val = WMCreatePLString(newfont);
584 wfree(newfont);
587 WMPutInPLDictionary(style, key, val);
588 WMReleasePropList(val);
590 WMReleasePropList(key);
593 val = WMGetFromPLDictionary(prop, WMCreatePLString("PixmapPath"));
594 if (val)
595 PixmapPath = val;
597 if (theme_too) {
598 for (i = 0; theme_options[i] != NULL; i++) {
599 key = WMCreatePLString(theme_options[i]);
601 val = WMGetFromPLDictionary(prop, key);
602 if (val)
603 WMPutInPLDictionary(style, key, val);
607 if (make_pack) {
608 char *path;
610 makeThemePack(style, style_file);
612 path = wmalloc(strlen(ThemePath) + 32);
613 strcpy(path, ThemePath);
614 strcat(path, "/style");
615 WMWritePropListToFile(style, path, False);
616 wfree(path);
617 } else {
618 if (style_file) {
619 WMWritePropListToFile(style, style_file, False);
620 } else {
621 puts(WMGetPropListDescription(style, True));
624 exit(0);