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