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