]> icculus.org git repositories - dana/openbox.git/blob - render/theme.c
renamed the _t bitmaps, and added disabled and hover bitmaps
[dana/openbox.git] / render / theme.c
1 #include "render.h"
2 #include "color.h"
3 #include "font.h"
4 #include "mask.h"
5 #include "theme.h"
6
7 #include <X11/Xlib.h>
8 #include <X11/Xresource.h>
9 #include <ctype.h>
10 #include <stdlib.h>
11 #include <string.h>
12
13 static XrmDatabase loaddb(RrTheme *theme, char *name);
14 static gboolean read_int(XrmDatabase db, char *rname, int *value);
15 static gboolean read_string(XrmDatabase db, char *rname, char **value);
16 static gboolean read_color(XrmDatabase db, const RrInstance *inst,
17                            gchar *rname, RrColor **value);
18 static gboolean read_mask(const RrInstance *inst,
19                           gchar *maskname, RrTheme *theme,
20                           RrPixmapMask **value);
21 static gboolean read_appearance(XrmDatabase db, const RrInstance *inst,
22                                 gchar *rname, RrAppearance *value,
23                                 gboolean allow_trans);
24 static void set_default_appearance(RrAppearance *a);
25
26 RrTheme* RrThemeNew(const RrInstance *inst, gchar *name)
27 {
28     XrmDatabase db = NULL;
29     RrJustify winjust, mtitlejust, mjust;
30     gchar *str;
31     gchar *font_str;
32     RrTheme *theme;
33
34     theme = g_new0(RrTheme, 1);
35
36     theme->inst = inst;
37
38     theme->a_disabled_focused_max = RrAppearanceNew(inst, 1);
39     theme->a_disabled_unfocused_max = RrAppearanceNew(inst, 1);
40     theme->a_hover_focused_max = RrAppearanceNew(inst, 1);
41     theme->a_hover_unfocused_max = RrAppearanceNew(inst, 1);
42     theme->a_focused_unpressed_max = RrAppearanceNew(inst, 1);
43     theme->a_focused_pressed_max = RrAppearanceNew(inst, 1);
44     theme->a_focused_pressed_set_max = RrAppearanceNew(inst, 1);
45     theme->a_unfocused_unpressed_max = RrAppearanceNew(inst, 1);
46     theme->a_unfocused_pressed_max = RrAppearanceNew(inst, 1);
47     theme->a_unfocused_pressed_set_max = RrAppearanceNew(inst, 1);
48     theme->a_focused_grip = RrAppearanceNew(inst, 0);
49     theme->a_unfocused_grip = RrAppearanceNew(inst, 0);
50     theme->a_focused_title = RrAppearanceNew(inst, 0);
51     theme->a_unfocused_title = RrAppearanceNew(inst, 0);
52     theme->a_focused_label = RrAppearanceNew(inst, 1);
53     theme->a_unfocused_label = RrAppearanceNew(inst, 1);
54     theme->a_icon = RrAppearanceNew(inst, 1);
55     theme->a_focused_handle = RrAppearanceNew(inst, 0);
56     theme->a_unfocused_handle = RrAppearanceNew(inst, 0);
57     theme->a_menu = RrAppearanceNew(inst, 0);
58     theme->a_menu_title = RrAppearanceNew(inst, 1);
59     theme->a_menu_item = RrAppearanceNew(inst, 1);
60     theme->a_menu_disabled = RrAppearanceNew(inst, 1);
61     theme->a_menu_hilite = RrAppearanceNew(inst, 1);
62
63     theme->app_hilite_bg = RrAppearanceNew(inst, 0);
64     theme->app_unhilite_bg = RrAppearanceNew(inst, 0);
65     theme->app_hilite_label = RrAppearanceNew(inst, 1);
66     theme->app_unhilite_label = RrAppearanceNew(inst, 1);
67     theme->app_icon = RrAppearanceNew(inst, 1);
68
69     if (name) {
70         db = loaddb(theme, name);
71         if (db == NULL) {
72             g_warning("Failed to load the theme '%s'\n"
73                       "Falling back to the default: '%s'",
74                       name, DEFAULT_THEME);
75         } else
76             theme->name = g_path_get_basename(name);
77     }
78     if (db == NULL) {
79         db = loaddb(theme, DEFAULT_THEME);
80         if (db == NULL) {
81             g_warning("Failed to load the theme '%s'.", DEFAULT_THEME);
82             return NULL;
83         } else
84             theme->name = g_path_get_basename(DEFAULT_THEME);
85     }
86
87     /* load the font stuff */
88     if (!read_string(db, "window.title.xftfont", &font_str))
89         font_str = "arial,sans:bold:pixelsize=10:shadow=y:shadowtint=50";
90
91     if (!(theme->winfont = RrFontOpen(inst, font_str))) {
92         RrThemeFree(theme);
93         return NULL;
94     }
95     theme->winfont_height = RrFontHeight(theme->winfont);
96
97     winjust = RR_JUSTIFY_LEFT;
98     if (read_string(db, "window.justify", &str)) {
99         if (!g_ascii_strcasecmp(str, "right"))
100             winjust = RR_JUSTIFY_RIGHT;
101         else if (!g_ascii_strcasecmp(str, "center"))
102             winjust = RR_JUSTIFY_CENTER;
103     }
104
105     if (!read_string(db, "menu.title.xftfont", &font_str))
106         font_str = "arial,sans:bold:pixelsize=12:shadow=y";
107
108     if (!(theme->mtitlefont = RrFontOpen(inst, font_str))) {
109         RrThemeFree(theme);
110         return NULL;
111     }
112     theme->mtitlefont_height = RrFontHeight(theme->mtitlefont);
113
114     mtitlejust = RR_JUSTIFY_LEFT;
115     if (read_string(db, "menu.title.justify", &str)) {
116         if (!g_ascii_strcasecmp(str, "right"))
117             mtitlejust = RR_JUSTIFY_RIGHT;
118         else if (!g_ascii_strcasecmp(str, "center"))
119             mtitlejust = RR_JUSTIFY_CENTER;
120     }
121
122     if (!read_string(db, "menu.frame.xftfont", &font_str))
123         font_str = "arial,sans:bold:pixelsize=11:shadow=y";
124
125     if (!(theme->mfont = RrFontOpen(inst, font_str))) {
126         RrThemeFree(theme);
127         return NULL;
128     }
129     theme->mfont_height = RrFontHeight(theme->mfont);
130
131     mjust = RR_JUSTIFY_LEFT;
132     if (read_string(db, "menu.frame.justify", &str)) {
133         if (!g_ascii_strcasecmp(str, "right"))
134             mjust = RR_JUSTIFY_RIGHT;
135         else if (!g_ascii_strcasecmp(str, "center"))
136             mjust = RR_JUSTIFY_CENTER;
137     }
138
139     /* load direct dimensions */
140     if (!read_int(db, "menuOverlap", &theme->menu_overlap) ||
141         theme->menu_overlap < 0 || theme->menu_overlap > 20)
142         theme->handle_height = 0;
143     if (!read_int(db, "handleWidth", &theme->handle_height) ||
144         theme->handle_height < 0 || theme->handle_height > 100)
145         theme->handle_height = 6;
146     if (!read_int(db, "bevelWidth", &theme->bevel) ||
147         theme->bevel <= 0 || theme->bevel > 100) theme->bevel = 3;
148     if (!read_int(db, "borderWidth", &theme->bwidth) ||
149         theme->bwidth < 0 || theme->bwidth > 100) theme->bwidth = 1;
150     if (!read_int(db, "frameWidth", &theme->cbwidth) ||
151         theme->cbwidth < 0 || theme->cbwidth > 100)
152         theme->cbwidth = theme->bevel;
153
154     /* load colors */
155     if (!read_color(db, inst,
156                     "borderColor", &theme->b_color))
157         theme->b_color = RrColorNew(inst, 0, 0, 0);
158     if (!read_color(db, inst,
159                     "window.frame.focusColor", &theme->cb_focused_color))
160         theme->cb_focused_color = RrColorNew(inst, 0xff, 0xff, 0xff);
161     if (!read_color(db, inst,
162                     "window.frame.unfocusColor",&theme->cb_unfocused_color))
163         theme->cb_unfocused_color = RrColorNew(inst, 0xff, 0xff, 0xff);
164     if (!read_color(db, inst,
165                     "window.label.focus.textColor",
166                     &theme->title_focused_color))
167         theme->title_focused_color = RrColorNew(inst, 0x0, 0x0, 0x0);
168     if (!read_color(db, inst,
169                     "window.label.unfocus.textColor",
170                     &theme->title_unfocused_color))
171         theme->title_unfocused_color = RrColorNew(inst, 0xff, 0xff, 0xff);
172     if (!read_color(db, inst,
173                     "window.button.focus.picColor",
174                     &theme->titlebut_focused_unpressed_color))
175         theme->titlebut_focused_unpressed_color = RrColorNew(inst, 0, 0, 0);
176     if (!read_color(db, inst,
177                     "window.button.unfocus.picColor",
178                     &theme->titlebut_unfocused_unpressed_color))
179         theme->titlebut_unfocused_unpressed_color =
180             RrColorNew(inst, 0xff, 0xff, 0xff);
181     if (!read_color(db, inst,
182                     "window.button.pressed.focus.picColor",
183                     &theme->titlebut_focused_pressed_color))
184         theme->titlebut_focused_pressed_color =
185             RrColorNew(inst,
186                        theme->titlebut_focused_unpressed_color->r,
187                        theme->titlebut_focused_unpressed_color->g,
188                        theme->titlebut_focused_unpressed_color->b);
189     if (!read_color(db, inst,
190                     "window.button.pressed.unfocus.picColor",
191                     &theme->titlebut_unfocused_pressed_color))
192         theme->titlebut_unfocused_pressed_color =
193             RrColorNew(inst,
194                        theme->titlebut_unfocused_unpressed_color->r,
195                        theme->titlebut_unfocused_unpressed_color->g,
196                        theme->titlebut_unfocused_unpressed_color->b);
197     if (!read_color(db, inst,
198                     "window.button.disabled.focus.picColor",
199                     &theme->titlebut_disabled_focused_color))
200         theme->titlebut_disabled_focused_color =
201             RrColorNew(inst, 0xff, 0xff, 0xff);
202     if (!read_color(db, inst,
203                     "window.button.disabled.unfocus.picColor",
204                     &theme->titlebut_disabled_unfocused_color))
205         theme->titlebut_disabled_unfocused_color = RrColorNew(inst, 0, 0, 0);
206     if (!read_color(db, inst,
207                     "window.button.hover.focus.picColor",
208                     &theme->titlebut_hover_focused_color))
209         theme->titlebut_hover_focused_color =
210             RrColorNew(inst,
211                        theme->titlebut_focused_unpressed_color->r,
212                        theme->titlebut_focused_unpressed_color->g,
213                        theme->titlebut_focused_unpressed_color->b);
214     if (!read_color(db, inst,
215                     "window.button.hover.unfocus.picColor",
216                     &theme->titlebut_hover_unfocused_color))
217         theme->titlebut_hover_unfocused_color =
218             RrColorNew(inst,
219                        theme->titlebut_unfocused_unpressed_color->r,
220                        theme->titlebut_unfocused_unpressed_color->g,
221                        theme->titlebut_unfocused_unpressed_color->b);
222     if (!read_color(db, inst,
223                     "menu.title.textColor", &theme->menu_title_color))
224         theme->menu_title_color = RrColorNew(inst, 0, 0, 0);
225     if (!read_color(db, inst,
226                     "menu.frame.textColor", &theme->menu_color))
227         theme->menu_color = RrColorNew(inst, 0xff, 0xff, 0xff);
228     if (!read_color(db, inst,
229                     "menu.frame.disableColor", &theme->menu_disabled_color))
230         theme->menu_disabled_color = RrColorNew(inst, 0, 0, 0);
231     if (!read_color(db, inst,
232                     "menu.hilite.textColor", &theme->menu_hilite_color))
233         theme->menu_hilite_color = RrColorNew(inst, 0, 0, 0);
234
235     if (read_mask(inst, "max.xbm", theme, &theme->max_unset_mask)) {
236         if (!read_mask(inst, "max_toggled.xbm", theme, &theme->max_set_mask)) {
237             theme->max_set_mask = RrPixmapMaskCopy(theme->max_unset_mask);
238         }
239         if (!read_mask(inst, "max_disabled.xbm", theme,
240                        &theme->max_disabled_mask)) {
241             theme->max_disabled_mask = RrPixmapMaskCopy(theme->max_unset_mask);
242         } 
243         if (!read_mask(inst, "max_hover.xbm", theme, &theme->max_hover_mask)) {
244             theme->max_hover_mask = RrPixmapMaskCopy(theme->max_unset_mask);
245         }
246    } else {
247         {
248             char data[] = { 0x7f, 0x7f, 0x7f, 0x41, 0x41, 0x41, 0x7f };
249             theme->max_unset_mask = RrPixmapMaskNew(inst, 7, 7, data);
250         }
251         {
252             char data[] = { 0x7c, 0x44, 0x47, 0x47, 0x7f, 0x1f, 0x1f };
253             theme->max_set_mask = RrPixmapMaskNew(inst, 7, 7, data);
254         }
255         theme->max_disabled_mask = RrPixmapMaskCopy(theme->max_unset_mask);
256         theme->max_hover_mask = RrPixmapMaskCopy(theme->max_unset_mask);
257     }
258
259     if (read_mask(inst, "iconify.xbm", theme, &theme->iconify_mask)) {
260         if (!read_mask(inst, "iconify_disabled.xbm", theme,
261                        &theme->iconify_disabled_mask)) {
262             theme->iconify_disabled_mask =
263                 RrPixmapMaskCopy(theme->iconify_mask);
264         } 
265         if (!read_mask(inst, "iconify_hover.xbm", theme,
266                        &theme->iconify_hover_mask)) {
267             theme->iconify_hover_mask =
268                 RrPixmapMaskCopy(theme->iconify_mask);
269         }
270     } else {
271         {
272             char data[] = { 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x7f };
273             theme->iconify_mask = RrPixmapMaskNew(inst, 7, 7, data);
274         }
275         theme->iconify_disabled_mask = RrPixmapMaskCopy(theme->iconify_mask);
276         theme->iconify_hover_mask = RrPixmapMaskCopy(theme->iconify_mask);
277     }
278
279     if (read_mask(inst, "stick.xbm", theme, &theme->desk_unset_mask)) {
280         if (!read_mask(inst, "stick_toggled.xbm", theme,
281                        &theme->desk_set_mask)) {
282             theme->desk_set_mask =
283                 RrPixmapMaskCopy(theme->desk_unset_mask);
284         }
285     } else {
286         {
287             char data[] = { 0x63, 0x63, 0x00, 0x00, 0x00, 0x63, 0x63 };
288             theme->desk_unset_mask = RrPixmapMaskNew(inst, 7, 7, data);
289         }
290         {
291             char data[] = { 0x00, 0x36, 0x36, 0x08, 0x36, 0x36, 0x00 };
292             theme->desk_set_mask = RrPixmapMaskNew(inst, 7, 7, data);
293         }
294     }
295
296     if (read_mask(inst, "shade.xbm", theme, &theme->shade_unset_mask)) {
297         if (!read_mask(inst, "shade_toggled.xbm", theme,
298                        &theme->shade_set_mask)) {
299             theme->shade_set_mask =
300                 RrPixmapMaskCopy(theme->shade_unset_mask);
301         }
302         if (!read_mask(inst, "shade_disabled.xbm", theme,
303                        &theme->shade_disabled_mask)) {
304             theme->shade_disabled_mask =
305                 RrPixmapMaskCopy(theme->shade_unset_mask);
306         } 
307         if (!read_mask(inst, "shade_hover.xbm", theme, 
308                        &theme->shade_hover_mask)) {
309             theme->shade_hover_mask =
310                 RrPixmapMaskCopy(theme->shade_unset_mask);
311         }
312     } else {
313         {
314             char data[] = { 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00 };
315             theme->shade_unset_mask = RrPixmapMaskNew(inst, 7, 7, data);
316         }
317         {
318             char data[] = { 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x7f };
319             theme->shade_set_mask = RrPixmapMaskNew(inst, 7, 7, data);
320         }
321         theme->shade_disabled_mask = RrPixmapMaskCopy(theme->shade_unset_mask);
322         theme->shade_hover_mask = RrPixmapMaskCopy(theme->shade_unset_mask);
323     }
324
325     if (read_mask(inst, "close.xbm", theme, &theme->close_mask)) {
326         if (!read_mask(inst, "close_disabled.xbm", theme,
327                        &theme->close_disabled_mask)) {
328             theme->close_disabled_mask = RrPixmapMaskCopy(theme->close_mask);
329         } 
330         if (!read_mask(inst, "close_hover.xbm", theme,
331                        &theme->close_hover_mask)) {
332             theme->close_hover_mask = RrPixmapMaskCopy(theme->close_mask);
333         }
334     } else {
335         {
336             char data[] = { 0x63, 0x77, 0x3e, 0x1c, 0x3e, 0x77, 0x63 };
337             theme->close_mask = RrPixmapMaskNew(inst, 7, 7, data);
338         }
339         theme->close_disabled_mask = RrPixmapMaskCopy(theme->close_mask);
340         theme->close_hover_mask = RrPixmapMaskCopy(theme->close_mask);
341     }        
342
343     /* read the decoration textures */
344     if (!read_appearance(db, inst,
345                          "window.title.focus", theme->a_focused_title,
346                          FALSE))
347         set_default_appearance(theme->a_focused_title);
348     if (!read_appearance(db, inst,
349                          "window.title.unfocus", theme->a_unfocused_title,
350                          FALSE))
351         set_default_appearance(theme->a_unfocused_title);
352     if (!read_appearance(db, inst,
353                          "window.label.focus", theme->a_focused_label,
354                          TRUE))
355         set_default_appearance(theme->a_focused_label);
356     if (!read_appearance(db, inst,
357                          "window.label.unfocus", theme->a_unfocused_label,
358                          TRUE))
359         set_default_appearance(theme->a_unfocused_label);
360     if (!read_appearance(db, inst,
361                          "window.handle.focus", theme->a_focused_handle,
362                          FALSE))
363         set_default_appearance(theme->a_focused_handle);
364     if (!read_appearance(db, inst,
365                          "window.handle.unfocus",theme->a_unfocused_handle,
366                          FALSE))
367         set_default_appearance(theme->a_unfocused_handle);
368     if (!read_appearance(db, inst,
369                          "window.grip.focus", theme->a_focused_grip,
370                          TRUE))
371         set_default_appearance(theme->a_focused_grip);
372     if (!read_appearance(db, inst,
373                          "window.grip.unfocus", theme->a_unfocused_grip,
374                          TRUE))
375         set_default_appearance(theme->a_unfocused_grip);
376     if (!read_appearance(db, inst,
377                          "menu.frame", theme->a_menu,
378                          FALSE))
379         set_default_appearance(theme->a_menu);
380     if (!read_appearance(db, inst,
381                          "menu.title", theme->a_menu_title,
382                          FALSE))
383         set_default_appearance(theme->a_menu_title);
384     if (!read_appearance(db, inst,
385                          "menu.hilite", theme->a_menu_hilite,
386                          TRUE))
387         set_default_appearance(theme->a_menu_hilite);
388
389     /* read the appearances for rendering non-decorations */
390     if (!read_appearance(db, inst,
391                          "window.title.focus", theme->app_hilite_bg,
392                          FALSE))
393         set_default_appearance(theme->app_hilite_bg);
394     if (!read_appearance(db, inst,
395                          "window.label.focus", theme->app_hilite_label,
396                          TRUE))
397         set_default_appearance(theme->app_hilite_label);
398     if (!read_appearance(db, inst,
399                          "window.title.unfocus", theme->app_unhilite_bg,
400                          FALSE))
401         set_default_appearance(theme->app_unhilite_bg);
402     if (!read_appearance(db, inst,
403                          "window.label.unfocus", theme->app_unhilite_label,
404                          TRUE))
405         set_default_appearance(theme->app_unhilite_label);
406
407     /* read buttons textures */
408     if (!read_appearance(db, inst,
409                          "window.button.disabled.focus",
410                          theme->a_disabled_focused_max,
411                          TRUE))
412         set_default_appearance(theme->a_disabled_focused_max);
413     if (!read_appearance(db, inst,
414                          "window.button.disabled.unfocus",
415                          theme->a_disabled_unfocused_max,
416                          TRUE))
417         set_default_appearance(theme->a_disabled_unfocused_max);
418     if (!read_appearance(db, inst,
419                          "window.button.pressed.focus",
420                          theme->a_focused_pressed_max,
421                          TRUE))
422         if (!read_appearance(db, inst,
423                              "window.button.pressed",
424                              theme->a_focused_pressed_max,
425                          TRUE))
426             set_default_appearance(theme->a_focused_pressed_max);
427     if (!read_appearance(db, inst,
428                          "window.button.pressed.unfocus",
429                          theme->a_unfocused_pressed_max,
430                          TRUE))
431         if (!read_appearance(db, inst,
432                              "window.button.pressed",
433                              theme->a_unfocused_pressed_max,
434                              TRUE))
435             set_default_appearance(theme->a_unfocused_pressed_max);
436     if (!read_appearance(db, inst,
437                          "window.button.focus",
438                          theme->a_focused_unpressed_max,
439                          TRUE))
440         set_default_appearance(theme->a_focused_unpressed_max);
441     if (!read_appearance(db, inst,
442                          "window.button.unfocus",
443                          theme->a_unfocused_unpressed_max,
444                          TRUE))
445         set_default_appearance(theme->a_unfocused_unpressed_max);
446     if (!read_appearance(db, inst,
447                          "window.button.hover.focus",
448                          theme->a_hover_focused_max,
449                          TRUE))
450         theme->a_hover_focused_max =
451             RrAppearanceCopy(theme->a_focused_unpressed_max);
452     if (!read_appearance(db, inst,
453                          "window.button.hover.unfocus",
454                          theme->a_hover_unfocused_max,
455                          TRUE))
456         theme->a_hover_unfocused_max =
457             RrAppearanceCopy(theme->a_unfocused_unpressed_max);
458
459     theme->a_disabled_focused_close =
460         RrAppearanceCopy(theme->a_disabled_focused_max);
461     theme->a_disabled_unfocused_close =
462         RrAppearanceCopy(theme->a_disabled_unfocused_max);
463     theme->a_hover_focused_close =
464         RrAppearanceCopy(theme->a_hover_focused_max);
465     theme->a_hover_unfocused_close =
466         RrAppearanceCopy(theme->a_hover_unfocused_max);
467     theme->a_unfocused_unpressed_close =
468         RrAppearanceCopy(theme->a_unfocused_unpressed_max);
469     theme->a_unfocused_pressed_close =
470         RrAppearanceCopy(theme->a_unfocused_pressed_max);
471     theme->a_focused_unpressed_close =
472         RrAppearanceCopy(theme->a_focused_unpressed_max);
473     theme->a_focused_pressed_close =
474         RrAppearanceCopy(theme->a_focused_pressed_max);
475     theme->a_disabled_focused_desk =
476         RrAppearanceCopy(theme->a_disabled_focused_max);
477     theme->a_disabled_unfocused_desk =
478         RrAppearanceCopy(theme->a_disabled_unfocused_max);
479     theme->a_hover_focused_desk =
480         RrAppearanceCopy(theme->a_hover_focused_max);
481     theme->a_hover_unfocused_desk =
482         RrAppearanceCopy(theme->a_hover_unfocused_max);
483     theme->a_unfocused_unpressed_desk =
484         RrAppearanceCopy(theme->a_unfocused_unpressed_max);
485     theme->a_unfocused_pressed_desk =
486         RrAppearanceCopy(theme->a_unfocused_pressed_max);
487     theme->a_unfocused_pressed_set_desk =
488         RrAppearanceCopy(theme->a_unfocused_pressed_max);
489     theme->a_focused_unpressed_desk =
490         RrAppearanceCopy(theme->a_focused_unpressed_max);
491     theme->a_focused_pressed_desk =
492         RrAppearanceCopy(theme->a_focused_pressed_max);
493     theme->a_focused_pressed_set_desk =
494         RrAppearanceCopy(theme->a_focused_pressed_max);
495     theme->a_disabled_focused_shade =
496         RrAppearanceCopy(theme->a_disabled_focused_max);
497     theme->a_disabled_unfocused_shade =
498         RrAppearanceCopy(theme->a_disabled_unfocused_max);
499     theme->a_hover_focused_shade =
500         RrAppearanceCopy(theme->a_hover_focused_max);
501     theme->a_hover_unfocused_shade =
502         RrAppearanceCopy(theme->a_hover_unfocused_max);
503     theme->a_unfocused_unpressed_shade =
504         RrAppearanceCopy(theme->a_unfocused_unpressed_max);
505     theme->a_unfocused_pressed_shade =
506         RrAppearanceCopy(theme->a_unfocused_pressed_max);
507     theme->a_unfocused_pressed_set_shade =
508         RrAppearanceCopy(theme->a_unfocused_pressed_max);
509     theme->a_focused_unpressed_shade =
510         RrAppearanceCopy(theme->a_focused_unpressed_max);
511     theme->a_focused_pressed_shade =
512         RrAppearanceCopy(theme->a_focused_pressed_max);
513     theme->a_focused_pressed_set_shade =
514         RrAppearanceCopy(theme->a_focused_pressed_max);
515     theme->a_disabled_focused_iconify =
516         RrAppearanceCopy(theme->a_disabled_focused_max);
517     theme->a_disabled_unfocused_iconify =
518         RrAppearanceCopy(theme->a_disabled_focused_max);
519     theme->a_hover_focused_iconify =
520         RrAppearanceCopy(theme->a_hover_focused_max);
521     theme->a_hover_unfocused_iconify =
522         RrAppearanceCopy(theme->a_hover_unfocused_max);
523     theme->a_unfocused_unpressed_iconify =
524         RrAppearanceCopy(theme->a_unfocused_unpressed_max);
525     theme->a_unfocused_pressed_iconify =
526         RrAppearanceCopy(theme->a_unfocused_pressed_max);
527     theme->a_focused_unpressed_iconify =
528         RrAppearanceCopy(theme->a_focused_unpressed_max);
529     theme->a_focused_pressed_iconify =
530         RrAppearanceCopy(theme->a_focused_pressed_max);
531     theme->a_unfocused_pressed_set_max =
532         RrAppearanceCopy(theme->a_unfocused_pressed_max);
533     theme->a_focused_pressed_set_max =
534         RrAppearanceCopy(theme->a_focused_pressed_max);
535
536     theme->a_icon->surface.grad = RR_SURFACE_PARENTREL;
537
538     /* set up the textures */
539     theme->a_focused_label->texture[0].type = 
540         theme->app_hilite_label->texture[0].type = RR_TEXTURE_TEXT;
541     theme->a_focused_label->texture[0].data.text.justify = winjust;
542     theme->app_hilite_label->texture[0].data.text.justify = RR_JUSTIFY_LEFT;
543     theme->a_focused_label->texture[0].data.text.font =
544         theme->app_hilite_label->texture[0].data.text.font = theme->winfont;
545     theme->a_focused_label->texture[0].data.text.color =
546         theme->app_hilite_label->texture[0].data.text.color =
547         theme->title_focused_color;
548
549     theme->a_unfocused_label->texture[0].type =
550         theme->app_unhilite_label->texture[0].type = RR_TEXTURE_TEXT;
551     theme->a_unfocused_label->texture[0].data.text.justify = winjust;
552     theme->app_unhilite_label->texture[0].data.text.justify = RR_JUSTIFY_LEFT;
553     theme->a_unfocused_label->texture[0].data.text.font =
554         theme->app_unhilite_label->texture[0].data.text.font = theme->winfont;
555     theme->a_unfocused_label->texture[0].data.text.color =
556         theme->app_unhilite_label->texture[0].data.text.color =
557         theme->title_unfocused_color;
558
559     theme->a_menu_title->texture[0].type = RR_TEXTURE_TEXT;
560     theme->a_menu_title->texture[0].data.text.justify = mtitlejust;
561     theme->a_menu_title->texture[0].data.text.font = theme->mtitlefont;
562     theme->a_menu_title->texture[0].data.text.color = theme->menu_title_color;
563
564     theme->a_menu_item->surface.grad = 
565         theme->a_menu_disabled->surface.grad =
566         theme->app_icon->surface.grad = RR_SURFACE_PARENTREL;
567
568     theme->a_menu_item->texture[0].type =
569         theme->a_menu_disabled->texture[0].type = 
570         theme->a_menu_hilite->texture[0].type = RR_TEXTURE_TEXT;
571     theme->a_menu_item->texture[0].data.text.justify = 
572         theme->a_menu_disabled->texture[0].data.text.justify = 
573         theme->a_menu_hilite->texture[0].data.text.justify = mjust;
574     theme->a_menu_item->texture[0].data.text.font =
575         theme->a_menu_disabled->texture[0].data.text.font =
576         theme->a_menu_hilite->texture[0].data.text.font = theme->mfont;
577     theme->a_menu_item->texture[0].data.text.color = theme->menu_color;
578     theme->a_menu_disabled->texture[0].data.text.color =
579         theme->menu_disabled_color;
580     theme->a_menu_hilite->texture[0].data.text.color =
581         theme->menu_hilite_color;
582
583     theme->a_disabled_focused_max->texture[0].type = 
584         theme->a_disabled_unfocused_max->texture[0].type = 
585         theme->a_hover_focused_max->texture[0].type = 
586         theme->a_hover_unfocused_max->texture[0].type = 
587         theme->a_focused_unpressed_max->texture[0].type = 
588         theme->a_focused_pressed_max->texture[0].type = 
589         theme->a_focused_pressed_set_max->texture[0].type =  
590         theme->a_unfocused_unpressed_max->texture[0].type = 
591         theme->a_unfocused_pressed_max->texture[0].type = 
592         theme->a_unfocused_pressed_set_max->texture[0].type = 
593         theme->a_disabled_focused_close->texture[0].type = 
594         theme->a_disabled_unfocused_close->texture[0].type = 
595         theme->a_hover_focused_close->texture[0].type = 
596         theme->a_hover_unfocused_close->texture[0].type = 
597         theme->a_focused_unpressed_close->texture[0].type = 
598         theme->a_focused_pressed_close->texture[0].type = 
599         theme->a_unfocused_unpressed_close->texture[0].type = 
600         theme->a_unfocused_pressed_close->texture[0].type = 
601         theme->a_disabled_focused_desk->texture[0].type = 
602         theme->a_disabled_unfocused_desk->texture[0].type = 
603         theme->a_hover_focused_desk->texture[0].type = 
604         theme->a_hover_unfocused_desk->texture[0].type = 
605         theme->a_focused_unpressed_desk->texture[0].type = 
606         theme->a_focused_pressed_desk->texture[0].type = 
607         theme->a_focused_pressed_set_desk->texture[0].type = 
608         theme->a_unfocused_unpressed_desk->texture[0].type = 
609         theme->a_unfocused_pressed_desk->texture[0].type = 
610         theme->a_unfocused_pressed_set_desk->texture[0].type = 
611         theme->a_disabled_focused_shade->texture[0].type = 
612         theme->a_disabled_unfocused_shade->texture[0].type = 
613         theme->a_hover_focused_shade->texture[0].type = 
614         theme->a_hover_unfocused_shade->texture[0].type = 
615         theme->a_focused_unpressed_shade->texture[0].type = 
616         theme->a_focused_pressed_shade->texture[0].type = 
617         theme->a_focused_pressed_set_shade->texture[0].type = 
618         theme->a_unfocused_unpressed_shade->texture[0].type = 
619         theme->a_unfocused_pressed_shade->texture[0].type = 
620         theme->a_unfocused_pressed_set_shade->texture[0].type = 
621         theme->a_disabled_focused_iconify->texture[0].type = 
622         theme->a_disabled_unfocused_iconify->texture[0].type = 
623         theme->a_hover_focused_iconify->texture[0].type = 
624         theme->a_hover_unfocused_iconify->texture[0].type = 
625         theme->a_focused_unpressed_iconify->texture[0].type = 
626         theme->a_focused_pressed_iconify->texture[0].type = 
627         theme->a_unfocused_unpressed_iconify->texture[0].type = 
628         theme->a_unfocused_pressed_iconify->texture[0].type = RR_TEXTURE_MASK;
629     theme->a_disabled_focused_max->texture[0].data.mask.mask = 
630         theme->a_disabled_unfocused_max->texture[0].data.mask.mask = 
631         theme->max_disabled_mask;
632     theme->a_hover_focused_max->texture[0].data.mask.mask = 
633         theme->a_hover_unfocused_max->texture[0].data.mask.mask = 
634         theme->max_hover_mask;
635     theme->a_focused_unpressed_max->texture[0].data.mask.mask = 
636         theme->a_unfocused_unpressed_max->texture[0].data.mask.mask = 
637         theme->a_focused_pressed_max->texture[0].data.mask.mask = 
638         theme->a_unfocused_pressed_max->texture[0].data.mask.mask =
639         theme->max_unset_mask;
640     theme->a_focused_pressed_set_max->texture[0].data.mask.mask = 
641         theme->a_unfocused_pressed_set_max->texture[0].data.mask.mask =
642         theme->max_set_mask;
643     theme->a_disabled_focused_close->texture[0].data.mask.mask = 
644         theme->a_disabled_unfocused_close->texture[0].data.mask.mask = 
645         theme->close_disabled_mask;
646     theme->a_hover_focused_close->texture[0].data.mask.mask = 
647         theme->a_hover_unfocused_close->texture[0].data.mask.mask = 
648         theme->close_hover_mask;
649     theme->a_focused_pressed_close->texture[0].data.mask.mask = 
650         theme->a_unfocused_pressed_close->texture[0].data.mask.mask =
651         theme->a_focused_unpressed_close->texture[0].data.mask.mask = 
652         theme->a_unfocused_unpressed_close->texture[0].data.mask.mask =
653         theme->close_mask;
654     theme->a_disabled_focused_desk->texture[0].data.mask.mask = 
655         theme->a_disabled_unfocused_desk->texture[0].data.mask.mask = 
656         theme->desk_disabled_mask;
657     theme->a_hover_focused_desk->texture[0].data.mask.mask = 
658         theme->a_hover_unfocused_desk->texture[0].data.mask.mask = 
659         theme->desk_hover_mask;
660     theme->a_focused_unpressed_desk->texture[0].data.mask.mask = 
661         theme->a_unfocused_unpressed_desk->texture[0].data.mask.mask = 
662         theme->a_focused_pressed_desk->texture[0].data.mask.mask = 
663         theme->a_unfocused_pressed_desk->texture[0].data.mask.mask =
664         theme->desk_unset_mask;
665     theme->a_focused_pressed_set_desk->texture[0].data.mask.mask = 
666         theme->a_unfocused_pressed_set_desk->texture[0].data.mask.mask =
667         theme->desk_set_mask;
668     theme->a_disabled_focused_shade->texture[0].data.mask.mask = 
669         theme->a_disabled_unfocused_shade->texture[0].data.mask.mask = 
670         theme->shade_disabled_mask;
671     theme->a_hover_focused_shade->texture[0].data.mask.mask = 
672         theme->a_hover_unfocused_shade->texture[0].data.mask.mask = 
673         theme->shade_hover_mask;
674     theme->a_focused_unpressed_shade->texture[0].data.mask.mask = 
675         theme->a_unfocused_unpressed_shade->texture[0].data.mask.mask = 
676         theme->a_focused_pressed_shade->texture[0].data.mask.mask = 
677         theme->a_unfocused_pressed_shade->texture[0].data.mask.mask =
678         theme->shade_unset_mask;
679     theme->a_focused_pressed_set_shade->texture[0].data.mask.mask = 
680         theme->a_unfocused_pressed_set_shade->texture[0].data.mask.mask =
681         theme->shade_set_mask;
682     theme->a_disabled_focused_iconify->texture[0].data.mask.mask = 
683         theme->a_disabled_unfocused_iconify->texture[0].data.mask.mask = 
684         theme->iconify_disabled_mask;
685     theme->a_hover_focused_iconify->texture[0].data.mask.mask = 
686         theme->a_hover_unfocused_iconify->texture[0].data.mask.mask = 
687         theme->iconify_hover_mask;
688     theme->a_focused_unpressed_iconify->texture[0].data.mask.mask = 
689         theme->a_unfocused_unpressed_iconify->texture[0].data.mask.mask = 
690         theme->a_focused_pressed_iconify->texture[0].data.mask.mask = 
691         theme->a_unfocused_pressed_iconify->texture[0].data.mask.mask =
692         theme->iconify_mask;
693     theme->a_disabled_focused_max->texture[0].data.mask.color = 
694         theme->a_disabled_focused_close->texture[0].data.mask.color = 
695         theme->a_disabled_focused_desk->texture[0].data.mask.color = 
696         theme->a_disabled_focused_shade->texture[0].data.mask.color = 
697         theme->a_disabled_focused_iconify->texture[0].data.mask.color = 
698         theme->titlebut_disabled_focused_color;
699     theme->a_disabled_unfocused_max->texture[0].data.mask.color = 
700         theme->a_disabled_unfocused_close->texture[0].data.mask.color = 
701         theme->a_disabled_unfocused_desk->texture[0].data.mask.color = 
702         theme->a_disabled_unfocused_shade->texture[0].data.mask.color = 
703         theme->a_disabled_unfocused_iconify->texture[0].data.mask.color = 
704         theme->titlebut_disabled_unfocused_color;
705     theme->a_hover_focused_max->texture[0].data.mask.color = 
706         theme->a_hover_focused_close->texture[0].data.mask.color = 
707         theme->a_hover_focused_desk->texture[0].data.mask.color = 
708         theme->a_hover_focused_shade->texture[0].data.mask.color = 
709         theme->a_hover_focused_iconify->texture[0].data.mask.color = 
710         theme->titlebut_hover_focused_color;
711     theme->a_hover_unfocused_max->texture[0].data.mask.color = 
712         theme->a_hover_unfocused_close->texture[0].data.mask.color = 
713         theme->a_hover_unfocused_desk->texture[0].data.mask.color = 
714         theme->a_hover_unfocused_shade->texture[0].data.mask.color = 
715         theme->a_hover_unfocused_iconify->texture[0].data.mask.color = 
716         theme->titlebut_hover_unfocused_color;
717     theme->a_focused_unpressed_max->texture[0].data.mask.color = 
718         theme->a_focused_unpressed_close->texture[0].data.mask.color = 
719         theme->a_focused_unpressed_desk->texture[0].data.mask.color = 
720         theme->a_focused_unpressed_shade->texture[0].data.mask.color = 
721         theme->a_focused_unpressed_iconify->texture[0].data.mask.color = 
722         theme->titlebut_focused_unpressed_color;
723     theme->a_focused_pressed_max->texture[0].data.mask.color = 
724         theme->a_focused_pressed_set_max->texture[0].data.mask.color = 
725         theme->a_focused_pressed_close->texture[0].data.mask.color = 
726         theme->a_focused_pressed_desk->texture[0].data.mask.color = 
727         theme->a_focused_pressed_set_desk->texture[0].data.mask.color = 
728         theme->a_focused_pressed_shade->texture[0].data.mask.color = 
729         theme->a_focused_pressed_set_shade->texture[0].data.mask.color = 
730         theme->a_focused_pressed_iconify->texture[0].data.mask.color =
731         theme->titlebut_focused_pressed_color;
732     theme->a_unfocused_unpressed_max->texture[0].data.mask.color = 
733         theme->a_unfocused_unpressed_close->texture[0].data.mask.color = 
734         theme->a_unfocused_unpressed_desk->texture[0].data.mask.color = 
735         theme->a_unfocused_unpressed_shade->texture[0].data.mask.color = 
736         theme->a_unfocused_unpressed_iconify->texture[0].data.mask.color = 
737         theme->titlebut_unfocused_unpressed_color;
738         theme->a_unfocused_pressed_max->texture[0].data.mask.color = 
739         theme->a_unfocused_pressed_set_max->texture[0].data.mask.color = 
740         theme->a_unfocused_pressed_close->texture[0].data.mask.color = 
741         theme->a_unfocused_pressed_desk->texture[0].data.mask.color = 
742         theme->a_unfocused_pressed_set_desk->texture[0].data.mask.color = 
743         theme->a_unfocused_pressed_shade->texture[0].data.mask.color = 
744         theme->a_unfocused_pressed_set_shade->texture[0].data.mask.color = 
745         theme->a_unfocused_pressed_iconify->texture[0].data.mask.color =
746         theme->titlebut_unfocused_pressed_color;
747
748     XrmDestroyDatabase(db);
749
750     theme->label_height = theme->winfont_height;
751     theme->title_height = theme->label_height + theme->bevel * 2;
752     theme->button_size = theme->label_height - 2;
753     theme->grip_width = theme->button_size * 2;
754
755     return theme;
756 }
757
758 void RrThemeFree(RrTheme *theme)
759 {
760     if (theme) {
761         g_free(theme->name);
762
763         RrColorFree(theme->b_color);
764         RrColorFree(theme->cb_unfocused_color);
765         RrColorFree(theme->cb_focused_color);
766         RrColorFree(theme->title_unfocused_color);
767         RrColorFree(theme->title_focused_color);
768         RrColorFree(theme->titlebut_disabled_focused_color);
769         RrColorFree(theme->titlebut_disabled_unfocused_color);
770         RrColorFree(theme->titlebut_hover_focused_color);
771         RrColorFree(theme->titlebut_hover_unfocused_color);
772         RrColorFree(theme->titlebut_unfocused_pressed_color);
773         RrColorFree(theme->titlebut_focused_pressed_color);
774         RrColorFree(theme->titlebut_unfocused_unpressed_color);
775         RrColorFree(theme->titlebut_focused_unpressed_color);
776         RrColorFree(theme->menu_color);
777         RrColorFree(theme->menu_title_color);
778         RrColorFree(theme->menu_disabled_color);
779         RrColorFree(theme->menu_hilite_color);
780
781         RrPixmapMaskFree(theme->max_set_mask);
782         RrPixmapMaskFree(theme->max_unset_mask);
783         RrPixmapMaskFree(theme->max_disabled_mask);
784         RrPixmapMaskFree(theme->max_hover_mask);
785         RrPixmapMaskFree(theme->desk_set_mask);
786         RrPixmapMaskFree(theme->desk_unset_mask);
787         RrPixmapMaskFree(theme->desk_disabled_mask);
788         RrPixmapMaskFree(theme->desk_hover_mask);
789         RrPixmapMaskFree(theme->shade_set_mask);
790         RrPixmapMaskFree(theme->shade_unset_mask);
791         RrPixmapMaskFree(theme->shade_disabled_mask);
792         RrPixmapMaskFree(theme->shade_hover_mask);
793         RrPixmapMaskFree(theme->iconify_mask);
794         RrPixmapMaskFree(theme->iconify_disabled_mask);
795         RrPixmapMaskFree(theme->iconify_hover_mask);
796         RrPixmapMaskFree(theme->close_mask);
797         RrPixmapMaskFree(theme->close_disabled_mask);
798         RrPixmapMaskFree(theme->close_hover_mask);
799
800         RrFontClose(theme->winfont);
801         RrFontClose(theme->mtitlefont);
802         RrFontClose(theme->mfont);
803
804         RrAppearanceFree(theme->a_disabled_focused_max);
805         RrAppearanceFree(theme->a_disabled_unfocused_max);
806         RrAppearanceFree(theme->a_hover_focused_max);
807         RrAppearanceFree(theme->a_hover_unfocused_max);
808         RrAppearanceFree(theme->a_focused_unpressed_max);
809         RrAppearanceFree(theme->a_focused_pressed_max);
810         RrAppearanceFree(theme->a_focused_pressed_set_max);
811         RrAppearanceFree(theme->a_unfocused_unpressed_max);
812         RrAppearanceFree(theme->a_unfocused_pressed_max);
813         RrAppearanceFree(theme->a_unfocused_pressed_set_max);
814         RrAppearanceFree(theme->a_disabled_focused_close);
815         RrAppearanceFree(theme->a_disabled_unfocused_close);
816         RrAppearanceFree(theme->a_hover_focused_close);
817         RrAppearanceFree(theme->a_hover_unfocused_close);
818         RrAppearanceFree(theme->a_focused_unpressed_close);
819         RrAppearanceFree(theme->a_focused_pressed_close);
820         RrAppearanceFree(theme->a_unfocused_unpressed_close);
821         RrAppearanceFree(theme->a_unfocused_pressed_close);
822         RrAppearanceFree(theme->a_disabled_focused_desk);
823         RrAppearanceFree(theme->a_disabled_unfocused_desk);
824         RrAppearanceFree(theme->a_hover_focused_desk);
825         RrAppearanceFree(theme->a_hover_unfocused_desk);
826         RrAppearanceFree(theme->a_focused_unpressed_desk);
827         RrAppearanceFree(theme->a_focused_pressed_desk);
828         RrAppearanceFree(theme->a_unfocused_unpressed_desk);
829         RrAppearanceFree(theme->a_unfocused_pressed_desk);
830         RrAppearanceFree(theme->a_disabled_focused_shade);
831         RrAppearanceFree(theme->a_disabled_unfocused_shade);
832         RrAppearanceFree(theme->a_hover_focused_shade);
833         RrAppearanceFree(theme->a_hover_unfocused_shade);
834         RrAppearanceFree(theme->a_focused_unpressed_shade);
835         RrAppearanceFree(theme->a_focused_pressed_shade);
836         RrAppearanceFree(theme->a_unfocused_unpressed_shade);
837         RrAppearanceFree(theme->a_unfocused_pressed_shade);
838         RrAppearanceFree(theme->a_disabled_focused_iconify);
839         RrAppearanceFree(theme->a_disabled_unfocused_iconify);
840         RrAppearanceFree(theme->a_hover_focused_iconify);
841         RrAppearanceFree(theme->a_hover_unfocused_iconify);
842         RrAppearanceFree(theme->a_focused_unpressed_iconify);
843         RrAppearanceFree(theme->a_focused_pressed_iconify);
844         RrAppearanceFree(theme->a_unfocused_unpressed_iconify);
845         RrAppearanceFree(theme->a_unfocused_pressed_iconify);
846         RrAppearanceFree(theme->a_focused_grip);
847         RrAppearanceFree(theme->a_unfocused_grip);
848         RrAppearanceFree(theme->a_focused_title);
849         RrAppearanceFree(theme->a_unfocused_title);
850         RrAppearanceFree(theme->a_focused_label);
851         RrAppearanceFree(theme->a_unfocused_label);
852         RrAppearanceFree(theme->a_icon);
853         RrAppearanceFree(theme->a_focused_handle);
854         RrAppearanceFree(theme->a_unfocused_handle);
855         RrAppearanceFree(theme->a_menu);
856         RrAppearanceFree(theme->a_menu_title);
857         RrAppearanceFree(theme->a_menu_item);
858         RrAppearanceFree(theme->a_menu_disabled);
859         RrAppearanceFree(theme->a_menu_hilite);
860         RrAppearanceFree(theme->app_hilite_bg);
861         RrAppearanceFree(theme->app_unhilite_bg);
862         RrAppearanceFree(theme->app_hilite_label);
863         RrAppearanceFree(theme->app_unhilite_label);
864         RrAppearanceFree(theme->app_icon);
865     }
866 }
867
868 static XrmDatabase loaddb(RrTheme *theme, char *name)
869 {
870     XrmDatabase db;
871
872     char *s = g_build_filename(name, "themerc", NULL);
873     if ((db = XrmGetFileDatabase(s)))
874         theme->path = g_path_get_dirname(s);
875     g_free(s);
876     if (db == NULL) {
877         char *s = g_build_filename(g_get_home_dir(), ".openbox", "themes",
878                                    name, "themerc", NULL);
879         if ((db = XrmGetFileDatabase(s)))
880             theme->path = g_path_get_dirname(s);
881         g_free(s);
882     }
883     if (db == NULL) {
884         char *s = g_build_filename(THEMEDIR, name, "themerc", NULL);
885         if ((db = XrmGetFileDatabase(s)))
886             theme->path = g_path_get_dirname(s);
887         g_free(s);
888     }
889
890     return db;
891 }
892
893 static char *create_class_name(char *rname)
894 {
895     char *rclass = g_strdup(rname);
896     char *p = rclass;
897
898     while (TRUE) {
899         *p = toupper(*p);
900         p = strchr(p+1, '.');
901         if (p == NULL) break;
902         ++p;
903         if (*p == '\0') break;
904     }
905     return rclass;
906 }
907
908 static gboolean read_int(XrmDatabase db, char *rname, int *value)
909 {
910     gboolean ret = FALSE;
911     char *rclass = create_class_name(rname);
912     char *rettype, *end;
913     XrmValue retvalue;
914   
915     if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
916         retvalue.addr != NULL) {
917         *value = (int)strtol(retvalue.addr, &end, 10);
918         if (end != retvalue.addr)
919             ret = TRUE;
920     }
921
922     g_free(rclass);
923     return ret;
924 }
925
926 static gboolean read_string(XrmDatabase db, char *rname, char **value)
927 {
928     gboolean ret = FALSE;
929     char *rclass = create_class_name(rname);
930     char *rettype;
931     XrmValue retvalue;
932   
933     if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
934         retvalue.addr != NULL) {
935         *value = retvalue.addr;
936         ret = TRUE;
937     }
938
939     g_free(rclass);
940     return ret;
941 }
942
943 static gboolean read_color(XrmDatabase db, const RrInstance *inst,
944                            gchar *rname, RrColor **value)
945 {
946     gboolean ret = FALSE;
947     char *rclass = create_class_name(rname);
948     char *rettype;
949     XrmValue retvalue;
950   
951     if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
952         retvalue.addr != NULL) {
953         RrColor *c = RrColorParse(inst, retvalue.addr);
954         if (c != NULL) {
955             *value = c;
956             ret = TRUE;
957         }
958     }
959
960     g_free(rclass);
961     return ret;
962 }
963
964 static gboolean read_mask(const RrInstance *inst,
965                           gchar *maskname, RrTheme *theme,
966                           RrPixmapMask **value)
967 {
968     gboolean ret = FALSE;
969     char *s;
970     int hx, hy; /* ignored */
971     unsigned int w, h;
972     unsigned char *b;
973
974     s = g_build_filename(g_get_home_dir(), ".openbox", "themes",
975                          theme->name, maskname, NULL);
976     if (XReadBitmapFileData(s, &w, &h, &b, &hx, &hy) == BitmapSuccess)
977         ret = TRUE;
978     else {
979         g_free(s);
980         s = g_build_filename(THEMEDIR, theme->name, maskname, NULL);
981         if (XReadBitmapFileData(s, &w, &h, &b, &hx, &hy) == BitmapSuccess) 
982             ret = TRUE;
983         else {
984             g_free(s);
985             s = g_build_filename(theme->path, maskname, NULL);
986             if (XReadBitmapFileData(s, &w, &h, &b, &hx, &hy) == BitmapSuccess) 
987                 ret = TRUE;
988         }
989     }
990
991     if (ret) {
992         *value = RrPixmapMaskNew(inst, w, h, (char*)b);
993         XFree(b);
994     }
995       
996     g_free(s);
997
998     return ret;
999 }
1000
1001 static void parse_appearance(gchar *tex, RrSurfaceColorType *grad,
1002                              RrReliefType *relief, RrBevelType *bevel,
1003                              gboolean *interlaced, gboolean *border,
1004                              gboolean allow_trans)
1005 {
1006     char *t;
1007
1008     /* convert to all lowercase */
1009     for (t = tex; *t != '\0'; ++t)
1010         *t = g_ascii_tolower(*t);
1011
1012     if (allow_trans && strstr(tex, "parentrelative") != NULL) {
1013         *grad = RR_SURFACE_PARENTREL;
1014     } else {
1015         if (strstr(tex, "gradient") != NULL) {
1016             if (strstr(tex, "crossdiagonal") != NULL)
1017                 *grad = RR_SURFACE_CROSS_DIAGONAL;
1018             else if (strstr(tex, "pyramid") != NULL)
1019                 *grad = RR_SURFACE_PYRAMID;
1020             else if (strstr(tex, "horizontal") != NULL)
1021                 *grad = RR_SURFACE_HORIZONTAL;
1022             else if (strstr(tex, "vertical") != NULL)
1023                 *grad = RR_SURFACE_VERTICAL;
1024             else
1025                 *grad = RR_SURFACE_DIAGONAL;
1026         } else {
1027             *grad = RR_SURFACE_SOLID;
1028         }
1029
1030         if (strstr(tex, "sunken") != NULL)
1031             *relief = RR_RELIEF_SUNKEN;
1032         else if (strstr(tex, "flat") != NULL)
1033             *relief = RR_RELIEF_FLAT;
1034         else
1035             *relief = RR_RELIEF_RAISED;
1036         
1037         *border = FALSE;
1038         if (*relief == RR_RELIEF_FLAT) {
1039             if (strstr(tex, "border") != NULL)
1040                 *border = TRUE;
1041         } else {
1042             if (strstr(tex, "bevel2") != NULL)
1043                 *bevel = RR_BEVEL_2;
1044             else
1045                 *bevel = RR_BEVEL_1;
1046         }
1047
1048         if (strstr(tex, "interlaced") != NULL)
1049             *interlaced = TRUE;
1050         else
1051             *interlaced = FALSE;
1052     }
1053 }
1054
1055
1056 static gboolean read_appearance(XrmDatabase db, const RrInstance *inst,
1057                                 gchar *rname, RrAppearance *value,
1058                                 gboolean allow_trans)
1059 {
1060     gboolean ret = FALSE;
1061     char *rclass = create_class_name(rname), *cname, *ctoname, *bcname;
1062     char *rettype;
1063     XrmValue retvalue;
1064
1065     cname = g_strconcat(rname, ".color", NULL);
1066     ctoname = g_strconcat(rname, ".colorTo", NULL);
1067     bcname = g_strconcat(rname, ".borderColor", NULL);
1068
1069     if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
1070         retvalue.addr != NULL) {
1071         parse_appearance(retvalue.addr,
1072                          &value->surface.grad,
1073                          &value->surface.relief,
1074                          &value->surface.bevel,
1075                          &value->surface.interlaced,
1076                          &value->surface.border,
1077                          allow_trans);
1078         if (!read_color(db, inst, cname, &value->surface.primary))
1079             value->surface.primary = RrColorNew(inst, 0, 0, 0);
1080         if (!read_color(db, inst, ctoname, &value->surface.secondary))
1081             value->surface.secondary = RrColorNew(inst, 0, 0, 0);
1082         if (value->surface.border)
1083             if (!read_color(db, inst, bcname,
1084                             &value->surface.border_color))
1085                 value->surface.border_color = RrColorNew(inst, 0, 0, 0);
1086         ret = TRUE;
1087     }
1088
1089     g_free(bcname);
1090     g_free(ctoname);
1091     g_free(cname);
1092     g_free(rclass);
1093     return ret;
1094 }
1095
1096 static void set_default_appearance(RrAppearance *a)
1097 {
1098     a->surface.grad = RR_SURFACE_SOLID;
1099     a->surface.relief = RR_RELIEF_FLAT;
1100     a->surface.bevel = RR_BEVEL_1;
1101     a->surface.interlaced = FALSE;
1102     a->surface.border = FALSE;
1103     a->surface.primary = RrColorNew(a->inst, 0, 0, 0);
1104     a->surface.secondary = RrColorNew(a->inst, 0, 0, 0);
1105 }