Fixed problem with undefined EXTENDED_WINDOWSHORTCUTS in WPrefs.app
[wmaker-crm.git] / util / getstyle.c
blobc9e67f32ca21fa2d0619ca382cbdbe073a13431a
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.4"
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 "HighlightColor",
55 "HighlightTextColor",
56 "ClipTitleColor",
57 "CClipTitleColor",
58 "FTitleColor",
59 "PTitleColor",
60 "UTitleColor",
61 "FTitleBack",
62 "PTitleBack",
63 "UTitleBack",
64 "ResizebarBack",
65 "MenuTitleColor",
66 "MenuTextColor",
67 "MenuDisabledColor",
68 "MenuTitleBack",
69 "MenuTextBack",
70 "IconBack",
71 "IconTitleColor",
72 "IconTitleBack",
73 "MenuStyle",
74 NULL
78 /* table of theme related options */
79 static char *theme_options[] = {
80 "WorkspaceBack",
81 NULL
87 char *ProgName;
89 proplist_t PixmapPath = NULL;
91 char *ThemePath = NULL;
94 void
95 print_help()
97 printf("Usage: %s [OPTIONS] [FILE]\n", ProgName);
98 puts("Retrieves style/theme configuration and output to FILE or to stdout");
99 puts("");
100 puts(" -t, --theme-options output theme related options when producing a style file");
101 puts(" -p, --pack produce output as a theme pack");
102 puts(" --help display this help and exit");
103 puts(" --version output version information and exit");
107 char*
108 globalDefaultsPathForDomain(char *domain)
110 char path[1024];
111 char *tmp;
113 sprintf(path, "%s/WindowMaker/%s", SYSCONFDIR, domain);
115 tmp = malloc(strlen(path)+2);
116 assert(tmp!=NULL);
117 strcpy(tmp, path);
119 return tmp;
123 char*
124 defaultsPathForDomain(char *domain)
126 char path[1024];
127 char *gspath, *tmp;
129 gspath = getenv("GNUSTEP_USER_ROOT");
130 if (gspath) {
131 strcpy(path, gspath);
132 strcat(path, "/");
133 } else {
134 char *home;
136 home = getenv("HOME");
137 if (!home) {
138 printf("%s:could not get HOME environment variable!\n", ProgName);
139 exit(0);
141 strcpy(path, home);
142 strcat(path, "/GNUstep/");
144 strcat(path, DEFAULTS_DIR);
145 strcat(path, "/");
146 strcat(path, domain);
148 tmp = malloc(strlen(path)+2);
149 strcpy(tmp, path);
151 return tmp;
155 BOOL
156 StringCompareHook(proplist_t pl1, proplist_t pl2)
158 char *str1, *str2;
160 str1 = PLGetString(pl1);
161 str2 = PLGetString(pl2);
163 if (strcasecmp(str1, str2)==0)
164 return YES;
165 else
166 return NO;
170 void
171 abortar(char *reason)
173 char buffer[4000];
175 printf("%s: %s\n", ProgName, reason);
177 if (ThemePath) {
178 printf("Removing unfinished theme pack\n");
179 sprintf(buffer, "/bin/rm -fr \"%s\"", ThemePath);
181 if (system(buffer)!=0) {
182 printf("%s: could not execute command %s\n", ProgName, buffer);
185 exit(1);
191 char*
192 wgethomedir()
194 char *home = getenv("HOME");
195 struct passwd *user;
197 if (home)
198 return home;
200 user = getpwuid(getuid());
201 if (!user) {
202 char buffer[80];
204 sprintf(buffer, "could not get password entry for UID %i", getuid());
205 perror(buffer);
206 return "/";
208 if (!user->pw_dir) {
209 return "/";
210 } else {
211 return user->pw_dir;
216 void*
217 wmalloc(int size)
219 void *tmp;
221 tmp = malloc(size);
222 if (!tmp) {
223 abortar("out of memory");
226 return tmp;
230 char*
231 wstrdup(char *str)
233 char *tmp;
235 tmp = wmalloc(strlen(str)+1);
237 strcpy(tmp, str);
239 return tmp;
243 static char*
244 getuserhomedir(char *username)
246 struct passwd *user;
248 user = getpwnam(username);
249 if (!user) {
250 char buffer[100];
252 sprintf(buffer,"could not get password entry for user %s", username);
253 perror(buffer);
254 return NULL;
256 if (!user->pw_dir) {
257 return "/";
258 } else {
259 return user->pw_dir;
266 char*
267 wexpandpath(char *path)
269 char buffer2[PATH_MAX+2];
270 char buffer[PATH_MAX+2];
271 int i;
273 memset(buffer, 0, PATH_MAX+2);
275 if (*path=='~') {
276 char *home;
278 path++;
279 if (*path=='/' || *path==0) {
280 home = wgethomedir();
281 strcat(buffer, home);
282 } else {
283 int j;
284 j = 0;
285 while (*path!=0 && *path!='/') {
286 buffer2[j++] = *path;
287 buffer2[j] = 0;
288 path++;
290 home = getuserhomedir(buffer2);
291 if (!home)
292 return NULL;
293 strcat(buffer, home);
297 i = strlen(buffer);
299 while (*path!=0) {
300 char *tmp;
302 if (*path=='$') {
303 int j = 0;
304 path++;
305 /* expand $(HOME) or $HOME style environment variables */
306 if (*path=='(') {
307 path++;
308 while (*path!=0 && *path!=')') {
309 buffer2[j++] = *(path++);
310 buffer2[j] = 0;
312 if (*path==')')
313 path++;
314 tmp = getenv(buffer2);
315 if (!tmp) {
316 buffer[i] = 0;
317 strcat(buffer, "$(");
318 strcat(buffer, buffer2);
319 strcat(buffer, ")");
320 i += strlen(buffer2)+3;
321 } else {
322 strcat(buffer, tmp);
323 i += strlen(tmp);
325 } else {
326 while (*path!=0 && *path!='/') {
327 buffer2[j++] = *(path++);
328 buffer2[j] = 0;
330 tmp = getenv(buffer2);
331 if (!tmp) {
332 strcat(buffer, "$");
333 strcat(buffer, buffer2);
334 i += strlen(buffer2)+1;
335 } else {
336 strcat(buffer, tmp);
337 i += strlen(tmp);
340 } else {
341 buffer[i++] = *path;
342 path++;
346 return wstrdup(buffer);
351 char*
352 wfindfileinarray(proplist_t paths, char *file)
354 int i;
355 char *path;
356 int len, flen;
357 char *fullpath;
359 if (!file)
360 return NULL;
362 if (*file=='/' || *file=='~' || !paths || !PLIsArray(paths)
363 || PLGetNumberOfElements(paths)==0) {
364 if (access(file, R_OK)<0) {
365 fullpath = wexpandpath(file);
366 if (!fullpath)
367 return NULL;
369 if (access(fullpath, R_OK)<0) {
370 free(fullpath);
371 return NULL;
372 } else {
373 return fullpath;
375 } else {
376 return wstrdup(file);
380 flen = strlen(file);
381 for (i=0; i < PLGetNumberOfElements(paths); i++) {
382 proplist_t tmp;
383 char *dir;
385 tmp = PLGetArrayElement(paths, i);
386 if (!PLIsString(tmp) || !(dir = PLGetString(tmp)))
387 continue;
389 len = strlen(dir);
390 path = wmalloc(len+flen+2);
391 path = memcpy(path, dir, len);
392 path[len]=0;
393 strcat(path, "/");
394 strcat(path, file);
395 /* expand tilde */
396 fullpath = wexpandpath(path);
397 free(path);
398 if (fullpath) {
399 /* check if file is readable */
400 if (access(fullpath, R_OK)==0) {
401 return fullpath;
403 free(fullpath);
406 return NULL;
412 void
413 copyFile(char *dir, char *file)
415 char buffer[4000];
417 sprintf(buffer, "/bin/cp \"%s\" \"%s\"", file, dir);
418 if (system(buffer)!=0) {
419 printf("%s: could not copy file %s\n", ProgName, file);
424 void
425 findCopyFile(char *dir, char *file)
427 char *fullPath;
429 fullPath = wfindfileinarray(PixmapPath, file);
430 if (!fullPath) {
431 char buffer[4000];
433 sprintf(buffer, "coould not find file %s", file);
434 abortar(buffer);
436 copyFile(dir, fullPath);
437 free(fullPath);
441 char*
442 makeThemePack(proplist_t style, char *themeName)
444 proplist_t keys;
445 proplist_t key;
446 proplist_t value;
447 int i;
448 char *themeDir;
450 themeDir = wmalloc(strlen(themeName)+50);
451 sprintf(themeDir, "%s.themed", themeName);
452 ThemePath = themeDir;
454 char *tmp;
456 tmp = wmalloc(strlen(themeDir)+20);
457 sprintf(tmp, "/bin/mkdir \"%s\"", themeDir);
458 if (system(tmp)!=0) {
459 printf("%s: could not create directory %s. Probably there's already a theme with that name in this directory.\n", ProgName, themeDir);
460 exit(1);
462 free(tmp);
464 keys = PLGetAllDictionaryKeys(style);
466 for (i = 0; i < PLGetNumberOfElements(keys); i++) {
467 key = PLGetArrayElement(keys, i);
469 value = PLGetDictionaryEntry(style, key);
470 if (value && PLIsArray(value) && PLGetNumberOfElements(value) > 2) {
471 proplist_t type;
472 char *t;
474 type = PLGetArrayElement(value, 0);
475 t = PLGetString(type);
476 if (t && (strcasecmp(t, "tpixmap")==0
477 || strcasecmp(t, "spixmap")==0
478 || strcasecmp(t, "cpixmap")==0
479 || strcasecmp(t, "mpixmap")==0
480 || strcasecmp(t, "tdgradient")==0
481 || strcasecmp(t, "tvgradient")==0
482 || strcasecmp(t, "thgradient")==0)) {
483 proplist_t file;
484 char *p;
485 char *newPath;
487 file = PLGetArrayElement(value, 1);
489 p = strrchr(PLGetString(file), '/');
490 if (p) {
491 copyFile(themeDir, PLGetString(file));
493 newPath = wstrdup(p+1);
494 PLRemoveArrayElement(value, 1);
495 PLInsertArrayElement(value, PLMakeString(newPath), 1);
496 free(newPath);
497 } else {
498 findCopyFile(themeDir, PLGetString(file));
504 return themeDir;
508 int
509 main(int argc, char **argv)
511 proplist_t prop, style, key, val;
512 char *path;
513 int i, theme_too=0;
514 int make_pack = 0;
515 char *style_file = NULL;
518 ProgName = argv[0];
520 if (argc>1) {
521 for (i=1; i<argc; i++) {
522 if (strcmp(argv[i], "-p")==0
523 || strcmp(argv[i], "--pack")==0) {
524 make_pack = 1;
525 theme_too = 1;
526 } else if (strcmp(argv[i], "-t")==0
527 || strcmp(argv[i], "--theme-options")==0) {
528 theme_too++;
529 } else if (strcmp(argv[i], "--help")==0) {
530 print_help();
531 exit(0);
532 } else if (strcmp(argv[i], "--version")==0) {
533 puts(PROG_VERSION);
534 exit(0);
535 } else {
536 if (style_file!=NULL) {
537 printf("%s: invalid argument '%s'\n", argv[0],
538 style_file[0]=='-' ? style_file : argv[i]);
539 printf("Try '%s --help' for more information\n", argv[0]);
540 exit(1);
542 style_file = argv[i];
547 if (make_pack && !style_file) {
548 printf("%s: you must supply a name for the theme pack\n", ProgName);
549 exit(1);
552 PLSetStringCmpHook(StringCompareHook);
554 path = defaultsPathForDomain("WindowMaker");
556 prop = PLGetProplistWithPath(path);
557 if (!prop) {
558 printf("%s:could not load WindowMaker configuration file \"%s\".\n",
559 ProgName, path);
560 exit(1);
562 free(path);
564 /* get global value */
565 path = globalDefaultsPathForDomain("WindowMaker");
566 val = PLGetProplistWithPath(path);
567 if (val) {
568 PLMergeDictionaries(val, prop);
569 PLRelease(prop);
570 prop = val;
573 style = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
576 for (i=0; options[i]!=NULL; i++) {
577 key = PLMakeString(options[i]);
579 val = PLGetDictionaryEntry(prop, key);
580 if (val)
581 PLInsertDictionaryEntry(style, key, val);
584 val = PLGetDictionaryEntry(prop, PLMakeString("PixmapPath"));
585 if (val)
586 PixmapPath = val;
588 if (theme_too) {
589 for (i=0; theme_options[i]!=NULL; i++) {
590 key = PLMakeString(theme_options[i]);
592 val = PLGetDictionaryEntry(prop, key);
593 if (val)
594 PLInsertDictionaryEntry(style, key, val);
598 if (make_pack) {
599 char *path;
601 makeThemePack(style, style_file);
603 path = wmalloc(strlen(ThemePath)+32);
604 strcpy(path, ThemePath);
605 strcat(path, "/style");
606 PLSetFilename(style, PLMakeString(path));
607 PLSave(style, NO);
608 } else {
609 if (style_file) {
610 val = PLMakeString(style_file);
611 PLSetFilename(style, val);
612 PLSave(style, NO);
613 } else {
614 puts(PLGetDescriptionIndent(style, 0));
617 exit(0);