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