ResizebarBack option
[wmaker-crm.git] / util / setstyle.c
blob2330b2d0c2df197e9c6d93ec14c742aa328829d4
1 /* setstyle.c - loads style related options to wmaker
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 "setstyle (Window Maker) 0.3"
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"
39 char *FontOptions[] = {
40 "IconTitleFont",
41 "ClipTitleFont",
42 "DisplayFont",
43 "MenuTextFont",
44 "MenuTitleFont",
45 "WindowTitleFont",
46 NULL
51 char *ProgName;
52 int ignoreFonts = 0;
54 Display *dpy;
56 char*
57 defaultsPathForDomain(char *domain)
59 char path[1024];
60 char *gspath, *tmp;
62 gspath = getenv("GNUSTEP_USER_ROOT");
63 if (gspath) {
64 strcpy(path, gspath);
65 strcat(path, "/");
66 } else {
67 char *home;
69 home = getenv("HOME");
70 if (!home) {
71 printf("%s:could not get HOME environment variable!\n", ProgName);
72 exit(0);
75 strcpy(path, home);
76 strcat(path, "/GNUstep/");
78 strcat(path, DEFAULTS_DIR);
79 strcat(path, "/");
80 strcat(path, domain);
82 tmp = malloc(strlen(path)+2);
83 strcpy(tmp, path);
85 return tmp;
89 void
90 hackPaths(proplist_t style, char *prefix)
92 proplist_t keys;
93 proplist_t key;
94 proplist_t value;
95 int i;
98 keys = PLGetAllDictionaryKeys(style);
100 for (i = 0; i < PLGetNumberOfElements(keys); i++) {
101 key = PLGetArrayElement(keys, i);
103 value = PLGetDictionaryEntry(style, key);
104 if (value && PLIsArray(value) && PLGetNumberOfElements(value) > 2) {
105 proplist_t type;
106 char *t;
108 type = PLGetArrayElement(value, 0);
109 t = PLGetString(type);
110 if (t && (strcasecmp(t, "tpixmap")==0
111 || strcasecmp(t, "spixmap")==0
112 || strcasecmp(t, "mpixmap")==0
113 || strcasecmp(t, "cpixmap")==0
114 || strcasecmp(t, "tvgradient")==0
115 || strcasecmp(t, "thgradient")==0
116 || strcasecmp(t, "tdgradient")==0)) {
117 proplist_t file;
118 char buffer[4018];
120 file = PLGetArrayElement(value, 1);
121 sprintf(buffer, "%s/%s", prefix, PLGetString(file));
122 PLRemoveArrayElement(value, 1);
123 PLInsertArrayElement(value, PLMakeString(buffer), 1);
131 static proplist_t
132 getColor(proplist_t texture)
134 proplist_t value, type;
135 char *str;
137 type = PLGetArrayElement(texture, 0);
138 if (!type)
139 return NULL;
141 value = NULL;
143 str = PLGetString(type);
144 if (strcasecmp(str, "solid")==0) {
145 value = PLGetArrayElement(texture, 1);
146 } else if (strcasecmp(str, "dgradient")==0
147 || strcasecmp(str, "hgradient")==0
148 || strcasecmp(str, "vgradient")==0) {
149 proplist_t c1, c2;
150 int r1, g1, b1, r2, g2, b2;
151 char buffer[32];
153 c1 = PLGetArrayElement(texture, 1);
154 c2 = PLGetArrayElement(texture, 2);
155 if (!dpy) {
156 if (sscanf(PLGetString(c1), "#%2x%2x%2x", &r1, &g1, &b1)==3
157 && sscanf(PLGetString(c2), "#%2x%2x%2x", &r2, &g2, &b2)==3) {
158 sprintf(buffer, "#%2x%2x%2x", (r1+r2)/2, (g1+g2)/2,
159 (b1+b2)/2);
160 value = PLMakeString(buffer);
161 } else {
162 value = c1;
164 } else {
165 XColor color1;
166 XColor color2;
168 XParseColor(dpy, DefaultColormap(dpy, DefaultScreen(dpy)),
169 PLGetString(c1), &color1);
170 XParseColor(dpy, DefaultColormap(dpy, DefaultScreen(dpy)),
171 PLGetString(c1), &color2);
173 sprintf(buffer, "#%4x%4x%4x", (color1.red+color2.red)/2,
174 (color1.green+color2.green)/2,
175 (color1.blue+color2.blue)/2);
176 value = PLMakeString(buffer);
178 } else if (strcasecmp(str, "mdgradient")==0
179 || strcasecmp(str, "mhgradient")==0
180 || strcasecmp(str, "mvgradient")==0) {
182 value = PLGetArrayElement(texture, 1);
184 } else if (strcasecmp(str, "tpixmap")==0
185 || strcasecmp(str, "cpixmap")==0
186 || strcasecmp(str, "spixmap")==0) {
188 value = PLGetArrayElement(texture, 2);
191 return value;
196 * since some of the options introduce incompatibilities, we will need
197 * to do a kluge here or the themes ppl will get real annoying.
198 * So, treat for the absence of the following options:
199 * IconTitleColor
200 * IconTitleBack
202 void
203 hackStyle(proplist_t style)
205 proplist_t keys;
206 proplist_t tmp;
207 int i;
208 int foundIconTitle = 0;
209 int foundResizebarBack = 0;
211 keys = PLGetAllDictionaryKeys(style);
213 for (i = 0; i < PLGetNumberOfElements(keys); i++) {
214 char *str;
216 tmp = PLGetArrayElement(keys, i);
217 str = PLGetString(tmp);
218 if (str) {
219 int j, found;
221 if (ignoreFonts) {
222 for (j = 0, found = 0; FontOptions[j]!=NULL; j++) {
223 if (strcasecmp(str, FontOptions[j])==0) {
224 PLRemoveDictionaryEntry(style, tmp);
225 found = 1;
226 break;
229 if (found)
230 continue;
233 if (strcasecmp(str, "IconTitleColor")==0
234 || strcasecmp(str, "IconTitleBack")==0) {
235 foundIconTitle = 1;
236 } else if (strcasecmp(str, "ResizebarBack")==0) {
237 foundResizebarBack = 1;
242 if (!foundIconTitle) {
243 /* set the default values */
244 tmp = PLGetDictionaryEntry(style, PLMakeString("FTitleColor"));
245 if (tmp) {
246 PLInsertDictionaryEntry(style, PLMakeString("IconTitleColor"),
247 tmp);
250 tmp = PLGetDictionaryEntry(style, PLMakeString("FTitleBack"));
251 if (tmp) {
252 proplist_t value;
254 value = getColor(tmp);
256 if (value) {
257 PLInsertDictionaryEntry(style, PLMakeString("IconTitleBack"),
258 value);
263 if (!foundResizebarBack) {
264 /* set the default values */
265 tmp = PLGetDictionaryEntry(style, PLMakeString("UTitleBack"));
266 if (tmp) {
267 proplist_t value;
269 value = getColor(tmp);
271 if (value) {
272 proplist_t t;
274 t = PLMakeArrayFromElements(PLMakeString("solid"), value,
275 NULL);
276 PLInsertDictionaryEntry(style, PLMakeString("ResizebarBack"),
283 if (!PLGetDictionaryEntry(style, PLMakeString("MenuStyle"))) {
284 PLInsertDictionaryEntry(style, PLMakeString("MenuStyle"),
285 PLMakeString("normal"));
290 BOOL
291 StringCompareHook(proplist_t pl1, proplist_t pl2)
293 char *str1, *str2;
295 str1 = PLGetString(pl1);
296 str2 = PLGetString(pl2);
298 if (strcasecmp(str1, str2)==0)
299 return YES;
300 else
301 return NO;
306 void
307 print_help()
309 printf("Usage: %s [OPTIONS] FILE\n", ProgName);
310 puts("Reads style/theme configuration from FILE and updates Window Maker.");
311 puts("");
312 puts(" --no-fonts ignore font related options");
313 puts(" --help display this help and exit");
314 puts(" --version output version information and exit");
319 int
320 main(int argc, char **argv)
322 proplist_t prop, style;
323 char *path;
324 char *file = NULL;
325 struct stat statbuf;
326 int i;
328 dpy = XOpenDisplay("");
330 ProgName = argv[0];
332 if (argc<2) {
333 printf("%s: missing argument\n", ProgName);
334 printf("Try '%s --help' for more information\n", ProgName);
335 exit(1);
338 for (i = 1; i < argc; i++) {
339 if (strcmp("--no-fonts", argv[i])==0) {
340 ignoreFonts = 1;
341 } else if (strcmp("--version", argv[i])==0) {
342 puts(PROG_VERSION);
343 exit(0);
344 } else if (strcmp("--help", argv[i])==0) {
345 print_help();
346 exit(0);
347 } else {
348 if (file) {
349 printf("%s: invalid argument '%s'\n", ProgName, argv[i]);
350 printf("Try '%s --help' for more information\n", ProgName);
351 exit(1);
353 file = argv[i];
357 PLSetStringCmpHook(StringCompareHook);
359 path = defaultsPathForDomain("WindowMaker");
361 prop = PLGetProplistWithPath(path);
362 if (!prop) {
363 perror(path);
364 printf("%s:could not load WindowMaker configuration file.\n",
365 ProgName);
366 exit(1);
369 if (stat(file, &statbuf) < 0) {
370 perror(file);
371 exit(1);
374 if (S_ISDIR(statbuf.st_mode)) {
375 char buffer[4018];
376 char *prefix;
378 if (*argv[argc-1] != '/') {
379 if (!getcwd(buffer, 4000)) {
380 printf("%s: complete path for %s is too long\n", ProgName,
381 file);
382 exit(1);
384 if (strlen(buffer) + strlen(file) > 4000) {
385 printf("%s: complete path for %s is too long\n", ProgName,
386 file);
387 exit(1);
389 strcat(buffer, "/");
390 } else {
391 buffer[0] = 0;
393 strcat(buffer, file);
395 prefix = malloc(strlen(buffer)+10);
396 if (!prefix) {
397 printf("%s: out of memory\n", ProgName);
398 exit(1);
400 strcpy(prefix, buffer);
402 strcat(buffer, "/style");
404 style = PLGetProplistWithPath(buffer);
405 if (!style) {
406 perror(buffer);
407 printf("%s:could not load style file.\n", ProgName);
408 exit(1);
411 hackPaths(style, prefix);
412 free(prefix);
413 } else {
414 style = PLGetProplistWithPath(file);
415 if (!style) {
416 perror(file);
417 printf("%s:could not load style file.\n", ProgName);
418 exit(1);
422 if (!PLIsDictionary(style)) {
423 printf("%s: '%s' is not a style file/theme\n", ProgName, file);
424 exit(1);
427 hackStyle(style);
429 PLMergeDictionaries(prop, style);
431 PLSave(prop, YES);
433 XEvent ev;
435 if (dpy) {
436 int i;
437 char *msg = "Reconfigure";
439 memset(&ev, 0, sizeof(XEvent));
441 ev.xclient.type = ClientMessage;
442 ev.xclient.message_type = XInternAtom(dpy, "_WINDOWMAKER_COMMAND",
443 False);
444 ev.xclient.window = DefaultRootWindow(dpy);
445 ev.xclient.format = 8;
447 for (i = 0; i <= strlen(msg); i++) {
448 ev.xclient.data.b[i] = msg[i];
450 XSendEvent(dpy, DefaultRootWindow(dpy), False,
451 SubstructureRedirectMask, &ev);
452 XFlush(dpy);
456 exit(0);