eccc2c8a7dc80dcb96786c40e9e2f6aa4dc3f700
[mikachu/openbox.git] / render / theme.c
1 #include "render.h"
2 #include "color.h"
3 #include "font.h"
4 #include "mask.h"
5
6 #include <X11/Xlib.h>
7 #include <X11/Xresource.h>
8
9 /* style settings - geometry */
10 int theme_bevel;
11 int theme_handle_height;
12 int theme_bwidth;
13 int theme_cbwidth;
14 /* style settings - colors */
15 color_rgb *theme_b_color;
16 color_rgb *theme_cb_focused_color;
17 color_rgb *theme_cb_unfocused_color;
18 color_rgb *theme_title_focused_color;
19 color_rgb *theme_title_unfocused_color;
20 color_rgb *theme_titlebut_focused_color;
21 color_rgb *theme_titlebut_unfocused_color;
22 color_rgb *theme_menu_title_color;
23 color_rgb *theme_menu_color;
24 color_rgb *theme_menu_disabled_color;
25 color_rgb *theme_menu_hilite_color;
26 /* style settings - fonts */
27 int theme_winfont_height;
28 ObFont *theme_winfont;
29 gboolean theme_winfont_shadow;
30 int theme_winfont_shadow_offset;
31 int theme_winfont_shadow_tint;
32 int theme_mtitlefont_height;
33 ObFont *theme_mtitlefont;
34 gboolean theme_mtitlefont_shadow;
35 int theme_mtitlefont_shadow_offset;
36 int theme_mtitlefont_shadow_tint;
37 int theme_mfont_height;
38 ObFont *theme_mfont;
39 gboolean theme_mfont_shadow;
40 int theme_mfont_shadow_offset;
41 int theme_mfont_shadow_tint;
42 /* style settings - title layout */
43 char *theme_title_layout;
44 /* style settings - masks */
45 pixmap_mask *theme_max_set_mask;
46 pixmap_mask *theme_max_unset_mask;
47 pixmap_mask *theme_iconify_mask;
48 pixmap_mask *theme_desk_set_mask;
49 pixmap_mask *theme_desk_unset_mask;
50 pixmap_mask *theme_shade_set_mask;
51 pixmap_mask *theme_shade_unset_mask;
52 pixmap_mask *theme_close_mask;
53
54 /* global appearances */
55 Appearance *theme_a_focused_unpressed_max;
56 Appearance *theme_a_focused_pressed_max;
57 Appearance *theme_a_focused_pressed_set_max;
58 Appearance *theme_a_unfocused_unpressed_max;
59 Appearance *theme_a_unfocused_pressed_max;
60 Appearance *theme_a_unfocused_pressed_set_max;
61 Appearance *theme_a_focused_unpressed_close;
62 Appearance *theme_a_focused_pressed_close;
63 Appearance *theme_a_unfocused_unpressed_close;
64 Appearance *theme_a_unfocused_pressed_close;
65 Appearance *theme_a_focused_unpressed_desk;
66 Appearance *theme_a_focused_pressed_desk;
67 Appearance *theme_a_focused_pressed_set_desk;
68 Appearance *theme_a_unfocused_unpressed_desk;
69 Appearance *theme_a_unfocused_pressed_desk;
70 Appearance *theme_a_unfocused_pressed_set_desk;
71 Appearance *theme_a_focused_unpressed_shade;
72 Appearance *theme_a_focused_pressed_shade;
73 Appearance *theme_a_focused_pressed_set_shade;
74 Appearance *theme_a_unfocused_unpressed_shade;
75 Appearance *theme_a_unfocused_pressed_shade;
76 Appearance *theme_a_unfocused_pressed_set_shade;
77 Appearance *theme_a_focused_unpressed_iconify;
78 Appearance *theme_a_focused_pressed_iconify;
79 Appearance *theme_a_unfocused_unpressed_iconify;
80 Appearance *theme_a_unfocused_pressed_iconify;
81 Appearance *theme_a_focused_grip;
82 Appearance *theme_a_unfocused_grip;
83 Appearance *theme_a_focused_title;
84 Appearance *theme_a_unfocused_title;
85 Appearance *theme_a_focused_label;
86 Appearance *theme_a_unfocused_label;
87 Appearance *theme_a_icon; /* always parentrelative, so no focused/unfocused */
88 Appearance *theme_a_focused_handle;
89 Appearance *theme_a_unfocused_handle;
90 Appearance *theme_a_menu_title;
91 Appearance *theme_a_menu;
92 Appearance *theme_a_menu_item;
93 Appearance *theme_a_menu_disabled;
94 Appearance *theme_a_menu_hilite;
95
96 Appearance *theme_app_hilite_label;
97 Appearance *theme_app_unhilite_label;
98
99 void theme_startup()
100 {
101     theme_b_color = theme_cb_unfocused_color = theme_cb_focused_color = 
102         theme_title_unfocused_color = theme_title_focused_color = 
103         theme_titlebut_unfocused_color = theme_titlebut_focused_color = 
104         theme_menu_color = theme_menu_title_color = theme_menu_disabled_color =
105         theme_menu_hilite_color = NULL;
106     theme_winfont = theme_mtitlefont = theme_mfont = NULL;
107     theme_title_layout = NULL;
108     theme_max_set_mask = theme_max_unset_mask = NULL;
109     theme_desk_set_mask = theme_desk_unset_mask = NULL;
110     theme_shade_set_mask = theme_shade_unset_mask = NULL;
111     theme_iconify_mask = theme_close_mask = NULL;
112
113     theme_a_focused_unpressed_max = appearance_new(Surface_Planar, 1);
114     theme_a_focused_pressed_max = appearance_new(Surface_Planar, 1);
115     theme_a_focused_pressed_set_max = appearance_new(Surface_Planar, 1);
116     theme_a_unfocused_unpressed_max = appearance_new(Surface_Planar, 1);
117     theme_a_unfocused_pressed_max = appearance_new(Surface_Planar, 1);
118     theme_a_unfocused_pressed_set_max = appearance_new(Surface_Planar, 1);
119     theme_a_focused_unpressed_close = NULL;
120     theme_a_focused_pressed_close = NULL;
121     theme_a_unfocused_unpressed_close = NULL;
122     theme_a_unfocused_pressed_close = NULL;
123     theme_a_focused_unpressed_desk = NULL;
124     theme_a_focused_pressed_desk = NULL;
125     theme_a_focused_pressed_set_desk = NULL;
126     theme_a_unfocused_unpressed_desk = NULL;
127     theme_a_unfocused_pressed_desk = NULL;
128     theme_a_unfocused_pressed_set_desk = NULL;
129     theme_a_focused_unpressed_shade = NULL;
130     theme_a_focused_pressed_shade = NULL;
131     theme_a_focused_pressed_set_shade = NULL;
132     theme_a_unfocused_unpressed_shade = NULL;
133     theme_a_unfocused_pressed_shade = NULL;
134     theme_a_unfocused_pressed_set_shade = NULL;
135     theme_a_focused_unpressed_iconify = NULL;
136     theme_a_focused_pressed_iconify = NULL;
137     theme_a_unfocused_unpressed_iconify = NULL;
138     theme_a_unfocused_pressed_iconify = NULL;
139     theme_a_focused_grip = appearance_new(Surface_Planar, 0);
140     theme_a_unfocused_grip = appearance_new(Surface_Planar, 0);
141     theme_a_focused_title = appearance_new(Surface_Planar, 0);
142     theme_a_unfocused_title = appearance_new(Surface_Planar, 0);
143     theme_a_focused_label = appearance_new(Surface_Planar, 1);
144     theme_a_unfocused_label = appearance_new(Surface_Planar, 1);
145     theme_a_icon = appearance_new(Surface_Planar, 1);
146     theme_a_focused_handle = appearance_new(Surface_Planar, 0);
147     theme_a_unfocused_handle = appearance_new(Surface_Planar, 0);
148     theme_a_menu = appearance_new(Surface_Planar, 0);
149     theme_a_menu_title = appearance_new(Surface_Planar, 1);
150     theme_a_menu_item = appearance_new(Surface_Planar, 1);
151     theme_a_menu_disabled = appearance_new(Surface_Planar, 1);
152     theme_a_menu_hilite = appearance_new(Surface_Planar, 1);
153
154     theme_app_hilite_label = appearance_new(Surface_Planar, 1);
155     theme_app_unhilite_label = appearance_new(Surface_Planar, 1);
156
157 }
158
159 void theme_shutdown()
160 {
161     color_free(theme_b_color);
162     color_free(theme_cb_unfocused_color);
163     color_free(theme_cb_focused_color);
164     color_free(theme_title_unfocused_color);
165     color_free(theme_title_focused_color);
166     color_free(theme_titlebut_unfocused_color);
167     color_free(theme_titlebut_focused_color);
168     color_free(theme_menu_color);
169     color_free(theme_menu_title_color);
170     color_free(theme_menu_disabled_color);
171     color_free(theme_menu_hilite_color);
172
173     pixmap_mask_free(theme_max_set_mask);
174     pixmap_mask_free(theme_max_unset_mask);
175     pixmap_mask_free(theme_desk_set_mask);
176     pixmap_mask_free(theme_desk_unset_mask);
177     pixmap_mask_free(theme_shade_set_mask);
178     pixmap_mask_free(theme_shade_unset_mask);
179     pixmap_mask_free(theme_iconify_mask);
180     pixmap_mask_free(theme_close_mask);
181
182     font_close(theme_winfont);
183     font_close(theme_mtitlefont);
184     font_close(theme_mfont);
185
186     g_free(theme_title_layout);
187
188     appearance_free(theme_a_focused_unpressed_max);
189     appearance_free(theme_a_focused_pressed_max);
190     appearance_free(theme_a_focused_pressed_set_max);
191     appearance_free(theme_a_unfocused_unpressed_max);
192     appearance_free(theme_a_unfocused_pressed_max);
193     appearance_free(theme_a_unfocused_pressed_set_max);
194     appearance_free(theme_a_focused_unpressed_close);
195     appearance_free(theme_a_focused_pressed_close);
196     appearance_free(theme_a_unfocused_unpressed_close);
197     appearance_free(theme_a_unfocused_pressed_close);
198     appearance_free(theme_a_focused_unpressed_desk);
199     appearance_free(theme_a_focused_pressed_desk);
200     appearance_free(theme_a_unfocused_unpressed_desk);
201     appearance_free(theme_a_unfocused_pressed_desk);
202     appearance_free(theme_a_focused_unpressed_shade);
203     appearance_free(theme_a_focused_pressed_shade);
204     appearance_free(theme_a_unfocused_unpressed_shade);
205     appearance_free(theme_a_unfocused_pressed_shade);
206     appearance_free(theme_a_focused_unpressed_iconify);
207     appearance_free(theme_a_focused_pressed_iconify);
208     appearance_free(theme_a_unfocused_unpressed_iconify);
209     appearance_free(theme_a_unfocused_pressed_iconify);
210     appearance_free(theme_a_focused_grip);
211     appearance_free(theme_a_unfocused_grip);
212     appearance_free(theme_a_focused_title);
213     appearance_free(theme_a_unfocused_title);
214     appearance_free(theme_a_focused_label);
215     appearance_free(theme_a_unfocused_label);
216     appearance_free(theme_a_icon);
217     appearance_free(theme_a_focused_handle);
218     appearance_free(theme_a_unfocused_handle);
219     appearance_free(theme_a_menu);
220     appearance_free(theme_a_menu_title);
221     appearance_free(theme_a_menu_item);
222     appearance_free(theme_a_menu_disabled);
223     appearance_free(theme_a_menu_hilite);
224     appearance_free(theme_app_hilite_label);
225     appearance_free(theme_app_unhilite_label);
226 }
227
228 static XrmDatabase loaddb(char *theme)
229 {
230     XrmDatabase db;
231
232     db = XrmGetFileDatabase(theme);
233     if (db == NULL) {
234         char *s = g_build_filename(g_get_home_dir(), ".openbox", "themes",
235                                    theme, NULL);
236         db = XrmGetFileDatabase(s);
237         g_free(s);
238     }
239     if (db == NULL) {
240         char *s = g_build_filename(THEMEDIR, theme, NULL);
241         db = XrmGetFileDatabase(s);
242         g_free(s);
243     }
244     return db;
245 }
246
247 static char *create_class_name(char *rname)
248 {
249     char *rclass = g_strdup(rname);
250     char *p = rclass;
251
252     while (TRUE) {
253         *p = toupper(*p);
254         p = strchr(p+1, '.');
255         if (p == NULL) break;
256         ++p;
257         if (*p == '\0') break;
258     }
259     return rclass;
260 }
261
262 static gboolean read_int(XrmDatabase db, char *rname, int *value)
263 {
264     gboolean ret = FALSE;
265     char *rclass = create_class_name(rname);
266     char *rettype, *end;
267     XrmValue retvalue;
268   
269     if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
270         retvalue.addr != NULL) {
271         *value = (int)strtol(retvalue.addr, &end, 10);
272         if (end != retvalue.addr)
273             ret = TRUE;
274     }
275
276     g_free(rclass);
277     return ret;
278 }
279
280 static gboolean read_string(XrmDatabase db, char *rname, char **value)
281 {
282     gboolean ret = FALSE;
283     char *rclass = create_class_name(rname);
284     char *rettype;
285     XrmValue retvalue;
286   
287     if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
288         retvalue.addr != NULL) {
289         *value = g_strdup(retvalue.addr);
290         ret = TRUE;
291     }
292
293     g_free(rclass);
294     return ret;
295 }
296
297 static gboolean read_color(XrmDatabase db, char *rname, color_rgb **value)
298 {
299     gboolean ret = FALSE;
300     char *rclass = create_class_name(rname);
301     char *rettype;
302     XrmValue retvalue;
303   
304     if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
305         retvalue.addr != NULL) {
306         color_rgb *c = color_parse(retvalue.addr);
307         if (c != NULL) {
308             *value = c;
309             ret = TRUE;
310         }
311     }
312
313     g_free(rclass);
314     return ret;
315 }
316
317 static gboolean read_mask(XrmDatabase db, char *rname, char *theme,
318                           pixmap_mask **value)
319 {
320     gboolean ret = FALSE;
321     char *rclass = create_class_name(rname);
322     char *rettype;
323     char *s;
324     char *button_dir;
325     XrmValue retvalue;
326     int hx, hy; /* ignored */
327     unsigned int w, h;
328     unsigned char *b;
329   
330     if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
331         retvalue.addr != NULL) {
332
333         button_dir = g_strdup_printf("%s_buttons", theme);
334
335         s = g_build_filename(g_get_home_dir(), ".openbox", "themes",
336                              button_dir, retvalue.addr, NULL);
337
338         if (XReadBitmapFileData(s, &w, &h, &b, &hx, &hy) == BitmapSuccess)
339             ret = TRUE;
340         else {
341             g_free(s);
342             s = g_build_filename(THEMEDIR, button_dir, retvalue.addr, NULL);
343         
344             if (XReadBitmapFileData(s, &w, &h, &b, &hx, &hy) == BitmapSuccess) 
345                 ret = TRUE;
346             else {
347                 char *themename;
348
349                 g_free(s);
350                 themename = g_path_get_basename(theme);
351                 s = g_strdup_printf("%s/%s_buttons/%s", theme,
352                                     themename, retvalue.addr);
353                 g_free(themename);
354                 if (XReadBitmapFileData(s, &w, &h, &b, &hx, &hy) ==
355                     BitmapSuccess) 
356                     ret = TRUE;
357                 else
358                     g_message("Unable to find bitmap '%s'", retvalue.addr);
359             }
360         }
361
362         if (ret) {
363             *value = pixmap_mask_new(w, h, (char*)b);
364             XFree(b);
365         }
366       
367         g_free(s);
368         g_free(button_dir);
369     }
370
371     g_free(rclass);
372     return ret;
373 }
374
375 static void parse_appearance(char *tex, SurfaceColorType *grad,
376                              ReliefType *relief, BevelType *bevel,
377                              gboolean *interlaced, gboolean *border)
378 {
379     char *t;
380
381     /* convert to all lowercase */
382     for (t = tex; *t != '\0'; ++t)
383         *t = g_ascii_tolower(*t);
384
385     if (strstr(tex, "parentrelative") != NULL) {
386         *grad = Background_ParentRelative;
387     } else {
388         if (strstr(tex, "gradient") != NULL) {
389             if (strstr(tex, "crossdiagonal") != NULL)
390                 *grad = Background_CrossDiagonal;
391             else if (strstr(tex, "rectangle") != NULL)
392                 *grad = Background_Rectangle;
393             else if (strstr(tex, "pyramid") != NULL)
394                 *grad = Background_Pyramid;
395             else if (strstr(tex, "pipecross") != NULL)
396                 *grad = Background_PipeCross;
397             else if (strstr(tex, "elliptic") != NULL)
398                 *grad = Background_Elliptic;
399             else if (strstr(tex, "horizontal") != NULL)
400                 *grad = Background_Horizontal;
401             else if (strstr(tex, "vertical") != NULL)
402                 *grad = Background_Vertical;
403             else
404                 *grad = Background_Diagonal;
405         } else {
406             *grad = Background_Solid;
407         }
408
409         if (strstr(tex, "sunken") != NULL)
410             *relief = Sunken;
411         else if (strstr(tex, "flat") != NULL)
412             *relief = Flat;
413         else
414             *relief = Raised;
415         
416         *border = FALSE;
417         if (*relief == Flat) {
418             if (strstr(tex, "border") != NULL)
419                 *border = TRUE;
420         } else {
421             if (strstr(tex, "bevel2") != NULL)
422                 *bevel = Bevel2;
423             else
424                 *bevel = Bevel1;
425         }
426
427         if (strstr(tex, "interlaced") != NULL)
428             *interlaced = TRUE;
429         else
430             *interlaced = FALSE;
431     }
432 }
433
434
435 static gboolean read_appearance(XrmDatabase db, char *rname, Appearance *value)
436 {
437     gboolean ret = FALSE;
438     char *rclass = create_class_name(rname), *cname, *ctoname, *bcname;
439     char *rettype;
440     XrmValue retvalue;
441
442     cname = g_strconcat(rname, ".color", NULL);
443     ctoname = g_strconcat(rname, ".colorTo", NULL);
444     bcname = g_strconcat(rname, ".borderColor", NULL);
445
446     if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
447         retvalue.addr != NULL) {
448         parse_appearance(retvalue.addr,
449                          &value->surface.data.planar.grad,
450                          &value->surface.data.planar.relief,
451                          &value->surface.data.planar.bevel,
452                          &value->surface.data.planar.interlaced,
453                          &value->surface.data.planar.border);
454         if (!read_color(db, cname, &value->surface.data.planar.primary))
455             value->surface.data.planar.primary = color_new(0, 0, 0);
456         if (!read_color(db, ctoname, &value->surface.data.planar.secondary))
457             value->surface.data.planar.secondary = color_new(0, 0, 0);
458         if (value->surface.data.planar.border)
459             if (!read_color(db, bcname,
460                             &value->surface.data.planar.border_color))
461                 value->surface.data.planar.border_color = color_new(0, 0, 0);
462         ret = TRUE;
463     }
464
465     g_free(bcname);
466     g_free(ctoname);
467     g_free(cname);
468     g_free(rclass);
469     return ret;
470 }
471
472 static void set_default_appearance(Appearance *a)
473 {
474     a->surface.data.planar.grad = Background_Solid;
475     a->surface.data.planar.relief = Flat;
476     a->surface.data.planar.bevel = Bevel1;
477     a->surface.data.planar.interlaced = FALSE;
478     a->surface.data.planar.border = FALSE;
479     a->surface.data.planar.primary = color_new(0, 0, 0);
480     a->surface.data.planar.secondary = color_new(0, 0, 0);
481 }
482
483 char *theme_load(char *theme)
484 {
485     XrmDatabase db = NULL;
486     char *loaded = NULL;
487     Justify winjust, mtitlejust, mjust;
488     char *str;
489     char *font_str;
490
491     if (theme) {
492         db = loaddb(theme);
493         if (db == NULL) {
494             g_warning("Failed to load the theme '%s'", theme);
495             g_message("Falling back to the default: '%s'", DEFAULT_THEME);
496         } else
497             loaded = g_strdup(theme);
498     }
499     if (db == NULL) {
500         db = loaddb(DEFAULT_THEME);
501         if (db == NULL) {
502             g_warning("Failed to load the theme '%s'.", DEFAULT_THEME);
503             return NULL;
504         } else
505             loaded = g_strdup(DEFAULT_THEME);
506     }
507
508     /* load the font stuff */
509     font_str = "arial-8:bold";
510
511     theme_winfont_shadow = FALSE;
512     if (read_string(db, "window.xft.flags", &str)) {
513         if (g_strrstr(str, "shadow"))
514             theme_winfont_shadow = TRUE;
515         g_free(str);
516     }
517  
518     if (!read_int(db, "window.xft.shadow.offset",
519                   &theme_winfont_shadow_offset))
520         theme_winfont_shadow_offset = 1;
521     if (!read_int(db, "window.xft.shadow.tint",
522                   &theme_winfont_shadow_tint) ||
523         theme_winfont_shadow_tint < 100 || theme_winfont_shadow_tint > 100)
524         theme_winfont_shadow_tint = 25;
525
526     theme_winfont = font_open(font_str);
527     theme_winfont_height = font_height(theme_winfont, theme_winfont_shadow,
528                                        theme_winfont_shadow_offset);
529
530     winjust = Justify_Left;
531     if (read_string(db, "window.justify", &str)) {
532         if (!g_ascii_strcasecmp(str, "right"))
533             winjust = Justify_Right;
534         else if (!g_ascii_strcasecmp(str, "center"))
535             winjust = Justify_Center;
536         g_free(str);
537     }
538
539     font_str = "arial-10:bold";
540
541     theme_mtitlefont_shadow = FALSE;
542     if (read_string(db, "menu.title.xft.flags", &str)) {
543         if (g_strrstr(str, "shadow"))
544             theme_mtitlefont_shadow = TRUE;
545         g_free(str);
546     }
547  
548     if (!read_int(db, "menu.title.xft.shadow.offset",
549                   &theme_mtitlefont_shadow_offset))
550         theme_mtitlefont_shadow_offset = 1;
551     if (!read_int(db, "menu.title.xft.shadow.tint",
552                   &theme_mtitlefont_shadow_tint) ||
553         theme_mtitlefont_shadow_tint < 100 ||
554         theme_mtitlefont_shadow_tint > 100)
555         theme_mtitlefont_shadow_tint = 25;
556
557     theme_mtitlefont = font_open(font_str);
558     theme_mtitlefont_height = font_height(theme_mtitlefont,
559                                           theme_mtitlefont_shadow,
560                                           theme_mtitlefont_shadow_offset);
561
562     mtitlejust = Justify_Left;
563     if (read_string(db, "menu.title.justify", &str)) {
564         if (!g_ascii_strcasecmp(str, "right"))
565             mtitlejust = Justify_Right;
566         else if (!g_ascii_strcasecmp(str, "center"))
567             mtitlejust = Justify_Center;
568         g_free(str);
569     }
570
571     font_str = "arial-8";
572
573     theme_mfont_shadow = FALSE;
574     if (read_string(db, "menu.frame.xft.flags", &str)) {
575         if (g_strrstr(str, "shadow"))
576             theme_mfont_shadow = TRUE;
577         g_free(str);
578     }
579  
580     if (!read_int(db, "menu.frame.xft.shadow.offset",
581                   &theme_mfont_shadow_offset))
582         theme_mfont_shadow_offset = 1;
583     if (!read_int(db, "menu.frame.xft.shadow.tint",
584                   &theme_mfont_shadow_tint) ||
585         theme_mfont_shadow_tint < 100 ||
586         theme_mfont_shadow_tint > 100)
587         theme_mfont_shadow_tint = 25;
588
589     theme_mfont = font_open(font_str);
590     theme_mfont_height = font_height(theme_mfont, theme_mfont_shadow,
591                                      theme_mfont_shadow_offset);
592
593     mjust = Justify_Left;
594     if (read_string(db, "menu.frame.justify", &str)) {
595         if (!g_ascii_strcasecmp(str, "right"))
596             mjust = Justify_Right;
597         else if (!g_ascii_strcasecmp(str, "center"))
598             mjust = Justify_Center;
599         g_free(str);
600     }
601
602     /* load the title layout */
603     theme_title_layout = g_strdup("NLIMC");
604
605     if (!read_int(db, "handleWidth", &theme_handle_height) ||
606         theme_handle_height < 0 || theme_handle_height > 100)
607         theme_handle_height = 6;
608     if (!read_int(db, "bevelWidth", &theme_bevel) ||
609         theme_bevel <= 0 || theme_bevel > 100) theme_bevel = 3;
610     if (!read_int(db, "borderWidth", &theme_bwidth) ||
611         theme_bwidth < 0 || theme_bwidth > 100) theme_bwidth = 1;
612     if (!read_int(db, "frameWidth", &theme_cbwidth) ||
613         theme_cbwidth < 0 || theme_cbwidth > 100) theme_cbwidth = theme_bevel;
614
615     /* load colors */
616     if (!read_color(db, "borderColor", &theme_b_color))
617         theme_b_color = color_new(0, 0, 0);
618     if (!read_color(db, "window.frame.focusColor", &theme_cb_focused_color))
619         theme_cb_focused_color = color_new(0xff, 0xff, 0xff);
620     if (!read_color(db, "window.frame.unfocusColor",&theme_cb_unfocused_color))
621         theme_cb_unfocused_color = color_new(0xff, 0xff, 0xff);
622     if (!read_color(db, "window.label.focus.textColor",
623                     &theme_title_focused_color))
624         theme_title_focused_color = color_new(0x0, 0x0, 0x0);
625     if (!read_color(db, "window.label.unfocus.textColor",
626                     &theme_title_unfocused_color))
627         theme_title_unfocused_color = color_new(0xff, 0xff, 0xff);
628     if (!read_color(db, "window.button.focus.picColor",
629                     &theme_titlebut_focused_color))
630         theme_titlebut_focused_color = color_new(0, 0, 0);
631     if (!read_color(db, "window.button.unfocus.picColor",
632                     &theme_titlebut_unfocused_color))
633         theme_titlebut_unfocused_color = color_new(0xff, 0xff, 0xff);
634     if (!read_color(db, "menu.title.textColor", &theme_menu_title_color))
635         theme_menu_title_color = color_new(0, 0, 0);
636     if (!read_color(db, "menu.frame.textColor", &theme_menu_color))
637         theme_menu_color = color_new(0xff, 0xff, 0xff);
638     if (!read_color(db, "menu.frame.disableColor", &theme_menu_disabled_color))
639         theme_menu_disabled_color = color_new(0, 0, 0);
640     if (!read_color(db, "menu.hilite.textColor", &theme_menu_hilite_color))
641         theme_menu_hilite_color = color_new(0, 0, 0);
642
643     if (read_mask(db, "window.button.max.mask", theme, &theme_max_unset_mask)){
644         if (!read_mask(db, "window.button.max.toggled.mask", theme,
645                        &theme_max_set_mask)) {
646             theme_max_set_mask = pixmap_mask_copy(theme_max_unset_mask);
647         }
648     } else {
649         {
650             char data[] = { 0x7f, 0x7f, 0x7f, 0x41, 0x41, 0x41, 0x7f };
651             theme_max_unset_mask = pixmap_mask_new(7, 7, data);
652         }
653         {
654             char data[] = { 0x7c, 0x44, 0x47, 0x47, 0x7f, 0x1f, 0x1f };
655             theme_max_set_mask = pixmap_mask_new(7, 7, data);
656         }
657     }
658
659     if (!read_mask(db, "window.button.icon.mask", theme,
660                    &theme_iconify_mask)) {
661         char data[] = { 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x7f };
662         theme_iconify_mask = pixmap_mask_new(7, 7, data);
663     }
664
665     if (read_mask(db, "window.button.stick.mask", theme,
666                    &theme_desk_unset_mask)) {
667         if (!read_mask(db, "window.button.stick.toggled.mask", theme,
668                        &theme_desk_set_mask)) {
669             theme_desk_set_mask =
670                 pixmap_mask_copy(theme_desk_unset_mask);
671         }
672     } else {
673         {
674             char data[] = { 0x63, 0x63, 0x00, 0x00, 0x00, 0x63, 0x63 };
675             theme_desk_unset_mask = pixmap_mask_new(7, 7, data);
676         }
677         {
678             char data[] = { 0x00, 0x36, 0x36, 0x08, 0x36, 0x36, 0x00 };
679             theme_desk_set_mask = pixmap_mask_new(7, 7, data);
680         }
681     }
682
683     if (read_mask(db, "window.button.shade.mask", theme,
684                    &theme_shade_unset_mask)) {
685         if (!read_mask(db, "window.button.shade.toggled.mask", theme,
686                        &theme_shade_set_mask)) {
687             theme_shade_set_mask =
688                 pixmap_mask_copy(theme_shade_unset_mask);
689         }
690     } else {
691         {
692             char data[] = { 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00 };
693             theme_shade_unset_mask = pixmap_mask_new(7, 7, data);
694         }
695         {
696             char data[] = { 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x7f };
697             theme_shade_set_mask = pixmap_mask_new(7, 7, data);
698         }
699     }
700
701     if (!read_mask(db, "window.button.close.mask", theme,
702                    &theme_close_mask)) {
703         char data[] = { 0x63, 0x77, 0x3e, 0x1c, 0x3e, 0x77, 0x63 };
704         theme_close_mask = pixmap_mask_new(7, 7, data);
705     }        
706
707     /* read the decoration textures */
708     if (!read_appearance(db, "window.title.focus", theme_a_focused_title))
709         set_default_appearance(theme_a_focused_title);
710     if (!read_appearance(db, "window.title.unfocus", theme_a_unfocused_title))
711         set_default_appearance(theme_a_unfocused_title);
712     if (!read_appearance(db, "window.label.focus", theme_a_focused_label))
713         set_default_appearance(theme_a_focused_label);
714     if (!read_appearance(db, "window.label.unfocus", theme_a_unfocused_label))
715         set_default_appearance(theme_a_unfocused_label);
716     if (!read_appearance(db, "window.handle.focus", theme_a_focused_handle))
717         set_default_appearance(theme_a_focused_handle);
718     if (!read_appearance(db, "window.handle.unfocus",theme_a_unfocused_handle))
719         set_default_appearance(theme_a_unfocused_handle);
720     if (!read_appearance(db, "window.grip.focus", theme_a_focused_grip))
721         set_default_appearance(theme_a_focused_grip);
722     if (!read_appearance(db, "window.grip.unfocus", theme_a_unfocused_grip))
723         set_default_appearance(theme_a_unfocused_grip);
724     if (!read_appearance(db, "menu.frame", theme_a_menu))
725         set_default_appearance(theme_a_menu);
726     if (!read_appearance(db, "menu.title", theme_a_menu_title))
727         set_default_appearance(theme_a_menu_title);
728     if (!read_appearance(db, "menu.hilite", theme_a_menu_hilite))
729         set_default_appearance(theme_a_menu_hilite);
730
731     /* read the appearances for rendering non-decorations. these cannot be
732        parent-relative */
733     if (theme_a_focused_label->surface.data.planar.grad !=
734         Background_ParentRelative) {
735         if (!read_appearance(db, "window.label.focus", theme_app_hilite_label))
736             set_default_appearance(theme_app_hilite_label);
737     } else {
738         if (!read_appearance(db, "window.title.focus", theme_app_hilite_label))
739             set_default_appearance(theme_app_hilite_label);
740     }
741     if (theme_a_unfocused_label->surface.data.planar.grad !=
742         Background_ParentRelative) {
743         if (!read_appearance(db, "window.label.unfocus",
744                              theme_app_unhilite_label))
745             set_default_appearance(theme_app_unhilite_label);
746     } else {
747         if (!read_appearance(db, "window.title.unfocus",
748                              theme_app_unhilite_label))
749             set_default_appearance(theme_app_unhilite_label);
750     }
751
752     /* read buttons textures */
753     if (!read_appearance(db, "window.button.pressed.focus",
754                          theme_a_focused_pressed_max))
755         if (!read_appearance(db, "window.button.pressed",
756                              theme_a_focused_pressed_max))
757             set_default_appearance(theme_a_focused_pressed_max);
758     if (!read_appearance(db, "window.button.pressed.unfocus",
759                          theme_a_unfocused_pressed_max))
760         if (!read_appearance(db, "window.button.pressed",
761                              theme_a_unfocused_pressed_max))
762             set_default_appearance(theme_a_unfocused_pressed_max);
763     if (!read_appearance(db, "window.button.focus",
764                          theme_a_focused_unpressed_max))
765         set_default_appearance(theme_a_focused_unpressed_max);
766     if (!read_appearance(db, "window.button.unfocus",
767                          theme_a_unfocused_unpressed_max))
768         set_default_appearance(theme_a_unfocused_unpressed_max);
769
770     theme_a_unfocused_unpressed_close =
771         appearance_copy(theme_a_unfocused_unpressed_max);
772     theme_a_unfocused_pressed_close =
773         appearance_copy(theme_a_unfocused_pressed_max);
774     theme_a_focused_unpressed_close =
775         appearance_copy(theme_a_focused_unpressed_max);
776     theme_a_focused_pressed_close =
777         appearance_copy(theme_a_focused_pressed_max);
778     theme_a_unfocused_unpressed_desk =
779         appearance_copy(theme_a_unfocused_unpressed_max);
780     theme_a_unfocused_pressed_desk =
781         appearance_copy(theme_a_unfocused_pressed_max);
782     theme_a_unfocused_pressed_set_desk =
783         appearance_copy(theme_a_unfocused_pressed_max);
784     theme_a_focused_unpressed_desk =
785         appearance_copy(theme_a_focused_unpressed_max);
786     theme_a_focused_pressed_desk =
787         appearance_copy(theme_a_focused_pressed_max);
788     theme_a_focused_pressed_set_desk =
789         appearance_copy(theme_a_focused_pressed_max);
790     theme_a_unfocused_unpressed_shade =
791         appearance_copy(theme_a_unfocused_unpressed_max);
792     theme_a_unfocused_pressed_shade =
793         appearance_copy(theme_a_unfocused_pressed_max);
794     theme_a_unfocused_pressed_set_shade =
795         appearance_copy(theme_a_unfocused_pressed_max);
796     theme_a_focused_unpressed_shade =
797         appearance_copy(theme_a_focused_unpressed_max);
798     theme_a_focused_pressed_shade =
799         appearance_copy(theme_a_focused_pressed_max);
800     theme_a_focused_pressed_set_shade =
801         appearance_copy(theme_a_focused_pressed_max);
802     theme_a_unfocused_unpressed_iconify =
803         appearance_copy(theme_a_unfocused_unpressed_max);
804     theme_a_unfocused_pressed_iconify =
805         appearance_copy(theme_a_unfocused_pressed_max);
806     theme_a_focused_unpressed_iconify =
807         appearance_copy(theme_a_focused_unpressed_max);
808     theme_a_focused_pressed_iconify =
809         appearance_copy(theme_a_focused_pressed_max);
810     theme_a_unfocused_pressed_set_max =
811         appearance_copy(theme_a_unfocused_pressed_max);
812     theme_a_focused_pressed_set_max =
813         appearance_copy(theme_a_focused_pressed_max);
814
815     theme_a_icon->surface.data.planar.grad = Background_ParentRelative;
816
817     /* set up the textures */
818     theme_a_focused_label->texture[0].type = 
819         theme_app_hilite_label->texture[0].type = Text;
820     theme_a_focused_label->texture[0].data.text.justify =
821         theme_app_hilite_label->texture[0].data.text.justify = winjust;
822     theme_a_focused_label->texture[0].data.text.font =
823         theme_app_hilite_label->texture[0].data.text.font = theme_winfont;
824     theme_a_focused_label->texture[0].data.text.shadow =
825         theme_app_hilite_label->texture[0].data.text.shadow =
826         theme_winfont_shadow;
827     theme_a_focused_label->texture[0].data.text.offset =
828         theme_app_hilite_label->texture[0].data.text.offset =
829         theme_winfont_shadow_offset;
830     theme_a_focused_label->texture[0].data.text.tint =
831         theme_app_hilite_label->texture[0].data.text.tint =
832         theme_winfont_shadow_tint;
833     theme_a_focused_label->texture[0].data.text.color =
834         theme_app_hilite_label->texture[0].data.text.color =
835         theme_title_focused_color;
836
837     theme_a_unfocused_label->texture[0].type =
838         theme_app_unhilite_label->texture[0].type = Text;
839     theme_a_unfocused_label->texture[0].data.text.justify =
840         theme_app_unhilite_label->texture[0].data.text.justify = winjust;
841     theme_a_unfocused_label->texture[0].data.text.font =
842         theme_app_unhilite_label->texture[0].data.text.font = theme_winfont;
843     theme_a_unfocused_label->texture[0].data.text.shadow =
844         theme_app_unhilite_label->texture[0].data.text.shadow =
845         theme_winfont_shadow;
846     theme_a_unfocused_label->texture[0].data.text.offset =
847         theme_app_unhilite_label->texture[0].data.text.offset =
848         theme_winfont_shadow_offset;
849     theme_a_unfocused_label->texture[0].data.text.tint =
850         theme_app_unhilite_label->texture[0].data.text.tint =
851         theme_winfont_shadow_tint;
852     theme_a_unfocused_label->texture[0].data.text.color =
853         theme_app_unhilite_label->texture[0].data.text.color =
854         theme_title_unfocused_color;
855
856     theme_a_menu_title->texture[0].type = Text;
857     theme_a_menu_title->texture[0].data.text.justify = mtitlejust;
858     theme_a_menu_title->texture[0].data.text.font = theme_mtitlefont;
859     theme_a_menu_title->texture[0].data.text.shadow = theme_mtitlefont_shadow;
860     theme_a_menu_title->texture[0].data.text.offset =
861         theme_mtitlefont_shadow_offset;
862     theme_a_menu_title->texture[0].data.text.tint =
863         theme_mtitlefont_shadow_tint;
864     theme_a_menu_title->texture[0].data.text.color = theme_menu_title_color;
865
866     theme_a_menu_item->surface.data.planar.grad = 
867         theme_a_menu_disabled->surface.data.planar.grad =
868         Background_ParentRelative;
869
870     theme_a_menu_item->texture[0].type =
871         theme_a_menu_disabled->texture[0].type = 
872         theme_a_menu_hilite->texture[0].type = Text;
873     theme_a_menu_item->texture[0].data.text.justify = 
874         theme_a_menu_disabled->texture[0].data.text.justify = 
875         theme_a_menu_hilite->texture[0].data.text.justify = mjust;
876     theme_a_menu_item->texture[0].data.text.font =
877         theme_a_menu_disabled->texture[0].data.text.font =
878         theme_a_menu_hilite->texture[0].data.text.font = theme_mfont;
879     theme_a_menu_item->texture[0].data.text.shadow = 
880         theme_a_menu_disabled->texture[0].data.text.shadow = 
881         theme_a_menu_hilite->texture[0].data.text.shadow = theme_mfont_shadow;
882     theme_a_menu_item->texture[0].data.text.offset =
883         theme_a_menu_disabled->texture[0].data.text.offset = 
884         theme_a_menu_hilite->texture[0].data.text.offset = 
885         theme_mfont_shadow_offset;
886     theme_a_menu_item->texture[0].data.text.tint =
887         theme_a_menu_disabled->texture[0].data.text.tint =
888         theme_a_menu_hilite->texture[0].data.text.tint =
889         theme_mfont_shadow_tint;
890     theme_a_menu_item->texture[0].data.text.color = theme_menu_color;
891     theme_a_menu_disabled->texture[0].data.text.color =
892         theme_menu_disabled_color;
893     theme_a_menu_hilite->texture[0].data.text.color =  theme_menu_hilite_color;
894
895     theme_a_focused_unpressed_max->texture[0].type = 
896         theme_a_focused_pressed_max->texture[0].type = 
897         theme_a_focused_pressed_set_max->texture[0].type =  
898         theme_a_unfocused_unpressed_max->texture[0].type = 
899         theme_a_unfocused_pressed_max->texture[0].type = 
900         theme_a_unfocused_pressed_set_max->texture[0].type = 
901         theme_a_focused_unpressed_close->texture[0].type = 
902         theme_a_focused_pressed_close->texture[0].type = 
903         theme_a_unfocused_unpressed_close->texture[0].type = 
904         theme_a_unfocused_pressed_close->texture[0].type = 
905         theme_a_focused_unpressed_desk->texture[0].type = 
906         theme_a_focused_pressed_desk->texture[0].type = 
907         theme_a_focused_pressed_set_desk->texture[0].type = 
908         theme_a_unfocused_unpressed_desk->texture[0].type = 
909         theme_a_unfocused_pressed_desk->texture[0].type = 
910         theme_a_unfocused_pressed_set_desk->texture[0].type = 
911         theme_a_focused_unpressed_shade->texture[0].type = 
912         theme_a_focused_pressed_shade->texture[0].type = 
913         theme_a_focused_pressed_set_shade->texture[0].type = 
914         theme_a_unfocused_unpressed_shade->texture[0].type = 
915         theme_a_unfocused_pressed_shade->texture[0].type = 
916         theme_a_unfocused_pressed_set_shade->texture[0].type = 
917         theme_a_focused_unpressed_iconify->texture[0].type = 
918         theme_a_focused_pressed_iconify->texture[0].type = 
919         theme_a_unfocused_unpressed_iconify->texture[0].type = 
920         theme_a_unfocused_pressed_iconify->texture[0].type = Bitmask;
921     theme_a_focused_unpressed_max->texture[0].data.mask.mask = 
922         theme_a_unfocused_unpressed_max->texture[0].data.mask.mask = 
923         theme_a_focused_pressed_max->texture[0].data.mask.mask = 
924         theme_a_unfocused_pressed_max->texture[0].data.mask.mask =
925         theme_max_unset_mask;
926     theme_a_focused_pressed_set_max->texture[0].data.mask.mask = 
927         theme_a_unfocused_pressed_set_max->texture[0].data.mask.mask =
928         theme_max_set_mask;
929     theme_a_focused_pressed_close->texture[0].data.mask.mask = 
930         theme_a_unfocused_pressed_close->texture[0].data.mask.mask =
931         theme_a_focused_unpressed_close->texture[0].data.mask.mask = 
932         theme_a_unfocused_unpressed_close->texture[0].data.mask.mask =
933         theme_close_mask;
934     theme_a_focused_unpressed_desk->texture[0].data.mask.mask = 
935         theme_a_unfocused_unpressed_desk->texture[0].data.mask.mask = 
936         theme_a_focused_pressed_desk->texture[0].data.mask.mask = 
937         theme_a_unfocused_pressed_desk->texture[0].data.mask.mask =
938         theme_desk_unset_mask;
939     theme_a_focused_pressed_set_desk->texture[0].data.mask.mask = 
940         theme_a_unfocused_pressed_set_desk->texture[0].data.mask.mask =
941         theme_desk_set_mask;
942     theme_a_focused_unpressed_shade->texture[0].data.mask.mask = 
943         theme_a_unfocused_unpressed_shade->texture[0].data.mask.mask = 
944         theme_a_focused_pressed_shade->texture[0].data.mask.mask = 
945         theme_a_unfocused_pressed_shade->texture[0].data.mask.mask =
946         theme_shade_unset_mask;
947     theme_a_focused_pressed_set_shade->texture[0].data.mask.mask = 
948         theme_a_unfocused_pressed_set_shade->texture[0].data.mask.mask =
949         theme_shade_set_mask;
950     theme_a_focused_unpressed_iconify->texture[0].data.mask.mask = 
951         theme_a_unfocused_unpressed_iconify->texture[0].data.mask.mask = 
952         theme_a_focused_pressed_iconify->texture[0].data.mask.mask = 
953         theme_a_unfocused_pressed_iconify->texture[0].data.mask.mask =
954         theme_iconify_mask;
955     theme_a_focused_unpressed_max->texture[0].data.mask.color = 
956         theme_a_focused_pressed_max->texture[0].data.mask.color = 
957         theme_a_focused_pressed_set_max->texture[0].data.mask.color = 
958         theme_a_focused_unpressed_close->texture[0].data.mask.color = 
959         theme_a_focused_pressed_close->texture[0].data.mask.color = 
960         theme_a_focused_unpressed_desk->texture[0].data.mask.color = 
961         theme_a_focused_pressed_desk->texture[0].data.mask.color = 
962         theme_a_focused_pressed_set_desk->texture[0].data.mask.color = 
963         theme_a_focused_unpressed_shade->texture[0].data.mask.color = 
964         theme_a_focused_pressed_shade->texture[0].data.mask.color = 
965         theme_a_focused_pressed_set_shade->texture[0].data.mask.color = 
966         theme_a_focused_unpressed_iconify->texture[0].data.mask.color = 
967         theme_a_focused_pressed_iconify->texture[0].data.mask.color =
968         theme_titlebut_focused_color;
969     theme_a_unfocused_unpressed_max->texture[0].data.mask.color = 
970         theme_a_unfocused_pressed_max->texture[0].data.mask.color = 
971         theme_a_unfocused_pressed_set_max->texture[0].data.mask.color = 
972         theme_a_unfocused_unpressed_close->texture[0].data.mask.color = 
973         theme_a_unfocused_pressed_close->texture[0].data.mask.color = 
974         theme_a_unfocused_unpressed_desk->texture[0].data.mask.color = 
975         theme_a_unfocused_pressed_desk->texture[0].data.mask.color = 
976         theme_a_unfocused_pressed_set_desk->texture[0].data.mask.color = 
977         theme_a_unfocused_unpressed_shade->texture[0].data.mask.color = 
978         theme_a_unfocused_pressed_shade->texture[0].data.mask.color = 
979         theme_a_unfocused_pressed_set_shade->texture[0].data.mask.color = 
980         theme_a_unfocused_unpressed_iconify->texture[0].data.mask.color = 
981         theme_a_unfocused_pressed_iconify->texture[0].data.mask.color =
982         theme_titlebut_unfocused_color;
983
984     XrmDestroyDatabase(db);
985
986     return loaded;
987 }