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