default WMRootMenu is now a proplist menu instead of text
[wmaker-crm.git] / util / getstyle.c
blob0348cfb53e060ac138ad04534742c3d7598371ff
1 /* getstyle.c - outputs style related options from WindowMaker to stdout
3 * WindowMaker window manager
4 *
5 * Copyright (c) 1997~2000 Alfredo K. Kojima
6 *
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.
24 #define PROG_VERSION "getstyle (Window Maker) 0.6"
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <proplist.h>
31 #include <string.h>
32 #include <unistd.h>
33 #include <string.h>
34 #include <pwd.h>
35 #include <limits.h>
36 #include <assert.h>
38 #ifndef PATH_MAX
39 #define PATH_MAX 1024
40 #endif
42 #include "../src/wconfig.h"
44 /* table of style related options */
45 static char *options[] = {
46 "TitleJustify",
47 "ClipTitleFont",
48 "WindowTitleFont",
49 "MenuTitleFont",
50 "MenuTextFont",
51 "IconTitleFont",
52 "DisplayFont",
53 "LargeDisplayFont",
54 "WindowTitleExtendSpace",
55 "MenuTitleExtendSpace",
56 "MenuTextExtendSpace",
57 "HighlightColor",
58 "HighlightTextColor",
59 "ClipTitleColor",
60 "CClipTitleColor",
61 "FTitleColor",
62 "PTitleColor",
63 "UTitleColor",
64 "FTitleBack",
65 "PTitleBack",
66 "UTitleBack",
67 "ResizebarBack",
68 "MenuTitleColor",
69 "MenuTextColor",
70 "MenuDisabledColor",
71 "MenuTitleBack",
72 "MenuTextBack",
73 "IconBack",
74 "IconTitleColor",
75 "IconTitleBack",
76 "MenuStyle",
77 "WindowTitleExtendSpace",
78 "MenuTitleExtendSpace",
79 "MenuTextExtendSpace",
80 "NormalCursor",
81 NULL
85 /* table of theme related options */
86 static char *theme_options[] = {
87 "WorkspaceBack",
88 NULL
94 char *ProgName;
96 proplist_t PixmapPath = NULL;
98 char *ThemePath = NULL;
101 void
102 print_help()
104 printf("Usage: %s [OPTIONS] [FILE]\n", ProgName);
105 puts("Retrieves style/theme configuration and output to FILE or to stdout");
106 puts("");
107 puts(" -t, --theme-options output theme related options when producing a style file");
108 puts(" -p, --pack produce output as a theme pack");
109 puts(" --help display this help and exit");
110 puts(" --version output version information and exit");
114 char*
115 globalDefaultsPathForDomain(char *domain)
117 char path[1024];
118 char *tmp;
120 sprintf(path, "%s/WindowMaker/%s", SYSCONFDIR, domain);
122 tmp = malloc(strlen(path)+2);
123 assert(tmp!=NULL);
124 strcpy(tmp, path);
126 return tmp;
130 char*
131 defaultsPathForDomain(char *domain)
133 char path[1024];
134 char *gspath, *tmp;
136 gspath = getenv("GNUSTEP_USER_ROOT");
137 if (gspath) {
138 strcpy(path, gspath);
139 strcat(path, "/");
140 } else {
141 char *home;
143 home = getenv("HOME");
144 if (!home) {
145 printf("%s:could not get HOME environment variable!\n", ProgName);
146 exit(0);
148 strcpy(path, home);
149 strcat(path, "/GNUstep/");
151 strcat(path, DEFAULTS_DIR);
152 strcat(path, "/");
153 strcat(path, domain);
155 tmp = malloc(strlen(path)+2);
156 strcpy(tmp, path);
158 return tmp;
162 BOOL
163 StringCompareHook(proplist_t pl1, proplist_t pl2)
165 char *str1, *str2;
167 str1 = PLGetString(pl1);
168 str2 = PLGetString(pl2);
170 if (strcasecmp(str1, str2)==0)
171 return YES;
172 else
173 return NO;
177 void
178 abortar(char *reason)
180 char buffer[4000];
182 printf("%s: %s\n", ProgName, reason);
184 if (ThemePath) {
185 printf("Removing unfinished theme pack\n");
186 sprintf(buffer, "/bin/rm -fr \"%s\"", ThemePath);
188 if (system(buffer)!=0) {
189 printf("%s: could not execute command %s\n", ProgName, buffer);
192 exit(1);
198 char*
199 wgethomedir()
201 char *home = getenv("HOME");
202 struct passwd *user;
204 if (home)
205 return home;
207 user = getpwuid(getuid());
208 if (!user) {
209 char buffer[80];
211 sprintf(buffer, "could not get password entry for UID %i", getuid());
212 perror(buffer);
213 return "/";
215 if (!user->pw_dir) {
216 return "/";
217 } else {
218 return user->pw_dir;
223 void*
224 wmalloc(int size)
226 void *tmp;
228 tmp = malloc(size);
229 if (!tmp) {
230 abortar("out of memory");
233 return tmp;
237 char*
238 wstrdup(char *str)
240 char *tmp;
242 tmp = wmalloc(strlen(str)+1);
244 strcpy(tmp, str);
246 return tmp;
250 static char*
251 getuserhomedir(char *username)
253 struct passwd *user;
255 user = getpwnam(username);
256 if (!user) {
257 char buffer[100];
259 sprintf(buffer,"could not get password entry for user %s", username);
260 perror(buffer);
261 return NULL;
263 if (!user->pw_dir) {
264 return "/";
265 } else {
266 return user->pw_dir;
273 char*
274 wexpandpath(char *path)
276 char buffer2[PATH_MAX+2];
277 char buffer[PATH_MAX+2];
278 int i;
280 memset(buffer, 0, PATH_MAX+2);
282 if (*path=='~') {
283 char *home;
285 path++;
286 if (*path=='/' || *path==0) {
287 home = wgethomedir();
288 strcat(buffer, home);
289 } else {
290 int j;
291 j = 0;
292 while (*path!=0 && *path!='/') {
293 buffer2[j++] = *path;
294 buffer2[j] = 0;
295 path++;
297 home = getuserhomedir(buffer2);
298 if (!home)
299 return NULL;
300 strcat(buffer, home);
304 i = strlen(buffer);
306 while (*path!=0) {
307 char *tmp;
309 if (*path=='$') {
310 int j = 0;
311 path++;
312 /* expand $(HOME) or $HOME style environment variables */
313 if (*path=='(') {
314 path++;
315 while (*path!=0 && *path!=')') {
316 buffer2[j++] = *(path++);
317 buffer2[j] = 0;
319 if (*path==')')
320 path++;
321 tmp = getenv(buffer2);
322 if (!tmp) {
323 buffer[i] = 0;
324 strcat(buffer, "$(");
325 strcat(buffer, buffer2);
326 strcat(buffer, ")");
327 i += strlen(buffer2)+3;
328 } else {
329 strcat(buffer, tmp);
330 i += strlen(tmp);
332 } else {
333 while (*path!=0 && *path!='/') {
334 buffer2[j++] = *(path++);
335 buffer2[j] = 0;
337 tmp = getenv(buffer2);
338 if (!tmp) {
339 strcat(buffer, "$");
340 strcat(buffer, buffer2);
341 i += strlen(buffer2)+1;
342 } else {
343 strcat(buffer, tmp);
344 i += strlen(tmp);
347 } else {
348 buffer[i++] = *path;
349 path++;
353 return wstrdup(buffer);
358 char*
359 wfindfileinarray(proplist_t paths, char *file)
361 int i;
362 char *path;
363 int len, flen;
364 char *fullpath;
366 if (!file)
367 return NULL;
369 if (*file=='/' || *file=='~' || !paths || !PLIsArray(paths)
370 || PLGetNumberOfElements(paths)==0) {
371 if (access(file, R_OK)<0) {
372 fullpath = wexpandpath(file);
373 if (!fullpath)
374 return NULL;
376 if (access(fullpath, R_OK)<0) {
377 free(fullpath);
378 return NULL;
379 } else {
380 return fullpath;
382 } else {
383 return wstrdup(file);
387 flen = strlen(file);
388 for (i=0; i < PLGetNumberOfElements(paths); i++) {
389 proplist_t tmp;
390 char *dir;
392 tmp = PLGetArrayElement(paths, i);
393 if (!PLIsString(tmp) || !(dir = PLGetString(tmp)))
394 continue;
396 len = strlen(dir);
397 path = wmalloc(len+flen+2);
398 path = memcpy(path, dir, len);
399 path[len]=0;
400 strcat(path, "/");
401 strcat(path, file);
402 /* expand tilde */
403 fullpath = wexpandpath(path);
404 free(path);
405 if (fullpath) {
406 /* check if file is readable */
407 if (access(fullpath, R_OK)==0) {
408 return fullpath;
410 free(fullpath);
413 return NULL;
419 void
420 copyFile(char *dir, char *file)
422 char buffer[4000];
424 sprintf(buffer, "/bin/cp \"%s\" \"%s\"", file, dir);
425 if (system(buffer)!=0) {
426 printf("%s: could not copy file %s\n", ProgName, file);
431 void
432 findCopyFile(char *dir, char *file)
434 char *fullPath;
436 fullPath = wfindfileinarray(PixmapPath, file);
437 if (!fullPath) {
438 char buffer[4000];
440 sprintf(buffer, "coould not find file %s", file);
441 abortar(buffer);
443 copyFile(dir, fullPath);
444 free(fullPath);
448 char*
449 makeThemePack(proplist_t style, char *themeName)
451 proplist_t keys;
452 proplist_t key;
453 proplist_t value;
454 int i;
455 char *themeDir;
457 themeDir = wmalloc(strlen(themeName)+50);
458 sprintf(themeDir, "%s.themed", themeName);
459 ThemePath = themeDir;
461 char *tmp;
463 tmp = wmalloc(strlen(themeDir)+20);
464 sprintf(tmp, "/bin/mkdir \"%s\"", themeDir);
465 if (system(tmp)!=0) {
466 printf("%s: could not create directory %s. Probably there's already a theme with that name in this directory.\n", ProgName, themeDir);
467 exit(1);
469 free(tmp);
471 keys = PLGetAllDictionaryKeys(style);
473 for (i = 0; i < PLGetNumberOfElements(keys); i++) {
474 key = PLGetArrayElement(keys, i);
476 value = PLGetDictionaryEntry(style, key);
477 if (value && PLIsArray(value) && PLGetNumberOfElements(value) > 2) {
478 proplist_t type;
479 char *t;
481 type = PLGetArrayElement(value, 0);
482 t = PLGetString(type);
483 if (t == NULL)
484 continue;
486 if (strcasecmp(t, "tpixmap")==0
487 || strcasecmp(t, "spixmap")==0
488 || strcasecmp(t, "cpixmap")==0
489 || strcasecmp(t, "mpixmap")==0
490 || strcasecmp(t, "tdgradient")==0
491 || strcasecmp(t, "tvgradient")==0
492 || strcasecmp(t, "thgradient")==0) {
493 proplist_t file;
494 char *p;
495 char *newPath;
497 file = PLGetArrayElement(value, 1);
499 p = strrchr(PLGetString(file), '/');
500 if (p) {
501 copyFile(themeDir, PLGetString(file));
503 newPath = wstrdup(p+1);
504 PLRemoveArrayElement(value, 1);
505 PLInsertArrayElement(value, PLMakeString(newPath), 1);
506 free(newPath);
507 } else {
508 findCopyFile(themeDir, PLGetString(file));
510 } else if (strcasecmp(t, "bitmap")==0) {
511 proplist_t file;
512 char *p;
513 char *newPath;
515 file = PLGetArrayElement(value, 1);
517 p = strrchr(PLGetString(file), '/');
518 if (p) {
519 copyFile(themeDir, PLGetString(file));
521 newPath = wstrdup(p+1);
522 PLRemoveArrayElement(value, 1);
523 PLInsertArrayElement(value, PLMakeString(newPath), 1);
524 free(newPath);
525 } else {
526 findCopyFile(themeDir, PLGetString(file));
530 file = PLGetArrayElement(value, 2);
532 p = strrchr(PLGetString(file), '/');
533 if (p) {
534 copyFile(themeDir, PLGetString(file));
536 newPath = wstrdup(p+1);
537 PLRemoveArrayElement(value, 2);
538 PLInsertArrayElement(value, PLMakeString(newPath), 2);
539 free(newPath);
540 } else {
541 findCopyFile(themeDir, PLGetString(file));
547 return themeDir;
551 int
552 main(int argc, char **argv)
554 proplist_t prop, style, key, val;
555 char *path;
556 int i, theme_too=0;
557 int make_pack = 0;
558 char *style_file = NULL;
561 ProgName = argv[0];
563 if (argc>1) {
564 for (i=1; i<argc; i++) {
565 if (strcmp(argv[i], "-p")==0
566 || strcmp(argv[i], "--pack")==0) {
567 make_pack = 1;
568 theme_too = 1;
569 } else if (strcmp(argv[i], "-t")==0
570 || strcmp(argv[i], "--theme-options")==0) {
571 theme_too++;
572 } else if (strcmp(argv[i], "--help")==0) {
573 print_help();
574 exit(0);
575 } else if (strcmp(argv[i], "--version")==0) {
576 puts(PROG_VERSION);
577 exit(0);
578 } else {
579 if (style_file!=NULL) {
580 printf("%s: invalid argument '%s'\n", argv[0],
581 style_file[0]=='-' ? style_file : argv[i]);
582 printf("Try '%s --help' for more information\n", argv[0]);
583 exit(1);
585 style_file = argv[i];
590 if (make_pack && !style_file) {
591 printf("%s: you must supply a name for the theme pack\n", ProgName);
592 exit(1);
595 PLSetStringCmpHook(StringCompareHook);
597 path = defaultsPathForDomain("WindowMaker");
599 prop = PLGetProplistWithPath(path);
600 if (!prop) {
601 printf("%s:could not load WindowMaker configuration file \"%s\".\n",
602 ProgName, path);
603 exit(1);
605 free(path);
607 /* get global value */
608 path = globalDefaultsPathForDomain("WindowMaker");
609 val = PLGetProplistWithPath(path);
610 if (val) {
611 PLMergeDictionaries(val, prop);
612 PLRelease(prop);
613 prop = val;
616 style = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
619 for (i=0; options[i]!=NULL; i++) {
620 key = PLMakeString(options[i]);
622 val = PLGetDictionaryEntry(prop, key);
623 if (val)
624 PLInsertDictionaryEntry(style, key, val);
627 val = PLGetDictionaryEntry(prop, PLMakeString("PixmapPath"));
628 if (val)
629 PixmapPath = val;
631 if (theme_too) {
632 for (i=0; theme_options[i]!=NULL; i++) {
633 key = PLMakeString(theme_options[i]);
635 val = PLGetDictionaryEntry(prop, key);
636 if (val)
637 PLInsertDictionaryEntry(style, key, val);
641 if (make_pack) {
642 char *path;
644 makeThemePack(style, style_file);
646 path = wmalloc(strlen(ThemePath)+32);
647 strcpy(path, ThemePath);
648 strcat(path, "/style");
649 PLSetFilename(style, PLMakeString(path));
650 PLSave(style, NO);
651 } else {
652 if (style_file) {
653 val = PLMakeString(style_file);
654 PLSetFilename(style, val);
655 PLSave(style, NO);
656 } else {
657 puts(PLGetDescriptionIndent(style, 0));
660 exit(0);