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