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