ResizebarBack option
[wmaker-crm.git] / util / getstyle.c
blob1b815d8d27ff0401bf62c8ab5a9911a049f0b2ac
1 /* getstyle.c - outputs style related options from WindowMaker to stdout
3 * WindowMaker window manager
4 *
5 * Copyright (c) 1997, 1998 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.3"
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 "HighlightColor",
54 "HighlightTextColor",
55 "ClipTitleColor",
56 "CClipTitleColor",
57 "FTitleColor",
58 "PTitleColor",
59 "UTitleColor",
60 "FTitleBack",
61 "PTitleBack",
62 "UTitleBack",
63 "ResizebarBack",
64 "MenuTitleColor",
65 "MenuTextColor",
66 "MenuDisabledColor",
67 "MenuTitleBack",
68 "MenuTextBack",
69 "IconBack",
70 "IconTitleColor",
71 "IconTitleBack",
72 "MenuStyle",
73 #ifdef TITLE_TEXT_SHADOW
74 "Shadow",
75 "FShadowColor",
76 "PShadowColor",
77 "UShadowColor",
78 "MShadowColor",
79 #endif
80 NULL
84 /* table of theme related options */
85 static char *theme_options[] = {
86 "WorkspaceBack",
87 NULL
93 char *ProgName;
95 proplist_t PixmapPath = NULL;
97 char *ThemePath = NULL;
100 void
101 print_help()
103 printf("Usage: %s [OPTIONS] [FILE]\n", ProgName);
104 puts("Retrieves style/theme configuration and output to FILE or to stdout");
105 puts("");
106 puts(" -t, --theme-options output theme related options when producing a style file");
107 puts(" -p, --pack produce output as a theme pack");
108 puts(" --help display this help and exit");
109 puts(" --version output version information and exit");
113 char*
114 globalDefaultsPathForDomain(char *domain)
116 char path[1024];
117 char *tmp;
119 sprintf(path, "%s/%s", SYSCONFDIR, domain);
121 tmp = malloc(strlen(path)+2);
122 assert(tmp!=NULL);
123 strcpy(tmp, path);
125 return tmp;
129 char*
130 defaultsPathForDomain(char *domain)
132 char path[1024];
133 char *gspath, *tmp;
135 gspath = getenv("GNUSTEP_USER_ROOT");
136 if (gspath) {
137 strcpy(path, gspath);
138 strcat(path, "/");
139 } else {
140 char *home;
142 home = getenv("HOME");
143 if (!home) {
144 printf("%s:could not get HOME environment variable!\n", ProgName);
145 exit(0);
147 strcpy(path, home);
148 strcat(path, "/GNUstep/");
150 strcat(path, DEFAULTS_DIR);
151 strcat(path, "/");
152 strcat(path, domain);
154 tmp = malloc(strlen(path)+2);
155 strcpy(tmp, path);
157 return tmp;
161 BOOL
162 StringCompareHook(proplist_t pl1, proplist_t pl2)
164 char *str1, *str2;
166 str1 = PLGetString(pl1);
167 str2 = PLGetString(pl2);
169 if (strcasecmp(str1, str2)==0)
170 return YES;
171 else
172 return NO;
176 void
177 abortar(char *reason)
179 char buffer[4000];
181 printf("%s: %s\n", ProgName, reason);
183 if (ThemePath) {
184 printf("Removing unfinished theme pack\n");
185 sprintf(buffer, "/bin/rm -fr %s", ThemePath);
187 if (system(buffer)!=0) {
188 printf("%s: could not execute command %s\n", ProgName, buffer);
191 exit(1);
197 char*
198 wgethomedir()
200 char *home = getenv("HOME");
201 struct passwd *user;
203 if (home)
204 return home;
206 user = getpwuid(getuid());
207 if (!user) {
208 char buffer[80];
210 sprintf(buffer, "could not get password entry for UID %i", getuid());
211 perror(buffer);
212 return "/";
214 if (!user->pw_dir) {
215 return "/";
216 } else {
217 return user->pw_dir;
222 void*
223 wmalloc(int size)
225 void *tmp;
227 tmp = malloc(size);
228 if (!tmp) {
229 abortar("out of memory");
232 return tmp;
236 char*
237 wstrdup(char *str)
239 char *tmp;
241 tmp = wmalloc(strlen(str)+1);
243 strcpy(tmp, str);
245 return tmp;
249 static char*
250 getuserhomedir(char *username)
252 struct passwd *user;
254 user = getpwnam(username);
255 if (!user) {
256 char buffer[100];
258 sprintf(buffer,"could not get password entry for user %s", username);
259 perror(buffer);
260 return NULL;
262 if (!user->pw_dir) {
263 return "/";
264 } else {
265 return user->pw_dir;
272 char*
273 wexpandpath(char *path)
275 char buffer2[PATH_MAX+2];
276 char buffer[PATH_MAX+2];
277 int i;
279 memset(buffer, 0, PATH_MAX+2);
281 if (*path=='~') {
282 char *home;
284 path++;
285 if (*path=='/' || *path==0) {
286 home = wgethomedir();
287 strcat(buffer, home);
288 } else {
289 int j;
290 j = 0;
291 while (*path!=0 && *path!='/') {
292 buffer2[j++] = *path;
293 buffer2[j] = 0;
294 path++;
296 home = getuserhomedir(buffer2);
297 if (!home)
298 return NULL;
299 strcat(buffer, home);
303 i = strlen(buffer);
305 while (*path!=0) {
306 char *tmp;
308 if (*path=='$') {
309 int j = 0;
310 path++;
311 /* expand $(HOME) or $HOME style environment variables */
312 if (*path=='(') {
313 path++;
314 while (*path!=0 && *path!=')') {
315 buffer2[j++] = *(path++);
316 buffer2[j] = 0;
318 if (*path==')')
319 path++;
320 tmp = getenv(buffer2);
321 if (!tmp) {
322 buffer[i] = 0;
323 strcat(buffer, "$(");
324 strcat(buffer, buffer2);
325 strcat(buffer, ")");
326 i += strlen(buffer2)+3;
327 } else {
328 strcat(buffer, tmp);
329 i += strlen(tmp);
331 } else {
332 while (*path!=0 && *path!='/') {
333 buffer2[j++] = *(path++);
334 buffer2[j] = 0;
336 tmp = getenv(buffer2);
337 if (!tmp) {
338 strcat(buffer, "$");
339 strcat(buffer, buffer2);
340 i += strlen(buffer2)+1;
341 } else {
342 strcat(buffer, tmp);
343 i += strlen(tmp);
346 } else {
347 buffer[i++] = *path;
348 path++;
352 return wstrdup(buffer);
357 char*
358 wfindfileinarray(proplist_t paths, char *file)
360 int i;
361 char *path;
362 int len, flen;
363 char *fullpath;
365 if (!file)
366 return NULL;
368 if (*file=='/' || *file=='~' || !paths || !PLIsArray(paths)
369 || PLGetNumberOfElements(paths)==0) {
370 if (access(file, R_OK)<0) {
371 fullpath = wexpandpath(file);
372 if (!fullpath)
373 return NULL;
375 if (access(fullpath, R_OK)<0) {
376 free(fullpath);
377 return NULL;
378 } else {
379 return fullpath;
381 } else {
382 return wstrdup(file);
386 flen = strlen(file);
387 for (i=0; i < PLGetNumberOfElements(paths); i++) {
388 proplist_t tmp;
389 char *dir;
391 tmp = PLGetArrayElement(paths, i);
392 if (!PLIsString(tmp) || !(dir = PLGetString(tmp)))
393 continue;
395 len = strlen(dir);
396 path = wmalloc(len+flen+2);
397 path = memcpy(path, dir, len);
398 path[len]=0;
399 strcat(path, "/");
400 strcat(path, file);
401 /* expand tilde */
402 fullpath = wexpandpath(path);
403 free(path);
404 if (fullpath) {
405 /* check if file is readable */
406 if (access(fullpath, R_OK)==0) {
407 return fullpath;
409 free(fullpath);
412 return NULL;
418 void
419 copyFile(char *dir, char *file)
421 char buffer[4000];
423 sprintf(buffer, "/bin/cp %s %s", file, dir);
424 if (system(buffer)!=0) {
425 printf("%s: could not copy file %s\n", ProgName, file);
430 void
431 findCopyFile(char *dir, char *file)
433 char *fullPath;
435 fullPath = wfindfileinarray(PixmapPath, file);
436 if (!fullPath) {
437 char buffer[4000];
439 sprintf(buffer, "coould not find file %s", file);
440 abortar(buffer);
442 copyFile(dir, fullPath);
443 free(fullPath);
447 char*
448 makeThemePack(proplist_t style, char *themeName)
450 proplist_t keys;
451 proplist_t key;
452 proplist_t value;
453 int i;
454 char *themeDir;
456 themeDir = wmalloc(strlen(themeName)+50);
457 sprintf(themeDir, "%s.themed", themeName);
458 ThemePath = themeDir;
460 char *tmp;
462 tmp = wmalloc(strlen(themeDir)+20);
463 sprintf(tmp, "/bin/mkdir %s", themeDir);
464 if (system(tmp)!=0) {
465 printf("%s: could not create directory %s. Probably there's already a theme with that name in this directory.\n", ProgName, themeDir);
466 exit(1);
468 free(tmp);
470 keys = PLGetAllDictionaryKeys(style);
472 for (i = 0; i < PLGetNumberOfElements(keys); i++) {
473 key = PLGetArrayElement(keys, i);
475 value = PLGetDictionaryEntry(style, key);
476 if (value && PLIsArray(value) && PLGetNumberOfElements(value) > 2) {
477 proplist_t type;
478 char *t;
480 type = PLGetArrayElement(value, 0);
481 t = PLGetString(type);
482 if (t && (strcasecmp(t, "tpixmap")==0
483 || strcasecmp(t, "spixmap")==0
484 || strcasecmp(t, "cpixmap")==0
485 || strcasecmp(t, "mpixmap")==0
486 || strcasecmp(t, "tdgradient")==0
487 || strcasecmp(t, "tvgradient")==0
488 || strcasecmp(t, "thgradient")==0)) {
489 proplist_t file;
490 char *p;
491 char *newPath;
493 file = PLGetArrayElement(value, 1);
495 p = strrchr(PLGetString(file), '/');
496 if (p) {
497 copyFile(themeDir, PLGetString(file));
499 newPath = wstrdup(p+1);
500 PLRemoveArrayElement(value, 1);
501 PLInsertArrayElement(value, PLMakeString(newPath), 1);
502 free(newPath);
503 } else {
504 findCopyFile(themeDir, PLGetString(file));
510 return themeDir;
514 int
515 main(int argc, char **argv)
517 proplist_t prop, style, key, val;
518 char *path;
519 int i, theme_too=0;
520 int make_pack = 0;
521 char *style_file = NULL;
524 ProgName = argv[0];
526 if (argc>1) {
527 for (i=1; i<argc; i++) {
528 if (strcmp(argv[i], "-p")==0
529 || strcmp(argv[i], "--pack")==0) {
530 make_pack = 1;
531 theme_too = 1;
532 } else if (strcmp(argv[i], "-t")==0
533 || strcmp(argv[i], "--theme-options")==0) {
534 theme_too++;
535 } else if (strcmp(argv[i], "--help")==0) {
536 print_help();
537 exit(0);
538 } else if (strcmp(argv[i], "--version")==0) {
539 puts(PROG_VERSION);
540 exit(0);
541 } else {
542 if (style_file!=NULL) {
543 printf("%s: invalid argument '%s'\n", argv[0],
544 style_file[0]=='-' ? style_file : argv[i]);
545 printf("Try '%s --help' for more information\n", argv[0]);
546 exit(1);
548 style_file = argv[i];
553 if (make_pack && !style_file) {
554 printf("%s: you must supply a name for the theme pack\n", ProgName);
555 exit(1);
558 PLSetStringCmpHook(StringCompareHook);
560 path = defaultsPathForDomain("WindowMaker");
562 prop = PLGetProplistWithPath(path);
563 if (!prop) {
564 printf("%s:could not load WindowMaker configuration file \"%s\".\n",
565 ProgName, path);
566 exit(1);
568 free(path);
570 /* get global value */
571 path = globalDefaultsPathForDomain("WindowMaker");
572 val = PLGetProplistWithPath(path);
573 if (val) {
574 PLMergeDictionaries(val, prop);
575 PLRelease(prop);
576 prop = val;
579 style = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
582 for (i=0; options[i]!=NULL; i++) {
583 key = PLMakeString(options[i]);
585 val = PLGetDictionaryEntry(prop, key);
586 if (val)
587 PLInsertDictionaryEntry(style, key, val);
590 val = PLGetDictionaryEntry(prop, PLMakeString("PixmapPath"));
591 if (val)
592 PixmapPath = val;
594 if (theme_too) {
595 for (i=0; theme_options[i]!=NULL; i++) {
596 key = PLMakeString(theme_options[i]);
598 val = PLGetDictionaryEntry(prop, key);
599 if (val)
600 PLInsertDictionaryEntry(style, key, val);
604 if (make_pack) {
605 char *path;
607 makeThemePack(style, style_file);
609 path = wmalloc(strlen(ThemePath)+32);
610 strcpy(path, ThemePath);
611 strcat(path, "/style");
612 PLSetFilename(style, PLMakeString(path));
613 PLSave(style, NO);
614 } else {
615 if (style_file) {
616 val = PLMakeString(style_file);
617 PLSetFilename(style, val);
618 PLSave(style, NO);
619 } else {
620 puts(PLGetDescriptionIndent(style, 0));
623 exit(0);