8481eee3edd4633900b398a8a9e9e2365eabedd2
[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     READ_APPEARANCE("window.active.button.disabled.bg",
614                     a_disabled_focused_tmp, TRUE);
615     READ_APPEARANCE("window.inactive.button.disabled.bg",
616                     a_disabled_unfocused_tmp, TRUE);
617     READ_APPEARANCE("window.active.button.pressed.bg",
618                     a_focused_pressed_tmp, TRUE);
619     READ_APPEARANCE("window.inactive.button.pressed.bg",
620                     a_unfocused_pressed_tmp, TRUE);
621
622     READ_APPEARANCE_("window.active.button.toggled.unpressed.bg",
623                      "window.active.button.toggled.bg",
624                      a_toggled_focused_unpressed_tmp, TRUE,
625                      a_focused_pressed_tmp);
626     READ_APPEARANCE_("window.inactive.button.toggled.unpressed.bg",
627                      "window.inactive.button.toggled.bg",
628                      a_toggled_unfocused_unpressed_tmp, TRUE,
629                      a_unfocused_pressed_tmp);
630
631     READ_APPEARANCE_COPY("window.active.button.toggled.hover.bg",
632                          a_toggled_hover_focused_tmp, TRUE,
633                          a_toggled_focused_unpressed_tmp);
634     READ_APPEARANCE_COPY("window.inactive.button.toggled.hover.bg",
635                          a_toggled_hover_unfocused_tmp, TRUE,
636                          a_toggled_unfocused_unpressed_tmp);
637
638     READ_APPEARANCE_COPY("window.active.button.toggled.pressed.bg",
639                          a_toggled_focused_pressed_tmp, TRUE,
640                          a_focused_pressed_tmp);
641     READ_APPEARANCE_COPY("window.inactive.button.toggled.pressed.bg",
642                          a_toggled_unfocused_pressed_tmp, TRUE,
643                          a_unfocused_pressed_tmp);
644
645     READ_APPEARANCE("window.active.button.unpressed.bg",
646                     a_focused_unpressed_tmp, TRUE);
647     READ_APPEARANCE("window.inactive.button.unpressed.bg",
648                     a_unfocused_unpressed_tmp, TRUE);
649
650     READ_APPEARANCE_COPY("window.active.button.hover.bg",
651                          a_hover_focused_tmp, TRUE,
652                          a_focused_unpressed_tmp);
653     READ_APPEARANCE_COPY("window.inactive.button.hover.bg",
654                          a_hover_unfocused_tmp, TRUE,
655                          a_unfocused_unpressed_tmp);
656
657     /* now do individual buttons, if specified */
658
659     /* max button */
660     READ_APPEARANCE_COPY("window.active.button-max.disabled.bg",
661                          theme->a_disabled_focused_max, TRUE,
662                          a_disabled_focused_tmp);
663     READ_APPEARANCE_COPY("window.inactive.button-max.disabled.bg",
664                          theme->a_disabled_unfocused_max, TRUE,
665                          a_disabled_unfocused_tmp);
666     READ_APPEARANCE_COPY("window.active.button-max.pressed.bg",
667                          theme->a_hover_focused_max, TRUE,
668                          a_hover_focused_tmp);
669     READ_APPEARANCE_COPY("window.inactive.button-max.pressed.bg",
670                          theme->a_hover_unfocused_max, TRUE,
671                          a_hover_unfocused_tmp);
672     READ_APPEARANCE_COPY("window.active.button-max.unpressed.bg",
673                          theme->a_focused_unpressed_max, TRUE,
674                          a_focused_unpressed_tmp);
675     READ_APPEARANCE_COPY("window.active.button-max.pressed.bg",
676                          theme->a_focused_pressed_max, TRUE,
677                          a_focused_pressed_tmp);
678     READ_APPEARANCE_COPY("window.inactive.button-max.unpressed.bg",
679                          theme->a_unfocused_unpressed_max, TRUE,
680                          a_unfocused_unpressed_tmp);
681     READ_APPEARANCE_COPY("window.inactive.button-max.pressed.bg",
682                          theme->a_unfocused_pressed_max, TRUE,
683                          a_unfocused_pressed_tmp);
684     READ_APPEARANCE_COPY("window.active.button-max.toggled.hover.bg",
685                          theme->a_toggled_hover_focused_max, TRUE,
686                          a_toggled_hover_focused_tmp);
687     READ_APPEARANCE_COPY("window.inactive.button-max.toggled.hover.bg",
688                          theme->a_toggled_hover_unfocused_max, TRUE,
689                          a_toggled_hover_unfocused_tmp);
690     READ_APPEARANCE_COPY("window.active.button-max.toggled.unpressed.bg",
691                          theme->a_toggled_focused_unpressed_max, TRUE,
692                          a_toggled_focused_unpressed_tmp);
693     READ_APPEARANCE_COPY("window.active.button-max.toggled.pressed.bg",
694                          theme->a_toggled_focused_pressed_max, TRUE,
695                          a_toggled_focused_pressed_tmp);
696     READ_APPEARANCE_COPY("window.inactive.button-max.toggled.unpressed.bg",
697                          theme->a_toggled_unfocused_unpressed_max, TRUE,
698                          a_toggled_unfocused_unpressed_tmp);
699     READ_APPEARANCE_COPY("window.inactive.button-max.toggled.pressed.bg",
700                          theme->a_toggled_unfocused_pressed_max, TRUE,
701                          a_toggled_unfocused_pressed_tmp);
702
703     /* close button */
704     READ_APPEARANCE_COPY("window.active.button-close.disabled.bg",
705                          theme->a_disabled_focused_close, TRUE,
706                          a_disabled_focused_tmp);
707     READ_APPEARANCE_COPY("window.inactive.button-close.disabled.bg",
708                          theme->a_disabled_unfocused_close, TRUE,
709                          a_disabled_unfocused_tmp);
710     READ_APPEARANCE_COPY("window.active.button-close.hover.bg",
711                          theme->a_hover_focused_close, TRUE,
712                          a_hover_focused_tmp);
713     READ_APPEARANCE_COPY("window.inactive.button-close.hover.bg",
714                          theme->a_hover_unfocused_close, TRUE,
715                          a_hover_unfocused_tmp);
716     READ_APPEARANCE_COPY("window.active.button-close.unpressed.bg",
717                          theme->a_focused_unpressed_close, TRUE,
718                          a_focused_unpressed_tmp);
719     READ_APPEARANCE_COPY("window.active.button-close.pressed.bg",
720                          theme->a_focused_pressed_close, TRUE,
721                          a_focused_pressed_tmp);
722     READ_APPEARANCE_COPY("window.inactive.button-close.unpressed.bg",
723                          theme->a_unfocused_unpressed_close, TRUE,
724                          a_unfocused_unpressed_tmp);
725     READ_APPEARANCE_COPY("window.inactive.button-close.pressed.bg",
726                          theme->a_unfocused_pressed_close, TRUE,
727                          a_unfocused_pressed_tmp);
728
729     /* desk button */
730     READ_APPEARANCE_COPY("window.active.button-desk.disabled.bg",
731                          theme->a_disabled_focused_desk, TRUE,
732                          a_disabled_focused_tmp);
733     READ_APPEARANCE_COPY("window.inactive.button-desk.disabled.bg",
734                          theme->a_disabled_unfocused_desk, TRUE,
735                          a_disabled_unfocused_tmp);
736     READ_APPEARANCE_COPY("window.active.button-desk.pressed.bg",
737                          theme->a_hover_focused_desk, TRUE,
738                          a_hover_focused_tmp);
739     READ_APPEARANCE_COPY("window.inactive.button-desk.pressed.bg",
740                          theme->a_hover_unfocused_desk, TRUE,
741                          a_hover_unfocused_tmp);
742     READ_APPEARANCE_COPY("window.active.button-desk.unpressed.bg",
743                          theme->a_focused_unpressed_desk, TRUE,
744                          a_focused_unpressed_tmp);
745     READ_APPEARANCE_COPY("window.active.button-desk.pressed.bg",
746                          theme->a_focused_pressed_desk, TRUE,
747                          a_focused_pressed_tmp);
748     READ_APPEARANCE_COPY("window.inactive.button-desk.unpressed.bg",
749                          theme->a_unfocused_unpressed_desk, TRUE,
750                          a_unfocused_unpressed_tmp);
751     READ_APPEARANCE_COPY("window.inactive.button-desk.pressed.bg",
752                          theme->a_unfocused_pressed_desk, TRUE,
753                          a_unfocused_pressed_tmp);
754     READ_APPEARANCE_COPY("window.active.button-desk.toggled.hover.bg",
755                          theme->a_toggled_hover_focused_desk, TRUE,
756                          a_toggled_hover_focused_tmp);
757     READ_APPEARANCE_COPY("window.inactive.button-desk.toggled.hover.bg",
758                          theme->a_toggled_hover_unfocused_desk, TRUE,
759                          a_toggled_hover_unfocused_tmp);
760     READ_APPEARANCE_COPY("window.active.button-desk.toggled.unpressed.bg",
761                          theme->a_toggled_focused_unpressed_desk, TRUE,
762                          a_toggled_focused_unpressed_tmp);
763     READ_APPEARANCE_COPY("window.active.button-desk.toggled.pressed.bg",
764                          theme->a_toggled_focused_pressed_desk, TRUE,
765                          a_toggled_focused_pressed_tmp);
766     READ_APPEARANCE_COPY("window.inactive.button-desk.toggled.unpressed.bg",
767                          theme->a_toggled_unfocused_unpressed_desk, TRUE,
768                          a_toggled_unfocused_unpressed_tmp);
769     READ_APPEARANCE_COPY("window.inactive.button-desk.toggled.pressed.bg",
770                          theme->a_toggled_unfocused_pressed_desk, TRUE,
771                          a_toggled_unfocused_pressed_tmp);
772
773     /* shade button */
774     READ_APPEARANCE_COPY("window.active.button-shade.disabled.bg",
775                          theme->a_disabled_focused_shade, TRUE,
776                          a_disabled_focused_tmp);
777     READ_APPEARANCE_COPY("window.inactive.button-shade.disabled.bg",
778                          theme->a_disabled_unfocused_shade, TRUE,
779                          a_disabled_unfocused_tmp);
780     READ_APPEARANCE_COPY("window.active.button-shade.pressed.bg",
781                          theme->a_hover_focused_shade, TRUE,
782                          a_hover_focused_tmp);
783     READ_APPEARANCE_COPY("window.inactive.button-shade.pressed.bg",
784                          theme->a_hover_unfocused_shade, TRUE,
785                          a_hover_unfocused_tmp);
786     READ_APPEARANCE_COPY("window.active.button-shade.unpressed.bg",
787                          theme->a_focused_unpressed_shade, TRUE,
788                          a_focused_unpressed_tmp);
789     READ_APPEARANCE_COPY("window.active.button-shade.pressed.bg",
790                          theme->a_focused_pressed_shade, TRUE,
791                          a_focused_pressed_tmp);
792     READ_APPEARANCE_COPY("window.inactive.button-shade.unpressed.bg",
793                          theme->a_unfocused_unpressed_shade, TRUE,
794                          a_unfocused_unpressed_tmp);
795     READ_APPEARANCE_COPY("window.inactive.button-shade.pressed.bg",
796                          theme->a_unfocused_pressed_shade, TRUE,
797                          a_unfocused_pressed_tmp);
798     READ_APPEARANCE_COPY("window.active.button-shade.toggled.hover.bg",
799                          theme->a_toggled_hover_focused_shade, TRUE,
800                          a_toggled_hover_focused_tmp);
801     READ_APPEARANCE_COPY("window.inactive.button-shade.toggled.hover.bg",
802                          theme->a_toggled_hover_unfocused_shade, TRUE,
803                          a_toggled_hover_unfocused_tmp);
804     READ_APPEARANCE_COPY("window.active.button-shade.toggled.unpressed.bg",
805                          theme->a_toggled_focused_unpressed_shade, TRUE,
806                          a_toggled_focused_unpressed_tmp);
807     READ_APPEARANCE_COPY("window.active.button-shade.toggled.pressed.bg",
808                          theme->a_toggled_focused_pressed_shade, TRUE,
809                          a_toggled_focused_pressed_tmp);
810     READ_APPEARANCE_COPY("window.inactive.button-shade.toggled.unpressed.bg",
811                          theme->a_toggled_unfocused_unpressed_shade, TRUE,
812                          a_toggled_unfocused_unpressed_tmp);
813     READ_APPEARANCE_COPY("window.inactive.button-shade.toggled.pressed.bg",
814                          theme->a_toggled_unfocused_pressed_shade, TRUE,
815                          a_toggled_unfocused_pressed_tmp);
816
817     /* iconify button */
818     READ_APPEARANCE_COPY("window.active.button-iconify.disabled.bg",
819                          theme->a_disabled_focused_iconify, TRUE,
820                          a_disabled_focused_tmp);
821     READ_APPEARANCE_COPY("window.inactive.button-iconify.disabled.bg",
822                          theme->a_disabled_unfocused_iconify, TRUE,
823                          a_disabled_unfocused_tmp);
824     READ_APPEARANCE_COPY("window.active.button-iconify.hover.bg",
825                          theme->a_hover_focused_iconify, TRUE,
826                          a_hover_focused_tmp);
827     READ_APPEARANCE_COPY("window.inactive.button-iconify.hover.bg",
828                          theme->a_hover_unfocused_iconify, TRUE,
829                          a_hover_unfocused_tmp);
830     READ_APPEARANCE_COPY("window.active.button-iconify.unpressed.bg",
831                          theme->a_focused_unpressed_iconify, TRUE,
832                          a_focused_unpressed_tmp);
833     READ_APPEARANCE_COPY("window.active.button-iconify.pressed.bg",
834                          theme->a_focused_pressed_iconify, TRUE,
835                          a_focused_pressed_tmp);
836     READ_APPEARANCE_COPY("window.inactive.button-iconify.unpressed.bg",
837                          theme->a_unfocused_unpressed_iconify, TRUE,
838                          a_unfocused_unpressed_tmp);
839     READ_APPEARANCE_COPY("window.inactive.button-iconify.pressed.bg",
840                          theme->a_unfocused_pressed_iconify, TRUE,
841                          a_unfocused_pressed_tmp);
842
843     theme->a_icon->surface.grad =
844         theme->a_clear->surface.grad =
845         theme->a_clear_tex->surface.grad =
846         theme->a_menu_text_title->surface.grad =
847         theme->a_menu_normal->surface.grad =
848         theme->a_menu_disabled->surface.grad =
849         theme->a_menu_text_normal->surface.grad =
850         theme->a_menu_text_selected->surface.grad =
851         theme->a_menu_text_disabled->surface.grad =
852         theme->a_menu_text_disabled_selected->surface.grad =
853         theme->a_menu_bullet_normal->surface.grad =
854         theme->a_menu_bullet_selected->surface.grad = RR_SURFACE_PARENTREL;
855
856     /* set up the textures */
857     theme->a_focused_label->texture[0].type = RR_TEXTURE_TEXT;
858     theme->a_focused_label->texture[0].data.text.justify = winjust;
859     theme->a_focused_label->texture[0].data.text.font=theme->win_font_focused;
860     theme->a_focused_label->texture[0].data.text.color =
861         theme->title_focused_color;
862
863     if (read_string(db, "window.active.label.text.font", &str)) {
864         char *p;
865         gint i = 0;
866         gint j;
867         if (strstr(str, "shadow=y")) {
868             if ((p = strstr(str, "shadowoffset=")))
869                 i = parse_inline_number(p + strlen("shadowoffset="));
870             else
871                 i = 1;
872             theme->a_focused_label->texture[0].data.text.shadow_offset_x = i;
873             theme->a_focused_label->texture[0].data.text.shadow_offset_y = i;
874         }
875         if ((p = strstr(str, "shadowtint=")))
876         {
877             i = parse_inline_number(p + strlen("shadowtint="));
878             j = (i > 0 ? 0 : 255);
879             i = ABS(i*255/100);
880
881             theme->title_focused_shadow_color = RrColorNew(inst, j, j, j);
882             theme->title_focused_shadow_alpha = i;
883         } else {
884             theme->title_focused_shadow_color = RrColorNew(inst, 0, 0, 0);
885             theme->title_focused_shadow_alpha = 50;
886         }
887     }
888
889     theme->a_focused_label->texture[0].data.text.shadow_color =
890         theme->title_focused_shadow_color;
891     theme->a_focused_label->texture[0].data.text.shadow_alpha =
892         theme->title_focused_shadow_alpha;
893
894     theme->osd_hilite_label->texture[0].type = RR_TEXTURE_TEXT;
895     theme->osd_hilite_label->texture[0].data.text.justify = RR_JUSTIFY_LEFT;
896     theme->osd_hilite_label->texture[0].data.text.font =
897         theme->osd_font_hilite;
898     theme->osd_hilite_label->texture[0].data.text.color =
899         theme->osd_text_active_color;
900
901     if (read_string(db, "osd.active.label.text.font", &str) ||
902         read_string(db, "osd.label.text.font", &str))
903     {
904         char *p;
905         gint i = 0;
906         gint j;
907         if (strstr(str, "shadow=y")) {
908             if ((p = strstr(str, "shadowoffset=")))
909                 i = parse_inline_number(p + strlen("shadowoffset="));
910             else
911                 i = 1;
912             theme->osd_hilite_label->texture[0].data.text.shadow_offset_x = i;
913             theme->osd_hilite_label->texture[0].data.text.shadow_offset_y = i;
914         }
915         if ((p = strstr(str, "shadowtint=")))
916         {
917             i = parse_inline_number(p + strlen("shadowtint="));
918             j = (i > 0 ? 0 : 255);
919             i = ABS(i*255/100);
920
921             theme->osd_text_active_shadow_color = RrColorNew(inst, j, j, j);
922             theme->osd_text_active_shadow_alpha = i;
923         } else {
924             theme->osd_text_active_shadow_color = RrColorNew(inst, 0, 0, 0);
925             theme->osd_text_active_shadow_alpha = 50;
926         }
927     } else {
928         /* inherit the font settings from the focused label */
929         theme->osd_hilite_label->texture[0].data.text.shadow_offset_x =
930             theme->a_focused_label->texture[0].data.text.shadow_offset_x;
931         theme->osd_hilite_label->texture[0].data.text.shadow_offset_y =
932             theme->a_focused_label->texture[0].data.text.shadow_offset_y;
933         if (theme->title_focused_shadow_color)
934             theme->osd_text_active_shadow_color =
935                 RrColorNew(inst,
936                            theme->title_focused_shadow_color->r,
937                            theme->title_focused_shadow_color->g,
938                            theme->title_focused_shadow_color->b);
939         else
940             theme->osd_text_active_shadow_color = RrColorNew(inst, 0, 0, 0);
941         theme->osd_text_active_shadow_alpha =
942             theme->title_focused_shadow_alpha;
943     }
944
945     theme->osd_hilite_label->texture[0].data.text.shadow_color =
946         theme->osd_text_active_shadow_color;
947     theme->osd_hilite_label->texture[0].data.text.shadow_alpha =
948         theme->osd_text_active_shadow_alpha;
949
950     theme->a_unfocused_label->texture[0].type = RR_TEXTURE_TEXT;
951     theme->a_unfocused_label->texture[0].data.text.justify = winjust;
952     theme->a_unfocused_label->texture[0].data.text.font =
953         theme->win_font_unfocused;
954     theme->a_unfocused_label->texture[0].data.text.color =
955         theme->title_unfocused_color;
956
957     if (read_string(db, "window.inactive.label.text.font", &str)) {
958         char *p;
959         gint i = 0;
960         gint j;
961         if (strstr(str, "shadow=y")) {
962             if ((p = strstr(str, "shadowoffset=")))
963                 i = parse_inline_number(p + strlen("shadowoffset="));
964             else
965                 i = 1;
966             theme->a_unfocused_label->texture[0].data.text.shadow_offset_x = i;
967             theme->a_unfocused_label->texture[0].data.text.shadow_offset_y = i;
968         }
969         if ((p = strstr(str, "shadowtint=")))
970         {
971             i = parse_inline_number(p + strlen("shadowtint="));
972             j = (i > 0 ? 0 : 255);
973             i = ABS(i*255/100);
974
975             theme->title_unfocused_shadow_color = RrColorNew(inst, j, j, j);
976             theme->title_unfocused_shadow_alpha = i;
977         } else {
978             theme->title_unfocused_shadow_color = RrColorNew(inst, 0, 0, 0);
979             theme->title_unfocused_shadow_alpha = 50;
980         }
981     }
982
983     theme->a_unfocused_label->texture[0].data.text.shadow_color =
984         theme->title_unfocused_shadow_color;
985     theme->a_unfocused_label->texture[0].data.text.shadow_alpha =
986         theme->title_unfocused_shadow_alpha;
987
988     theme->osd_unhilite_label->texture[0].type = RR_TEXTURE_TEXT;
989     theme->osd_unhilite_label->texture[0].data.text.justify = RR_JUSTIFY_LEFT;
990     theme->osd_unhilite_label->texture[0].data.text.font =
991         theme->osd_font_unhilite;
992     theme->osd_unhilite_label->texture[0].data.text.color =
993         theme->osd_text_inactive_color;
994
995     if (read_string(db, "osd.inactive.label.text.font", &str))
996     {
997         char *p;
998         gint i = 0;
999         gint j;
1000         if (strstr(str, "shadow=y")) {
1001             if ((p = strstr(str, "shadowoffset=")))
1002                 i = parse_inline_number(p + strlen("shadowoffset="));
1003             else
1004                 i = 1;
1005             theme->osd_unhilite_label->texture[0].data.text.shadow_offset_x=i;
1006             theme->osd_unhilite_label->texture[0].data.text.shadow_offset_y=i;
1007         }
1008         if ((p = strstr(str, "shadowtint=")))
1009         {
1010             i = parse_inline_number(p + strlen("shadowtint="));
1011             j = (i > 0 ? 0 : 255);
1012             i = ABS(i*255/100);
1013
1014             theme->osd_text_inactive_shadow_color = RrColorNew(inst, j, j, j);
1015             theme->osd_text_inactive_shadow_alpha = i;
1016         } else {
1017             theme->osd_text_inactive_shadow_color = RrColorNew(inst, 0, 0, 0);
1018             theme->osd_text_inactive_shadow_alpha = 50;
1019         }
1020     } else {
1021         /* inherit the font settings from the unfocused label */
1022         theme->osd_unhilite_label->texture[0].data.text.shadow_offset_x =
1023             theme->a_unfocused_label->texture[0].data.text.shadow_offset_x;
1024         theme->osd_unhilite_label->texture[0].data.text.shadow_offset_y =
1025             theme->a_unfocused_label->texture[0].data.text.shadow_offset_y;
1026         if (theme->title_unfocused_shadow_color)
1027             theme->osd_text_inactive_shadow_color =
1028                 RrColorNew(inst,
1029                            theme->title_unfocused_shadow_color->r,
1030                            theme->title_unfocused_shadow_color->g,
1031                            theme->title_unfocused_shadow_color->b);
1032         else
1033             theme->osd_text_inactive_shadow_color = RrColorNew(inst, 0, 0, 0);
1034         theme->osd_text_inactive_shadow_alpha =
1035             theme->title_unfocused_shadow_alpha;
1036     }
1037
1038     theme->osd_unhilite_label->texture[0].data.text.shadow_color =
1039         theme->osd_text_inactive_shadow_color;
1040     theme->osd_unhilite_label->texture[0].data.text.shadow_alpha =
1041         theme->osd_text_inactive_shadow_alpha;
1042
1043     theme->a_menu_text_title->texture[0].type = RR_TEXTURE_TEXT;
1044     theme->a_menu_text_title->texture[0].data.text.justify = mtitlejust;
1045     theme->a_menu_text_title->texture[0].data.text.font =
1046         theme->menu_title_font;
1047     theme->a_menu_text_title->texture[0].data.text.color =
1048         theme->menu_title_color;
1049
1050     if (read_string(db, "menu.title.text.font", &str)) {
1051         char *p;
1052         gint i = 0;
1053         gint j;
1054         if (strstr(str, "shadow=y")) {
1055             if ((p = strstr(str, "shadowoffset=")))
1056                 i = parse_inline_number(p + strlen("shadowoffset="));
1057             else
1058                 i = 1;
1059             theme->a_menu_text_title->texture[0].data.text.shadow_offset_x = i;
1060             theme->a_menu_text_title->texture[0].data.text.shadow_offset_y = i;
1061         }
1062         if ((p = strstr(str, "shadowtint=")))
1063         {
1064             i = parse_inline_number(p + strlen("shadowtint="));
1065             j = (i > 0 ? 0 : 255);
1066             i = ABS(i*255/100);
1067
1068             theme->menu_title_shadow_color = RrColorNew(inst, j, j, j);
1069             theme->menu_title_shadow_alpha = i;
1070         } else {
1071             theme->menu_title_shadow_color = RrColorNew(inst, 0, 0, 0);
1072             theme->menu_title_shadow_alpha = 50;
1073         }
1074     }
1075
1076     theme->a_menu_text_title->texture[0].data.text.shadow_color =
1077         theme->menu_title_shadow_color;
1078     theme->a_menu_text_title->texture[0].data.text.shadow_alpha =
1079         theme->menu_title_shadow_alpha;
1080
1081     theme->a_menu_text_normal->texture[0].type =
1082         theme->a_menu_text_selected->texture[0].type =
1083         theme->a_menu_text_disabled->texture[0].type =
1084         theme->a_menu_text_disabled_selected->texture[0].type =
1085         RR_TEXTURE_TEXT;
1086     theme->a_menu_text_normal->texture[0].data.text.justify =
1087         theme->a_menu_text_selected->texture[0].data.text.justify =
1088         theme->a_menu_text_disabled->texture[0].data.text.justify =
1089         theme->a_menu_text_disabled_selected->texture[0].data.text.justify =
1090         RR_JUSTIFY_LEFT;
1091     theme->a_menu_text_normal->texture[0].data.text.font =
1092         theme->a_menu_text_selected->texture[0].data.text.font =
1093         theme->a_menu_text_disabled->texture[0].data.text.font =
1094         theme->a_menu_text_disabled_selected->texture[0].data.text.font =
1095         theme->menu_font;
1096     theme->a_menu_text_normal->texture[0].data.text.color = theme->menu_color;
1097     theme->a_menu_text_selected->texture[0].data.text.color =
1098         theme->menu_selected_color;
1099     theme->a_menu_text_disabled->texture[0].data.text.color =
1100         theme->menu_disabled_color;
1101     theme->a_menu_text_disabled_selected->texture[0].data.text.color =
1102         theme->menu_disabled_selected_color;
1103
1104     if (read_string(db, "menu.items.font", &str)) {
1105         char *p;
1106         gint i = 0;
1107         gint j;
1108         if (strstr(str, "shadow=y")) {
1109             if ((p = strstr(str, "shadowoffset=")))
1110                 i = parse_inline_number(p + strlen("shadowoffset="));
1111             else
1112                 i = 1;
1113             theme->a_menu_text_normal->
1114                 texture[0].data.text.shadow_offset_x = i;
1115             theme->a_menu_text_normal->
1116                 texture[0].data.text.shadow_offset_y = i;
1117             theme->a_menu_text_selected->
1118                 texture[0].data.text.shadow_offset_x = i;
1119             theme->a_menu_text_selected->
1120                 texture[0].data.text.shadow_offset_y = i;
1121             theme->a_menu_text_disabled->
1122                 texture[0].data.text.shadow_offset_x = i;
1123             theme->a_menu_text_disabled->
1124                 texture[0].data.text.shadow_offset_y = i;
1125             theme->a_menu_text_disabled_selected->
1126                 texture[0].data.text.shadow_offset_x = i;
1127             theme->a_menu_text_disabled_selected->
1128                 texture[0].data.text.shadow_offset_y = i;
1129         }
1130         if ((p = strstr(str, "shadowtint=")))
1131         {
1132             i = parse_inline_number(p + strlen("shadowtint="));
1133             j = (i > 0 ? 0 : 255);
1134             i = ABS(i*255/100);
1135
1136             theme->menu_text_normal_shadow_color = RrColorNew(inst, j, j, j);
1137             theme->menu_text_selected_shadow_color = RrColorNew(inst, j, j, j);
1138             theme->menu_text_disabled_shadow_color = RrColorNew(inst, j, j, j);
1139             theme->menu_text_normal_shadow_alpha = i;
1140             theme->menu_text_selected_shadow_alpha = i;
1141             theme->menu_text_disabled_shadow_alpha = i;
1142             theme->menu_text_disabled_selected_shadow_alpha = i;
1143         } else {
1144             theme->menu_text_normal_shadow_color = RrColorNew(inst, 0, 0, 0);
1145             theme->menu_text_selected_shadow_color = RrColorNew(inst, 0, 0, 0);
1146             theme->menu_text_disabled_shadow_color = RrColorNew(inst, 0, 0, 0);
1147             theme->menu_text_normal_shadow_alpha = 50;
1148             theme->menu_text_selected_shadow_alpha = 50;
1149             theme->menu_text_disabled_selected_shadow_alpha = 50;
1150         }
1151     }
1152
1153     theme->a_menu_text_normal->texture[0].data.text.shadow_color =
1154         theme->menu_text_normal_shadow_color;
1155     theme->a_menu_text_normal->texture[0].data.text.shadow_alpha =
1156         theme->menu_text_normal_shadow_alpha;
1157     theme->a_menu_text_selected->texture[0].data.text.shadow_color =
1158         theme->menu_text_selected_shadow_color;
1159     theme->a_menu_text_selected->texture[0].data.text.shadow_alpha =
1160         theme->menu_text_selected_shadow_alpha;
1161     theme->a_menu_text_disabled->texture[0].data.text.shadow_color =
1162         theme->menu_text_disabled_shadow_color;
1163     theme->a_menu_text_disabled->texture[0].data.text.shadow_alpha =
1164         theme->menu_text_disabled_shadow_alpha;
1165     theme->a_menu_text_disabled_selected->texture[0].data.text.shadow_color =
1166         theme->menu_text_disabled_shadow_color;
1167     theme->a_menu_text_disabled_selected->texture[0].data.text.shadow_alpha =
1168         theme->menu_text_disabled_shadow_alpha;
1169
1170     theme->a_disabled_focused_max->texture[0].type =
1171         theme->a_disabled_unfocused_max->texture[0].type =
1172         theme->a_hover_focused_max->texture[0].type =
1173         theme->a_hover_unfocused_max->texture[0].type =
1174         theme->a_toggled_hover_focused_max->texture[0].type =
1175         theme->a_toggled_hover_unfocused_max->texture[0].type =
1176         theme->a_toggled_focused_unpressed_max->texture[0].type =
1177         theme->a_toggled_unfocused_unpressed_max->texture[0].type =
1178         theme->a_toggled_focused_pressed_max->texture[0].type =
1179         theme->a_toggled_unfocused_pressed_max->texture[0].type =
1180         theme->a_focused_unpressed_max->texture[0].type =
1181         theme->a_focused_pressed_max->texture[0].type =
1182         theme->a_unfocused_unpressed_max->texture[0].type =
1183         theme->a_unfocused_pressed_max->texture[0].type =
1184         theme->a_disabled_focused_close->texture[0].type =
1185         theme->a_disabled_unfocused_close->texture[0].type =
1186         theme->a_hover_focused_close->texture[0].type =
1187         theme->a_hover_unfocused_close->texture[0].type =
1188         theme->a_focused_unpressed_close->texture[0].type =
1189         theme->a_focused_pressed_close->texture[0].type =
1190         theme->a_unfocused_unpressed_close->texture[0].type =
1191         theme->a_unfocused_pressed_close->texture[0].type =
1192         theme->a_disabled_focused_desk->texture[0].type =
1193         theme->a_disabled_unfocused_desk->texture[0].type =
1194         theme->a_hover_focused_desk->texture[0].type =
1195         theme->a_hover_unfocused_desk->texture[0].type =
1196         theme->a_toggled_hover_focused_desk->texture[0].type =
1197         theme->a_toggled_hover_unfocused_desk->texture[0].type =
1198         theme->a_toggled_focused_unpressed_desk->texture[0].type =
1199         theme->a_toggled_unfocused_unpressed_desk->texture[0].type =
1200         theme->a_toggled_focused_pressed_desk->texture[0].type =
1201         theme->a_toggled_unfocused_pressed_desk->texture[0].type =
1202         theme->a_focused_unpressed_desk->texture[0].type =
1203         theme->a_focused_pressed_desk->texture[0].type =
1204         theme->a_unfocused_unpressed_desk->texture[0].type =
1205         theme->a_unfocused_pressed_desk->texture[0].type =
1206         theme->a_disabled_focused_shade->texture[0].type =
1207         theme->a_disabled_unfocused_shade->texture[0].type =
1208         theme->a_hover_focused_shade->texture[0].type =
1209         theme->a_hover_unfocused_shade->texture[0].type =
1210         theme->a_toggled_hover_focused_shade->texture[0].type =
1211         theme->a_toggled_hover_unfocused_shade->texture[0].type =
1212         theme->a_toggled_focused_unpressed_shade->texture[0].type =
1213         theme->a_toggled_unfocused_unpressed_shade->texture[0].type =
1214         theme->a_toggled_focused_pressed_shade->texture[0].type =
1215         theme->a_toggled_unfocused_pressed_shade->texture[0].type =
1216         theme->a_focused_unpressed_shade->texture[0].type =
1217         theme->a_focused_pressed_shade->texture[0].type =
1218         theme->a_unfocused_unpressed_shade->texture[0].type =
1219         theme->a_unfocused_pressed_shade->texture[0].type =
1220         theme->a_disabled_focused_iconify->texture[0].type =
1221         theme->a_disabled_unfocused_iconify->texture[0].type =
1222         theme->a_hover_focused_iconify->texture[0].type =
1223         theme->a_hover_unfocused_iconify->texture[0].type =
1224         theme->a_focused_unpressed_iconify->texture[0].type =
1225         theme->a_focused_pressed_iconify->texture[0].type =
1226         theme->a_unfocused_unpressed_iconify->texture[0].type =
1227         theme->a_unfocused_pressed_iconify->texture[0].type =
1228         theme->a_menu_bullet_normal->texture[0].type =
1229         theme->a_menu_bullet_selected->texture[0].type = RR_TEXTURE_MASK;
1230
1231     theme->a_disabled_focused_max->texture[0].data.mask.mask =
1232         theme->a_disabled_unfocused_max->texture[0].data.mask.mask =
1233         theme->max_disabled_mask;
1234     theme->a_hover_focused_max->texture[0].data.mask.mask =
1235         theme->a_hover_unfocused_max->texture[0].data.mask.mask =
1236         theme->max_hover_mask;
1237     theme->a_focused_pressed_max->texture[0].data.mask.mask =
1238         theme->a_unfocused_pressed_max->texture[0].data.mask.mask =
1239         theme->max_pressed_mask;
1240     theme->a_focused_unpressed_max->texture[0].data.mask.mask =
1241         theme->a_unfocused_unpressed_max->texture[0].data.mask.mask =
1242         theme->max_mask;
1243     theme->a_toggled_hover_focused_max->texture[0].data.mask.mask =
1244         theme->a_toggled_hover_unfocused_max->texture[0].data.mask.mask =
1245         theme->max_toggled_hover_mask;
1246     theme->a_toggled_focused_unpressed_max->texture[0].data.mask.mask =
1247         theme->a_toggled_unfocused_unpressed_max->texture[0].data.mask.mask =
1248         theme->max_toggled_mask;
1249     theme->a_toggled_focused_pressed_max->texture[0].data.mask.mask =
1250         theme->a_toggled_unfocused_pressed_max->texture[0].data.mask.mask =
1251         theme->max_toggled_pressed_mask;
1252     theme->a_disabled_focused_close->texture[0].data.mask.mask =
1253         theme->a_disabled_unfocused_close->texture[0].data.mask.mask =
1254         theme->close_disabled_mask;
1255     theme->a_hover_focused_close->texture[0].data.mask.mask =
1256         theme->a_hover_unfocused_close->texture[0].data.mask.mask =
1257         theme->close_hover_mask;
1258     theme->a_focused_pressed_close->texture[0].data.mask.mask =
1259         theme->a_unfocused_pressed_close->texture[0].data.mask.mask =
1260         theme->close_pressed_mask;
1261     theme->a_focused_unpressed_close->texture[0].data.mask.mask =
1262         theme->a_unfocused_unpressed_close->texture[0].data.mask.mask =
1263         theme->close_mask;
1264     theme->a_disabled_focused_desk->texture[0].data.mask.mask =
1265         theme->a_disabled_unfocused_desk->texture[0].data.mask.mask =
1266         theme->desk_disabled_mask;
1267     theme->a_hover_focused_desk->texture[0].data.mask.mask =
1268         theme->a_hover_unfocused_desk->texture[0].data.mask.mask =
1269         theme->desk_hover_mask;
1270     theme->a_focused_pressed_desk->texture[0].data.mask.mask =
1271         theme->a_unfocused_pressed_desk->texture[0].data.mask.mask =
1272         theme->desk_pressed_mask;
1273     theme->a_focused_unpressed_desk->texture[0].data.mask.mask =
1274         theme->a_unfocused_unpressed_desk->texture[0].data.mask.mask =
1275         theme->desk_mask;
1276     theme->a_toggled_hover_focused_desk->texture[0].data.mask.mask =
1277         theme->a_toggled_hover_unfocused_desk->texture[0].data.mask.mask =
1278         theme->desk_toggled_hover_mask;
1279     theme->a_toggled_focused_unpressed_desk->texture[0].data.mask.mask =
1280         theme->a_toggled_unfocused_unpressed_desk->texture[0].data.mask.mask =
1281         theme->desk_toggled_mask;
1282     theme->a_toggled_focused_pressed_desk->texture[0].data.mask.mask =
1283         theme->a_toggled_unfocused_pressed_desk->texture[0].data.mask.mask =
1284         theme->desk_toggled_pressed_mask;
1285     theme->a_disabled_focused_shade->texture[0].data.mask.mask =
1286         theme->a_disabled_unfocused_shade->texture[0].data.mask.mask =
1287         theme->shade_disabled_mask;
1288     theme->a_hover_focused_shade->texture[0].data.mask.mask =
1289         theme->a_hover_unfocused_shade->texture[0].data.mask.mask =
1290         theme->shade_hover_mask;
1291     theme->a_focused_pressed_shade->texture[0].data.mask.mask =
1292         theme->a_unfocused_pressed_shade->texture[0].data.mask.mask =
1293         theme->shade_pressed_mask;
1294     theme->a_focused_unpressed_shade->texture[0].data.mask.mask =
1295         theme->a_unfocused_unpressed_shade->texture[0].data.mask.mask =
1296         theme->shade_mask;
1297     theme->a_toggled_hover_focused_shade->texture[0].data.mask.mask =
1298         theme->a_toggled_hover_unfocused_shade->texture[0].data.mask.mask =
1299         theme->shade_toggled_hover_mask;
1300     theme->a_toggled_focused_unpressed_shade->texture[0].data.mask.mask =
1301         theme->a_toggled_unfocused_unpressed_shade->texture[0].data.mask.mask =
1302         theme->shade_toggled_mask;
1303     theme->a_toggled_focused_pressed_shade->texture[0].data.mask.mask =
1304         theme->a_toggled_unfocused_pressed_shade->texture[0].data.mask.mask =
1305         theme->shade_toggled_pressed_mask;
1306     theme->a_disabled_focused_iconify->texture[0].data.mask.mask =
1307         theme->a_disabled_unfocused_iconify->texture[0].data.mask.mask =
1308         theme->iconify_disabled_mask;
1309     theme->a_hover_focused_iconify->texture[0].data.mask.mask =
1310         theme->a_hover_unfocused_iconify->texture[0].data.mask.mask =
1311         theme->iconify_hover_mask;
1312     theme->a_focused_pressed_iconify->texture[0].data.mask.mask =
1313         theme->a_unfocused_pressed_iconify->texture[0].data.mask.mask =
1314         theme->iconify_pressed_mask;
1315     theme->a_focused_unpressed_iconify->texture[0].data.mask.mask =
1316         theme->a_unfocused_unpressed_iconify->texture[0].data.mask.mask =
1317         theme->iconify_mask;
1318     theme->a_menu_bullet_normal->texture[0].data.mask.mask =
1319     theme->a_menu_bullet_selected->texture[0].data.mask.mask =
1320         theme->menu_bullet_mask;
1321     theme->a_disabled_focused_max->texture[0].data.mask.color =
1322         theme->a_disabled_focused_close->texture[0].data.mask.color =
1323         theme->a_disabled_focused_desk->texture[0].data.mask.color =
1324         theme->a_disabled_focused_shade->texture[0].data.mask.color =
1325         theme->a_disabled_focused_iconify->texture[0].data.mask.color =
1326         theme->titlebut_disabled_focused_color;
1327     theme->a_disabled_unfocused_max->texture[0].data.mask.color =
1328         theme->a_disabled_unfocused_close->texture[0].data.mask.color =
1329         theme->a_disabled_unfocused_desk->texture[0].data.mask.color =
1330         theme->a_disabled_unfocused_shade->texture[0].data.mask.color =
1331         theme->a_disabled_unfocused_iconify->texture[0].data.mask.color =
1332         theme->titlebut_disabled_unfocused_color;
1333     theme->a_hover_focused_max->texture[0].data.mask.color =
1334         theme->a_hover_focused_close->texture[0].data.mask.color =
1335         theme->a_hover_focused_desk->texture[0].data.mask.color =
1336         theme->a_hover_focused_shade->texture[0].data.mask.color =
1337         theme->a_hover_focused_iconify->texture[0].data.mask.color =
1338         theme->titlebut_hover_focused_color;
1339     theme->a_hover_unfocused_max->texture[0].data.mask.color =
1340         theme->a_hover_unfocused_close->texture[0].data.mask.color =
1341         theme->a_hover_unfocused_desk->texture[0].data.mask.color =
1342         theme->a_hover_unfocused_shade->texture[0].data.mask.color =
1343         theme->a_hover_unfocused_iconify->texture[0].data.mask.color =
1344         theme->titlebut_hover_unfocused_color;
1345     theme->a_toggled_hover_focused_max->texture[0].data.mask.color =
1346         theme->a_toggled_hover_focused_desk->texture[0].data.mask.color =
1347         theme->a_toggled_hover_focused_shade->texture[0].data.mask.color =
1348         theme->titlebut_toggled_hover_focused_color;
1349     theme->a_toggled_hover_unfocused_max->texture[0].data.mask.color =
1350         theme->a_toggled_hover_unfocused_desk->texture[0].data.mask.color =
1351         theme->a_toggled_hover_unfocused_shade->texture[0].data.mask.color =
1352         theme->titlebut_toggled_hover_unfocused_color;
1353     theme->a_toggled_focused_unpressed_max->texture[0].data.mask.color =
1354         theme->a_toggled_focused_unpressed_desk->texture[0].data.mask.color =
1355         theme->a_toggled_focused_unpressed_shade->texture[0].data.mask.color =
1356         theme->titlebut_toggled_focused_unpressed_color;
1357     theme->a_toggled_unfocused_unpressed_max->texture[0].data.mask.color =
1358         theme->a_toggled_unfocused_unpressed_desk->texture[0].data.mask.color =
1359         theme->a_toggled_unfocused_unpressed_shade->texture[0].data.mask.color=
1360         theme->titlebut_toggled_unfocused_unpressed_color;
1361     theme->a_toggled_focused_pressed_max->texture[0].data.mask.color =
1362         theme->a_toggled_focused_pressed_desk->texture[0].data.mask.color =
1363         theme->a_toggled_focused_pressed_shade->texture[0].data.mask.color =
1364         theme->titlebut_toggled_focused_pressed_color;
1365     theme->a_toggled_unfocused_pressed_max->texture[0].data.mask.color =
1366         theme->a_toggled_unfocused_pressed_desk->texture[0].data.mask.color =
1367         theme->a_toggled_unfocused_pressed_shade->texture[0].data.mask.color =
1368         theme->titlebut_toggled_unfocused_pressed_color;
1369     theme->a_focused_unpressed_max->texture[0].data.mask.color =
1370         theme->a_focused_unpressed_close->texture[0].data.mask.color =
1371         theme->a_focused_unpressed_desk->texture[0].data.mask.color =
1372         theme->a_focused_unpressed_shade->texture[0].data.mask.color =
1373         theme->a_focused_unpressed_iconify->texture[0].data.mask.color =
1374         theme->titlebut_focused_unpressed_color;
1375     theme->a_focused_pressed_max->texture[0].data.mask.color =
1376         theme->a_focused_pressed_close->texture[0].data.mask.color =
1377         theme->a_focused_pressed_desk->texture[0].data.mask.color =
1378         theme->a_focused_pressed_shade->texture[0].data.mask.color =
1379         theme->a_focused_pressed_iconify->texture[0].data.mask.color =
1380         theme->titlebut_focused_pressed_color;
1381     theme->a_unfocused_unpressed_max->texture[0].data.mask.color =
1382         theme->a_unfocused_unpressed_close->texture[0].data.mask.color =
1383         theme->a_unfocused_unpressed_desk->texture[0].data.mask.color =
1384         theme->a_unfocused_unpressed_shade->texture[0].data.mask.color =
1385         theme->a_unfocused_unpressed_iconify->texture[0].data.mask.color =
1386         theme->titlebut_unfocused_unpressed_color;
1387     theme->a_unfocused_pressed_max->texture[0].data.mask.color =
1388         theme->a_unfocused_pressed_close->texture[0].data.mask.color =
1389         theme->a_unfocused_pressed_desk->texture[0].data.mask.color =
1390         theme->a_unfocused_pressed_shade->texture[0].data.mask.color =
1391         theme->a_unfocused_pressed_iconify->texture[0].data.mask.color =
1392         theme->titlebut_unfocused_pressed_color;
1393     theme->a_menu_bullet_normal->texture[0].data.mask.color =
1394         theme->menu_color;
1395     theme->a_menu_bullet_selected->texture[0].data.mask.color =
1396         theme->menu_selected_color;
1397
1398     g_free(path);
1399     XrmDestroyDatabase(db);
1400
1401     /* set the font heights */
1402     theme->win_font_height = RrFontHeight
1403         (theme->win_font_focused,
1404          theme->a_focused_label->texture[0].data.text.shadow_offset_y);
1405     theme->win_font_height =
1406         MAX(theme->win_font_height,
1407             RrFontHeight
1408             (theme->win_font_focused,
1409              theme->a_unfocused_label->texture[0].data.text.shadow_offset_y));
1410     theme->menu_title_font_height = RrFontHeight
1411         (theme->menu_title_font,
1412          theme->a_menu_text_title->texture[0].data.text.shadow_offset_y);
1413     theme->menu_font_height = RrFontHeight
1414         (theme->menu_font,
1415          theme->a_menu_text_normal->texture[0].data.text.shadow_offset_y);
1416
1417     /* calculate some last extents */
1418     {
1419         gint ft, fb, fl, fr, ut, ub, ul, ur;
1420
1421         RrMargins(theme->a_focused_label, &fl, &ft, &fr, &fb);
1422         RrMargins(theme->a_unfocused_label, &ul, &ut, &ur, &ub);
1423         theme->label_height = theme->win_font_height + MAX(ft + fb, ut + ub);
1424         theme->label_height += theme->label_height % 2;
1425
1426         /* this would be nice I think, since padding.width can now be 0,
1427            but it breaks frame.c horribly and I don't feel like fixing that
1428            right now, so if anyone complains, here is how to keep text from
1429            going over the title's bevel/border with a padding.width of 0 and a
1430            bevelless/borderless label
1431            RrMargins(theme->a_focused_title, &fl, &ft, &fr, &fb);
1432            RrMargins(theme->a_unfocused_title, &ul, &ut, &ur, &ub);
1433            theme->title_height = theme->label_height +
1434            MAX(MAX(theme->padding * 2, ft + fb),
1435            MAX(theme->padding * 2, ut + ub));
1436         */
1437         theme->title_height = theme->label_height + theme->paddingy * 2;
1438
1439         RrMargins(theme->a_menu_title, &ul, &ut, &ur, &ub);
1440         theme->menu_title_label_height = theme->menu_title_font_height+ut+ub;
1441         theme->menu_title_height = theme->menu_title_label_height +
1442             theme->paddingy * 2;
1443     }
1444     theme->button_size = theme->label_height - 2;
1445     theme->grip_width = 25;
1446
1447     RrAppearanceFree(a_disabled_focused_tmp);
1448     RrAppearanceFree(a_disabled_unfocused_tmp);
1449     RrAppearanceFree(a_hover_focused_tmp);
1450     RrAppearanceFree(a_hover_unfocused_tmp);
1451     RrAppearanceFree(a_focused_unpressed_tmp);
1452     RrAppearanceFree(a_focused_pressed_tmp);
1453     RrAppearanceFree(a_unfocused_unpressed_tmp);
1454     RrAppearanceFree(a_unfocused_pressed_tmp);
1455     RrAppearanceFree(a_toggled_hover_focused_tmp);
1456     RrAppearanceFree(a_toggled_hover_unfocused_tmp);
1457     RrAppearanceFree(a_toggled_focused_unpressed_tmp);
1458     RrAppearanceFree(a_toggled_focused_pressed_tmp);
1459     RrAppearanceFree(a_toggled_unfocused_unpressed_tmp);
1460     RrAppearanceFree(a_toggled_unfocused_pressed_tmp);
1461
1462     return theme;
1463 }
1464
1465 void RrThemeFree(RrTheme *theme)
1466 {
1467     if (theme) {
1468         g_free(theme->name);
1469
1470         RrColorFree(theme->menu_border_color);
1471         RrColorFree(theme->osd_border_color);
1472         RrColorFree(theme->frame_focused_border_color);
1473         RrColorFree(theme->frame_unfocused_border_color);
1474         RrColorFree(theme->title_separator_focused_color);
1475         RrColorFree(theme->title_separator_unfocused_color);
1476         RrColorFree(theme->cb_unfocused_color);
1477         RrColorFree(theme->cb_focused_color);
1478         RrColorFree(theme->title_focused_color);
1479         RrColorFree(theme->title_unfocused_color);
1480         RrColorFree(theme->titlebut_disabled_focused_color);
1481         RrColorFree(theme->titlebut_disabled_unfocused_color);
1482         RrColorFree(theme->titlebut_hover_focused_color);
1483         RrColorFree(theme->titlebut_hover_unfocused_color);
1484         RrColorFree(theme->titlebut_toggled_hover_focused_color);
1485         RrColorFree(theme->titlebut_toggled_hover_unfocused_color);
1486         RrColorFree(theme->titlebut_toggled_focused_pressed_color);
1487         RrColorFree(theme->titlebut_toggled_unfocused_pressed_color);
1488         RrColorFree(theme->titlebut_toggled_focused_unpressed_color);
1489         RrColorFree(theme->titlebut_toggled_unfocused_unpressed_color);
1490         RrColorFree(theme->titlebut_focused_pressed_color);
1491         RrColorFree(theme->titlebut_unfocused_pressed_color);
1492         RrColorFree(theme->titlebut_focused_unpressed_color);
1493         RrColorFree(theme->titlebut_unfocused_unpressed_color);
1494         RrColorFree(theme->menu_title_color);
1495         RrColorFree(theme->menu_sep_color);
1496         RrColorFree(theme->menu_color);
1497         RrColorFree(theme->menu_selected_color);
1498         RrColorFree(theme->menu_disabled_color);
1499         RrColorFree(theme->menu_disabled_selected_color);
1500         RrColorFree(theme->title_focused_shadow_color);
1501         RrColorFree(theme->title_unfocused_shadow_color);
1502         RrColorFree(theme->osd_text_active_color);
1503         RrColorFree(theme->osd_text_inactive_color);
1504         RrColorFree(theme->osd_text_active_shadow_color);
1505         RrColorFree(theme->osd_text_inactive_shadow_color);
1506         RrColorFree(theme->menu_title_shadow_color);
1507         RrColorFree(theme->menu_text_normal_shadow_color);
1508         RrColorFree(theme->menu_text_selected_shadow_color);
1509         RrColorFree(theme->menu_text_disabled_shadow_color);
1510         RrColorFree(theme->menu_text_disabled_selected_shadow_color);
1511
1512         g_free(theme->def_win_icon);
1513
1514         RrPixmapMaskFree(theme->max_mask);
1515         RrPixmapMaskFree(theme->max_toggled_mask);
1516         RrPixmapMaskFree(theme->max_toggled_hover_mask);
1517         RrPixmapMaskFree(theme->max_toggled_pressed_mask);
1518         RrPixmapMaskFree(theme->max_disabled_mask);
1519         RrPixmapMaskFree(theme->max_hover_mask);
1520         RrPixmapMaskFree(theme->max_pressed_mask);
1521         RrPixmapMaskFree(theme->desk_mask);
1522         RrPixmapMaskFree(theme->desk_toggled_mask);
1523         RrPixmapMaskFree(theme->desk_toggled_hover_mask);
1524         RrPixmapMaskFree(theme->desk_toggled_pressed_mask);
1525         RrPixmapMaskFree(theme->desk_disabled_mask);
1526         RrPixmapMaskFree(theme->desk_hover_mask);
1527         RrPixmapMaskFree(theme->desk_pressed_mask);
1528         RrPixmapMaskFree(theme->shade_mask);
1529         RrPixmapMaskFree(theme->shade_toggled_mask);
1530         RrPixmapMaskFree(theme->shade_toggled_hover_mask);
1531         RrPixmapMaskFree(theme->shade_toggled_pressed_mask);
1532         RrPixmapMaskFree(theme->shade_disabled_mask);
1533         RrPixmapMaskFree(theme->shade_hover_mask);
1534         RrPixmapMaskFree(theme->shade_pressed_mask);
1535         RrPixmapMaskFree(theme->iconify_mask);
1536         RrPixmapMaskFree(theme->iconify_disabled_mask);
1537         RrPixmapMaskFree(theme->iconify_hover_mask);
1538         RrPixmapMaskFree(theme->iconify_pressed_mask);
1539         RrPixmapMaskFree(theme->close_mask);
1540         RrPixmapMaskFree(theme->close_disabled_mask);
1541         RrPixmapMaskFree(theme->close_hover_mask);
1542         RrPixmapMaskFree(theme->close_pressed_mask);
1543         RrPixmapMaskFree(theme->menu_bullet_mask);
1544         RrPixmapMaskFree(theme->down_arrow_mask);
1545         RrPixmapMaskFree(theme->up_arrow_mask);
1546
1547         RrFontClose(theme->win_font_focused);
1548         RrFontClose(theme->win_font_unfocused);
1549         RrFontClose(theme->menu_title_font);
1550         RrFontClose(theme->menu_font);
1551         RrFontClose(theme->osd_font_hilite);
1552         RrFontClose(theme->osd_font_unhilite);
1553
1554         RrAppearanceFree(theme->a_disabled_focused_max);
1555         RrAppearanceFree(theme->a_disabled_unfocused_max);
1556         RrAppearanceFree(theme->a_hover_focused_max);
1557         RrAppearanceFree(theme->a_hover_unfocused_max);
1558         RrAppearanceFree(theme->a_toggled_hover_focused_max);
1559         RrAppearanceFree(theme->a_toggled_hover_unfocused_max);
1560         RrAppearanceFree(theme->a_toggled_focused_unpressed_max);
1561         RrAppearanceFree(theme->a_toggled_focused_pressed_max);
1562         RrAppearanceFree(theme->a_toggled_unfocused_unpressed_max);
1563         RrAppearanceFree(theme->a_toggled_unfocused_pressed_max);
1564         RrAppearanceFree(theme->a_focused_unpressed_max);
1565         RrAppearanceFree(theme->a_focused_pressed_max);
1566         RrAppearanceFree(theme->a_unfocused_unpressed_max);
1567         RrAppearanceFree(theme->a_unfocused_pressed_max);
1568         RrAppearanceFree(theme->a_disabled_focused_close);
1569         RrAppearanceFree(theme->a_disabled_unfocused_close);
1570         RrAppearanceFree(theme->a_hover_focused_close);
1571         RrAppearanceFree(theme->a_hover_unfocused_close);
1572         RrAppearanceFree(theme->a_focused_unpressed_close);
1573         RrAppearanceFree(theme->a_focused_pressed_close);
1574         RrAppearanceFree(theme->a_unfocused_unpressed_close);
1575         RrAppearanceFree(theme->a_unfocused_pressed_close);
1576         RrAppearanceFree(theme->a_disabled_focused_desk);
1577         RrAppearanceFree(theme->a_disabled_unfocused_desk);
1578         RrAppearanceFree(theme->a_hover_focused_desk);
1579         RrAppearanceFree(theme->a_hover_unfocused_desk);
1580         RrAppearanceFree(theme->a_toggled_hover_focused_desk);
1581         RrAppearanceFree(theme->a_toggled_hover_unfocused_desk);
1582         RrAppearanceFree(theme->a_toggled_focused_unpressed_desk);
1583         RrAppearanceFree(theme->a_toggled_focused_pressed_desk);
1584         RrAppearanceFree(theme->a_toggled_unfocused_unpressed_desk);
1585         RrAppearanceFree(theme->a_toggled_unfocused_pressed_desk);
1586         RrAppearanceFree(theme->a_focused_unpressed_desk);
1587         RrAppearanceFree(theme->a_focused_pressed_desk);
1588         RrAppearanceFree(theme->a_unfocused_unpressed_desk);
1589         RrAppearanceFree(theme->a_unfocused_pressed_desk);
1590         RrAppearanceFree(theme->a_disabled_focused_shade);
1591         RrAppearanceFree(theme->a_disabled_unfocused_shade);
1592         RrAppearanceFree(theme->a_hover_focused_shade);
1593         RrAppearanceFree(theme->a_hover_unfocused_shade);
1594         RrAppearanceFree(theme->a_toggled_hover_focused_shade);
1595         RrAppearanceFree(theme->a_toggled_hover_unfocused_shade);
1596         RrAppearanceFree(theme->a_toggled_focused_unpressed_shade);
1597         RrAppearanceFree(theme->a_toggled_focused_pressed_shade);
1598         RrAppearanceFree(theme->a_toggled_unfocused_unpressed_shade);
1599         RrAppearanceFree(theme->a_toggled_unfocused_pressed_shade);
1600         RrAppearanceFree(theme->a_focused_unpressed_shade);
1601         RrAppearanceFree(theme->a_focused_pressed_shade);
1602         RrAppearanceFree(theme->a_unfocused_unpressed_shade);
1603         RrAppearanceFree(theme->a_unfocused_pressed_shade);
1604         RrAppearanceFree(theme->a_disabled_focused_iconify);
1605         RrAppearanceFree(theme->a_disabled_unfocused_iconify);
1606         RrAppearanceFree(theme->a_hover_focused_iconify);
1607         RrAppearanceFree(theme->a_hover_unfocused_iconify);
1608         RrAppearanceFree(theme->a_focused_unpressed_iconify);
1609         RrAppearanceFree(theme->a_focused_pressed_iconify);
1610         RrAppearanceFree(theme->a_unfocused_unpressed_iconify);
1611         RrAppearanceFree(theme->a_unfocused_pressed_iconify);
1612         RrAppearanceFree(theme->a_focused_grip);
1613         RrAppearanceFree(theme->a_unfocused_grip);
1614         RrAppearanceFree(theme->a_focused_title);
1615         RrAppearanceFree(theme->a_unfocused_title);
1616         RrAppearanceFree(theme->a_focused_label);
1617         RrAppearanceFree(theme->a_unfocused_label);
1618         RrAppearanceFree(theme->a_icon);
1619         RrAppearanceFree(theme->a_focused_handle);
1620         RrAppearanceFree(theme->a_unfocused_handle);
1621         RrAppearanceFree(theme->a_menu);
1622         RrAppearanceFree(theme->a_menu_title);
1623         RrAppearanceFree(theme->a_menu_text_title);
1624         RrAppearanceFree(theme->a_menu_normal);
1625         RrAppearanceFree(theme->a_menu_selected);
1626         RrAppearanceFree(theme->a_menu_disabled);
1627         RrAppearanceFree(theme->a_menu_disabled_selected);
1628         RrAppearanceFree(theme->a_menu_text_normal);
1629         RrAppearanceFree(theme->a_menu_text_selected);
1630         RrAppearanceFree(theme->a_menu_text_disabled);
1631         RrAppearanceFree(theme->a_menu_text_disabled_selected);
1632         RrAppearanceFree(theme->a_menu_bullet_normal);
1633         RrAppearanceFree(theme->a_menu_bullet_selected);
1634         RrAppearanceFree(theme->a_clear);
1635         RrAppearanceFree(theme->a_clear_tex);
1636         RrAppearanceFree(theme->osd_bg);
1637         RrAppearanceFree(theme->osd_hilite_bg);
1638         RrAppearanceFree(theme->osd_hilite_label);
1639         RrAppearanceFree(theme->osd_unhilite_bg);
1640         RrAppearanceFree(theme->osd_unhilite_label);
1641
1642         g_slice_free(RrTheme, theme);
1643     }
1644 }
1645
1646 static XrmDatabase loaddb(const gchar *name, gchar **path)
1647 {
1648     GSList *it;
1649     XrmDatabase db = NULL;
1650     gchar *s;
1651
1652     if (name[0] == '/') {
1653         s = g_build_filename(name, "openbox-3", "themerc", NULL);
1654         if ((db = XrmGetFileDatabase(s)))
1655             *path = g_path_get_dirname(s);
1656         g_free(s);
1657     } else {
1658         ObtPaths *p;
1659
1660         p = obt_paths_new();
1661
1662         /* XXX backwards compatibility, remove me sometime later */
1663         s = g_build_filename(g_get_home_dir(), ".themes", name,
1664                              "openbox-3", "themerc", NULL);
1665         if ((db = XrmGetFileDatabase(s)))
1666             *path = g_path_get_dirname(s);
1667         g_free(s);
1668
1669         for (it = obt_paths_data_dirs(p); !db && it; it = g_slist_next(it))
1670         {
1671             s = g_build_filename(it->data, "themes", name,
1672                                  "openbox-3", "themerc", NULL);
1673             if ((db = XrmGetFileDatabase(s)))
1674                 *path = g_path_get_dirname(s);
1675             g_free(s);
1676         }
1677
1678         obt_paths_unref(p);
1679     }
1680
1681     if (db == NULL) {
1682         s = g_build_filename(name, "themerc", NULL);
1683         if ((db = XrmGetFileDatabase(s)))
1684             *path = g_path_get_dirname(s);
1685         g_free(s);
1686     }
1687
1688     return db;
1689 }
1690
1691 static gchar *create_class_name(const gchar *rname)
1692 {
1693     gchar *rclass = g_strdup(rname);
1694     gchar *p = rclass;
1695
1696     while (TRUE) {
1697         *p = toupper(*p);
1698         p = strchr(p+1, '.');
1699         if (p == NULL) break;
1700         ++p;
1701         if (*p == '\0') break;
1702     }
1703     return rclass;
1704 }
1705
1706 static gboolean read_int(XrmDatabase db, const gchar *rname, gint *value)
1707 {
1708     gboolean ret = FALSE;
1709     gchar *rclass = create_class_name(rname);
1710     gchar *rettype, *end;
1711     XrmValue retvalue;
1712
1713     if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
1714         retvalue.addr != NULL) {
1715         *value = (gint)strtol(retvalue.addr, &end, 10);
1716         if (end != retvalue.addr)
1717             ret = TRUE;
1718     }
1719
1720     g_free(rclass);
1721     return ret;
1722 }
1723
1724 static gboolean read_string(XrmDatabase db, const gchar *rname, gchar **value)
1725 {
1726     gboolean ret = FALSE;
1727     gchar *rclass = create_class_name(rname);
1728     gchar *rettype;
1729     XrmValue retvalue;
1730
1731     if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
1732         retvalue.addr != NULL) {
1733         *value = retvalue.addr;
1734         ret = TRUE;
1735     }
1736
1737     g_free(rclass);
1738     return ret;
1739 }
1740
1741 static gboolean read_color(XrmDatabase db, const RrInstance *inst,
1742                            const gchar *rname, RrColor **value)
1743 {
1744     gboolean ret = FALSE;
1745     gchar *rclass = create_class_name(rname);
1746     gchar *rettype;
1747     XrmValue retvalue;
1748
1749     if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
1750         retvalue.addr != NULL) {
1751         RrColor *c = RrColorParse(inst, retvalue.addr);
1752         if (c != NULL) {
1753             *value = c;
1754             ret = TRUE;
1755         }
1756     }
1757
1758     g_free(rclass);
1759     return ret;
1760 }
1761
1762 static gboolean read_mask(const RrInstance *inst, const gchar *path,
1763                           RrTheme *theme, const gchar *maskname,
1764                           RrPixmapMask **value)
1765 {
1766     gboolean ret = FALSE;
1767     gchar *s;
1768     gint hx, hy; /* ignored */
1769     guint w, h;
1770     guchar *b;
1771
1772     s = g_build_filename(path, maskname, NULL);
1773     if (XReadBitmapFileData(s, &w, &h, &b, &hx, &hy) == BitmapSuccess) {
1774         ret = TRUE;
1775         *value = RrPixmapMaskNew(inst, w, h, (gchar*)b);
1776         XFree(b);
1777     }
1778     g_free(s);
1779
1780     return ret;
1781 }
1782
1783 static void parse_appearance(gchar *tex, RrSurfaceColorType *grad,
1784                              RrReliefType *relief, RrBevelType *bevel,
1785                              gboolean *interlaced, gboolean *border,
1786                              gboolean allow_trans)
1787 {
1788     gchar *t;
1789
1790     /* convert to all lowercase */
1791     for (t = tex; *t != '\0'; ++t)
1792         *t = g_ascii_tolower(*t);
1793
1794     if (allow_trans && strstr(tex, "parentrelative") != NULL) {
1795         *grad = RR_SURFACE_PARENTREL;
1796     } else {
1797         if (strstr(tex, "gradient") != NULL) {
1798             if (strstr(tex, "crossdiagonal") != NULL)
1799                 *grad = RR_SURFACE_CROSS_DIAGONAL;
1800             else if (strstr(tex, "pyramid") != NULL)
1801                 *grad = RR_SURFACE_PYRAMID;
1802             else if (strstr(tex, "mirrorhorizontal") != NULL)
1803                 *grad = RR_SURFACE_MIRROR_HORIZONTAL;
1804             else if (strstr(tex, "horizontal") != NULL)
1805                 *grad = RR_SURFACE_HORIZONTAL;
1806             else if (strstr(tex, "splitvertical") != NULL)
1807                 *grad = RR_SURFACE_SPLIT_VERTICAL;
1808             else if (strstr(tex, "vertical") != NULL)
1809                 *grad = RR_SURFACE_VERTICAL;
1810             else
1811                 *grad = RR_SURFACE_DIAGONAL;
1812         } else {
1813             *grad = RR_SURFACE_SOLID;
1814         }
1815     }
1816
1817     if (strstr(tex, "sunken") != NULL)
1818         *relief = RR_RELIEF_SUNKEN;
1819     else if (strstr(tex, "flat") != NULL)
1820         *relief = RR_RELIEF_FLAT;
1821     else if (strstr(tex, "raised") != NULL)
1822         *relief = RR_RELIEF_RAISED;
1823     else
1824         *relief = (*grad == RR_SURFACE_PARENTREL) ?
1825                   RR_RELIEF_FLAT : RR_RELIEF_RAISED;
1826
1827     *border = FALSE;
1828     if (*relief == RR_RELIEF_FLAT) {
1829         if (strstr(tex, "border") != NULL)
1830             *border = TRUE;
1831     } else {
1832         if (strstr(tex, "bevel2") != NULL)
1833             *bevel = RR_BEVEL_2;
1834         else
1835             *bevel = RR_BEVEL_1;
1836     }
1837
1838     if (strstr(tex, "interlaced") != NULL)
1839         *interlaced = TRUE;
1840     else
1841         *interlaced = FALSE;
1842 }
1843
1844 static gboolean read_appearance(XrmDatabase db, const RrInstance *inst,
1845                                 const gchar *rname, RrAppearance *value,
1846                                 gboolean allow_trans)
1847 {
1848     gboolean ret = FALSE;
1849     gchar *rclass = create_class_name(rname);
1850     gchar *cname, *ctoname, *bcname, *icname, *hname, *sname;
1851     gchar *csplitname, *ctosplitname;
1852     gchar *rettype;
1853     XrmValue retvalue;
1854     gint i;
1855
1856     cname = g_strconcat(rname, ".color", NULL);
1857     ctoname = g_strconcat(rname, ".colorTo", NULL);
1858     bcname = g_strconcat(rname, ".border.color", NULL);
1859     icname = g_strconcat(rname, ".interlace.color", NULL);
1860     hname = g_strconcat(rname, ".highlight", NULL);
1861     sname = g_strconcat(rname, ".shadow", NULL);
1862     csplitname = g_strconcat(rname, ".color.splitTo", NULL);
1863     ctosplitname = g_strconcat(rname, ".colorTo.splitTo", NULL);
1864
1865     if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
1866         retvalue.addr != NULL) {
1867         parse_appearance(retvalue.addr,
1868                          &value->surface.grad,
1869                          &value->surface.relief,
1870                          &value->surface.bevel,
1871                          &value->surface.interlaced,
1872                          &value->surface.border,
1873                          allow_trans);
1874         if (!read_color(db, inst, cname, &value->surface.primary))
1875             value->surface.primary = RrColorNew(inst, 0, 0, 0);
1876         if (!read_color(db, inst, ctoname, &value->surface.secondary))
1877             value->surface.secondary = RrColorNew(inst, 0, 0, 0);
1878         if (value->surface.border)
1879             if (!read_color(db, inst, bcname,
1880                             &value->surface.border_color))
1881                 value->surface.border_color = RrColorNew(inst, 0, 0, 0);
1882         if (value->surface.interlaced)
1883             if (!read_color(db, inst, icname,
1884                             &value->surface.interlace_color))
1885                 value->surface.interlace_color = RrColorNew(inst, 0, 0, 0);
1886         if (read_int(db, hname, &i) && i >= 0)
1887             value->surface.bevel_light_adjust = i;
1888         if (read_int(db, sname, &i) && i >= 0 && i <= 256)
1889             value->surface.bevel_dark_adjust = i;
1890
1891         if (value->surface.grad == RR_SURFACE_SPLIT_VERTICAL) {
1892             gint r, g, b;
1893
1894             if (!read_color(db, inst, csplitname,
1895                             &value->surface.split_primary))
1896             {
1897                 r = value->surface.primary->r;
1898                 r += r >> 2;
1899                 g = value->surface.primary->g;
1900                 g += g >> 2;
1901                 b = value->surface.primary->b;
1902                 b += b >> 2;
1903                 if (r > 0xFF) r = 0xFF;
1904                 if (g > 0xFF) g = 0xFF;
1905                 if (b > 0xFF) b = 0xFF;
1906                 value->surface.split_primary = RrColorNew(inst, r, g, b);
1907             }
1908
1909             if (!read_color(db, inst, ctosplitname,
1910                             &value->surface.split_secondary))
1911             {
1912                 r = value->surface.secondary->r;
1913                 r += r >> 4;
1914                 g = value->surface.secondary->g;
1915                 g += g >> 4;
1916                 b = value->surface.secondary->b;
1917                 b += b >> 4;
1918                 if (r > 0xFF) r = 0xFF;
1919                 if (g > 0xFF) g = 0xFF;
1920                 if (b > 0xFF) b = 0xFF;
1921                 value->surface.split_secondary = RrColorNew(inst, r, g, b);
1922             }
1923         }
1924
1925         ret = TRUE;
1926     }
1927
1928     g_free(ctosplitname);
1929     g_free(csplitname);
1930     g_free(sname);
1931     g_free(hname);
1932     g_free(icname);
1933     g_free(bcname);
1934     g_free(ctoname);
1935     g_free(cname);
1936     g_free(rclass);
1937     return ret;
1938 }
1939
1940 static int parse_inline_number(const char *p)
1941 {
1942     int neg = 1;
1943     int res = 0;
1944     if (*p == '-') {
1945         neg = -1;
1946         ++p;
1947     }
1948     for (; isdigit(*p); ++p)
1949         res = res * 10 + *p - '0';
1950     res *= neg;
1951     return res;
1952 }
1953
1954 static void set_default_appearance(RrAppearance *a)
1955 {
1956     a->surface.grad = RR_SURFACE_SOLID;
1957     a->surface.relief = RR_RELIEF_FLAT;
1958     a->surface.bevel = RR_BEVEL_1;
1959     a->surface.interlaced = FALSE;
1960     a->surface.border = FALSE;
1961     a->surface.primary = RrColorNew(a->inst, 0, 0, 0);
1962     a->surface.secondary = RrColorNew(a->inst, 0, 0, 0);
1963 }
1964
1965 /* Reads the output from gimp's C-Source file format into valid RGBA data for
1966    an RrTextureRGBA. */
1967 static RrPixel32* read_c_image(gint width, gint height, const guint8 *data)
1968 {
1969     RrPixel32 *im, *p;
1970     gint i;
1971
1972     p = im = g_memdup(data, width * height * sizeof(RrPixel32));
1973
1974     for (i = 0; i < width * height; ++i) {
1975         guchar a = ((*p >> 24) & 0xff);
1976         guchar b = ((*p >> 16) & 0xff);
1977         guchar g = ((*p >>  8) & 0xff);
1978         guchar r = ((*p >>  0) & 0xff);
1979
1980         *p = ((r << RrDefaultRedOffset) +
1981               (g << RrDefaultGreenOffset) +
1982               (b << RrDefaultBlueOffset) +
1983               (a << RrDefaultAlphaOffset));
1984         p++;
1985     }
1986
1987     return im;
1988 }