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