fixed Restart() function, and crashing dialog call to this function
[wmaker-crm.git] / util / setstyle.c
blob5995659d62729cf91ec0b119c81e7724f84db750
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, "#%02x%02x%02x", (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(c2), &color2);
173 sprintf(buffer, "#%02x%02x%02x",
174 (color1.red+color2.red)>>9,
175 (color1.green+color2.green)>>9,
176 (color1.blue+color2.blue)>>9);
177 value = PLMakeString(buffer);
179 } else if (strcasecmp(str, "mdgradient")==0
180 || strcasecmp(str, "mhgradient")==0
181 || strcasecmp(str, "mvgradient")==0) {
183 value = PLGetArrayElement(texture, 1);
185 } else if (strcasecmp(str, "tpixmap")==0
186 || strcasecmp(str, "cpixmap")==0
187 || strcasecmp(str, "spixmap")==0) {
189 value = PLGetArrayElement(texture, 2);
192 return value;
197 * since some of the options introduce incompatibilities, we will need
198 * to do a kluge here or the themes ppl will get real annoying.
199 * So, treat for the absence of the following options:
200 * IconTitleColor
201 * IconTitleBack
203 void
204 hackStyle(proplist_t style)
206 proplist_t keys;
207 proplist_t tmp;
208 int i;
209 int foundIconTitle = 0;
210 int foundResizebarBack = 0;
212 keys = PLGetAllDictionaryKeys(style);
214 for (i = 0; i < PLGetNumberOfElements(keys); i++) {
215 char *str;
217 tmp = PLGetArrayElement(keys, i);
218 str = PLGetString(tmp);
219 if (str) {
220 int j, found;
222 if (ignoreFonts) {
223 for (j = 0, found = 0; FontOptions[j]!=NULL; j++) {
224 if (strcasecmp(str, FontOptions[j])==0) {
225 PLRemoveDictionaryEntry(style, tmp);
226 found = 1;
227 break;
230 if (found)
231 continue;
234 if (strcasecmp(str, "IconTitleColor")==0
235 || strcasecmp(str, "IconTitleBack")==0) {
236 foundIconTitle = 1;
237 } else if (strcasecmp(str, "ResizebarBack")==0) {
238 foundResizebarBack = 1;
243 if (!foundIconTitle) {
244 /* set the default values */
245 tmp = PLGetDictionaryEntry(style, PLMakeString("FTitleColor"));
246 if (tmp) {
247 PLInsertDictionaryEntry(style, PLMakeString("IconTitleColor"),
248 tmp);
251 tmp = PLGetDictionaryEntry(style, PLMakeString("FTitleBack"));
252 if (tmp) {
253 proplist_t value;
255 value = getColor(tmp);
257 if (value) {
258 PLInsertDictionaryEntry(style, PLMakeString("IconTitleBack"),
259 value);
264 if (!foundResizebarBack) {
265 /* set the default values */
266 tmp = PLGetDictionaryEntry(style, PLMakeString("UTitleBack"));
267 if (tmp) {
268 proplist_t value;
270 value = getColor(tmp);
272 if (value) {
273 proplist_t t;
275 t = PLMakeArrayFromElements(PLMakeString("solid"), value,
276 NULL);
277 PLInsertDictionaryEntry(style, PLMakeString("ResizebarBack"),
284 if (!PLGetDictionaryEntry(style, PLMakeString("MenuStyle"))) {
285 PLInsertDictionaryEntry(style, PLMakeString("MenuStyle"),
286 PLMakeString("normal"));
291 BOOL
292 StringCompareHook(proplist_t pl1, proplist_t pl2)
294 char *str1, *str2;
296 str1 = PLGetString(pl1);
297 str2 = PLGetString(pl2);
299 if (strcasecmp(str1, str2)==0)
300 return YES;
301 else
302 return NO;
307 void
308 print_help()
310 printf("Usage: %s [OPTIONS] FILE\n", ProgName);
311 puts("Reads style/theme configuration from FILE and updates Window Maker.");
312 puts("");
313 puts(" --no-fonts ignore font related options");
314 puts(" --help display this help and exit");
315 puts(" --version output version information and exit");
320 int
321 main(int argc, char **argv)
323 proplist_t prop, style;
324 char *path;
325 char *file = NULL;
326 struct stat statbuf;
327 int i;
329 dpy = XOpenDisplay("");
331 ProgName = argv[0];
333 if (argc<2) {
334 printf("%s: missing argument\n", ProgName);
335 printf("Try '%s --help' for more information\n", ProgName);
336 exit(1);
339 for (i = 1; i < argc; i++) {
340 if (strcmp("--no-fonts", argv[i])==0) {
341 ignoreFonts = 1;
342 } else if (strcmp("--version", argv[i])==0) {
343 puts(PROG_VERSION);
344 exit(0);
345 } else if (strcmp("--help", argv[i])==0) {
346 print_help();
347 exit(0);
348 } else {
349 if (file) {
350 printf("%s: invalid argument '%s'\n", ProgName, argv[i]);
351 printf("Try '%s --help' for more information\n", ProgName);
352 exit(1);
354 file = argv[i];
358 PLSetStringCmpHook(StringCompareHook);
360 path = defaultsPathForDomain("WindowMaker");
362 prop = PLGetProplistWithPath(path);
363 if (!prop) {
364 perror(path);
365 printf("%s:could not load WindowMaker configuration file.\n",
366 ProgName);
367 exit(1);
370 if (stat(file, &statbuf) < 0) {
371 perror(file);
372 exit(1);
375 if (S_ISDIR(statbuf.st_mode)) {
376 char buffer[4018];
377 char *prefix;
379 if (*argv[argc-1] != '/') {
380 if (!getcwd(buffer, 4000)) {
381 printf("%s: complete path for %s is too long\n", ProgName,
382 file);
383 exit(1);
385 if (strlen(buffer) + strlen(file) > 4000) {
386 printf("%s: complete path for %s is too long\n", ProgName,
387 file);
388 exit(1);
390 strcat(buffer, "/");
391 } else {
392 buffer[0] = 0;
394 strcat(buffer, file);
396 prefix = malloc(strlen(buffer)+10);
397 if (!prefix) {
398 printf("%s: out of memory\n", ProgName);
399 exit(1);
401 strcpy(prefix, buffer);
403 strcat(buffer, "/style");
405 style = PLGetProplistWithPath(buffer);
406 if (!style) {
407 perror(buffer);
408 printf("%s:could not load style file.\n", ProgName);
409 exit(1);
412 hackPaths(style, prefix);
413 free(prefix);
414 } else {
415 style = PLGetProplistWithPath(file);
416 if (!style) {
417 perror(file);
418 printf("%s:could not load style file.\n", ProgName);
419 exit(1);
423 if (!PLIsDictionary(style)) {
424 printf("%s: '%s' is not a style file/theme\n", ProgName, file);
425 exit(1);
428 hackStyle(style);
430 PLMergeDictionaries(prop, style);
432 PLSave(prop, YES);
434 XEvent ev;
436 if (dpy) {
437 int i;
438 char *msg = "Reconfigure";
440 memset(&ev, 0, sizeof(XEvent));
442 ev.xclient.type = ClientMessage;
443 ev.xclient.message_type = XInternAtom(dpy, "_WINDOWMAKER_COMMAND",
444 False);
445 ev.xclient.window = DefaultRootWindow(dpy);
446 ev.xclient.format = 8;
448 for (i = 0; i <= strlen(msg); i++) {
449 ev.xclient.data.b[i] = msg[i];
451 XSendEvent(dpy, DefaultRootWindow(dpy), False,
452 SubstructureRedirectMask, &ev);
453 XFlush(dpy);
457 exit(0);