- fixed problem with WINGs based apps exiting with a "X_RotateProperties"
[wmaker-crm.git] / util / getstyle.c
blob4e779ea4ef829fde5cd28daafb282f1870ec5cdf
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 static char path[1024];
119 sprintf(path, "%s/WindowMaker/%s", SYSCONFDIR, domain);
121 return path;
125 char*
126 defaultsPathForDomain(char *domain)
128 static char path[1024];
129 char *gspath;
131 gspath = getenv("GNUSTEP_USER_ROOT");
132 if (gspath) {
133 strcpy(path, gspath);
134 strcat(path, "/");
135 } else {
136 char *home;
138 home = getenv("HOME");
139 if (!home) {
140 printf("%s:could not get HOME environment variable!\n", ProgName);
141 exit(0);
143 strcpy(path, home);
144 strcat(path, "/GNUstep/");
146 strcat(path, DEFAULTS_DIR);
147 strcat(path, "/");
148 strcat(path, domain);
150 return path;
154 BOOL
155 StringCompareHook(proplist_t pl1, proplist_t pl2)
157 char *str1, *str2;
159 str1 = PLGetString(pl1);
160 str2 = PLGetString(pl2);
162 if (strcasecmp(str1, str2)==0)
163 return YES;
164 else
165 return NO;
169 void
170 abortar(char *reason)
172 char buffer[4000];
174 printf("%s: %s\n", ProgName, reason);
176 if (ThemePath) {
177 printf("Removing unfinished theme pack\n");
178 sprintf(buffer, "/bin/rm -fr \"%s\"", ThemePath);
180 if (system(buffer)!=0) {
181 printf("%s: could not execute command %s\n", ProgName, buffer);
184 exit(1);
190 char*
191 wgethomedir()
193 char *home = getenv("HOME");
194 struct passwd *user;
196 if (home)
197 return home;
199 user = getpwuid(getuid());
200 if (!user) {
201 char buffer[80];
203 sprintf(buffer, "could not get password entry for UID %i", getuid());
204 perror(buffer);
205 return "/";
207 if (!user->pw_dir) {
208 return "/";
209 } else {
210 return user->pw_dir;
215 void*
216 wmalloc(int size)
218 void *tmp;
220 tmp = malloc(size);
221 if (!tmp) {
222 abortar("out of memory");
225 return tmp;
229 char*
230 wstrdup(char *str)
232 char *tmp;
234 tmp = wmalloc(strlen(str)+1);
236 strcpy(tmp, str);
238 return tmp;
242 static char*
243 getuserhomedir(char *username)
245 struct passwd *user;
247 user = getpwnam(username);
248 if (!user) {
249 char buffer[100];
251 sprintf(buffer,"could not get password entry for user %s", username);
252 perror(buffer);
253 return NULL;
255 if (!user->pw_dir) {
256 return "/";
257 } else {
258 return user->pw_dir;
265 char*
266 wexpandpath(char *path)
268 char buffer2[PATH_MAX+2];
269 char buffer[PATH_MAX+2];
270 int i;
272 memset(buffer, 0, PATH_MAX+2);
274 if (*path=='~') {
275 char *home;
277 path++;
278 if (*path=='/' || *path==0) {
279 home = wgethomedir();
280 strcat(buffer, home);
281 } else {
282 int j;
283 j = 0;
284 while (*path!=0 && *path!='/') {
285 buffer2[j++] = *path;
286 buffer2[j] = 0;
287 path++;
289 home = getuserhomedir(buffer2);
290 if (!home)
291 return NULL;
292 strcat(buffer, home);
296 i = strlen(buffer);
298 while (*path!=0) {
299 char *tmp;
301 if (*path=='$') {
302 int j = 0;
303 path++;
304 /* expand $(HOME) or $HOME style environment variables */
305 if (*path=='(') {
306 path++;
307 while (*path!=0 && *path!=')') {
308 buffer2[j++] = *(path++);
309 buffer2[j] = 0;
311 if (*path==')')
312 path++;
313 tmp = getenv(buffer2);
314 if (!tmp) {
315 buffer[i] = 0;
316 strcat(buffer, "$(");
317 strcat(buffer, buffer2);
318 strcat(buffer, ")");
319 i += strlen(buffer2)+3;
320 } else {
321 strcat(buffer, tmp);
322 i += strlen(tmp);
324 } else {
325 while (*path!=0 && *path!='/') {
326 buffer2[j++] = *(path++);
327 buffer2[j] = 0;
329 tmp = getenv(buffer2);
330 if (!tmp) {
331 strcat(buffer, "$");
332 strcat(buffer, buffer2);
333 i += strlen(buffer2)+1;
334 } else {
335 strcat(buffer, tmp);
336 i += strlen(tmp);
339 } else {
340 buffer[i++] = *path;
341 path++;
345 return wstrdup(buffer);
350 char*
351 wfindfileinarray(proplist_t paths, char *file)
353 int i;
354 char *path;
355 int len, flen;
356 char *fullpath;
358 if (!file)
359 return NULL;
361 if (*file=='/' || *file=='~' || !paths || !PLIsArray(paths)
362 || PLGetNumberOfElements(paths)==0) {
363 if (access(file, R_OK)<0) {
364 fullpath = wexpandpath(file);
365 if (!fullpath)
366 return NULL;
368 if (access(fullpath, R_OK)<0) {
369 free(fullpath);
370 return NULL;
371 } else {
372 return fullpath;
374 } else {
375 return wstrdup(file);
379 flen = strlen(file);
380 for (i=0; i < PLGetNumberOfElements(paths); i++) {
381 proplist_t tmp;
382 char *dir;
384 tmp = PLGetArrayElement(paths, i);
385 if (!PLIsString(tmp) || !(dir = PLGetString(tmp)))
386 continue;
388 len = strlen(dir);
389 path = wmalloc(len+flen+2);
390 path = memcpy(path, dir, len);
391 path[len]=0;
392 strcat(path, "/");
393 strcat(path, file);
394 /* expand tilde */
395 fullpath = wexpandpath(path);
396 free(path);
397 if (fullpath) {
398 /* check if file is readable */
399 if (access(fullpath, R_OK)==0) {
400 return fullpath;
402 free(fullpath);
405 return NULL;
411 void
412 copyFile(char *dir, char *file)
414 char buffer[4000];
416 sprintf(buffer, "/bin/cp \"%s\" \"%s\"", file, dir);
417 if (system(buffer)!=0) {
418 printf("%s: could not copy file %s\n", ProgName, file);
423 void
424 findCopyFile(char *dir, char *file)
426 char *fullPath;
428 fullPath = wfindfileinarray(PixmapPath, file);
429 if (!fullPath) {
430 char buffer[4000];
432 sprintf(buffer, "coould not find file %s", file);
433 abortar(buffer);
435 copyFile(dir, fullPath);
436 free(fullPath);
440 char*
441 makeThemePack(proplist_t style, char *themeName)
443 proplist_t keys;
444 proplist_t key;
445 proplist_t value;
446 int i;
447 char *themeDir;
449 themeDir = wmalloc(strlen(themeName)+50);
450 sprintf(themeDir, "%s.themed", themeName);
451 ThemePath = themeDir;
453 char *tmp;
455 tmp = wmalloc(strlen(themeDir)+20);
456 sprintf(tmp, "/bin/mkdir \"%s\"", themeDir);
457 if (system(tmp)!=0) {
458 printf("%s: could not create directory %s. Probably there's already a theme with that name in this directory.\n", ProgName, themeDir);
459 exit(1);
461 free(tmp);
463 keys = PLGetAllDictionaryKeys(style);
465 for (i = 0; i < PLGetNumberOfElements(keys); i++) {
466 key = PLGetArrayElement(keys, i);
468 value = PLGetDictionaryEntry(style, key);
469 if (value && PLIsArray(value) && PLGetNumberOfElements(value) > 2) {
470 proplist_t type;
471 char *t;
473 type = PLGetArrayElement(value, 0);
474 t = PLGetString(type);
475 if (t == NULL)
476 continue;
478 if (strcasecmp(t, "tpixmap")==0
479 || strcasecmp(t, "spixmap")==0
480 || strcasecmp(t, "cpixmap")==0
481 || strcasecmp(t, "mpixmap")==0
482 || strcasecmp(t, "tdgradient")==0
483 || strcasecmp(t, "tvgradient")==0
484 || strcasecmp(t, "thgradient")==0) {
485 proplist_t file;
486 char *p;
487 char *newPath;
489 file = PLGetArrayElement(value, 1);
491 p = strrchr(PLGetString(file), '/');
492 if (p) {
493 copyFile(themeDir, PLGetString(file));
495 newPath = wstrdup(p+1);
496 PLRemoveArrayElement(value, 1);
497 PLInsertArrayElement(value, PLMakeString(newPath), 1);
498 free(newPath);
499 } else {
500 findCopyFile(themeDir, PLGetString(file));
502 } else if (strcasecmp(t, "bitmap")==0) {
503 proplist_t file;
504 char *p;
505 char *newPath;
507 file = PLGetArrayElement(value, 1);
509 p = strrchr(PLGetString(file), '/');
510 if (p) {
511 copyFile(themeDir, PLGetString(file));
513 newPath = wstrdup(p+1);
514 PLRemoveArrayElement(value, 1);
515 PLInsertArrayElement(value, PLMakeString(newPath), 1);
516 free(newPath);
517 } else {
518 findCopyFile(themeDir, PLGetString(file));
522 file = PLGetArrayElement(value, 2);
524 p = strrchr(PLGetString(file), '/');
525 if (p) {
526 copyFile(themeDir, PLGetString(file));
528 newPath = wstrdup(p+1);
529 PLRemoveArrayElement(value, 2);
530 PLInsertArrayElement(value, PLMakeString(newPath), 2);
531 free(newPath);
532 } else {
533 findCopyFile(themeDir, PLGetString(file));
539 return themeDir;
543 int
544 main(int argc, char **argv)
546 proplist_t prop, style, key, val;
547 char *path;
548 int i, theme_too=0;
549 int make_pack = 0;
550 char *style_file = NULL;
553 ProgName = argv[0];
555 if (argc>1) {
556 for (i=1; i<argc; i++) {
557 if (strcmp(argv[i], "-p")==0
558 || strcmp(argv[i], "--pack")==0) {
559 make_pack = 1;
560 theme_too = 1;
561 } else if (strcmp(argv[i], "-t")==0
562 || strcmp(argv[i], "--theme-options")==0) {
563 theme_too++;
564 } else if (strcmp(argv[i], "--help")==0) {
565 print_help();
566 exit(0);
567 } else if (strcmp(argv[i], "--version")==0) {
568 puts(PROG_VERSION);
569 exit(0);
570 } else {
571 if (style_file!=NULL) {
572 printf("%s: invalid argument '%s'\n", argv[0],
573 style_file[0]=='-' ? style_file : argv[i]);
574 printf("Try '%s --help' for more information\n", argv[0]);
575 exit(1);
577 style_file = argv[i];
582 if (make_pack && !style_file) {
583 printf("%s: you must supply a name for the theme pack\n", ProgName);
584 exit(1);
587 PLSetStringCmpHook(StringCompareHook);
589 path = defaultsPathForDomain("WindowMaker");
591 prop = PLGetProplistWithPath(path);
592 if (!prop) {
593 printf("%s:could not load WindowMaker configuration file \"%s\".\n",
594 ProgName, path);
595 exit(1);
598 /* get global value */
599 path = globalDefaultsPathForDomain("WindowMaker");
600 val = PLGetProplistWithPath(path);
601 if (val) {
602 PLMergeDictionaries(val, prop);
603 PLRelease(prop);
604 prop = val;
607 style = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
610 for (i=0; options[i]!=NULL; i++) {
611 key = PLMakeString(options[i]);
613 val = PLGetDictionaryEntry(prop, key);
614 if (val)
615 PLInsertDictionaryEntry(style, key, val);
618 val = PLGetDictionaryEntry(prop, PLMakeString("PixmapPath"));
619 if (val)
620 PixmapPath = val;
622 if (theme_too) {
623 for (i=0; theme_options[i]!=NULL; i++) {
624 key = PLMakeString(theme_options[i]);
626 val = PLGetDictionaryEntry(prop, key);
627 if (val)
628 PLInsertDictionaryEntry(style, key, val);
632 if (make_pack) {
633 char *path;
635 makeThemePack(style, style_file);
637 path = wmalloc(strlen(ThemePath)+32);
638 strcpy(path, ThemePath);
639 strcat(path, "/style");
640 PLSetFilename(style, PLMakeString(path));
641 PLSave(style, NO);
642 } else {
643 if (style_file) {
644 val = PLMakeString(style_file);
645 PLSetFilename(style, val);
646 PLSave(style, NO);
647 } else {
648 puts(PLGetDescriptionIndent(style, 0));
651 exit(0);