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