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