- fixed problem with WINGs based apps exiting with a "X_RotateProperties"
[wmaker-crm.git] / util / setstyle.c
blob4b98d83117b6fa55bd2b0317a9801a600aa1c507
1 /* setstyle.c - loads style related options to wmaker
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 "setstyle (Window Maker) 0.6"
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <proplist.h>
29 #include <sys/stat.h>
30 #include <unistd.h>
32 #include <X11/Xlib.h>
34 #include <string.h>
36 #include "../src/wconfig.h"
38 #define MAX_OPTIONS 128
40 char *FontOptions[] = {
41 "IconTitleFont",
42 "ClipTitleFont",
43 "DisplayFont",
44 "LargeDisplayFont",
45 "MenuTextFont",
46 "MenuTitleFont",
47 "WindowTitleFont",
48 NULL
53 char *ProgName;
54 int ignoreFonts = 0;
56 Display *dpy;
60 proplist_t readBlackBoxStyle(char *path);
64 char*
65 defaultsPathForDomain(char *domain)
67 static char path[1024];
68 char *gspath;
70 gspath = getenv("GNUSTEP_USER_ROOT");
71 if (gspath) {
72 strcpy(path, gspath);
73 strcat(path, "/");
74 } else {
75 char *home;
77 home = getenv("HOME");
78 if (!home) {
79 printf("%s:could not get HOME environment variable!\n", ProgName);
80 exit(0);
83 strcpy(path, home);
84 strcat(path, "/GNUstep/");
86 strcat(path, DEFAULTS_DIR);
87 strcat(path, "/");
88 strcat(path, domain);
90 return path;
95 void
96 hackPathInTexture(proplist_t texture, char *prefix)
98 proplist_t type;
99 char *t;
101 /* get texture type */
102 type = PLGetArrayElement(texture, 0);
103 t = PLGetString(type);
104 if (t == NULL)
105 return;
106 if (strcasecmp(t, "tpixmap")==0
107 || strcasecmp(t, "spixmap")==0
108 || strcasecmp(t, "mpixmap")==0
109 || strcasecmp(t, "cpixmap")==0
110 || strcasecmp(t, "tvgradient")==0
111 || strcasecmp(t, "thgradient")==0
112 || strcasecmp(t, "tdgradient")==0) {
113 proplist_t file;
114 char buffer[4018];
116 /* get pixmap file path */
117 file = PLGetArrayElement(texture, 1);
118 sprintf(buffer, "%s/%s", prefix, PLGetString(file));
119 /* replace path with full path */
120 PLRemoveArrayElement(texture, 1);
121 PLInsertArrayElement(texture, PLMakeString(buffer), 1);
122 } else if (strcasecmp(t, "bitmap") == 0) {
123 proplist_t file;
124 char buffer[4018];
126 /* get bitmap file path */
127 file = PLGetArrayElement(texture, 1);
128 sprintf(buffer, "%s/%s", prefix, PLGetString(file));
129 /* replace path with full path */
130 PLRemoveArrayElement(texture, 1);
131 PLInsertArrayElement(texture, PLMakeString(buffer), 1);
133 /* get mask file path */
134 file = PLGetArrayElement(texture, 2);
135 sprintf(buffer, "%s/%s", prefix, PLGetString(file));
136 /* replace path with full path */
137 PLRemoveArrayElement(texture, 2);
138 PLInsertArrayElement(texture, PLMakeString(buffer), 2);
143 void
144 hackPaths(proplist_t style, char *prefix)
146 proplist_t keys;
147 proplist_t key;
148 proplist_t value;
149 int i;
152 keys = PLGetAllDictionaryKeys(style);
154 for (i = 0; i < PLGetNumberOfElements(keys); i++) {
155 key = PLGetArrayElement(keys, i);
157 value = PLGetDictionaryEntry(style, key);
158 if (!value)
159 continue;
161 if (strcasecmp(PLGetString(key), "WorkspaceSpecificBack")==0) {
162 if (PLIsArray(value)) {
163 int j;
164 proplist_t texture;
166 for (j = 0; j < PLGetNumberOfElements(value); j++) {
167 texture = PLGetArrayElement(value, j);
169 if (texture && PLIsArray(texture)
170 && PLGetNumberOfElements(texture) > 2) {
172 hackPathInTexture(texture, prefix);
176 } else {
178 if (PLIsArray(value) && PLGetNumberOfElements(value) > 2) {
180 hackPathInTexture(value, prefix);
188 static proplist_t
189 getColor(proplist_t texture)
191 proplist_t value, type;
192 char *str;
194 type = PLGetArrayElement(texture, 0);
195 if (!type)
196 return NULL;
198 value = NULL;
200 str = PLGetString(type);
201 if (strcasecmp(str, "solid")==0) {
202 value = PLGetArrayElement(texture, 1);
203 } else if (strcasecmp(str, "dgradient")==0
204 || strcasecmp(str, "hgradient")==0
205 || strcasecmp(str, "vgradient")==0) {
206 proplist_t c1, c2;
207 int r1, g1, b1, r2, g2, b2;
208 char buffer[32];
210 c1 = PLGetArrayElement(texture, 1);
211 c2 = PLGetArrayElement(texture, 2);
212 if (!dpy) {
213 if (sscanf(PLGetString(c1), "#%2x%2x%2x", &r1, &g1, &b1)==3
214 && sscanf(PLGetString(c2), "#%2x%2x%2x", &r2, &g2, &b2)==3) {
215 sprintf(buffer, "#%02x%02x%02x", (r1+r2)/2, (g1+g2)/2,
216 (b1+b2)/2);
217 value = PLMakeString(buffer);
218 } else {
219 value = c1;
221 } else {
222 XColor color1;
223 XColor color2;
225 XParseColor(dpy, DefaultColormap(dpy, DefaultScreen(dpy)),
226 PLGetString(c1), &color1);
227 XParseColor(dpy, DefaultColormap(dpy, DefaultScreen(dpy)),
228 PLGetString(c2), &color2);
230 sprintf(buffer, "#%02x%02x%02x",
231 (color1.red+color2.red)>>9,
232 (color1.green+color2.green)>>9,
233 (color1.blue+color2.blue)>>9);
234 value = PLMakeString(buffer);
236 } else if (strcasecmp(str, "mdgradient")==0
237 || strcasecmp(str, "mhgradient")==0
238 || strcasecmp(str, "mvgradient")==0) {
240 value = PLGetArrayElement(texture, 1);
242 } else if (strcasecmp(str, "tpixmap")==0
243 || strcasecmp(str, "cpixmap")==0
244 || strcasecmp(str, "spixmap")==0) {
246 value = PLGetArrayElement(texture, 2);
249 return value;
254 * since some of the options introduce incompatibilities, we will need
255 * to do a kluge here or the themes ppl will get real annoying.
256 * So, treat for the absence of the following options:
257 * IconTitleColor
258 * IconTitleBack
260 void
261 hackStyle(proplist_t style)
263 proplist_t keys;
264 proplist_t tmp;
265 int i;
266 int foundIconTitle = 0;
267 int foundResizebarBack = 0;
269 keys = PLGetAllDictionaryKeys(style);
271 for (i = 0; i < PLGetNumberOfElements(keys); i++) {
272 char *str;
274 tmp = PLGetArrayElement(keys, i);
275 str = PLGetString(tmp);
276 if (str) {
277 int j, found;
279 if (ignoreFonts) {
280 for (j = 0, found = 0; FontOptions[j]!=NULL; j++) {
281 if (strcasecmp(str, FontOptions[j])==0) {
282 PLRemoveDictionaryEntry(style, tmp);
283 found = 1;
284 break;
287 if (found)
288 continue;
291 if (strcasecmp(str, "IconTitleColor")==0
292 || strcasecmp(str, "IconTitleBack")==0) {
293 foundIconTitle = 1;
294 } else if (strcasecmp(str, "ResizebarBack")==0) {
295 foundResizebarBack = 1;
300 if (!foundIconTitle) {
301 /* set the default values */
302 tmp = PLGetDictionaryEntry(style, PLMakeString("FTitleColor"));
303 if (tmp) {
304 PLInsertDictionaryEntry(style, PLMakeString("IconTitleColor"),
305 tmp);
308 tmp = PLGetDictionaryEntry(style, PLMakeString("FTitleBack"));
309 if (tmp) {
310 proplist_t value;
312 value = getColor(tmp);
314 if (value) {
315 PLInsertDictionaryEntry(style, PLMakeString("IconTitleBack"),
316 value);
321 if (!foundResizebarBack) {
322 /* set the default values */
323 tmp = PLGetDictionaryEntry(style, PLMakeString("UTitleBack"));
324 if (tmp) {
325 proplist_t value;
327 value = getColor(tmp);
329 if (value) {
330 proplist_t t;
332 t = PLMakeArrayFromElements(PLMakeString("solid"), value,
333 NULL);
334 PLInsertDictionaryEntry(style, PLMakeString("ResizebarBack"),
341 if (!PLGetDictionaryEntry(style, PLMakeString("MenuStyle"))) {
342 PLInsertDictionaryEntry(style, PLMakeString("MenuStyle"),
343 PLMakeString("normal"));
348 BOOL
349 StringCompareHook(proplist_t pl1, proplist_t pl2)
351 char *str1, *str2;
353 str1 = PLGetString(pl1);
354 str2 = PLGetString(pl2);
356 if (strcasecmp(str1, str2)==0)
357 return YES;
358 else
359 return NO;
363 void
364 print_help()
366 printf("Usage: %s [OPTIONS] FILE\n", ProgName);
367 puts("Reads style/theme configuration from FILE and updates Window Maker.");
368 puts("");
369 puts(" --no-fonts ignore font related options");
370 puts(" --ignore <option> ignore changes in the specified option");
371 puts(" --help display this help and exit");
373 puts(" --format <format> specifies the format of the theme to be converted");
375 puts(" --version output version information and exit");
376 puts("");
377 puts("Supported formats: blackbox");
381 #define F_BLACKBOX 1
383 int
384 main(int argc, char **argv)
386 proplist_t prop, style;
387 char *path;
388 char *file = NULL;
389 struct stat statbuf;
390 int i;
391 int ignoreCount = 0;
392 char *ignoreList[MAX_OPTIONS];
394 dpy = XOpenDisplay("");
396 ProgName = argv[0];
398 if (argc<2) {
399 printf("%s: missing argument\n", ProgName);
400 printf("Try '%s --help' for more information\n", ProgName);
401 exit(1);
404 for (i = 1; i < argc; i++) {
405 if (strcmp("--ignore", argv[i])==0) {
406 i++;
407 if (i == argc) {
408 printf("%s: missing argument for option --ignore\n", ProgName);
409 exit(1);
411 ignoreList[ignoreCount++] = argv[i];
413 } else if (strcmp("--no-fonts", argv[i])==0) {
414 ignoreFonts = 1;
415 } else if (strcmp("--version", argv[i])==0) {
416 puts(PROG_VERSION);
417 exit(0);
418 } else if (strcmp("--help", argv[i])==0) {
419 print_help();
420 exit(0);
421 #if 0
422 } else if (strcmp("--format", argv[i])==0) {
423 i++;
424 if (i == argc) {
425 printf("%s: missing argument for option --format\n", ProgName);
426 exit(1);
428 if (strcasecmp(argv[i], "blackbox")==0) {
429 format = F_BLACKBOX;
430 } else {
431 printf("%s: unknown theme format '%s'\n", ProgName, argv[i]);
432 exit(1);
434 #endif
435 } else {
436 if (file) {
437 printf("%s: invalid argument '%s'\n", ProgName, argv[i]);
438 printf("Try '%s --help' for more information\n", ProgName);
439 exit(1);
441 file = argv[i];
445 PLSetStringCmpHook(StringCompareHook);
447 path = defaultsPathForDomain("WindowMaker");
449 prop = PLGetProplistWithPath(path);
450 if (!prop) {
451 perror(path);
452 printf("%s:could not load WindowMaker configuration file.\n",
453 ProgName);
454 exit(1);
457 if (stat(file, &statbuf) < 0) {
458 perror(file);
459 exit(1);
461 #if 0
462 if (format == F_BLACKBOX) {
463 style = readBlackBoxStyle(file);
464 if (!style) {
465 printf("%s: could not open style file\n", ProgName);
466 exit(1);
468 } else
469 #endif
471 if (S_ISDIR(statbuf.st_mode)) {
472 char buffer[4018];
473 char *prefix;
474 /* theme pack */
476 if (*argv[argc-1] != '/') {
477 if (!getcwd(buffer, 4000)) {
478 printf("%s: complete path for %s is too long\n", ProgName,
479 file);
480 exit(1);
482 if (strlen(buffer) + strlen(file) > 4000) {
483 printf("%s: complete path for %s is too long\n", ProgName,
484 file);
485 exit(1);
487 strcat(buffer, "/");
488 } else {
489 buffer[0] = 0;
491 strcat(buffer, file);
493 prefix = malloc(strlen(buffer)+10);
494 if (!prefix) {
495 printf("%s: out of memory\n", ProgName);
496 exit(1);
498 strcpy(prefix, buffer);
500 strcat(buffer, "/style");
502 style = PLGetProplistWithPath(buffer);
503 if (!style) {
504 perror(buffer);
505 printf("%s:could not load style file.\n", ProgName);
506 exit(1);
509 hackPaths(style, prefix);
510 free(prefix);
511 } else {
512 /* normal style file */
514 style = PLGetProplistWithPath(file);
515 if (!style) {
516 perror(file);
517 printf("%s:could not load style file.\n", ProgName);
518 exit(1);
523 if (!PLIsDictionary(style)) {
524 printf("%s: '%s' is not a style file/theme\n", ProgName, file);
525 exit(1);
528 hackStyle(style);
530 if (ignoreCount > 0) {
531 for (i = 0; i < ignoreCount; i++) {
532 PLRemoveDictionaryEntry(style, PLMakeString(ignoreList[i]));
536 PLMergeDictionaries(prop, style);
538 PLSave(prop, YES);
540 XEvent ev;
542 if (dpy) {
543 int i;
544 char *msg = "Reconfigure";
546 memset(&ev, 0, sizeof(XEvent));
548 ev.xclient.type = ClientMessage;
549 ev.xclient.message_type = XInternAtom(dpy, "_WINDOWMAKER_COMMAND",
550 False);
551 ev.xclient.window = DefaultRootWindow(dpy);
552 ev.xclient.format = 8;
554 for (i = 0; i <= strlen(msg); i++) {
555 ev.xclient.data.b[i] = msg[i];
557 XSendEvent(dpy, DefaultRootWindow(dpy), False,
558 SubstructureRedirectMask, &ev);
559 XFlush(dpy);
563 exit(0);
567 #if 0
568 char*
569 getToken(char *str, int i, char *buf)
575 proplist_t
576 readBlackBoxStyle(char *path)
578 FILE *f;
579 char buffer[128], char token[128];
580 proplist_t style;
581 proplist_t p;
583 f = fopen(path, "r");
584 if (!f) {
585 perror(path);
586 return NULL;
589 while (1) {
590 if (!fgets(buffer, 127, f))
591 break;
593 if (strncasecmp(buffer, "menu.title:", 11)==0) {
598 #endif