dunno why this was lying around as an uncommitted change..
[mikachu/openbox.git] / obrender / theme.c
1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
2
3    theme.c for the Openbox window manager
4    Copyright (c) 2006        Mikael Magnusson
5    Copyright (c) 2003-2007   Dana Jansens
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    See the COPYING file for a copy of the GNU General Public License.
18 */
19
20 #include "render.h"
21 #include "color.h"
22 #include "font.h"
23 #include "mask.h"
24 #include "theme.h"
25 #ifdef MIKACHU
26 # include "icon-mikamika.h"
27 #else
28 # include "icon.h"
29 #endif
30 #include "obt/paths.h"
31
32 #include <X11/Xlib.h>
33 #include <X11/Xresource.h>
34 #include <ctype.h>
35 #include <stdlib.h>
36 #include <string.h>
37
38 static XrmDatabase loaddb(const gchar *name, gchar **path);
39 static gboolean read_int(XrmDatabase db, const gchar *rname, gint *value);
40 static gboolean read_string(XrmDatabase db, const gchar *rname, gchar **value);
41 static gboolean read_color(XrmDatabase db, const RrInstance *inst,
42                            const gchar *rname, RrColor **value);
43 static gboolean read_mask(const RrInstance *inst, const gchar *path,
44                           RrTheme *theme, const gchar *maskname,
45                           RrPixmapMask **value);
46 static gboolean read_appearance(XrmDatabase db, const RrInstance *inst,
47                                 const gchar *rname, RrAppearance *value,
48                                 gboolean allow_trans);
49 static int parse_inline_number(const char *p);
50 static RrPixel32* read_c_image(gint width, gint height, const guint8 *data);
51 static void set_default_appearance(RrAppearance *a);
52 static void read_button_colors(XrmDatabase db, const RrInstance *inst, 
53                                const RrTheme *theme, RrButton *btn, 
54                                const gchar *btnname);
55
56 static RrFont *get_font(RrFont *target, RrFont **default_font,
57                         const RrInstance *inst)
58 {
59     if (target) {
60         RrFontRef(target);
61         return target;
62     } else {
63         /* Only load the default font once */
64         if (*default_font) {
65             RrFontRef(*default_font);
66         } else {
67             *default_font = RrFontOpenDefault(inst);
68         }
69         return *default_font;
70     }
71 }
72
73 #define READ_INT(x_resstr, x_var, x_min, x_max, x_def) \
74     if (!read_int(db, x_resstr, & x_var) || \
75             x_var < x_min || x_var > x_max) \
76         x_var = x_def;
77
78 #define READ_COLOR(x_resstr, x_var, x_def) \
79     if (!read_color(db, inst, x_resstr, & x_var)) \
80         x_var = x_def;
81
82 #define READ_COLOR_(x_res1, x_res2, x_var, x_def) \
83     if (!read_color(db, inst, x_res1, & x_var) && \
84         !read_color(db, inst, x_res2, & x_var)) \
85         x_var = x_def;
86
87 #define READ_MASK_COPY(x_file, x_var, x_copysrc) \
88     if (!read_mask(inst, path, theme, x_file, & x_var)) \
89         x_var = RrPixmapMaskCopy(x_copysrc);
90
91 #define READ_APPEARANCE(x_resstr, x_var, x_parrel) \
92     if (!read_appearance(db, inst, x_resstr, x_var, x_parrel)) \
93         set_default_appearance(x_var);
94
95 #define READ_APPEARANCE_COPY(x_resstr, x_var, x_parrel, x_defval) \
96     if (!read_appearance(db, inst, x_resstr, x_var, x_parrel)) {\
97         RrAppearanceFree(x_var); \
98         x_var = RrAppearanceCopy(x_defval); }
99
100 #define READ_APPEARANCE_COPY_TEXTURES(x_resstr, x_var, x_parrel, x_defval, n_tex) \
101     if (!read_appearance(db, inst, x_resstr, x_var, x_parrel)) {\
102         RrAppearanceFree(x_var); \
103         x_var = RrAppearanceCopy(x_defval); \
104         RrAppearanceRemoveTextures(x_var); \
105         RrAppearanceAddTextures(x_var, 5); }
106
107 #define READ_APPEARANCE_(x_res1, x_res2, x_var, x_parrel, x_defval) \
108     if (!read_appearance(db, inst, x_res1, x_var, x_parrel) && \
109         !read_appearance(db, inst, x_res2, x_var, x_parrel)) {\
110         RrAppearanceFree(x_var); \
111         x_var = RrAppearanceCopy(x_defval); }
112
113 RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
114                     gboolean allow_fallback,
115                     RrFont *active_window_font, RrFont *inactive_window_font,
116                     RrFont *menu_title_font, RrFont *menu_item_font,
117                     RrFont *active_osd_font, RrFont *inactive_osd_font)
118 {
119     XrmDatabase db = NULL;
120     RrJustify winjust, mtitlejust;
121     gchar *str;
122     RrTheme *theme;
123     RrFont *default_font = NULL;
124     gchar *path;
125     gboolean userdef;
126     gint menu_overlap = 0;
127     RrAppearance *a_disabled_focused_tmp;
128     RrAppearance *a_disabled_unfocused_tmp;
129     RrAppearance *a_hover_focused_tmp;
130     RrAppearance *a_hover_unfocused_tmp;
131     RrAppearance *a_focused_unpressed_tmp;
132     RrAppearance *a_focused_pressed_tmp;
133     RrAppearance *a_unfocused_unpressed_tmp;
134     RrAppearance *a_unfocused_pressed_tmp;
135     RrAppearance *a_toggled_hover_focused_tmp;
136     RrAppearance *a_toggled_hover_unfocused_tmp;
137     RrAppearance *a_toggled_focused_unpressed_tmp;
138     RrAppearance *a_toggled_focused_pressed_tmp;
139     RrAppearance *a_toggled_unfocused_unpressed_tmp;
140     RrAppearance *a_toggled_unfocused_pressed_tmp;
141
142     if (name) {
143         db = loaddb(name, &path);
144         if (db == NULL) {
145             g_message("Unable to load the theme '%s'", name);
146             if (allow_fallback)
147                 g_message("Falling back to the default theme '%s'",
148                           DEFAULT_THEME);
149             /* fallback to the default theme */
150             name = NULL;
151         }
152     }
153     if (name == NULL) {
154         if (allow_fallback) {
155             db = loaddb(DEFAULT_THEME, &path);
156             if (db == NULL) {
157                 g_message("Unable to load the theme '%s'", DEFAULT_THEME);
158                 return NULL;
159             }
160         } else
161             return NULL;
162     }
163
164     /* initialize temp reading textures */
165     a_disabled_focused_tmp = RrAppearanceNew(inst, 1);
166     a_disabled_unfocused_tmp = RrAppearanceNew(inst, 1);
167     a_hover_focused_tmp = RrAppearanceNew(inst, 1);
168     a_hover_unfocused_tmp = RrAppearanceNew(inst, 1);
169     a_toggled_focused_unpressed_tmp = RrAppearanceNew(inst, 1);
170     a_toggled_unfocused_unpressed_tmp = RrAppearanceNew(inst, 1);
171     a_toggled_hover_focused_tmp = RrAppearanceNew(inst, 1);
172     a_toggled_hover_unfocused_tmp = RrAppearanceNew(inst, 1);
173     a_toggled_focused_pressed_tmp = RrAppearanceNew(inst, 1);
174     a_toggled_unfocused_pressed_tmp = RrAppearanceNew(inst, 1);
175     a_focused_unpressed_tmp = RrAppearanceNew(inst, 1);
176     a_focused_pressed_tmp = RrAppearanceNew(inst, 1);
177     a_unfocused_unpressed_tmp = RrAppearanceNew(inst, 1);
178     a_unfocused_pressed_tmp = RrAppearanceNew(inst, 1);
179
180     /* initialize theme */
181     theme = g_slice_new0(RrTheme);
182
183     theme->inst = inst;
184     theme->name = g_strdup(name ? name : DEFAULT_THEME);
185
186     /* init buttons */
187     theme->btn_max = RrButtonNew(inst);
188     theme->btn_close = RrButtonNew(inst);
189     theme->btn_desk = RrButtonNew(inst);
190     theme->btn_shade = RrButtonNew(inst);
191     theme->btn_iconify = RrButtonNew(inst);
192
193     /* init appearances */
194     theme->a_focused_grip = RrAppearanceNew(inst, 0);
195     theme->a_unfocused_grip = RrAppearanceNew(inst, 0);
196     theme->a_focused_title = RrAppearanceNew(inst, 0);
197     theme->a_unfocused_title = RrAppearanceNew(inst, 0);
198     theme->a_focused_label = RrAppearanceNew(inst, 1);
199     theme->a_unfocused_label = RrAppearanceNew(inst, 1);
200     theme->a_icon = RrAppearanceNew(inst, 1);
201     theme->a_focused_handle = RrAppearanceNew(inst, 0);
202     theme->a_unfocused_handle = RrAppearanceNew(inst, 0);
203     theme->a_menu = RrAppearanceNew(inst, 0);
204     theme->a_menu_title = RrAppearanceNew(inst, 0);
205     theme->a_menu_text_title = RrAppearanceNew(inst, 1);
206     theme->a_menu_normal = RrAppearanceNew(inst, 0);
207     theme->a_menu_selected = RrAppearanceNew(inst, 0);
208     theme->a_menu_disabled = RrAppearanceNew(inst, 0);
209     /* a_menu_disabled_selected is copied from a_menu_selected */
210     theme->a_menu_text_normal = RrAppearanceNew(inst, 1);
211     theme->a_menu_text_selected = RrAppearanceNew(inst, 1);
212     theme->a_menu_text_disabled = RrAppearanceNew(inst, 1);
213     theme->a_menu_text_disabled_selected = RrAppearanceNew(inst, 1);
214     theme->a_menu_bullet_normal = RrAppearanceNew(inst, 1);
215     theme->a_menu_bullet_selected = RrAppearanceNew(inst, 1);
216     theme->a_clear = RrAppearanceNew(inst, 0);
217     theme->a_clear_tex = RrAppearanceNew(inst, 1);
218     theme->osd_bg = RrAppearanceNew(inst, 0);
219     theme->osd_hilite_label = RrAppearanceNew(inst, 1);
220     theme->osd_hilite_bg = RrAppearanceNew(inst, 0);
221     theme->osd_unhilite_label = RrAppearanceNew(inst, 1);
222     theme->osd_unhilite_bg = RrAppearanceNew(inst, 0);
223     theme->osd_unpressed_button = RrAppearanceNew(inst, 1);
224     theme->osd_pressed_button = RrAppearanceNew(inst, 5);
225     theme->osd_focused_button = RrAppearanceNew(inst, 5);
226
227     /* load the font stuff */
228     theme->win_font_focused = get_font(active_window_font,
229                                        &default_font, inst);
230     theme->win_font_unfocused = get_font(inactive_window_font,
231                                          &default_font, inst);
232
233     winjust = RR_JUSTIFY_LEFT;
234     if (read_string(db, "window.label.text.justify", &str)) {
235         if (!g_ascii_strcasecmp(str, "right"))
236             winjust = RR_JUSTIFY_RIGHT;
237         else if (!g_ascii_strcasecmp(str, "center"))
238             winjust = RR_JUSTIFY_CENTER;
239     }
240
241     theme->menu_title_font = get_font(menu_title_font, &default_font, inst);
242
243     mtitlejust = RR_JUSTIFY_LEFT;
244     if (read_string(db, "menu.title.text.justify", &str)) {
245         if (!g_ascii_strcasecmp(str, "right"))
246             mtitlejust = RR_JUSTIFY_RIGHT;
247         else if (!g_ascii_strcasecmp(str, "center"))
248             mtitlejust = RR_JUSTIFY_CENTER;
249     }
250
251     theme->menu_font = get_font(menu_item_font, &default_font, inst);
252
253     theme->osd_font_hilite = get_font(active_osd_font, &default_font, inst);
254     theme->osd_font_unhilite = get_font(inactive_osd_font, &default_font,inst);
255
256     /* load direct dimensions */
257     READ_INT("menu.overlap", menu_overlap, -100, 100, 0);
258     READ_INT("menu.overlap.x", theme->menu_overlap_x, -100, 100, menu_overlap);
259     READ_INT("menu.overlap.y", theme->menu_overlap_y, -100, 100, menu_overlap);
260     READ_INT("window.handle.width", theme->handle_height, 0, 100, 6);
261     READ_INT("padding.width", theme->paddingx, 0, 100, 3);
262     READ_INT("padding.height", theme->paddingy, 0, 100, theme->paddingx);
263     READ_INT("border.width", theme->fbwidth, 0, 100, 1);
264     READ_INT("menu.border.width", theme->mbwidth, 0, 100, theme->fbwidth);
265     READ_INT("osd.border.width", theme->obwidth, 0, 100, theme->fbwidth);
266     READ_INT("undecorated.border.width", theme->ubwidth, 0, 100,
267              theme->fbwidth);
268     READ_INT("menu.separator.width", theme->menu_sep_width, 1, 100, 1);
269     READ_INT("menu.separator.padding.width", theme->menu_sep_paddingx,
270              0, 100, 6);
271     READ_INT("menu.separator.padding.height", theme->menu_sep_paddingy,
272              0, 100, 3);
273     READ_INT("window.client.padding.width", theme->cbwidthx, 0, 100,
274              theme->paddingx);
275     READ_INT("window.client.padding.height", theme->cbwidthy, 0, 100,
276              theme->cbwidthx);
277
278     /* load colors */
279     READ_COLOR_("window.active.border.color", "border.color",
280                 theme->frame_focused_border_color, RrColorNew(inst, 0, 0, 0));
281     /* undecorated focused border color inherits from frame focused border
282        color */
283     READ_COLOR("window.undecorated.active.border.color",
284                theme->frame_undecorated_focused_border_color,
285                RrColorCopy(theme->frame_focused_border_color));
286     /* title separator focused color inherits from focused border color */
287     READ_COLOR("window.active.title.separator.color",
288                theme->title_separator_focused_color,
289                RrColorCopy(theme->frame_focused_border_color));
290
291     /* unfocused border color inherits from frame focused border color */
292     READ_COLOR("window.inactive.border.color",
293                theme->frame_unfocused_border_color,
294                RrColorCopy(theme->frame_focused_border_color));
295
296     /* undecorated unfocused border color inherits from frame unfocused border
297        color */
298     READ_COLOR("window.undecorated.inactive.border.color",
299                theme->frame_undecorated_unfocused_border_color,
300                RrColorCopy(theme->frame_unfocused_border_color));
301
302     /* title separator unfocused color inherits from unfocused border color */
303     READ_COLOR("window.inactive.title.separator.color",
304                theme->title_separator_unfocused_color,
305                RrColorCopy(theme->frame_unfocused_border_color));
306
307     /* menu border color inherits from frame focused border color */
308     READ_COLOR("menu.border.color", theme->menu_border_color,
309                RrColorCopy(theme->frame_focused_border_color));
310
311     /* osd border color inherits from frame focused border color */
312     READ_COLOR("osd.border.color", theme->osd_border_color,
313                RrColorCopy(theme->frame_focused_border_color));
314
315     READ_COLOR("window.active.client.color", theme->cb_focused_color,
316                RrColorNew(inst, 0xff, 0xff, 0xff));
317
318     READ_COLOR("window.inactive.client.color", theme->cb_unfocused_color,
319                RrColorNew(inst, 0xff, 0xff, 0xff));
320
321     READ_COLOR("window.active.label.text.color", theme->title_focused_color,
322                RrColorNew(inst, 0x0, 0x0, 0x0));
323
324     READ_COLOR("window.inactive.label.text.color", theme->title_unfocused_color,
325                RrColorNew(inst, 0xff, 0xff, 0xff));
326
327     READ_COLOR_("osd.active.label.text.color",
328                 "osd.label.text.color",
329                 theme->osd_text_active_color, RrColorCopy(theme->title_focused_color));
330
331     READ_COLOR_("osd.inactive.label.text.color",
332                 "osd.label.text.color",
333                 theme->osd_text_inactive_color, RrColorCopy(theme->title_unfocused_color));
334
335     READ_COLOR("window.active.button.unpressed.image.color",
336                theme->titlebut_focused_unpressed_color,
337                RrColorNew(inst, 0, 0, 0));
338
339     READ_COLOR("window.inactive.button.unpressed.image.color",
340                theme->titlebut_unfocused_unpressed_color,
341                RrColorNew(inst, 0xff, 0xff, 0xff));
342
343     READ_COLOR("window.active.button.pressed.image.color",
344                theme->titlebut_focused_pressed_color,
345                RrColorCopy(theme->titlebut_focused_unpressed_color));
346
347     READ_COLOR("window.inactive.button.pressed.image.color",
348                theme->titlebut_unfocused_pressed_color,
349                RrColorCopy(theme->titlebut_unfocused_unpressed_color));
350
351     READ_COLOR("window.active.button.disabled.image.color",
352                theme->titlebut_disabled_focused_color,
353                RrColorNew(inst, 0xff, 0xff, 0xff));
354
355     READ_COLOR("window.inactive.button.disabled.image.color",
356                theme->titlebut_disabled_unfocused_color,
357                RrColorNew(inst, 0, 0, 0));
358
359     READ_COLOR("window.active.button.hover.image.color",
360                theme->titlebut_hover_focused_color,
361                RrColorCopy(theme->titlebut_focused_unpressed_color));
362
363     READ_COLOR("window.inactive.button.hover.image.color",
364                theme->titlebut_hover_unfocused_color,
365                RrColorCopy(theme->titlebut_unfocused_unpressed_color));
366
367     READ_COLOR_("window.active.button.toggled.unpressed.image.color",
368                 "window.active.button.toggled.image.color",
369                 theme->titlebut_toggled_focused_unpressed_color,
370                 RrColorCopy(theme->titlebut_focused_pressed_color));
371
372     READ_COLOR_("window.inactive.button.toggled.unpressed.image.color",
373                 "window.inactive.button.toggled.image.color",
374                 theme->titlebut_toggled_unfocused_unpressed_color,
375                 RrColorCopy(theme->titlebut_unfocused_pressed_color));
376
377     READ_COLOR("window.active.button.toggled.hover.image.color",
378                theme->titlebut_toggled_hover_focused_color,
379                RrColorCopy(theme->titlebut_toggled_focused_unpressed_color));
380
381     READ_COLOR("window.inactive.button.toggled.hover.image.color",
382                theme->titlebut_toggled_hover_unfocused_color,
383                RrColorCopy(theme->titlebut_toggled_unfocused_unpressed_color));
384
385     READ_COLOR("window.active.button.toggled.pressed.image.color",
386                theme->titlebut_toggled_focused_pressed_color,
387                RrColorCopy(theme->titlebut_focused_pressed_color));
388
389     READ_COLOR("window.inactive.button.toggled.pressed.image.color",
390                theme->titlebut_toggled_unfocused_pressed_color,
391                RrColorCopy(theme->titlebut_unfocused_pressed_color));
392
393     READ_COLOR("menu.title.text.color", theme->menu_title_color,
394                RrColorNew(inst, 0, 0, 0));
395
396     READ_COLOR("menu.items.text.color", theme->menu_color,
397                RrColorNew(inst, 0xff, 0xff, 0xff));
398
399     READ_COLOR("menu.bullet.image.color", theme->menu_bullet_color,
400                RrColorCopy(theme->menu_color));
401    
402     READ_COLOR("menu.items.disabled.text.color", theme->menu_disabled_color,
403                RrColorNew(inst, 0, 0, 0));
404
405     READ_COLOR("menu.items.active.disabled.text.color",
406                theme->menu_disabled_selected_color,
407                RrColorCopy(theme->menu_disabled_color));
408
409     READ_COLOR("menu.items.active.text.color", theme->menu_selected_color,
410                RrColorNew(inst, 0, 0, 0));
411
412     READ_COLOR("menu.separator.color", theme->menu_sep_color,
413                RrColorCopy(theme->menu_color));
414     
415     READ_COLOR("menu.bullet.selected.image.color", 
416                theme->menu_bullet_selected_color,
417                RrColorCopy(theme->menu_selected_color));
418
419     READ_COLOR("osd.button.unpressed.text.color", theme->osd_unpressed_color,
420                RrColorCopy(theme->osd_text_active_color));
421     READ_COLOR("osd.button.pressed.text.color", theme->osd_pressed_color,
422                RrColorCopy(theme->osd_text_active_color));
423     READ_COLOR("osd.button.focused.text.color", theme->osd_focused_color,
424                RrColorCopy(theme->osd_text_active_color));
425     READ_COLOR("osd.button.pressed.box.color", theme->osd_pressed_lineart,
426                RrColorCopy(theme->titlebut_focused_pressed_color));
427     READ_COLOR("osd.button.focused.box.color", theme->osd_focused_lineart,
428                RrColorCopy(theme->titlebut_hover_focused_color));
429  
430     /* load the image masks */
431
432     /* maximize button masks */
433     userdef = TRUE;
434     if (!read_mask(inst, path, theme, "max.xbm", &theme->btn_max->mask)) {
435             guchar data[] = { 0x3f, 0x3f, 0x21, 0x21, 0x21, 0x3f };
436             theme->btn_max->mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data);
437             userdef = FALSE;
438     }
439     if (!read_mask(inst, path, theme, "max_toggled.xbm",
440                    &theme->btn_max->toggled_mask))
441     {
442         if (userdef)
443             theme->btn_max->toggled_mask = RrPixmapMaskCopy(theme->btn_max->mask);
444         else {
445             guchar data[] = { 0x3e, 0x22, 0x2f, 0x29, 0x39, 0x0f };
446             theme->btn_max->toggled_mask = RrPixmapMaskNew(inst, 6, 6,(gchar*)data);
447         }
448     }
449     READ_MASK_COPY("max_pressed.xbm", theme->btn_max->pressed_mask,
450                    theme->btn_max->mask);
451     READ_MASK_COPY("max_disabled.xbm", theme->btn_max->disabled_mask,
452                    theme->btn_max->mask);
453     READ_MASK_COPY("max_hover.xbm", theme->btn_max->hover_mask, 
454                    theme->btn_max->mask);
455     READ_MASK_COPY("max_toggled_pressed.xbm", 
456                    theme->btn_max->toggled_pressed_mask, 
457                    theme->btn_max->toggled_mask);
458     READ_MASK_COPY("max_toggled_hover.xbm", 
459                    theme->btn_max->toggled_hover_mask,
460                    theme->btn_max->toggled_mask);
461
462     /* iconify button masks */
463     if (!read_mask(inst, path, theme, "iconify.xbm", &theme->btn_iconify->mask)) {
464         guchar data[] = { 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f };
465         theme->btn_iconify->mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data);
466     }
467     READ_MASK_COPY("iconify_pressed.xbm", theme->btn_iconify->pressed_mask,
468                    theme->btn_iconify->mask);
469     READ_MASK_COPY("iconify_disabled.xbm", theme->btn_iconify->disabled_mask,
470                    theme->btn_iconify->mask);
471     READ_MASK_COPY("iconify_hover.xbm", theme->btn_iconify->hover_mask,
472                    theme->btn_iconify->mask);
473
474     /* all desktops button masks */
475     userdef = TRUE;
476     if (!read_mask(inst, path, theme, "desk.xbm", &theme->btn_desk->mask)) {
477         guchar data[] = { 0x33, 0x33, 0x00, 0x00, 0x33, 0x33 };
478         theme->btn_desk->mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data);
479         userdef = FALSE;
480     }
481     if (!read_mask(inst, path, theme, "desk_toggled.xbm",
482                    &theme->btn_desk->toggled_mask)) {
483         if (userdef)
484             theme->btn_desk->toggled_mask = RrPixmapMaskCopy(theme->btn_desk->mask);
485         else {
486             guchar data[] = { 0x00, 0x1e, 0x1a, 0x16, 0x1e, 0x00 };
487             theme->btn_desk->toggled_mask =
488                 RrPixmapMaskNew(inst, 6, 6, (gchar*)data);
489         }
490     }
491     READ_MASK_COPY("desk_pressed.xbm", theme->btn_desk->pressed_mask,
492                    theme->btn_desk->mask);
493     READ_MASK_COPY("desk_disabled.xbm", theme->btn_desk->disabled_mask,
494                    theme->btn_desk->mask);
495     READ_MASK_COPY("desk_hover.xbm", theme->btn_desk->hover_mask, theme->btn_desk->mask);
496     READ_MASK_COPY("desk_toggled_pressed.xbm",
497                    theme->btn_desk->toggled_pressed_mask, theme->btn_desk->toggled_mask);
498     READ_MASK_COPY("desk_toggled_hover.xbm", theme->btn_desk->toggled_hover_mask,
499                    theme->btn_desk->toggled_mask);
500
501     /* shade button masks */
502     if (!read_mask(inst, path, theme, "shade.xbm", &theme->btn_shade->mask)) {
503         guchar data[] = { 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00 };
504         theme->btn_shade->mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data);
505     }
506     READ_MASK_COPY("shade_toggled.xbm", theme->btn_shade->toggled_mask,
507                    theme->btn_shade->mask);
508     READ_MASK_COPY("shade_pressed.xbm", theme->btn_shade->pressed_mask,
509                    theme->btn_shade->mask);
510     READ_MASK_COPY("shade_disabled.xbm", theme->btn_shade->disabled_mask,
511                    theme->btn_shade->mask);
512     READ_MASK_COPY("shade_hover.xbm", theme->btn_shade->hover_mask,
513                    theme->btn_shade->mask);
514     READ_MASK_COPY("shade_toggled_pressed.xbm",
515                    theme->btn_shade->toggled_pressed_mask,
516                    theme->btn_shade->toggled_mask);
517     READ_MASK_COPY("shade_toggled_hover.xbm",
518                    theme->btn_shade->toggled_hover_mask, 
519                    theme->btn_shade->toggled_mask);
520
521     /* close button masks */
522     if (!read_mask(inst, path, theme, "close.xbm", &theme->btn_close->mask)) {
523         guchar data[] = { 0x33, 0x3f, 0x1e, 0x1e, 0x3f, 0x33 };
524         theme->btn_close->mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data);
525     }
526     READ_MASK_COPY("close_pressed.xbm", theme->btn_close->pressed_mask,
527                    theme->btn_close->mask);
528     READ_MASK_COPY("close_disabled.xbm", theme->btn_close->disabled_mask,
529                    theme->btn_close->mask);
530     READ_MASK_COPY("close_hover.xbm", theme->btn_close->hover_mask,
531                    theme->btn_close->mask);
532
533     /* submenu bullet mask */
534     if (!read_mask(inst, path, theme, "bullet.xbm", &theme->menu_bullet_mask))
535     {
536         guchar data[] = { 0x01, 0x03, 0x07, 0x0f, 0x07, 0x03, 0x01 };
537         theme->menu_bullet_mask = RrPixmapMaskNew(inst, 4, 7, (gchar*)data);
538     }
539
540     /* up and down arrows */
541     {
542         guchar data[] = { 0xfe, 0x00, 0x7c, 0x00, 0x38, 0x00, 0x10, 0x00 };
543         theme->down_arrow_mask = RrPixmapMaskNew(inst, 9, 4, (gchar*)data);
544     }
545     {
546         guchar data[] = { 0x10, 0x00, 0x38, 0x00, 0x7c, 0x00, 0xfe, 0x00 };
547         theme->up_arrow_mask = RrPixmapMaskNew(inst, 9, 4, (gchar*)data);
548     }
549
550     /* setup the default window icon */
551     theme->def_win_icon = read_c_image(OB_DEFAULT_ICON_WIDTH,
552                                        OB_DEFAULT_ICON_HEIGHT,
553                                        OB_DEFAULT_ICON_pixel_data);
554     theme->def_win_icon_w = OB_DEFAULT_ICON_WIDTH;
555     theme->def_win_icon_h = OB_DEFAULT_ICON_HEIGHT;
556
557     /* the toggled hover mask = the toggled unpressed mask (i.e. no change) */
558     theme->btn_max->toggled_hover_mask =
559         RrPixmapMaskCopy(theme->btn_max->toggled_mask);
560     theme->btn_desk->toggled_hover_mask =
561         RrPixmapMaskCopy(theme->btn_desk->toggled_mask);
562     theme->btn_shade->toggled_hover_mask =
563         RrPixmapMaskCopy(theme->btn_shade->toggled_mask);
564     /* the toggled pressed mask = the toggled unpressed mask (i.e. no change)*/
565     theme->btn_max->toggled_pressed_mask =
566         RrPixmapMaskCopy(theme->btn_max->toggled_mask);
567     theme->btn_desk->toggled_pressed_mask =
568         RrPixmapMaskCopy(theme->btn_desk->toggled_mask);
569     theme->btn_shade->toggled_pressed_mask =
570         RrPixmapMaskCopy(theme->btn_shade->toggled_mask);
571
572     /* read the decoration textures */
573     READ_APPEARANCE("window.active.title.bg", theme->a_focused_title, FALSE);
574     READ_APPEARANCE("window.inactive.title.bg", theme->a_unfocused_title,
575                     FALSE);
576     READ_APPEARANCE("window.active.label.bg", theme->a_focused_label, TRUE);
577     READ_APPEARANCE("window.inactive.label.bg", theme->a_unfocused_label,
578                     TRUE);
579     READ_APPEARANCE("window.active.handle.bg", theme->a_focused_handle, FALSE);
580     READ_APPEARANCE("window.inactive.handle.bg",theme->a_unfocused_handle,
581                     FALSE);
582     READ_APPEARANCE("window.active.grip.bg", theme->a_focused_grip, TRUE);
583     READ_APPEARANCE("window.inactive.grip.bg", theme->a_unfocused_grip, TRUE);
584     READ_APPEARANCE("menu.items.bg", theme->a_menu, FALSE);
585     READ_APPEARANCE("menu.title.bg", theme->a_menu_title, TRUE);
586     READ_APPEARANCE("menu.items.active.bg", theme->a_menu_selected, TRUE);
587
588     theme->a_menu_disabled_selected =
589         RrAppearanceCopy(theme->a_menu_selected);
590
591     /* read appearances for non-decorations (on-screen-display) */
592     if (!read_appearance(db, inst, "osd.bg", theme->osd_bg, FALSE)) {
593         RrAppearanceFree(theme->osd_bg);
594         theme->osd_bg = RrAppearanceCopy(theme->a_focused_title);
595     }
596     if (!read_appearance(db, inst, "osd.active.label.bg",
597                          theme->osd_hilite_label, TRUE) &&
598         !read_appearance(db, inst, "osd.label.bg",
599                          theme->osd_hilite_label, TRUE)) {
600         RrAppearanceFree(theme->osd_hilite_label);
601         theme->osd_hilite_label = RrAppearanceCopy(theme->a_focused_label);
602     }
603     if (!read_appearance(db, inst, "osd.inactive.label.bg",
604                          theme->osd_unhilite_label, TRUE)) {
605         RrAppearanceFree(theme->osd_unhilite_label);
606         theme->osd_unhilite_label = RrAppearanceCopy(theme->a_unfocused_label);
607     }
608     /* osd_hilite_fg can't be parentrel */
609     if (!read_appearance(db, inst, "osd.hilight.bg",
610                          theme->osd_hilite_bg, FALSE)) {
611         RrAppearanceFree(theme->osd_hilite_bg);
612         if (theme->a_focused_label->surface.grad != RR_SURFACE_PARENTREL)
613             theme->osd_hilite_bg = RrAppearanceCopy(theme->a_focused_label);
614         else
615             theme->osd_hilite_bg = RrAppearanceCopy(theme->a_focused_title);
616     }
617     /* osd_unhilite_fg can't be parentrel either */
618     if (!read_appearance(db, inst, "osd.unhilight.bg",
619                          theme->osd_unhilite_bg, FALSE)) {
620         RrAppearanceFree(theme->osd_unhilite_bg);
621         if (theme->a_unfocused_label->surface.grad != RR_SURFACE_PARENTREL)
622             theme->osd_unhilite_bg=RrAppearanceCopy(theme->a_unfocused_label);
623         else
624             theme->osd_unhilite_bg=RrAppearanceCopy(theme->a_unfocused_title);
625     }
626
627     /* read buttons textures */
628
629     /* bases: unpressed, pressed, disabled */
630     READ_APPEARANCE("window.active.button.unpressed.bg",
631                     a_focused_unpressed_tmp, TRUE);
632     READ_APPEARANCE("window.inactive.button.unpressed.bg",
633                     a_unfocused_unpressed_tmp, TRUE);
634     READ_APPEARANCE("window.active.button.pressed.bg",
635                     a_focused_pressed_tmp, TRUE);
636     READ_APPEARANCE("window.inactive.button.pressed.bg",
637                     a_unfocused_pressed_tmp, TRUE);
638     READ_APPEARANCE("window.active.button.disabled.bg",
639                     a_disabled_focused_tmp, TRUE);
640     READ_APPEARANCE("window.inactive.button.disabled.bg",
641                     a_disabled_unfocused_tmp, TRUE);
642
643     /* hover */
644     READ_APPEARANCE_COPY("window.active.button.hover.bg",
645                          a_hover_focused_tmp, TRUE,
646                          a_focused_unpressed_tmp);
647     READ_APPEARANCE_COPY("window.inactive.button.hover.bg",
648                          a_hover_unfocused_tmp, TRUE,
649                          a_unfocused_unpressed_tmp);
650
651     /* toggled unpressed */
652     READ_APPEARANCE_("window.active.button.toggled.unpressed.bg",
653                      "window.active.button.toggled.bg",
654                      a_toggled_focused_unpressed_tmp, TRUE,
655                      a_focused_pressed_tmp);
656     READ_APPEARANCE_("window.inactive.button.toggled.unpressed.bg",
657                      "window.inactive.button.toggled.bg",
658                      a_toggled_unfocused_unpressed_tmp, TRUE,
659                      a_unfocused_pressed_tmp);
660
661     /* toggled pressed */
662     READ_APPEARANCE_COPY("window.active.button.toggled.pressed.bg",
663                          a_toggled_focused_pressed_tmp, TRUE,
664                          a_focused_pressed_tmp);
665     READ_APPEARANCE_COPY("window.inactive.button.toggled.pressed.bg",
666                          a_toggled_unfocused_pressed_tmp, TRUE,
667                          a_unfocused_pressed_tmp);
668
669     /* toggled hover */
670     READ_APPEARANCE_COPY("window.active.button.toggled.hover.bg",
671                          a_toggled_hover_focused_tmp, TRUE,
672                          a_toggled_focused_unpressed_tmp);
673     READ_APPEARANCE_COPY("window.inactive.button.toggled.hover.bg",
674                          a_toggled_hover_unfocused_tmp, TRUE,
675                          a_toggled_unfocused_unpressed_tmp);
676
677
678     /* now do individual buttons, if specified */
679
680     /* max button */
681     read_button_colors(db, inst, theme, theme->btn_max, "max");
682
683     /* bases:  unpressed, pressed, disabled */
684     READ_APPEARANCE_COPY("window.active.button.max.unpressed.bg",
685                          theme->btn_max->a_focused_unpressed, TRUE,
686                          a_focused_unpressed_tmp);
687     READ_APPEARANCE_COPY("window.inactive.button.max.unpressed.bg",
688                          theme->btn_max->a_unfocused_unpressed, TRUE,
689                          a_unfocused_unpressed_tmp);
690     READ_APPEARANCE_COPY("window.active.button.max.pressed.bg",
691                          theme->btn_max->a_focused_pressed, TRUE,
692                          a_focused_pressed_tmp);
693     READ_APPEARANCE_COPY("window.inactive.button.max.pressed.bg",
694                          theme->btn_max->a_unfocused_pressed, TRUE,
695                          a_unfocused_pressed_tmp);
696     READ_APPEARANCE_COPY("window.active.button.max.disabled.bg",
697                          theme->btn_max->a_disabled_focused, TRUE,
698                          a_disabled_focused_tmp);
699     READ_APPEARANCE_COPY("window.inactive.button.max.disabled.bg",
700                          theme->btn_max->a_disabled_unfocused, TRUE,
701                          a_disabled_unfocused_tmp);
702
703     /* hover */
704     READ_APPEARANCE_COPY("window.active.button.max.hover.bg",
705                          theme->btn_max->a_hover_focused, TRUE,
706                          a_hover_focused_tmp);
707     READ_APPEARANCE_COPY("window.inactive.button.max.hover.bg",
708                          theme->btn_max->a_hover_unfocused, TRUE,
709                          a_hover_unfocused_tmp);
710
711     /* toggled unpressed */
712     READ_APPEARANCE_("window.active.button.max.toggled.unpressed.bg",
713                      "window.active.button.max.toggled.bg",
714                      theme->btn_max->a_toggled_focused_unpressed, TRUE,
715                      a_toggled_focused_unpressed_tmp);
716     READ_APPEARANCE_("window.inactive.button.max.toggled.unpressed.bg",
717                      "window.inactive.button.max.toggled.bg",
718                      theme->btn_max->a_toggled_unfocused_unpressed, TRUE,
719                      a_toggled_unfocused_unpressed_tmp);
720
721     /* toggled pressed */
722     READ_APPEARANCE_COPY("window.active.button.max.toggled.pressed.bg",
723                          theme->btn_max->a_toggled_focused_pressed, TRUE,
724                          a_toggled_focused_pressed_tmp);
725     READ_APPEARANCE_COPY("window.inactive.button.max.toggled.pressed.bg",
726                          theme->btn_max->a_toggled_unfocused_pressed, TRUE,
727                          a_toggled_unfocused_pressed_tmp);
728
729     /* toggled hover */
730     READ_APPEARANCE_COPY("window.active.button.max.toggled.hover.bg",
731                          theme->btn_max->a_toggled_hover_focused, TRUE,
732                          a_toggled_hover_focused_tmp);
733     READ_APPEARANCE_COPY("window.inactive.button.max.toggled.hover.bg",
734                          theme->btn_max->a_toggled_hover_unfocused, TRUE,
735                          a_toggled_hover_unfocused_tmp);
736
737     /* close button */
738     read_button_colors(db, inst, theme, theme->btn_close, "close");
739
740     READ_APPEARANCE_COPY("window.active.button.close.unpressed.bg",
741                          theme->btn_close->a_focused_unpressed, TRUE,
742                          a_focused_unpressed_tmp);
743     READ_APPEARANCE_COPY("window.inactive.button.close.unpressed.bg",
744                          theme->btn_close->a_unfocused_unpressed, TRUE,
745                          a_unfocused_unpressed_tmp);
746     READ_APPEARANCE_COPY("window.active.button.close.pressed.bg",
747                          theme->btn_close->a_focused_pressed, TRUE,
748                          a_focused_pressed_tmp);
749     READ_APPEARANCE_COPY("window.inactive.button.close.pressed.bg",
750                          theme->btn_close->a_unfocused_pressed, TRUE,
751                          a_unfocused_pressed_tmp);
752     READ_APPEARANCE_COPY("window.active.button.close.disabled.bg",
753                          theme->btn_close->a_disabled_focused, TRUE,
754                          a_disabled_focused_tmp);
755     READ_APPEARANCE_COPY("window.inactive.button.close.disabled.bg",
756                          theme->btn_close->a_disabled_unfocused, TRUE,
757                          a_disabled_unfocused_tmp);
758     READ_APPEARANCE_COPY("window.active.button.close.hover.bg",
759                          theme->btn_close->a_hover_focused, TRUE,
760                          a_hover_focused_tmp);
761     READ_APPEARANCE_COPY("window.inactive.button.close.hover.bg",
762                          theme->btn_close->a_hover_unfocused, TRUE,
763                          a_hover_unfocused_tmp);
764
765     /* desk button */
766     read_button_colors(db, inst, theme, theme->btn_desk, "desk");
767
768     /* bases:  unpressed, pressed, disabled */
769     READ_APPEARANCE_COPY("window.active.button.desk.unpressed.bg",
770                          theme->btn_desk->a_focused_unpressed, TRUE,
771                          a_focused_unpressed_tmp);
772     READ_APPEARANCE_COPY("window.inactive.button.desk.unpressed.bg",
773                          theme->btn_desk->a_unfocused_unpressed, TRUE,
774                          a_unfocused_unpressed_tmp);
775     READ_APPEARANCE_COPY("window.active.button.desk.pressed.bg",
776                          theme->btn_desk->a_focused_pressed, TRUE,
777                          a_focused_pressed_tmp);
778     READ_APPEARANCE_COPY("window.inactive.button.desk.pressed.bg",
779                          theme->btn_desk->a_unfocused_pressed, TRUE,
780                          a_unfocused_pressed_tmp);
781     READ_APPEARANCE_COPY("window.active.button.desk.disabled.bg",
782                          theme->btn_desk->a_disabled_focused, TRUE,
783                          a_disabled_focused_tmp);
784     READ_APPEARANCE_COPY("window.inactive.button.desk.disabled.bg",
785                          theme->btn_desk->a_disabled_unfocused, TRUE,
786                          a_disabled_unfocused_tmp);
787
788     /* hover */
789     READ_APPEARANCE_COPY("window.active.button.desk.hover.bg",
790                          theme->btn_desk->a_hover_focused, TRUE,
791                          a_hover_focused_tmp);
792     READ_APPEARANCE_COPY("window.inactive.button.desk.hover.bg",
793                          theme->btn_desk->a_hover_unfocused, TRUE,
794                          a_hover_unfocused_tmp);
795
796     /* toggled unpressed */
797     READ_APPEARANCE_("window.active.button.desk.toggled.unpressed.bg",
798                      "window.active.button.desk.toggled.bg",
799                      theme->btn_desk->a_toggled_focused_unpressed, TRUE,
800                      a_toggled_focused_unpressed_tmp);
801     READ_APPEARANCE_("window.inactive.button.desk.toggled.unpressed.bg",
802                      "window.inactive.button.desk.toggled.bg",
803                      theme->btn_desk->a_toggled_unfocused_unpressed, TRUE,
804                      a_toggled_unfocused_unpressed_tmp);
805
806     /* toggled pressed */
807     READ_APPEARANCE_COPY("window.active.button.desk.toggled.pressed.bg",
808                          theme->btn_desk->a_toggled_focused_pressed, TRUE,
809                          a_toggled_focused_pressed_tmp);
810     READ_APPEARANCE_COPY("window.inactive.button.desk.toggled.pressed.bg",
811                          theme->btn_desk->a_toggled_unfocused_pressed, TRUE,
812                          a_toggled_unfocused_pressed_tmp);
813
814     /* toggled hover */
815     READ_APPEARANCE_COPY("window.active.button.desk.toggled.hover.bg",
816                          theme->btn_desk->a_toggled_hover_focused, TRUE,
817                          a_toggled_hover_focused_tmp);
818     READ_APPEARANCE_COPY("window.inactive.button.desk.toggled.hover.bg",
819                          theme->btn_desk->a_toggled_hover_unfocused, TRUE,
820                          a_toggled_hover_unfocused_tmp);
821
822     /* shade button */
823     read_button_colors(db, inst, theme, theme->btn_shade, "shade");
824
825     /* bases:  unpressed, pressed, disabled */
826     READ_APPEARANCE_COPY("window.active.button.shade.unpressed.bg",
827                          theme->btn_shade->a_focused_unpressed, TRUE,
828                          a_focused_unpressed_tmp);
829     READ_APPEARANCE_COPY("window.inactive.button.shade.unpressed.bg",
830                          theme->btn_shade->a_unfocused_unpressed, TRUE,
831                          a_unfocused_unpressed_tmp);
832     READ_APPEARANCE_COPY("window.active.button.shade.pressed.bg",
833                          theme->btn_shade->a_focused_pressed, TRUE,
834                          a_focused_pressed_tmp);
835     READ_APPEARANCE_COPY("window.inactive.button.shade.pressed.bg",
836                          theme->btn_shade->a_unfocused_pressed, TRUE,
837                          a_unfocused_pressed_tmp);
838     READ_APPEARANCE_COPY("window.active.button.shade.disabled.bg",
839                          theme->btn_shade->a_disabled_focused, TRUE,
840                          a_disabled_focused_tmp);
841     READ_APPEARANCE_COPY("window.inactive.button.shade.disabled.bg",
842                          theme->btn_shade->a_disabled_unfocused, TRUE,
843                          a_disabled_unfocused_tmp);
844
845     /* hover */
846     READ_APPEARANCE_COPY("window.active.button.shade.hover.bg",
847                          theme->btn_shade->a_hover_focused, TRUE,
848                          a_hover_focused_tmp);
849     READ_APPEARANCE_COPY("window.inactive.button.shade.hover.bg",
850                          theme->btn_shade->a_hover_unfocused, TRUE,
851                          a_hover_unfocused_tmp);
852
853     /* toggled unpressed */
854     READ_APPEARANCE_("window.active.button.shade.toggled.unpressed.bg",
855                      "window.active.button.shade.toggled.bg",
856                      theme->btn_shade->a_toggled_focused_unpressed, TRUE,
857                      a_toggled_focused_unpressed_tmp);
858     READ_APPEARANCE_("window.inactive.button.shade.toggled.unpressed.bg",
859                      "window.inactive.button.shade.toggled.bg",
860                      theme->btn_shade->a_toggled_unfocused_unpressed, TRUE,
861                      a_toggled_unfocused_unpressed_tmp);
862
863     /* toggled pressed */
864     READ_APPEARANCE_COPY("window.active.button.shade.toggled.pressed.bg",
865                          theme->btn_shade->a_toggled_focused_pressed, TRUE,
866                          a_toggled_focused_pressed_tmp);
867     READ_APPEARANCE_COPY("window.inactive.button.shade.toggled.pressed.bg",
868                          theme->btn_shade->a_toggled_unfocused_pressed, TRUE,
869                          a_toggled_unfocused_pressed_tmp);
870
871     /* toggled hover */
872     READ_APPEARANCE_COPY("window.active.button.shade.toggled.hover.bg",
873                          theme->btn_shade->a_toggled_hover_focused, TRUE,
874                          a_toggled_hover_focused_tmp);
875     READ_APPEARANCE_COPY("window.inactive.button.shade.toggled.hover.bg",
876                          theme->btn_shade->a_toggled_hover_unfocused, TRUE,
877                          a_toggled_hover_unfocused_tmp);
878
879     /* iconify button */
880     read_button_colors(db, inst, theme, theme->btn_iconify, "iconify");
881
882     READ_APPEARANCE_COPY("window.active.button.iconify.unpressed.bg",
883                          theme->btn_iconify->a_focused_unpressed, TRUE,
884                          a_focused_unpressed_tmp);
885     READ_APPEARANCE_COPY("window.inactive.button.iconify.unpressed.bg",
886                          theme->btn_iconify->a_unfocused_unpressed, TRUE,
887                          a_unfocused_unpressed_tmp);
888     READ_APPEARANCE_COPY("window.active.button.iconify.pressed.bg",
889                          theme->btn_iconify->a_focused_pressed, TRUE,
890                          a_focused_pressed_tmp);
891     READ_APPEARANCE_COPY("window.inactive.button.iconify.pressed.bg",
892                          theme->btn_iconify->a_unfocused_pressed, TRUE,
893                          a_unfocused_pressed_tmp);
894     READ_APPEARANCE_COPY("window.active.button.iconify.disabled.bg",
895                          theme->btn_iconify->a_disabled_focused, TRUE,
896                          a_disabled_focused_tmp);
897     READ_APPEARANCE_COPY("window.inactive.button.iconify.disabled.bg",
898                          theme->btn_iconify->a_disabled_unfocused, TRUE,
899                          a_disabled_unfocused_tmp);
900     READ_APPEARANCE_COPY("window.active.button.iconify.hover.bg",
901                          theme->btn_iconify->a_hover_focused, TRUE,
902                          a_hover_focused_tmp);
903     READ_APPEARANCE_COPY("window.inactive.button.iconify.hover.bg",
904                          theme->btn_iconify->a_hover_unfocused, TRUE,
905                          a_hover_unfocused_tmp);
906
907     /* osd buttons */
908     READ_APPEARANCE_COPY("osd.button.unpressed.bg", theme->osd_unpressed_button, TRUE, a_focused_unpressed_tmp);
909     READ_APPEARANCE_COPY_TEXTURES("osd.button.pressed.bg", theme->osd_pressed_button, TRUE, a_focused_pressed_tmp, 5);
910     READ_APPEARANCE_COPY_TEXTURES("osd.button.focused.bg", theme->osd_focused_button, TRUE, a_focused_unpressed_tmp, 5);
911
912     theme->a_icon->surface.grad =
913         theme->a_clear->surface.grad =
914         theme->a_clear_tex->surface.grad =
915         theme->a_menu_text_title->surface.grad =
916         theme->a_menu_normal->surface.grad =
917         theme->a_menu_disabled->surface.grad =
918         theme->a_menu_text_normal->surface.grad =
919         theme->a_menu_text_selected->surface.grad =
920         theme->a_menu_text_disabled->surface.grad =
921         theme->a_menu_text_disabled_selected->surface.grad =
922         theme->a_menu_bullet_normal->surface.grad =
923         theme->a_menu_bullet_selected->surface.grad = RR_SURFACE_PARENTREL;
924
925     /* set up the textures */
926     theme->a_focused_label->texture[0].type = RR_TEXTURE_TEXT;
927     theme->a_focused_label->texture[0].data.text.justify = winjust;
928     theme->a_focused_label->texture[0].data.text.font=theme->win_font_focused;
929     theme->a_focused_label->texture[0].data.text.color =
930         theme->title_focused_color;
931
932     if (read_string(db, "window.active.label.text.font", &str)) {
933         char *p;
934         gint i = 0;
935         gint j;
936         if (strstr(str, "shadow=y")) {
937             if ((p = strstr(str, "shadowoffset=")))
938                 i = parse_inline_number(p + strlen("shadowoffset="));
939             else
940                 i = 1;
941             theme->a_focused_label->texture[0].data.text.shadow_offset_x = i;
942             theme->a_focused_label->texture[0].data.text.shadow_offset_y = i;
943         }
944         if ((p = strstr(str, "shadowtint=")))
945         {
946             i = parse_inline_number(p + strlen("shadowtint="));
947             j = (i > 0 ? 0 : 255);
948             i = ABS(i*255/100);
949
950             theme->title_focused_shadow_color = RrColorNew(inst, j, j, j);
951             theme->title_focused_shadow_alpha = i;
952         } else {
953             theme->title_focused_shadow_color = RrColorNew(inst, 0, 0, 0);
954             theme->title_focused_shadow_alpha = 50;
955         }
956     }
957
958     theme->a_focused_label->texture[0].data.text.shadow_color =
959         theme->title_focused_shadow_color;
960     theme->a_focused_label->texture[0].data.text.shadow_alpha =
961         theme->title_focused_shadow_alpha;
962
963     theme->osd_hilite_label->texture[0].type = RR_TEXTURE_TEXT;
964     theme->osd_hilite_label->texture[0].data.text.justify = RR_JUSTIFY_LEFT;
965     theme->osd_hilite_label->texture[0].data.text.font =
966         theme->osd_font_hilite;
967     theme->osd_hilite_label->texture[0].data.text.color =
968         theme->osd_text_active_color;
969
970     if (read_string(db, "osd.active.label.text.font", &str) ||
971         read_string(db, "osd.label.text.font", &str))
972     {
973         char *p;
974         gint i = 0;
975         gint j;
976         if (strstr(str, "shadow=y")) {
977             if ((p = strstr(str, "shadowoffset=")))
978                 i = parse_inline_number(p + strlen("shadowoffset="));
979             else
980                 i = 1;
981             theme->osd_hilite_label->texture[0].data.text.shadow_offset_x = i;
982             theme->osd_hilite_label->texture[0].data.text.shadow_offset_y = i;
983         }
984         if ((p = strstr(str, "shadowtint=")))
985         {
986             i = parse_inline_number(p + strlen("shadowtint="));
987             j = (i > 0 ? 0 : 255);
988             i = ABS(i*255/100);
989
990             theme->osd_text_active_shadow_color = RrColorNew(inst, j, j, j);
991             theme->osd_text_active_shadow_alpha = i;
992         } else {
993             theme->osd_text_active_shadow_color = RrColorNew(inst, 0, 0, 0);
994             theme->osd_text_active_shadow_alpha = 50;
995         }
996     } else {
997         /* inherit the font settings from the focused label */
998         theme->osd_hilite_label->texture[0].data.text.shadow_offset_x =
999             theme->a_focused_label->texture[0].data.text.shadow_offset_x;
1000         theme->osd_hilite_label->texture[0].data.text.shadow_offset_y =
1001             theme->a_focused_label->texture[0].data.text.shadow_offset_y;
1002         if (theme->title_focused_shadow_color)
1003             theme->osd_text_active_shadow_color =
1004                 RrColorCopy(theme->title_focused_shadow_color);
1005         else
1006             theme->osd_text_active_shadow_color = RrColorNew(inst, 0, 0, 0);
1007         theme->osd_text_active_shadow_alpha =
1008             theme->title_focused_shadow_alpha;
1009     }
1010
1011     theme->osd_hilite_label->texture[0].data.text.shadow_color =
1012         theme->osd_text_active_shadow_color;
1013     theme->osd_hilite_label->texture[0].data.text.shadow_alpha =
1014         theme->osd_text_active_shadow_alpha;
1015
1016     theme->osd_unpressed_button->texture[0].type =
1017         theme->osd_pressed_button->texture[0].type =
1018         theme->osd_focused_button->texture[0].type =
1019         RR_TEXTURE_TEXT;
1020
1021     theme->osd_unpressed_button->texture[0].data.text.justify =
1022         theme->osd_pressed_button->texture[0].data.text.justify =
1023         theme->osd_focused_button->texture[0].data.text.justify =
1024         RR_JUSTIFY_CENTER;
1025
1026     theme->osd_unpressed_button->texture[0].data.text.font =
1027         theme->osd_pressed_button->texture[0].data.text.font =
1028         theme->osd_focused_button->texture[0].data.text.font =
1029         theme->osd_font_hilite;
1030
1031     theme->osd_unpressed_button->texture[0].data.text.color =
1032         theme->osd_unpressed_color;
1033     theme->osd_pressed_button->texture[0].data.text.color =
1034         theme->osd_pressed_color;
1035     theme->osd_focused_button->texture[0].data.text.color =
1036         theme->osd_focused_color;
1037
1038     theme->osd_pressed_button->texture[1].data.lineart.color =
1039         theme->osd_pressed_button->texture[2].data.lineart.color =
1040         theme->osd_pressed_button->texture[3].data.lineart.color =
1041         theme->osd_pressed_button->texture[4].data.lineart.color =
1042         theme->osd_pressed_lineart;
1043
1044     theme->osd_focused_button->texture[1].data.lineart.color =
1045         theme->osd_focused_button->texture[2].data.lineart.color =
1046         theme->osd_focused_button->texture[3].data.lineart.color =
1047         theme->osd_focused_button->texture[4].data.lineart.color =
1048         theme->osd_focused_lineart;
1049
1050     theme->a_unfocused_label->texture[0].type = RR_TEXTURE_TEXT;
1051     theme->a_unfocused_label->texture[0].data.text.justify = winjust;
1052     theme->a_unfocused_label->texture[0].data.text.font =
1053         theme->win_font_unfocused;
1054     theme->a_unfocused_label->texture[0].data.text.color =
1055         theme->title_unfocused_color;
1056
1057     if (read_string(db, "window.inactive.label.text.font", &str)) {
1058         char *p;
1059         gint i = 0;
1060         gint j;
1061         if (strstr(str, "shadow=y")) {
1062             if ((p = strstr(str, "shadowoffset=")))
1063                 i = parse_inline_number(p + strlen("shadowoffset="));
1064             else
1065                 i = 1;
1066             theme->a_unfocused_label->texture[0].data.text.shadow_offset_x = i;
1067             theme->a_unfocused_label->texture[0].data.text.shadow_offset_y = i;
1068         }
1069         if ((p = strstr(str, "shadowtint=")))
1070         {
1071             i = parse_inline_number(p + strlen("shadowtint="));
1072             j = (i > 0 ? 0 : 255);
1073             i = ABS(i*255/100);
1074
1075             theme->title_unfocused_shadow_color = RrColorNew(inst, j, j, j);
1076             theme->title_unfocused_shadow_alpha = i;
1077         } else {
1078             theme->title_unfocused_shadow_color = RrColorNew(inst, 0, 0, 0);
1079             theme->title_unfocused_shadow_alpha = 50;
1080         }
1081     }
1082
1083     theme->a_unfocused_label->texture[0].data.text.shadow_color =
1084         theme->title_unfocused_shadow_color;
1085     theme->a_unfocused_label->texture[0].data.text.shadow_alpha =
1086         theme->title_unfocused_shadow_alpha;
1087
1088     theme->osd_unhilite_label->texture[0].type = RR_TEXTURE_TEXT;
1089     theme->osd_unhilite_label->texture[0].data.text.justify = RR_JUSTIFY_LEFT;
1090     theme->osd_unhilite_label->texture[0].data.text.font =
1091         theme->osd_font_unhilite;
1092     theme->osd_unhilite_label->texture[0].data.text.color =
1093         theme->osd_text_inactive_color;
1094
1095     if (read_string(db, "osd.inactive.label.text.font", &str))
1096     {
1097         char *p;
1098         gint i = 0;
1099         gint j;
1100         if (strstr(str, "shadow=y")) {
1101             if ((p = strstr(str, "shadowoffset=")))
1102                 i = parse_inline_number(p + strlen("shadowoffset="));
1103             else
1104                 i = 1;
1105             theme->osd_unhilite_label->texture[0].data.text.shadow_offset_x=i;
1106             theme->osd_unhilite_label->texture[0].data.text.shadow_offset_y=i;
1107         }
1108         if ((p = strstr(str, "shadowtint=")))
1109         {
1110             i = parse_inline_number(p + strlen("shadowtint="));
1111             j = (i > 0 ? 0 : 255);
1112             i = ABS(i*255/100);
1113
1114             theme->osd_text_inactive_shadow_color = RrColorNew(inst, j, j, j);
1115             theme->osd_text_inactive_shadow_alpha = i;
1116         } else {
1117             theme->osd_text_inactive_shadow_color = RrColorNew(inst, 0, 0, 0);
1118             theme->osd_text_inactive_shadow_alpha = 50;
1119         }
1120     } else {
1121         /* inherit the font settings from the unfocused label */
1122         theme->osd_unhilite_label->texture[0].data.text.shadow_offset_x =
1123             theme->a_unfocused_label->texture[0].data.text.shadow_offset_x;
1124         theme->osd_unhilite_label->texture[0].data.text.shadow_offset_y =
1125             theme->a_unfocused_label->texture[0].data.text.shadow_offset_y;
1126         if (theme->title_unfocused_shadow_color)
1127             theme->osd_text_inactive_shadow_color =
1128                 RrColorCopy(theme->title_unfocused_shadow_color);
1129         else
1130             theme->osd_text_inactive_shadow_color = RrColorNew(inst, 0, 0, 0);
1131         theme->osd_text_inactive_shadow_alpha =
1132             theme->title_unfocused_shadow_alpha;
1133     }
1134
1135     theme->osd_unhilite_label->texture[0].data.text.shadow_color =
1136         theme->osd_text_inactive_shadow_color;
1137     theme->osd_unhilite_label->texture[0].data.text.shadow_alpha =
1138         theme->osd_text_inactive_shadow_alpha;
1139
1140     theme->a_menu_text_title->texture[0].type = RR_TEXTURE_TEXT;
1141     theme->a_menu_text_title->texture[0].data.text.justify = mtitlejust;
1142     theme->a_menu_text_title->texture[0].data.text.font =
1143         theme->menu_title_font;
1144     theme->a_menu_text_title->texture[0].data.text.color =
1145         theme->menu_title_color;
1146
1147     if (read_string(db, "menu.title.text.font", &str)) {
1148         char *p;
1149         gint i = 0;
1150         gint j;
1151         if (strstr(str, "shadow=y")) {
1152             if ((p = strstr(str, "shadowoffset=")))
1153                 i = parse_inline_number(p + strlen("shadowoffset="));
1154             else
1155                 i = 1;
1156             theme->a_menu_text_title->texture[0].data.text.shadow_offset_x = i;
1157             theme->a_menu_text_title->texture[0].data.text.shadow_offset_y = i;
1158         }
1159         if ((p = strstr(str, "shadowtint=")))
1160         {
1161             i = parse_inline_number(p + strlen("shadowtint="));
1162             j = (i > 0 ? 0 : 255);
1163             i = ABS(i*255/100);
1164
1165             theme->menu_title_shadow_color = RrColorNew(inst, j, j, j);
1166             theme->menu_title_shadow_alpha = i;
1167         } else {
1168             theme->menu_title_shadow_color = RrColorNew(inst, 0, 0, 0);
1169             theme->menu_title_shadow_alpha = 50;
1170         }
1171     }
1172
1173     theme->a_menu_text_title->texture[0].data.text.shadow_color =
1174         theme->menu_title_shadow_color;
1175     theme->a_menu_text_title->texture[0].data.text.shadow_alpha =
1176         theme->menu_title_shadow_alpha;
1177
1178     theme->a_menu_text_normal->texture[0].type =
1179         theme->a_menu_text_selected->texture[0].type =
1180         theme->a_menu_text_disabled->texture[0].type =
1181         theme->a_menu_text_disabled_selected->texture[0].type =
1182         RR_TEXTURE_TEXT;
1183     theme->a_menu_text_normal->texture[0].data.text.justify =
1184         theme->a_menu_text_selected->texture[0].data.text.justify =
1185         theme->a_menu_text_disabled->texture[0].data.text.justify =
1186         theme->a_menu_text_disabled_selected->texture[0].data.text.justify =
1187         RR_JUSTIFY_LEFT;
1188     theme->a_menu_text_normal->texture[0].data.text.font =
1189         theme->a_menu_text_selected->texture[0].data.text.font =
1190         theme->a_menu_text_disabled->texture[0].data.text.font =
1191         theme->a_menu_text_disabled_selected->texture[0].data.text.font =
1192         theme->menu_font;
1193     theme->a_menu_text_normal->texture[0].data.text.color = theme->menu_color;
1194     theme->a_menu_text_selected->texture[0].data.text.color =
1195         theme->menu_selected_color;
1196     theme->a_menu_text_disabled->texture[0].data.text.color =
1197         theme->menu_disabled_color;
1198     theme->a_menu_text_disabled_selected->texture[0].data.text.color =
1199         theme->menu_disabled_selected_color;
1200
1201     if (read_string(db, "menu.items.font", &str)) {
1202         char *p;
1203         gint i = 0;
1204         gint j;
1205         if (strstr(str, "shadow=y")) {
1206             if ((p = strstr(str, "shadowoffset=")))
1207                 i = parse_inline_number(p + strlen("shadowoffset="));
1208             else
1209                 i = 1;
1210             theme->a_menu_text_normal->
1211                 texture[0].data.text.shadow_offset_x = i;
1212             theme->a_menu_text_normal->
1213                 texture[0].data.text.shadow_offset_y = i;
1214             theme->a_menu_text_selected->
1215                 texture[0].data.text.shadow_offset_x = i;
1216             theme->a_menu_text_selected->
1217                 texture[0].data.text.shadow_offset_y = i;
1218             theme->a_menu_text_disabled->
1219                 texture[0].data.text.shadow_offset_x = i;
1220             theme->a_menu_text_disabled->
1221                 texture[0].data.text.shadow_offset_y = i;
1222             theme->a_menu_text_disabled_selected->
1223                 texture[0].data.text.shadow_offset_x = i;
1224             theme->a_menu_text_disabled_selected->
1225                 texture[0].data.text.shadow_offset_y = i;
1226         }
1227         if ((p = strstr(str, "shadowtint=")))
1228         {
1229             i = parse_inline_number(p + strlen("shadowtint="));
1230             j = (i > 0 ? 0 : 255);
1231             i = ABS(i*255/100);
1232
1233             theme->menu_text_normal_shadow_color = RrColorNew(inst, j, j, j);
1234             theme->menu_text_selected_shadow_color = RrColorNew(inst, j, j, j);
1235             theme->menu_text_disabled_shadow_color = RrColorNew(inst, j, j, j);
1236             theme->menu_text_normal_shadow_alpha = i;
1237             theme->menu_text_selected_shadow_alpha = i;
1238             theme->menu_text_disabled_shadow_alpha = i;
1239             theme->menu_text_disabled_selected_shadow_alpha = i;
1240         } else {
1241             theme->menu_text_normal_shadow_color = RrColorNew(inst, 0, 0, 0);
1242             theme->menu_text_selected_shadow_color = RrColorNew(inst, 0, 0, 0);
1243             theme->menu_text_disabled_shadow_color = RrColorNew(inst, 0, 0, 0);
1244             theme->menu_text_normal_shadow_alpha = 50;
1245             theme->menu_text_selected_shadow_alpha = 50;
1246             theme->menu_text_disabled_selected_shadow_alpha = 50;
1247         }
1248     }
1249
1250     theme->a_menu_text_normal->texture[0].data.text.shadow_color =
1251         theme->menu_text_normal_shadow_color;
1252     theme->a_menu_text_normal->texture[0].data.text.shadow_alpha =
1253         theme->menu_text_normal_shadow_alpha;
1254     theme->a_menu_text_selected->texture[0].data.text.shadow_color =
1255         theme->menu_text_selected_shadow_color;
1256     theme->a_menu_text_selected->texture[0].data.text.shadow_alpha =
1257         theme->menu_text_selected_shadow_alpha;
1258     theme->a_menu_text_disabled->texture[0].data.text.shadow_color =
1259         theme->menu_text_disabled_shadow_color;
1260     theme->a_menu_text_disabled->texture[0].data.text.shadow_alpha =
1261         theme->menu_text_disabled_shadow_alpha;
1262     theme->a_menu_text_disabled_selected->texture[0].data.text.shadow_color =
1263         theme->menu_text_disabled_shadow_color;
1264     theme->a_menu_text_disabled_selected->texture[0].data.text.shadow_alpha =
1265         theme->menu_text_disabled_shadow_alpha;
1266
1267     theme->btn_max->a_disabled_focused->texture[0].type =
1268         theme->btn_max->a_disabled_unfocused->texture[0].type =
1269         theme->btn_max->a_hover_focused->texture[0].type =
1270         theme->btn_max->a_hover_unfocused->texture[0].type =
1271         theme->btn_max->a_toggled_hover_focused->texture[0].type =
1272         theme->btn_max->a_toggled_hover_unfocused->texture[0].type =
1273         theme->btn_max->a_toggled_focused_unpressed->texture[0].type =
1274         theme->btn_max->a_toggled_unfocused_unpressed->texture[0].type =
1275         theme->btn_max->a_toggled_focused_pressed->texture[0].type =
1276         theme->btn_max->a_toggled_unfocused_pressed->texture[0].type =
1277         theme->btn_max->a_focused_unpressed->texture[0].type =
1278         theme->btn_max->a_focused_pressed->texture[0].type =
1279         theme->btn_max->a_unfocused_unpressed->texture[0].type =
1280         theme->btn_max->a_unfocused_pressed->texture[0].type =
1281         theme->btn_close->a_disabled_focused->texture[0].type =
1282         theme->btn_close->a_disabled_unfocused->texture[0].type =
1283         theme->btn_close->a_hover_focused->texture[0].type =
1284         theme->btn_close->a_hover_unfocused->texture[0].type =
1285         theme->btn_close->a_focused_unpressed->texture[0].type =
1286         theme->btn_close->a_focused_pressed->texture[0].type =
1287         theme->btn_close->a_unfocused_unpressed->texture[0].type =
1288         theme->btn_close->a_unfocused_pressed->texture[0].type =
1289         theme->btn_desk->a_disabled_focused->texture[0].type =
1290         theme->btn_desk->a_disabled_unfocused->texture[0].type =
1291         theme->btn_desk->a_hover_focused->texture[0].type =
1292         theme->btn_desk->a_hover_unfocused->texture[0].type =
1293         theme->btn_desk->a_toggled_hover_focused->texture[0].type =
1294         theme->btn_desk->a_toggled_hover_unfocused->texture[0].type =
1295         theme->btn_desk->a_toggled_focused_unpressed->texture[0].type =
1296         theme->btn_desk->a_toggled_unfocused_unpressed->texture[0].type =
1297         theme->btn_desk->a_toggled_focused_pressed->texture[0].type =
1298         theme->btn_desk->a_toggled_unfocused_pressed->texture[0].type =
1299         theme->btn_desk->a_focused_unpressed->texture[0].type =
1300         theme->btn_desk->a_focused_pressed->texture[0].type =
1301         theme->btn_desk->a_unfocused_unpressed->texture[0].type =
1302         theme->btn_desk->a_unfocused_pressed->texture[0].type =
1303         theme->btn_shade->a_disabled_focused->texture[0].type =
1304         theme->btn_shade->a_disabled_unfocused->texture[0].type =
1305         theme->btn_shade->a_hover_focused->texture[0].type =
1306         theme->btn_shade->a_hover_unfocused->texture[0].type =
1307         theme->btn_shade->a_toggled_hover_focused->texture[0].type =
1308         theme->btn_shade->a_toggled_hover_unfocused->texture[0].type =
1309         theme->btn_shade->a_toggled_focused_unpressed->texture[0].type =
1310         theme->btn_shade->a_toggled_unfocused_unpressed->texture[0].type =
1311         theme->btn_shade->a_toggled_focused_pressed->texture[0].type =
1312         theme->btn_shade->a_toggled_unfocused_pressed->texture[0].type =
1313         theme->btn_shade->a_focused_unpressed->texture[0].type =
1314         theme->btn_shade->a_focused_pressed->texture[0].type =
1315         theme->btn_shade->a_unfocused_unpressed->texture[0].type =
1316         theme->btn_shade->a_unfocused_pressed->texture[0].type =
1317         theme->btn_iconify->a_disabled_focused->texture[0].type =
1318         theme->btn_iconify->a_disabled_unfocused->texture[0].type =
1319         theme->btn_iconify->a_hover_focused->texture[0].type =
1320         theme->btn_iconify->a_hover_unfocused->texture[0].type =
1321         theme->btn_iconify->a_focused_unpressed->texture[0].type =
1322         theme->btn_iconify->a_focused_pressed->texture[0].type =
1323         theme->btn_iconify->a_unfocused_unpressed->texture[0].type =
1324         theme->btn_iconify->a_unfocused_pressed->texture[0].type =
1325         theme->a_menu_bullet_normal->texture[0].type =
1326         theme->a_menu_bullet_selected->texture[0].type = RR_TEXTURE_MASK;
1327
1328     theme->btn_max->a_disabled_focused->texture[0].data.mask.mask =
1329         theme->btn_max->a_disabled_unfocused->texture[0].data.mask.mask =
1330         theme->btn_max->disabled_mask;
1331     theme->btn_max->a_hover_focused->texture[0].data.mask.mask =
1332         theme->btn_max->a_hover_unfocused->texture[0].data.mask.mask =
1333         theme->btn_max->hover_mask;
1334     theme->btn_max->a_focused_pressed->texture[0].data.mask.mask =
1335         theme->btn_max->a_unfocused_pressed->texture[0].data.mask.mask =
1336         theme->btn_max->pressed_mask;
1337     theme->btn_max->a_focused_unpressed->texture[0].data.mask.mask =
1338         theme->btn_max->a_unfocused_unpressed->texture[0].data.mask.mask =
1339         theme->btn_max->mask;
1340     theme->btn_max->a_toggled_hover_focused->texture[0].data.mask.mask =
1341         theme->btn_max->a_toggled_hover_unfocused->texture[0].data.mask.mask =
1342         theme->btn_max->toggled_hover_mask;
1343     theme->btn_max->a_toggled_focused_unpressed->texture[0].data.mask.mask =
1344         theme->btn_max->a_toggled_unfocused_unpressed->
1345         texture[0].data.mask.mask = theme->btn_max->toggled_mask;
1346     theme->btn_max->a_toggled_focused_pressed->texture[0].data.mask.mask =
1347         theme->btn_max->a_toggled_unfocused_pressed->texture[0].data.mask.mask
1348         = theme->btn_max->toggled_pressed_mask;
1349     theme->btn_close->a_disabled_focused->texture[0].data.mask.mask =
1350         theme->btn_close->a_disabled_unfocused->texture[0].data.mask.mask =
1351         theme->btn_close->disabled_mask;
1352     theme->btn_close->a_hover_focused->texture[0].data.mask.mask =
1353         theme->btn_close->a_hover_unfocused->texture[0].data.mask.mask =
1354         theme->btn_close->hover_mask;
1355     theme->btn_close->a_focused_pressed->texture[0].data.mask.mask =
1356         theme->btn_close->a_unfocused_pressed->texture[0].data.mask.mask =
1357         theme->btn_close->pressed_mask;
1358     theme->btn_close->a_focused_unpressed->texture[0].data.mask.mask =
1359         theme->btn_close->a_unfocused_unpressed->texture[0].data.mask.mask =
1360         theme->btn_close->mask;
1361     theme->btn_desk->a_disabled_focused->texture[0].data.mask.mask =
1362         theme->btn_desk->a_disabled_unfocused->texture[0].data.mask.mask =
1363         theme->btn_desk->disabled_mask;
1364     theme->btn_desk->a_hover_focused->texture[0].data.mask.mask =
1365         theme->btn_desk->a_hover_unfocused->texture[0].data.mask.mask =
1366         theme->btn_desk->hover_mask;
1367     theme->btn_desk->a_focused_pressed->texture[0].data.mask.mask =
1368         theme->btn_desk->a_unfocused_pressed->texture[0].data.mask.mask =
1369         theme->btn_desk->pressed_mask;
1370     theme->btn_desk->a_focused_unpressed->texture[0].data.mask.mask =
1371         theme->btn_desk->a_unfocused_unpressed->texture[0].data.mask.mask =
1372         theme->btn_desk->mask;
1373     theme->btn_desk->a_toggled_hover_focused->texture[0].data.mask.mask =
1374         theme->btn_desk->a_toggled_hover_unfocused->texture[0].data.mask.mask =
1375         theme->btn_desk->toggled_hover_mask;
1376     theme->btn_desk->a_toggled_focused_unpressed->texture[0].data.mask.mask =
1377         theme->btn_desk->a_toggled_unfocused_unpressed->
1378         texture[0].data.mask.mask = theme->btn_desk->toggled_mask;
1379     theme->btn_desk->a_toggled_focused_pressed->texture[0].data.mask.mask =
1380         theme->btn_desk->a_toggled_unfocused_pressed->texture[0].data.mask.mask
1381         = theme->btn_desk->toggled_pressed_mask;
1382     theme->btn_shade->a_disabled_focused->texture[0].data.mask.mask =
1383         theme->btn_shade->a_disabled_unfocused->texture[0].data.mask.mask =
1384         theme->btn_shade->disabled_mask;
1385     theme->btn_shade->a_hover_focused->texture[0].data.mask.mask =
1386         theme->btn_shade->a_hover_unfocused->texture[0].data.mask.mask =
1387         theme->btn_shade->hover_mask;
1388     theme->btn_shade->a_focused_pressed->texture[0].data.mask.mask =
1389         theme->btn_shade->a_unfocused_pressed->texture[0].data.mask.mask =
1390         theme->btn_shade->pressed_mask;
1391     theme->btn_shade->a_focused_unpressed->texture[0].data.mask.mask =
1392         theme->btn_shade->a_unfocused_unpressed->texture[0].data.mask.mask =
1393         theme->btn_shade->mask;
1394     theme->btn_shade->a_toggled_hover_focused->texture[0].data.mask.mask =
1395         theme->btn_shade->a_toggled_hover_unfocused->texture[0].data.mask.mask
1396         = theme->btn_shade->toggled_hover_mask;
1397     theme->btn_shade->a_toggled_focused_unpressed->texture[0].data.mask.mask =
1398         theme->btn_shade->a_toggled_unfocused_unpressed->
1399         texture[0].data.mask.mask = theme->btn_shade->toggled_mask;
1400     theme->btn_shade->a_toggled_focused_pressed->texture[0].data.mask.mask =
1401         theme->btn_shade->a_toggled_unfocused_pressed->
1402         texture[0].data.mask.mask = theme->btn_shade->toggled_pressed_mask;
1403     theme->btn_iconify->a_disabled_focused->texture[0].data.mask.mask =
1404         theme->btn_iconify->a_disabled_unfocused->texture[0].data.mask.mask =
1405         theme->btn_iconify->disabled_mask;
1406     theme->btn_iconify->a_hover_focused->texture[0].data.mask.mask =
1407         theme->btn_iconify->a_hover_unfocused->texture[0].data.mask.mask =
1408         theme->btn_iconify->hover_mask;
1409     theme->btn_iconify->a_focused_pressed->texture[0].data.mask.mask =
1410         theme->btn_iconify->a_unfocused_pressed->texture[0].data.mask.mask =
1411         theme->btn_iconify->pressed_mask;
1412     theme->btn_iconify->a_focused_unpressed->texture[0].data.mask.mask =
1413         theme->btn_iconify->a_unfocused_unpressed->texture[0].data.mask.mask =
1414         theme->btn_iconify->mask;
1415     theme->a_menu_bullet_normal->texture[0].data.mask.mask =
1416     theme->a_menu_bullet_selected->texture[0].data.mask.mask =
1417         theme->menu_bullet_mask;
1418     theme->btn_max->a_disabled_focused->texture[0].data.mask.color = 
1419         theme->btn_max->disabled_focused_color;
1420     theme->btn_close->a_disabled_focused->texture[0].data.mask.color = 
1421         theme->btn_close->disabled_focused_color;
1422     theme->btn_desk->a_disabled_focused->texture[0].data.mask.color = 
1423         theme->btn_desk->disabled_focused_color;
1424     theme->btn_shade->a_disabled_focused->texture[0].data.mask.color = 
1425         theme->btn_shade->disabled_focused_color;
1426     theme->btn_iconify->a_disabled_focused->texture[0].data.mask.color = 
1427         theme->btn_iconify->disabled_focused_color;
1428     theme->btn_max->a_disabled_unfocused->texture[0].data.mask.color = 
1429         theme->btn_max->disabled_unfocused_color;
1430     theme->btn_close->a_disabled_unfocused->texture[0].data.mask.color = 
1431         theme->btn_close->disabled_unfocused_color;
1432     theme->btn_desk->a_disabled_unfocused->texture[0].data.mask.color = 
1433         theme->btn_desk->disabled_unfocused_color;
1434     theme->btn_shade->a_disabled_unfocused->texture[0].data.mask.color = 
1435         theme->btn_shade->disabled_unfocused_color;
1436     theme->btn_iconify->a_disabled_unfocused->texture[0].data.mask.color = 
1437         theme->btn_iconify->disabled_unfocused_color;
1438     theme->btn_max->a_hover_focused->texture[0].data.mask.color = 
1439         theme->btn_max->hover_focused_color;
1440     theme->btn_close->a_hover_focused->texture[0].data.mask.color = 
1441         theme->btn_close->hover_focused_color;
1442     theme->btn_desk->a_hover_focused->texture[0].data.mask.color = 
1443         theme->btn_desk->hover_focused_color;
1444     theme->btn_shade->a_hover_focused->texture[0].data.mask.color = 
1445         theme->btn_shade->hover_focused_color;
1446     theme->btn_iconify->a_hover_focused->texture[0].data.mask.color = 
1447         theme->btn_iconify->hover_focused_color;
1448     theme->btn_max->a_hover_unfocused->texture[0].data.mask.color = 
1449         theme->btn_max->hover_unfocused_color;
1450     theme->btn_close->a_hover_unfocused->texture[0].data.mask.color = 
1451         theme->btn_close->hover_unfocused_color;
1452     theme->btn_desk->a_hover_unfocused->texture[0].data.mask.color = 
1453         theme->btn_desk->hover_unfocused_color;
1454     theme->btn_shade->a_hover_unfocused->texture[0].data.mask.color = 
1455         theme->btn_shade->hover_unfocused_color;
1456     theme->btn_iconify->a_hover_unfocused->texture[0].data.mask.color = 
1457         theme->btn_iconify->hover_unfocused_color;
1458     theme->btn_max->a_toggled_hover_focused->texture[0].data.mask.color = 
1459         theme->btn_max->toggled_hover_focused_color;
1460     theme->btn_desk->a_toggled_hover_focused->texture[0].data.mask.color = 
1461         theme->btn_desk->toggled_hover_focused_color;
1462     theme->btn_shade->a_toggled_hover_focused->texture[0].data.mask.color = 
1463         theme->btn_shade->toggled_hover_focused_color;
1464     theme->btn_max->a_toggled_hover_unfocused->texture[0].data.mask.color = 
1465         theme->btn_max->toggled_hover_unfocused_color;
1466     theme->btn_desk->a_toggled_hover_unfocused->texture[0].data.mask.color = 
1467         theme->btn_desk->toggled_hover_unfocused_color;
1468     theme->btn_shade->a_toggled_hover_unfocused->texture[0].data.mask.color = 
1469         theme->btn_shade->toggled_hover_unfocused_color;
1470     theme->btn_max->a_toggled_focused_unpressed->texture[0].data.mask.color = 
1471         theme->btn_max->toggled_focused_unpressed_color;
1472     theme->btn_desk->a_toggled_focused_unpressed->texture[0].data.mask.color = 
1473         theme->btn_desk->toggled_focused_unpressed_color;
1474     theme->btn_shade->a_toggled_focused_unpressed->texture[0].data.mask.color = 
1475         theme->btn_shade->toggled_focused_unpressed_color;
1476     theme->btn_max->a_toggled_unfocused_unpressed->texture[0].data.mask.color = 
1477         theme->btn_max->toggled_unfocused_unpressed_color;
1478     theme->btn_desk->a_toggled_unfocused_unpressed->texture[0].data.mask.color
1479         = theme->btn_desk->toggled_unfocused_unpressed_color;
1480     theme->btn_shade->a_toggled_unfocused_unpressed->texture[0].data.mask.color
1481         = theme->btn_shade->toggled_unfocused_unpressed_color;
1482     theme->btn_max->a_toggled_focused_pressed->texture[0].data.mask.color = 
1483         theme->btn_max->toggled_focused_pressed_color;
1484     theme->btn_desk->a_toggled_focused_pressed->texture[0].data.mask.color = 
1485         theme->btn_desk->toggled_focused_pressed_color;
1486     theme->btn_shade->a_toggled_focused_pressed->texture[0].data.mask.color = 
1487         theme->btn_shade->toggled_focused_pressed_color;
1488     theme->btn_max->a_toggled_unfocused_pressed->texture[0].data.mask.color = 
1489         theme->btn_max->toggled_unfocused_pressed_color;
1490     theme->btn_desk->a_toggled_unfocused_pressed->texture[0].data.mask.color = 
1491         theme->btn_desk->toggled_unfocused_pressed_color;
1492     theme->btn_shade->a_toggled_unfocused_pressed->texture[0].data.mask.color = 
1493         theme->btn_shade->toggled_unfocused_pressed_color;
1494     theme->btn_max->a_focused_unpressed->texture[0].data.mask.color = 
1495         theme->btn_max->focused_unpressed_color;
1496     theme->btn_close->a_focused_unpressed->texture[0].data.mask.color = 
1497         theme->btn_close->focused_unpressed_color;
1498     theme->btn_desk->a_focused_unpressed->texture[0].data.mask.color = 
1499         theme->btn_desk->focused_unpressed_color;
1500     theme->btn_shade->a_focused_unpressed->texture[0].data.mask.color = 
1501         theme->btn_shade->focused_unpressed_color;
1502     theme->btn_iconify->a_focused_unpressed->texture[0].data.mask.color = 
1503         theme->btn_iconify->focused_unpressed_color;
1504     theme->btn_max->a_focused_pressed->texture[0].data.mask.color = 
1505         theme->btn_max->focused_pressed_color;
1506     theme->btn_close->a_focused_pressed->texture[0].data.mask.color = 
1507         theme->btn_close->focused_pressed_color;
1508     theme->btn_desk->a_focused_pressed->texture[0].data.mask.color = 
1509         theme->btn_desk->focused_pressed_color;
1510     theme->btn_shade->a_focused_pressed->texture[0].data.mask.color = 
1511         theme->btn_shade->focused_pressed_color;
1512     theme->btn_iconify->a_focused_pressed->texture[0].data.mask.color = 
1513         theme->btn_iconify->focused_pressed_color;
1514     theme->btn_max->a_unfocused_unpressed->texture[0].data.mask.color = 
1515         theme->btn_max->unfocused_unpressed_color;
1516     theme->btn_close->a_unfocused_unpressed->texture[0].data.mask.color = 
1517         theme->btn_close->unfocused_unpressed_color;
1518     theme->btn_desk->a_unfocused_unpressed->texture[0].data.mask.color = 
1519         theme->btn_desk->unfocused_unpressed_color;
1520     theme->btn_shade->a_unfocused_unpressed->texture[0].data.mask.color = 
1521         theme->btn_shade->unfocused_unpressed_color;
1522     theme->btn_iconify->a_unfocused_unpressed->texture[0].data.mask.color = 
1523         theme->btn_iconify->unfocused_unpressed_color;
1524     theme->btn_max->a_unfocused_pressed->texture[0].data.mask.color = 
1525         theme->btn_max->unfocused_pressed_color;
1526     theme->btn_close->a_unfocused_pressed->texture[0].data.mask.color = 
1527         theme->btn_close->unfocused_pressed_color;
1528     theme->btn_desk->a_unfocused_pressed->texture[0].data.mask.color = 
1529         theme->btn_desk->unfocused_pressed_color;
1530     theme->btn_shade->a_unfocused_pressed->texture[0].data.mask.color = 
1531         theme->btn_shade->unfocused_pressed_color;
1532     theme->btn_iconify->a_unfocused_pressed->texture[0].data.mask.color = 
1533         theme->btn_iconify->unfocused_pressed_color;
1534     theme->a_menu_bullet_normal->texture[0].data.mask.color =
1535         theme->menu_bullet_color;
1536     theme->a_menu_bullet_selected->texture[0].data.mask.color =
1537         theme->menu_bullet_selected_color;
1538
1539     g_free(path);
1540     XrmDestroyDatabase(db);
1541
1542     /* set the font heights */
1543     theme->win_font_height = RrFontHeight
1544         (theme->win_font_focused,
1545          theme->a_focused_label->texture[0].data.text.shadow_offset_y);
1546     theme->win_font_height =
1547         MAX(theme->win_font_height,
1548             RrFontHeight
1549             (theme->win_font_focused,
1550              theme->a_unfocused_label->texture[0].data.text.shadow_offset_y));
1551     theme->menu_title_font_height = RrFontHeight
1552         (theme->menu_title_font,
1553          theme->a_menu_text_title->texture[0].data.text.shadow_offset_y);
1554     theme->menu_font_height = RrFontHeight
1555         (theme->menu_font,
1556          theme->a_menu_text_normal->texture[0].data.text.shadow_offset_y);
1557
1558     /* calculate some last extents */
1559     {
1560         gint ft, fb, fl, fr, ut, ub, ul, ur;
1561
1562         RrMargins(theme->a_focused_label, &fl, &ft, &fr, &fb);
1563         RrMargins(theme->a_unfocused_label, &ul, &ut, &ur, &ub);
1564         theme->label_height = theme->win_font_height + MAX(ft + fb, ut + ub) + 1;
1565
1566         /* this would be nice I think, since padding.width can now be 0,
1567            but it breaks frame.c horribly and I don't feel like fixing that
1568            right now, so if anyone complains, here is how to keep text from
1569            going over the title's bevel/border with a padding.width of 0 and a
1570            bevelless/borderless label
1571            RrMargins(theme->a_focused_title, &fl, &ft, &fr, &fb);
1572            RrMargins(theme->a_unfocused_title, &ul, &ut, &ur, &ub);
1573            theme->title_height = theme->label_height +
1574            MAX(MAX(theme->padding * 2, ft + fb),
1575            MAX(theme->padding * 2, ut + ub));
1576         */
1577         theme->title_height = theme->label_height + theme->paddingy * 2;
1578
1579         RrMargins(theme->a_menu_title, &ul, &ut, &ur, &ub);
1580         theme->menu_title_label_height = theme->menu_title_font_height+ut+ub;
1581         theme->menu_title_height = theme->menu_title_label_height +
1582             theme->paddingy * 2;
1583     }
1584     theme->button_size = theme->label_height - 2;
1585     theme->grip_width = 25;
1586
1587     RrAppearanceFree(a_disabled_focused_tmp);
1588     RrAppearanceFree(a_disabled_unfocused_tmp);
1589     RrAppearanceFree(a_hover_focused_tmp);
1590     RrAppearanceFree(a_hover_unfocused_tmp);
1591     RrAppearanceFree(a_focused_unpressed_tmp);
1592     RrAppearanceFree(a_focused_pressed_tmp);
1593     RrAppearanceFree(a_unfocused_unpressed_tmp);
1594     RrAppearanceFree(a_unfocused_pressed_tmp);
1595     RrAppearanceFree(a_toggled_hover_focused_tmp);
1596     RrAppearanceFree(a_toggled_hover_unfocused_tmp);
1597     RrAppearanceFree(a_toggled_focused_unpressed_tmp);
1598     RrAppearanceFree(a_toggled_focused_pressed_tmp);
1599     RrAppearanceFree(a_toggled_unfocused_unpressed_tmp);
1600     RrAppearanceFree(a_toggled_unfocused_pressed_tmp);
1601
1602     return theme;
1603 }
1604
1605 void RrThemeFree(RrTheme *theme)
1606 {
1607     if (theme) {
1608         g_free(theme->name);
1609
1610         RrButtonFree(theme->btn_max);
1611         RrButtonFree(theme->btn_close);
1612         RrButtonFree(theme->btn_desk);
1613         RrButtonFree(theme->btn_shade);
1614         RrButtonFree(theme->btn_iconify);
1615
1616         RrColorFree(theme->menu_border_color);
1617         RrColorFree(theme->osd_border_color);
1618         RrColorFree(theme->frame_focused_border_color);
1619         RrColorFree(theme->frame_undecorated_focused_border_color);
1620         RrColorFree(theme->frame_unfocused_border_color);
1621         RrColorFree(theme->frame_undecorated_unfocused_border_color);
1622         RrColorFree(theme->title_separator_focused_color);
1623         RrColorFree(theme->title_separator_unfocused_color);
1624         RrColorFree(theme->cb_unfocused_color);
1625         RrColorFree(theme->cb_focused_color);
1626         RrColorFree(theme->title_focused_color);
1627         RrColorFree(theme->title_unfocused_color);
1628         RrColorFree(theme->titlebut_disabled_focused_color);
1629         RrColorFree(theme->titlebut_disabled_unfocused_color);
1630         RrColorFree(theme->titlebut_hover_focused_color);
1631         RrColorFree(theme->titlebut_hover_unfocused_color);
1632         RrColorFree(theme->titlebut_toggled_hover_focused_color);
1633         RrColorFree(theme->titlebut_toggled_hover_unfocused_color);
1634         RrColorFree(theme->titlebut_toggled_focused_pressed_color);
1635         RrColorFree(theme->titlebut_toggled_unfocused_pressed_color);
1636         RrColorFree(theme->titlebut_toggled_focused_unpressed_color);
1637         RrColorFree(theme->titlebut_toggled_unfocused_unpressed_color);
1638         RrColorFree(theme->titlebut_focused_pressed_color);
1639         RrColorFree(theme->titlebut_unfocused_pressed_color);
1640         RrColorFree(theme->titlebut_focused_unpressed_color);
1641         RrColorFree(theme->titlebut_unfocused_unpressed_color);
1642         RrColorFree(theme->menu_title_color);
1643         RrColorFree(theme->menu_sep_color);
1644         RrColorFree(theme->menu_color);
1645         RrColorFree(theme->menu_bullet_color);
1646         RrColorFree(theme->menu_bullet_selected_color);
1647         RrColorFree(theme->menu_selected_color);
1648         RrColorFree(theme->menu_disabled_color);
1649         RrColorFree(theme->menu_disabled_selected_color);
1650         RrColorFree(theme->title_focused_shadow_color);
1651         RrColorFree(theme->title_unfocused_shadow_color);
1652         RrColorFree(theme->osd_text_active_color);
1653         RrColorFree(theme->osd_text_inactive_color);
1654         RrColorFree(theme->osd_text_active_shadow_color);
1655         RrColorFree(theme->osd_text_inactive_shadow_color);
1656         RrColorFree(theme->osd_pressed_color);
1657         RrColorFree(theme->osd_unpressed_color);
1658         RrColorFree(theme->osd_focused_color);
1659         RrColorFree(theme->osd_pressed_lineart);
1660         RrColorFree(theme->osd_focused_lineart);
1661         RrColorFree(theme->menu_title_shadow_color);
1662         RrColorFree(theme->menu_text_normal_shadow_color);
1663         RrColorFree(theme->menu_text_selected_shadow_color);
1664         RrColorFree(theme->menu_text_disabled_shadow_color);
1665         RrColorFree(theme->menu_text_disabled_selected_shadow_color);
1666
1667         g_free(theme->def_win_icon);
1668         
1669         RrPixmapMaskFree(theme->menu_bullet_mask);
1670         RrPixmapMaskFree(theme->down_arrow_mask);
1671         RrPixmapMaskFree(theme->up_arrow_mask);
1672
1673         RrFontClose(theme->win_font_focused);
1674         RrFontClose(theme->win_font_unfocused);
1675         RrFontClose(theme->menu_title_font);
1676         RrFontClose(theme->menu_font);
1677         RrFontClose(theme->osd_font_hilite);
1678         RrFontClose(theme->osd_font_unhilite);
1679
1680         RrAppearanceFree(theme->a_focused_grip);
1681         RrAppearanceFree(theme->a_unfocused_grip);
1682         RrAppearanceFree(theme->a_focused_title);
1683         RrAppearanceFree(theme->a_unfocused_title);
1684         RrAppearanceFree(theme->a_focused_label);
1685         RrAppearanceFree(theme->a_unfocused_label);
1686         RrAppearanceFree(theme->a_icon);
1687         RrAppearanceFree(theme->a_focused_handle);
1688         RrAppearanceFree(theme->a_unfocused_handle);
1689         RrAppearanceFree(theme->a_menu);
1690         RrAppearanceFree(theme->a_menu_title);
1691         RrAppearanceFree(theme->a_menu_text_title);
1692         RrAppearanceFree(theme->a_menu_normal);
1693         RrAppearanceFree(theme->a_menu_selected);
1694         RrAppearanceFree(theme->a_menu_disabled);
1695         RrAppearanceFree(theme->a_menu_disabled_selected);
1696         RrAppearanceFree(theme->a_menu_text_normal);
1697         RrAppearanceFree(theme->a_menu_text_selected);
1698         RrAppearanceFree(theme->a_menu_text_disabled);
1699         RrAppearanceFree(theme->a_menu_text_disabled_selected);
1700         RrAppearanceFree(theme->a_menu_bullet_normal);
1701         RrAppearanceFree(theme->a_menu_bullet_selected);
1702         RrAppearanceFree(theme->a_clear);
1703         RrAppearanceFree(theme->a_clear_tex);
1704         RrAppearanceFree(theme->osd_bg);
1705         RrAppearanceFree(theme->osd_hilite_bg);
1706         RrAppearanceFree(theme->osd_hilite_label);
1707         RrAppearanceFree(theme->osd_unhilite_bg);
1708         RrAppearanceFree(theme->osd_unhilite_label);
1709         RrAppearanceFree(theme->osd_pressed_button);
1710         RrAppearanceFree(theme->osd_unpressed_button);
1711         RrAppearanceFree(theme->osd_focused_button);
1712
1713         g_slice_free(RrTheme, theme);
1714     }
1715 }
1716
1717 static XrmDatabase loaddb(const gchar *name, gchar **path)
1718 {
1719     GSList *it;
1720     XrmDatabase db = NULL;
1721     gchar *s;
1722
1723     if (name[0] == '/') {
1724         s = g_build_filename(name, "openbox-3", "themerc", NULL);
1725         if ((db = XrmGetFileDatabase(s)))
1726             *path = g_path_get_dirname(s);
1727         g_free(s);
1728     } else {
1729         ObtPaths *p;
1730
1731         p = obt_paths_new();
1732
1733         /* XXX backwards compatibility, remove me sometime later */
1734         s = g_build_filename(g_get_home_dir(), ".themes", name,
1735                              "openbox-3", "themerc", NULL);
1736         if ((db = XrmGetFileDatabase(s)))
1737             *path = g_path_get_dirname(s);
1738         g_free(s);
1739
1740         for (it = obt_paths_data_dirs(p); !db && it; it = g_slist_next(it))
1741         {
1742             s = g_build_filename(it->data, "themes", name,
1743                                  "openbox-3", "themerc", NULL);
1744             if ((db = XrmGetFileDatabase(s)))
1745                 *path = g_path_get_dirname(s);
1746             g_free(s);
1747         }
1748
1749         obt_paths_unref(p);
1750     }
1751
1752     if (db == NULL) {
1753         s = g_build_filename(name, "themerc", NULL);
1754         if ((db = XrmGetFileDatabase(s)))
1755             *path = g_path_get_dirname(s);
1756         g_free(s);
1757     }
1758
1759     return db;
1760 }
1761
1762 static gchar *create_class_name(const gchar *rname)
1763 {
1764     gchar *rclass = g_strdup(rname);
1765     gchar *p = rclass;
1766
1767     while (TRUE) {
1768         *p = toupper(*p);
1769         p = strchr(p+1, '.');
1770         if (p == NULL) break;
1771         ++p;
1772         if (*p == '\0') break;
1773     }
1774     return rclass;
1775 }
1776
1777 static gboolean read_int(XrmDatabase db, const gchar *rname, gint *value)
1778 {
1779     gboolean ret = FALSE;
1780     gchar *rclass = create_class_name(rname);
1781     gchar *rettype, *end;
1782     XrmValue retvalue;
1783
1784     if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
1785         retvalue.addr != NULL) {
1786         *value = (gint)strtol(retvalue.addr, &end, 10);
1787         if (end != retvalue.addr)
1788             ret = TRUE;
1789     }
1790
1791     g_free(rclass);
1792     return ret;
1793 }
1794
1795 static gboolean read_string(XrmDatabase db, const gchar *rname, gchar **value)
1796 {
1797     gboolean ret = FALSE;
1798     gchar *rclass = create_class_name(rname);
1799     gchar *rettype;
1800     XrmValue retvalue;
1801
1802     if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
1803         retvalue.addr != NULL) {
1804         g_strstrip(retvalue.addr);
1805         *value = retvalue.addr;
1806         ret = TRUE;
1807     }
1808
1809     g_free(rclass);
1810     return ret;
1811 }
1812
1813 static gboolean read_color(XrmDatabase db, const RrInstance *inst,
1814                            const gchar *rname, RrColor **value)
1815 {
1816     gboolean ret = FALSE;
1817     gchar *rclass = create_class_name(rname);
1818     gchar *rettype;
1819     XrmValue retvalue;
1820
1821     if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
1822         retvalue.addr != NULL) {
1823         RrColor *c;
1824
1825         /* retvalue.addr is inside the xrdb database so we can't destroy it
1826            but we can edit it in place, as g_strstrip does. */
1827         g_strstrip(retvalue.addr);
1828         c = RrColorParse(inst, retvalue.addr);
1829         if (c != NULL) {
1830             *value = c;
1831             ret = TRUE;
1832         }
1833     }
1834
1835     g_free(rclass);
1836     return ret;
1837 }
1838
1839 static gboolean read_mask(const RrInstance *inst, const gchar *path,
1840                           RrTheme *theme, const gchar *maskname,
1841                           RrPixmapMask **value)
1842 {
1843     gboolean ret = FALSE;
1844     gchar *s;
1845     gint hx, hy; /* ignored */
1846     guint w, h;
1847     guchar *b;
1848
1849     s = g_build_filename(path, maskname, NULL);
1850     if (XReadBitmapFileData(s, &w, &h, &b, &hx, &hy) == BitmapSuccess) {
1851         ret = TRUE;
1852         *value = RrPixmapMaskNew(inst, w, h, (gchar*)b);
1853         XFree(b);
1854     }
1855     g_free(s);
1856
1857     return ret;
1858 }
1859
1860 static void parse_appearance(gchar *tex, RrSurfaceColorType *grad,
1861                              RrReliefType *relief, RrBevelType *bevel,
1862                              gboolean *interlaced, gboolean *border,
1863                              gboolean allow_trans)
1864 {
1865     gchar *t;
1866
1867     /* convert to all lowercase */
1868     for (t = tex; *t != '\0'; ++t)
1869         *t = g_ascii_tolower(*t);
1870
1871     if (allow_trans && strstr(tex, "parentrelative") != NULL) {
1872         *grad = RR_SURFACE_PARENTREL;
1873     } else {
1874         if (strstr(tex, "gradient") != NULL) {
1875             if (strstr(tex, "crossdiagonal") != NULL)
1876                 *grad = RR_SURFACE_CROSS_DIAGONAL;
1877             else if (strstr(tex, "pyramid") != NULL)
1878                 *grad = RR_SURFACE_PYRAMID;
1879             else if (strstr(tex, "mirrorhorizontal") != NULL)
1880                 *grad = RR_SURFACE_MIRROR_HORIZONTAL;
1881             else if (strstr(tex, "horizontal") != NULL)
1882                 *grad = RR_SURFACE_HORIZONTAL;
1883             else if (strstr(tex, "splitvertical") != NULL)
1884                 *grad = RR_SURFACE_SPLIT_VERTICAL;
1885             else if (strstr(tex, "vertical") != NULL)
1886                 *grad = RR_SURFACE_VERTICAL;
1887             else
1888                 *grad = RR_SURFACE_DIAGONAL;
1889         } else {
1890             *grad = RR_SURFACE_SOLID;
1891         }
1892     }
1893
1894     if (strstr(tex, "sunken") != NULL)
1895         *relief = RR_RELIEF_SUNKEN;
1896     else if (strstr(tex, "flat") != NULL)
1897         *relief = RR_RELIEF_FLAT;
1898     else if (strstr(tex, "raised") != NULL)
1899         *relief = RR_RELIEF_RAISED;
1900     else
1901         *relief = (*grad == RR_SURFACE_PARENTREL) ?
1902                   RR_RELIEF_FLAT : RR_RELIEF_RAISED;
1903
1904     *border = FALSE;
1905     if (*relief == RR_RELIEF_FLAT) {
1906         if (strstr(tex, "border") != NULL)
1907             *border = TRUE;
1908     } else {
1909         if (strstr(tex, "bevel2") != NULL)
1910             *bevel = RR_BEVEL_2;
1911         else
1912             *bevel = RR_BEVEL_1;
1913     }
1914
1915     if (strstr(tex, "interlaced") != NULL)
1916         *interlaced = TRUE;
1917     else
1918         *interlaced = FALSE;
1919 }
1920
1921 static gboolean read_appearance(XrmDatabase db, const RrInstance *inst,
1922                                 const gchar *rname, RrAppearance *value,
1923                                 gboolean allow_trans)
1924 {
1925     gboolean ret = FALSE;
1926     gchar *rclass = create_class_name(rname);
1927     gchar *cname, *ctoname, *bcname, *icname, *hname, *sname;
1928     gchar *csplitname, *ctosplitname;
1929     gchar *rettype;
1930     XrmValue retvalue;
1931     gint i;
1932
1933     cname = g_strconcat(rname, ".color", NULL);
1934     ctoname = g_strconcat(rname, ".colorTo", NULL);
1935     bcname = g_strconcat(rname, ".border.color", NULL);
1936     icname = g_strconcat(rname, ".interlace.color", NULL);
1937     hname = g_strconcat(rname, ".highlight", NULL);
1938     sname = g_strconcat(rname, ".shadow", NULL);
1939     csplitname = g_strconcat(rname, ".color.splitTo", NULL);
1940     ctosplitname = g_strconcat(rname, ".colorTo.splitTo", NULL);
1941
1942     if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
1943         retvalue.addr != NULL) {
1944         parse_appearance(retvalue.addr,
1945                          &value->surface.grad,
1946                          &value->surface.relief,
1947                          &value->surface.bevel,
1948                          &value->surface.interlaced,
1949                          &value->surface.border,
1950                          allow_trans);
1951         if (!read_color(db, inst, cname, &value->surface.primary))
1952             value->surface.primary = RrColorNew(inst, 0, 0, 0);
1953         if (!read_color(db, inst, ctoname, &value->surface.secondary))
1954             value->surface.secondary = RrColorNew(inst, 0, 0, 0);
1955         if (value->surface.border)
1956             if (!read_color(db, inst, bcname,
1957                             &value->surface.border_color))
1958                 value->surface.border_color = RrColorNew(inst, 0, 0, 0);
1959         if (value->surface.interlaced)
1960             if (!read_color(db, inst, icname,
1961                             &value->surface.interlace_color))
1962                 value->surface.interlace_color = RrColorNew(inst, 0, 0, 0);
1963         if (read_int(db, hname, &i) && i >= 0)
1964             value->surface.bevel_light_adjust = i;
1965         if (read_int(db, sname, &i) && i >= 0 && i <= 256)
1966             value->surface.bevel_dark_adjust = i;
1967
1968         if (value->surface.grad == RR_SURFACE_SPLIT_VERTICAL) {
1969             gint r, g, b;
1970
1971             if (!read_color(db, inst, csplitname,
1972                             &value->surface.split_primary))
1973             {
1974                 r = value->surface.primary->r;
1975                 r += r >> 2;
1976                 g = value->surface.primary->g;
1977                 g += g >> 2;
1978                 b = value->surface.primary->b;
1979                 b += b >> 2;
1980                 if (r > 0xFF) r = 0xFF;
1981                 if (g > 0xFF) g = 0xFF;
1982                 if (b > 0xFF) b = 0xFF;
1983                 value->surface.split_primary = RrColorNew(inst, r, g, b);
1984             }
1985
1986             if (!read_color(db, inst, ctosplitname,
1987                             &value->surface.split_secondary))
1988             {
1989                 r = value->surface.secondary->r;
1990                 r += r >> 4;
1991                 g = value->surface.secondary->g;
1992                 g += g >> 4;
1993                 b = value->surface.secondary->b;
1994                 b += b >> 4;
1995                 if (r > 0xFF) r = 0xFF;
1996                 if (g > 0xFF) g = 0xFF;
1997                 if (b > 0xFF) b = 0xFF;
1998                 value->surface.split_secondary = RrColorNew(inst, r, g, b);
1999             }
2000         }
2001
2002         ret = TRUE;
2003     }
2004
2005     g_free(ctosplitname);
2006     g_free(csplitname);
2007     g_free(sname);
2008     g_free(hname);
2009     g_free(icname);
2010     g_free(bcname);
2011     g_free(ctoname);
2012     g_free(cname);
2013     g_free(rclass);
2014     return ret;
2015 }
2016
2017 static int parse_inline_number(const char *p)
2018 {
2019     int neg = 1;
2020     int res = 0;
2021     if (*p == '-') {
2022         neg = -1;
2023         ++p;
2024     }
2025     for (; isdigit(*p); ++p)
2026         res = res * 10 + *p - '0';
2027     res *= neg;
2028     return res;
2029 }
2030
2031 static void set_default_appearance(RrAppearance *a)
2032 {
2033     a->surface.grad = RR_SURFACE_SOLID;
2034     a->surface.relief = RR_RELIEF_FLAT;
2035     a->surface.bevel = RR_BEVEL_1;
2036     a->surface.interlaced = FALSE;
2037     a->surface.border = FALSE;
2038     a->surface.primary = RrColorNew(a->inst, 0, 0, 0);
2039     a->surface.secondary = RrColorNew(a->inst, 0, 0, 0);
2040 }
2041
2042 /* Reads the output from gimp's C-Source file format into valid RGBA data for
2043    an RrTextureRGBA. */
2044 static RrPixel32* read_c_image(gint width, gint height, const guint8 *data)
2045 {
2046     RrPixel32 *im, *p;
2047     gint i;
2048
2049     p = im = g_memdup(data, width * height * sizeof(RrPixel32));
2050
2051     for (i = 0; i < width * height; ++i) {
2052         guchar a = ((*p >> 24) & 0xff);
2053         guchar b = ((*p >> 16) & 0xff);
2054         guchar g = ((*p >>  8) & 0xff);
2055         guchar r = ((*p >>  0) & 0xff);
2056
2057         *p = ((r << RrDefaultRedOffset) +
2058               (g << RrDefaultGreenOffset) +
2059               (b << RrDefaultBlueOffset) +
2060               (a << RrDefaultAlphaOffset));
2061         p++;
2062     }
2063
2064     return im;
2065 }
2066
2067 static void read_button_colors(XrmDatabase db, const RrInstance *inst, 
2068                                const RrTheme *theme, RrButton *btn, 
2069                                const gchar *btnname)
2070 {
2071     gchar *name;
2072
2073     /* active unpressed */
2074     name = g_strdup_printf("window.active.button.%s.unpressed.image.color",
2075                            btnname);
2076     READ_COLOR(name, btn->focused_unpressed_color,
2077                RrColorCopy(theme->titlebut_focused_unpressed_color));
2078     g_free(name);
2079
2080     /* inactive unpressed */
2081     name = g_strdup_printf("window.inactive.button.%s.unpressed.image.color",
2082                            btnname);
2083     READ_COLOR(name, btn->unfocused_unpressed_color,
2084                RrColorCopy(theme->titlebut_unfocused_unpressed_color));
2085     g_free(name);
2086
2087     /* active pressed */
2088     name = g_strdup_printf("window.active.button.%s.pressed.image.color",
2089                            btnname);
2090     READ_COLOR(name, btn->focused_pressed_color,
2091                RrColorCopy(theme->titlebut_focused_pressed_color));
2092     g_free(name);
2093
2094     /* inactive pressed */
2095     name = g_strdup_printf("window.inactive.button.%s.pressed.image.color",
2096                           btnname);
2097     READ_COLOR(name, btn->unfocused_pressed_color,
2098                RrColorCopy(theme->titlebut_unfocused_pressed_color));
2099     g_free(name);
2100
2101     /* active disabled */
2102     name = g_strdup_printf("window.active.button.%s.disabled.image.color",
2103                            btnname);
2104     READ_COLOR(name, btn->disabled_focused_color,
2105                RrColorCopy(theme->titlebut_disabled_focused_color));
2106     g_free(name);
2107
2108     /* inactive disabled */
2109     name = g_strdup_printf("window.inactive.button.%s.disabled.image.color",
2110                            btnname);
2111     READ_COLOR(name, btn->disabled_unfocused_color,
2112                RrColorCopy(theme->titlebut_disabled_unfocused_color));
2113     g_free(name);
2114
2115     /* active hover */
2116     name = g_strdup_printf("window.active.button.%s.hover.image.color",
2117                            btnname);
2118     READ_COLOR(name, btn->hover_focused_color, 
2119                RrColorCopy(theme->titlebut_hover_focused_color));
2120     g_free(name);
2121
2122     /* inactive hover */
2123     name = g_strdup_printf("window.inactive.button.%s.hover.image.color",
2124                            btnname);
2125     READ_COLOR(name, btn->hover_unfocused_color,
2126                RrColorCopy(theme->titlebut_hover_unfocused_color));
2127     g_free(name);
2128
2129     /* active toggled unpressed */
2130     name = g_strdup_printf("window.active.button.%s.toggled."
2131                           "unpressed.image.color", btnname);
2132     READ_COLOR(name, btn->toggled_focused_unpressed_color,
2133                RrColorCopy(theme->titlebut_toggled_focused_unpressed_color));
2134     g_free(name);
2135
2136     /* inactive toggled unpressed */
2137     name = g_strdup_printf("window.inactive.button.%s.toggled."
2138                            "unpressed.image.color", btnname);
2139     READ_COLOR(name, btn->toggled_unfocused_unpressed_color,
2140                RrColorCopy(theme->titlebut_toggled_unfocused_unpressed_color));
2141     g_free(name);
2142
2143     /* active toggled hover */
2144     name = g_strdup_printf("window.active.button.%s.toggled.hover.image.color",
2145                            btnname);
2146     READ_COLOR(name, btn->toggled_hover_focused_color,
2147                RrColorCopy(theme->titlebut_toggled_hover_focused_color));
2148
2149     g_free(name);
2150
2151     /* inactive toggled hover */
2152     name = g_strdup_printf("window.inactive.button.%s.toggled.hover."
2153                            "image.color", btnname);
2154     READ_COLOR(name, btn->toggled_hover_unfocused_color,
2155                RrColorCopy(theme->titlebut_toggled_hover_unfocused_color));
2156     g_free(name);
2157
2158     /* active toggled pressed */
2159     name = g_strdup_printf("window.active.button.%s.toggled.pressed."
2160                            "image.color", btnname);
2161     READ_COLOR(name, btn->toggled_focused_pressed_color, 
2162                RrColorCopy(theme->titlebut_toggled_focused_pressed_color));
2163     g_free(name);
2164    
2165     /* inactive toggled pressed */
2166     name = g_strdup_printf("window.inactive.button.%s.toggled.pressed."
2167                            "image.color", btnname);
2168     READ_COLOR(name, btn->toggled_unfocused_pressed_color,
2169                RrColorCopy(theme->titlebut_toggled_unfocused_pressed_color));
2170     g_free(name);
2171 }
2172
2173