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