]> icculus.org git repositories - mikachu/openbox.git/blob - render/theme.c
node processing code/macros, and other fixes
[mikachu/openbox.git] / render / theme.c
1 #include "render.h"
2 #include "color.h"
3 #include "font.h"
4 #include "mask.h"
5
6 #include <X11/Xlib.h>
7 #include <X11/Xresource.h>
8
9 /* style settings - geometry */
10 int theme_bevel;
11 int theme_handle_height;
12 int theme_bwidth;
13 int theme_cbwidth;
14 /* style settings - colors */
15 color_rgb *theme_b_color;
16 color_rgb *theme_cb_focused_color;
17 color_rgb *theme_cb_unfocused_color;
18 color_rgb *theme_title_focused_color;
19 color_rgb *theme_title_unfocused_color;
20 color_rgb *theme_titlebut_focused_color;
21 color_rgb *theme_titlebut_unfocused_color;
22 /* style settings - fonts */
23 int theme_winfont_height;
24 ObFont *theme_winfont;
25 gboolean theme_winfont_shadow;
26 int theme_winfont_shadow_offset;
27 int theme_winfont_shadow_tint;
28 /* style settings - title layout */
29 char *theme_title_layout;
30 /* style settings - masks */
31 pixmap_mask *theme_max_set_mask;
32 pixmap_mask *theme_max_unset_mask;
33 pixmap_mask *theme_iconify_mask;
34 pixmap_mask *theme_desk_set_mask;
35 pixmap_mask *theme_desk_unset_mask;
36 pixmap_mask *theme_shade_set_mask;
37 pixmap_mask *theme_shade_unset_mask;
38 pixmap_mask *theme_close_mask;
39
40 /* global appearances */
41 Appearance *theme_a_focused_unpressed_max;
42 Appearance *theme_a_focused_pressed_max;
43 Appearance *theme_a_focused_pressed_set_max;
44 Appearance *theme_a_unfocused_unpressed_max;
45 Appearance *theme_a_unfocused_pressed_max;
46 Appearance *theme_a_unfocused_pressed_set_max;
47 Appearance *theme_a_focused_unpressed_close;
48 Appearance *theme_a_focused_pressed_close;
49 Appearance *theme_a_unfocused_unpressed_close;
50 Appearance *theme_a_unfocused_pressed_close;
51 Appearance *theme_a_focused_unpressed_desk;
52 Appearance *theme_a_focused_pressed_desk;
53 Appearance *theme_a_focused_pressed_set_desk;
54 Appearance *theme_a_unfocused_unpressed_desk;
55 Appearance *theme_a_unfocused_pressed_desk;
56 Appearance *theme_a_unfocused_pressed_set_desk;
57 Appearance *theme_a_focused_unpressed_shade;
58 Appearance *theme_a_focused_pressed_shade;
59 Appearance *theme_a_focused_pressed_set_shade;
60 Appearance *theme_a_unfocused_unpressed_shade;
61 Appearance *theme_a_unfocused_pressed_shade;
62 Appearance *theme_a_unfocused_pressed_set_shade;
63 Appearance *theme_a_focused_unpressed_iconify;
64 Appearance *theme_a_focused_pressed_iconify;
65 Appearance *theme_a_unfocused_unpressed_iconify;
66 Appearance *theme_a_unfocused_pressed_iconify;
67 Appearance *theme_a_focused_grip;
68 Appearance *theme_a_unfocused_grip;
69 Appearance *theme_a_focused_title;
70 Appearance *theme_a_unfocused_title;
71 Appearance *theme_a_focused_label;
72 Appearance *theme_a_unfocused_label;
73 Appearance *theme_a_icon; /* always parentrelative, so no focused/unfocused */
74 Appearance *theme_a_focused_handle;
75 Appearance *theme_a_unfocused_handle;
76
77 Appearance *theme_app_hilite_label;
78 Appearance *theme_app_unhilite_label;
79
80 void theme_startup()
81 {
82     theme_b_color = theme_cb_unfocused_color = theme_cb_focused_color = 
83         theme_title_unfocused_color = theme_title_focused_color = 
84         theme_titlebut_unfocused_color = theme_titlebut_focused_color = NULL;
85     theme_winfont = NULL;
86     theme_title_layout = NULL;
87     theme_max_set_mask = theme_max_unset_mask = NULL;
88     theme_desk_set_mask = theme_desk_unset_mask = NULL;
89     theme_shade_set_mask = theme_shade_unset_mask = NULL;
90     theme_iconify_mask = theme_close_mask = NULL;
91
92     theme_a_focused_unpressed_max = appearance_new(Surface_Planar, 1);
93     theme_a_focused_pressed_max = appearance_new(Surface_Planar, 1);
94     theme_a_focused_pressed_set_max = appearance_new(Surface_Planar, 1);
95     theme_a_unfocused_unpressed_max = appearance_new(Surface_Planar, 1);
96     theme_a_unfocused_pressed_max = appearance_new(Surface_Planar, 1);
97     theme_a_unfocused_pressed_set_max = appearance_new(Surface_Planar, 1);
98     theme_a_focused_unpressed_close = NULL;
99     theme_a_focused_pressed_close = NULL;
100     theme_a_unfocused_unpressed_close = NULL;
101     theme_a_unfocused_pressed_close = NULL;
102     theme_a_focused_unpressed_desk = NULL;
103     theme_a_focused_pressed_desk = NULL;
104     theme_a_focused_pressed_set_desk = NULL;
105     theme_a_unfocused_unpressed_desk = NULL;
106     theme_a_unfocused_pressed_desk = NULL;
107     theme_a_unfocused_pressed_set_desk = NULL;
108     theme_a_focused_unpressed_shade = NULL;
109     theme_a_focused_pressed_shade = NULL;
110     theme_a_focused_pressed_set_shade = NULL;
111     theme_a_unfocused_unpressed_shade = NULL;
112     theme_a_unfocused_pressed_shade = NULL;
113     theme_a_unfocused_pressed_set_shade = NULL;
114     theme_a_focused_unpressed_iconify = NULL;
115     theme_a_focused_pressed_iconify = NULL;
116     theme_a_unfocused_unpressed_iconify = NULL;
117     theme_a_unfocused_pressed_iconify = NULL;
118     theme_a_focused_grip = appearance_new(Surface_Planar, 0);
119     theme_a_unfocused_grip = appearance_new(Surface_Planar, 0);
120     theme_a_focused_title = appearance_new(Surface_Planar, 0);
121     theme_a_unfocused_title = appearance_new(Surface_Planar, 0);
122     theme_a_focused_label = appearance_new(Surface_Planar, 1);
123     theme_a_unfocused_label = appearance_new(Surface_Planar, 1);
124     theme_a_icon = appearance_new(Surface_Planar, 1);
125     theme_a_focused_handle = appearance_new(Surface_Planar, 0);
126     theme_a_unfocused_handle = appearance_new(Surface_Planar, 0);
127     theme_app_hilite_label = appearance_new(Surface_Planar, 1);
128     theme_app_unhilite_label = appearance_new(Surface_Planar, 1);
129
130 }
131
132 void theme_shutdown()
133 {
134     color_free(theme_b_color);
135     color_free(theme_cb_unfocused_color);
136     color_free(theme_cb_focused_color);
137     color_free(theme_title_unfocused_color);
138     color_free(theme_title_focused_color);
139     color_free(theme_titlebut_unfocused_color);
140     color_free(theme_titlebut_focused_color);
141
142     pixmap_mask_free(theme_max_set_mask);
143     pixmap_mask_free(theme_max_unset_mask);
144     pixmap_mask_free(theme_desk_set_mask);
145     pixmap_mask_free(theme_desk_unset_mask);
146     pixmap_mask_free(theme_shade_set_mask);
147     pixmap_mask_free(theme_shade_unset_mask);
148     pixmap_mask_free(theme_iconify_mask);
149     pixmap_mask_free(theme_close_mask);
150
151     font_close(theme_winfont);
152     g_free(theme_title_layout);
153
154     appearance_free(theme_a_focused_unpressed_max);
155     appearance_free(theme_a_focused_pressed_max);
156     appearance_free(theme_a_focused_pressed_set_max);
157     appearance_free(theme_a_unfocused_unpressed_max);
158     appearance_free(theme_a_unfocused_pressed_max);
159     appearance_free(theme_a_unfocused_pressed_set_max);
160     appearance_free(theme_a_focused_unpressed_close);
161     appearance_free(theme_a_focused_pressed_close);
162     appearance_free(theme_a_unfocused_unpressed_close);
163     appearance_free(theme_a_unfocused_pressed_close);
164     appearance_free(theme_a_focused_unpressed_desk);
165     appearance_free(theme_a_focused_pressed_desk);
166     appearance_free(theme_a_unfocused_unpressed_desk);
167     appearance_free(theme_a_unfocused_pressed_desk);
168     appearance_free(theme_a_focused_unpressed_shade);
169     appearance_free(theme_a_focused_pressed_shade);
170     appearance_free(theme_a_unfocused_unpressed_shade);
171     appearance_free(theme_a_unfocused_pressed_shade);
172     appearance_free(theme_a_focused_unpressed_iconify);
173     appearance_free(theme_a_focused_pressed_iconify);
174     appearance_free(theme_a_unfocused_unpressed_iconify);
175     appearance_free(theme_a_unfocused_pressed_iconify);
176     appearance_free(theme_a_focused_grip);
177     appearance_free(theme_a_unfocused_grip);
178     appearance_free(theme_a_focused_title);
179     appearance_free(theme_a_unfocused_title);
180     appearance_free(theme_a_focused_label);
181     appearance_free(theme_a_unfocused_label);
182     appearance_free(theme_a_icon);
183     appearance_free(theme_a_focused_handle);
184     appearance_free(theme_a_unfocused_handle);
185     appearance_free(theme_app_hilite_label);
186     appearance_free(theme_app_unhilite_label);
187 }
188
189 static XrmDatabase loaddb(char *theme)
190 {
191     XrmDatabase db;
192
193     db = XrmGetFileDatabase(theme);
194     if (db == NULL) {
195         char *s = g_build_filename(g_get_home_dir(), ".openbox", "themes",
196                                    theme, NULL);
197         db = XrmGetFileDatabase(s);
198         g_free(s);
199     }
200     if (db == NULL) {
201         char *s = g_build_filename(THEMEDIR, theme, NULL);
202         db = XrmGetFileDatabase(s);
203         g_free(s);
204     }
205     return db;
206 }
207
208 static char *create_class_name(char *rname)
209 {
210     char *rclass = g_strdup(rname);
211     char *p = rclass;
212
213     while (TRUE) {
214         *p = toupper(*p);
215         p = strchr(p+1, '.');
216         if (p == NULL) break;
217         ++p;
218         if (*p == '\0') break;
219     }
220     return rclass;
221 }
222
223 static gboolean read_int(XrmDatabase db, char *rname, int *value)
224 {
225     gboolean ret = FALSE;
226     char *rclass = create_class_name(rname);
227     char *rettype, *end;
228     XrmValue retvalue;
229   
230     if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
231         retvalue.addr != NULL) {
232         *value = (int)strtol(retvalue.addr, &end, 10);
233         if (end != retvalue.addr)
234             ret = TRUE;
235     }
236
237     g_free(rclass);
238     return ret;
239 }
240
241 static gboolean read_string(XrmDatabase db, char *rname, char **value)
242 {
243     gboolean ret = FALSE;
244     char *rclass = create_class_name(rname);
245     char *rettype;
246     XrmValue retvalue;
247   
248     if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
249         retvalue.addr != NULL) {
250         *value = g_strdup(retvalue.addr);
251         ret = TRUE;
252     }
253
254     g_free(rclass);
255     return ret;
256 }
257
258 static gboolean read_color(XrmDatabase db, char *rname, color_rgb **value)
259 {
260     gboolean ret = FALSE;
261     char *rclass = create_class_name(rname);
262     char *rettype;
263     XrmValue retvalue;
264   
265     if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
266         retvalue.addr != NULL) {
267         color_rgb *c = color_parse(retvalue.addr);
268         if (c != NULL) {
269             *value = c;
270             ret = TRUE;
271         }
272     }
273
274     g_free(rclass);
275     return ret;
276 }
277
278 static gboolean read_mask(XrmDatabase db, char *rname, char *theme,
279                           pixmap_mask **value)
280 {
281     gboolean ret = FALSE;
282     char *rclass = create_class_name(rname);
283     char *rettype;
284     char *s;
285     char *button_dir;
286     XrmValue retvalue;
287     int hx, hy; /* ignored */
288     unsigned int w, h;
289     unsigned char *b;
290   
291     if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
292         retvalue.addr != NULL) {
293
294         button_dir = g_strdup_printf("%s_buttons", theme);
295
296         s = g_build_filename(g_get_home_dir(), ".openbox", "themes",
297                              button_dir, retvalue.addr, NULL);
298
299         if (XReadBitmapFileData(s, &w, &h, &b, &hx, &hy) == BitmapSuccess)
300             ret = TRUE;
301         else {
302             g_free(s);
303             s = g_build_filename(THEMEDIR, button_dir, retvalue.addr, NULL);
304         
305             if (XReadBitmapFileData(s, &w, &h, &b, &hx, &hy) == BitmapSuccess) 
306                 ret = TRUE;
307             else {
308                 char *themename;
309
310                 g_free(s);
311                 themename = g_path_get_basename(theme);
312                 s = g_strdup_printf("%s/%s_buttons/%s", theme,
313                                     themename, retvalue.addr);
314                 g_free(themename);
315                 if (XReadBitmapFileData(s, &w, &h, &b, &hx, &hy) ==
316                     BitmapSuccess) 
317                     ret = TRUE;
318                 else
319                     g_message("Unable to find bitmap '%s'", retvalue.addr);
320             }
321         }
322
323         if (ret) {
324             *value = pixmap_mask_new(w, h, (char*)b);
325             XFree(b);
326         }
327       
328         g_free(s);
329         g_free(button_dir);
330     }
331
332     g_free(rclass);
333     return ret;
334 }
335
336 static void parse_appearance(char *tex, SurfaceColorType *grad,
337                              ReliefType *relief, BevelType *bevel,
338                              gboolean *interlaced, gboolean *border)
339 {
340     char *t;
341
342     /* convert to all lowercase */
343     for (t = tex; *t != '\0'; ++t)
344         *t = g_ascii_tolower(*t);
345
346     if (strstr(tex, "parentrelative") != NULL) {
347         *grad = Background_ParentRelative;
348     } else {
349         if (strstr(tex, "gradient") != NULL) {
350             if (strstr(tex, "crossdiagonal") != NULL)
351                 *grad = Background_CrossDiagonal;
352             else if (strstr(tex, "rectangle") != NULL)
353                 *grad = Background_Rectangle;
354             else if (strstr(tex, "pyramid") != NULL)
355                 *grad = Background_Pyramid;
356             else if (strstr(tex, "pipecross") != NULL)
357                 *grad = Background_PipeCross;
358             else if (strstr(tex, "elliptic") != NULL)
359                 *grad = Background_Elliptic;
360             else if (strstr(tex, "horizontal") != NULL)
361                 *grad = Background_Horizontal;
362             else if (strstr(tex, "vertical") != NULL)
363                 *grad = Background_Vertical;
364             else
365                 *grad = Background_Diagonal;
366         } else {
367             *grad = Background_Solid;
368         }
369
370         if (strstr(tex, "sunken") != NULL)
371             *relief = Sunken;
372         else if (strstr(tex, "flat") != NULL)
373             *relief = Flat;
374         else
375             *relief = Raised;
376         
377         *border = FALSE;
378         if (*relief == Flat) {
379             if (strstr(tex, "border") != NULL)
380                 *border = TRUE;
381         } else {
382             if (strstr(tex, "bevel2") != NULL)
383                 *bevel = Bevel2;
384             else
385                 *bevel = Bevel1;
386         }
387
388         if (strstr(tex, "interlaced") != NULL)
389             *interlaced = TRUE;
390         else
391             *interlaced = FALSE;
392     }
393 }
394
395
396 static gboolean read_appearance(XrmDatabase db, char *rname, Appearance *value)
397 {
398     gboolean ret = FALSE;
399     char *rclass = create_class_name(rname), *cname, *ctoname, *bcname;
400     char *rettype;
401     XrmValue retvalue;
402
403     cname = g_strconcat(rname, ".color", NULL);
404     ctoname = g_strconcat(rname, ".colorTo", NULL);
405     bcname = g_strconcat(rname, ".borderColor", NULL);
406
407     if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
408         retvalue.addr != NULL) {
409         parse_appearance(retvalue.addr,
410                          &value->surface.data.planar.grad,
411                          &value->surface.data.planar.relief,
412                          &value->surface.data.planar.bevel,
413                          &value->surface.data.planar.interlaced,
414                          &value->surface.data.planar.border);
415         if (!read_color(db, cname, &value->surface.data.planar.primary))
416             value->surface.data.planar.primary = color_new(0, 0, 0);
417         if (!read_color(db, ctoname, &value->surface.data.planar.secondary))
418             value->surface.data.planar.secondary = color_new(0, 0, 0);
419         if (value->surface.data.planar.border)
420             if (!read_color(db, bcname,
421                             &value->surface.data.planar.border_color))
422                 value->surface.data.planar.border_color = color_new(0, 0, 0);
423         ret = TRUE;
424     }
425
426     g_free(bcname);
427     g_free(ctoname);
428     g_free(cname);
429     g_free(rclass);
430     return ret;
431 }
432
433 static void set_default_appearance(Appearance *a)
434 {
435     a->surface.data.planar.grad = Background_Solid;
436     a->surface.data.planar.relief = Flat;
437     a->surface.data.planar.bevel = Bevel1;
438     a->surface.data.planar.interlaced = FALSE;
439     a->surface.data.planar.border = FALSE;
440     a->surface.data.planar.primary = color_new(0, 0, 0);
441     a->surface.data.planar.secondary = color_new(0, 0, 0);
442 }
443
444 char *theme_load(char *theme)
445 {
446     XrmDatabase db = NULL;
447     char *loaded = NULL;
448     Justify winjust;
449     char *str;
450     char *winfont_str;
451
452     if (theme) {
453         db = loaddb(theme);
454         if (db == NULL) {
455             g_warning("Failed to load the theme '%s'", theme);
456             g_message("Falling back to the default: '%s'", DEFAULT_THEME);
457         } else
458             loaded = g_strdup(theme);
459     }
460     if (db == NULL) {
461         db = loaddb(DEFAULT_THEME);
462         if (db == NULL) {
463             g_warning("Failed to load the theme '%s'.", DEFAULT_THEME);
464             return NULL;
465         } else
466             loaded = g_strdup(DEFAULT_THEME);
467     }
468
469     /* load the font stuff */
470     winfont_str = "arial-8:bold";
471
472     theme_winfont_shadow = FALSE;
473     if (read_string(db, "window.xft.flags", &str)) {
474         if (g_strrstr(str, "shadow"))
475             theme_winfont_shadow = TRUE;
476         g_free(str);
477     }
478  
479     if (!read_int(db, "window.xft.shadow.offset",
480                   &theme_winfont_shadow_offset))
481         theme_winfont_shadow_offset = 1;
482     if (!read_int(db, "window.xft.shadow.tint",
483                   &theme_winfont_shadow_tint) ||
484         theme_winfont_shadow_tint < 100 || theme_winfont_shadow_tint > 100)
485         theme_winfont_shadow_tint = 25;
486
487     theme_winfont = font_open(winfont_str);
488     theme_winfont_height = font_height(theme_winfont, theme_winfont_shadow,
489                                       theme_winfont_shadow_offset);
490
491     winjust = Justify_Left;
492     if (read_string(db, "window.justify", &str)) {
493         if (!g_ascii_strcasecmp(str, "right"))
494             winjust = Justify_Right;
495         else if (!g_ascii_strcasecmp(str, "center"))
496             winjust = Justify_Center;
497         g_free(str);
498     }
499
500     /* load the title layout */
501     theme_title_layout = g_strdup("NLIMC");
502
503     if (!read_int(db, "handleWidth", &theme_handle_height) ||
504         theme_handle_height < 0 || theme_handle_height > 100)
505         theme_handle_height = 6;
506     if (!read_int(db, "bevelWidth", &theme_bevel) ||
507         theme_bevel <= 0 || theme_bevel > 100) theme_bevel = 3;
508     if (!read_int(db, "borderWidth", &theme_bwidth) ||
509         theme_bwidth < 0 || theme_bwidth > 100) theme_bwidth = 1;
510     if (!read_int(db, "frameWidth", &theme_cbwidth) ||
511         theme_cbwidth < 0 || theme_cbwidth > 100) theme_cbwidth = theme_bevel;
512
513     if (!read_color(db, "borderColor", &theme_b_color))
514         theme_b_color = color_new(0, 0, 0);
515     if (!read_color(db, "window.frame.focusColor", &theme_cb_focused_color))
516         theme_cb_focused_color = color_new(0xff, 0xff, 0xff);
517     if (!read_color(db, "window.frame.unfocusColor", &theme_cb_unfocused_color))
518         theme_cb_unfocused_color = color_new(0xff, 0xff, 0xff);
519     if (!read_color(db, "window.label.focus.textColor",
520                     &theme_title_focused_color))
521         theme_title_focused_color = color_new(0x0, 0x0, 0x0);
522     if (!read_color(db, "window.label.unfocus.textColor",
523                     &theme_title_unfocused_color))
524         theme_title_unfocused_color = color_new(0xff, 0xff, 0xff);
525     if (!read_color(db, "window.button.focus.picColor",
526                     &theme_titlebut_focused_color))
527         theme_titlebut_focused_color = color_new(0, 0, 0);
528     if (!read_color(db, "window.button.unfocus.picColor",
529                     &theme_titlebut_unfocused_color))
530         theme_titlebut_unfocused_color = color_new(0xff, 0xff, 0xff);
531
532     if (read_mask(db, "window.button.max.mask", theme, &theme_max_unset_mask)){
533         if (!read_mask(db, "window.button.max.toggled.mask", theme,
534                        &theme_max_set_mask)) {
535             theme_max_set_mask = pixmap_mask_copy(theme_max_unset_mask);
536         }
537     } else {
538         {
539             char data[] = { 0x7f, 0x7f, 0x7f, 0x41, 0x41, 0x41, 0x7f };
540             theme_max_unset_mask = pixmap_mask_new(7, 7, data);
541         }
542         {
543             char data[] = { 0x7c, 0x44, 0x47, 0x47, 0x7f, 0x1f, 0x1f };
544             theme_max_set_mask = pixmap_mask_new(7, 7, data);
545         }
546     }
547
548     if (!read_mask(db, "window.button.icon.mask", theme,
549                    &theme_iconify_mask)) {
550         char data[] = { 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x7f };
551         theme_iconify_mask = pixmap_mask_new(7, 7, data);
552     }
553
554     if (read_mask(db, "window.button.stick.mask", theme,
555                    &theme_desk_unset_mask)) {
556         if (!read_mask(db, "window.button.stick.toggled.mask", theme,
557                        &theme_desk_set_mask)) {
558             theme_desk_set_mask =
559                 pixmap_mask_copy(theme_desk_unset_mask);
560         }
561     } else {
562         {
563             char data[] = { 0x63, 0x63, 0x00, 0x00, 0x00, 0x63, 0x63 };
564             theme_desk_unset_mask = pixmap_mask_new(7, 7, data);
565         }
566         {
567             char data[] = { 0x00, 0x36, 0x36, 0x08, 0x36, 0x36, 0x00 };
568             theme_desk_set_mask = pixmap_mask_new(7, 7, data);
569         }
570     }
571
572     if (read_mask(db, "window.button.shade.mask", theme,
573                    &theme_shade_unset_mask)) {
574         if (!read_mask(db, "window.button.shade.toggled.mask", theme,
575                        &theme_shade_set_mask)) {
576             theme_shade_set_mask =
577                 pixmap_mask_copy(theme_shade_unset_mask);
578         }
579     } else {
580         {
581             char data[] = { 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00 };
582             theme_shade_unset_mask = pixmap_mask_new(7, 7, data);
583         }
584         {
585             char data[] = { 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x7f };
586             theme_shade_set_mask = pixmap_mask_new(7, 7, data);
587         }
588     }
589
590     if (!read_mask(db, "window.button.close.mask", theme,
591                    &theme_close_mask)) {
592         char data[] = { 0x63, 0x77, 0x3e, 0x1c, 0x3e, 0x77, 0x63 };
593         theme_close_mask = pixmap_mask_new(7, 7, data);
594     }        
595
596     /* read the decoration textures */
597     if (!read_appearance(db, "window.title.focus", theme_a_focused_title))
598         set_default_appearance(theme_a_focused_title);
599     if (!read_appearance(db, "window.title.unfocus", theme_a_unfocused_title))
600         set_default_appearance(theme_a_unfocused_title);
601     if (!read_appearance(db, "window.label.focus", theme_a_focused_label))
602         set_default_appearance(theme_a_focused_label);
603     if (!read_appearance(db, "window.label.unfocus", theme_a_unfocused_label))
604         set_default_appearance(theme_a_unfocused_label);
605     if (!read_appearance(db, "window.handle.focus", theme_a_focused_handle))
606         set_default_appearance(theme_a_focused_handle);
607     if (!read_appearance(db, "window.handle.unfocus", theme_a_unfocused_handle))
608         set_default_appearance(theme_a_unfocused_handle);
609     if (!read_appearance(db, "window.grip.focus", theme_a_focused_grip))
610         set_default_appearance(theme_a_focused_grip);
611     if (!read_appearance(db, "window.grip.unfocus", theme_a_unfocused_grip))
612         set_default_appearance(theme_a_unfocused_grip);
613
614     /* read the appearances for rendering non-decorations. these cannot be
615        parent-relative */
616     if (theme_a_focused_label->surface.data.planar.grad !=
617         Background_ParentRelative) {
618         if (!read_appearance(db, "window.label.focus", theme_app_hilite_label))
619             set_default_appearance(theme_app_hilite_label);
620     } else {
621         if (!read_appearance(db, "window.title.focus", theme_app_hilite_label))
622             set_default_appearance(theme_app_hilite_label);
623     }
624     if (theme_a_unfocused_label->surface.data.planar.grad !=
625         Background_ParentRelative) {
626         if (!read_appearance(db, "window.label.unfocus",
627                              theme_app_unhilite_label))
628             set_default_appearance(theme_app_unhilite_label);
629     } else {
630         if (!read_appearance(db, "window.title.unfocus",
631                              theme_app_unhilite_label))
632             set_default_appearance(theme_app_unhilite_label);
633     }
634
635     /* read buttons textures */
636     if (!read_appearance(db, "window.button.pressed.focus",
637                          theme_a_focused_pressed_max))
638         if (!read_appearance(db, "window.button.pressed",
639                              theme_a_focused_pressed_max))
640             set_default_appearance(theme_a_focused_pressed_max);
641     if (!read_appearance(db, "window.button.pressed.unfocus",
642                          theme_a_unfocused_pressed_max))
643         if (!read_appearance(db, "window.button.pressed",
644                              theme_a_unfocused_pressed_max))
645             set_default_appearance(theme_a_unfocused_pressed_max);
646     if (!read_appearance(db, "window.button.focus",
647                          theme_a_focused_unpressed_max))
648         set_default_appearance(theme_a_focused_unpressed_max);
649     if (!read_appearance(db, "window.button.unfocus",
650                          theme_a_unfocused_unpressed_max))
651         set_default_appearance(theme_a_unfocused_unpressed_max);
652
653     theme_a_unfocused_unpressed_close =
654         appearance_copy(theme_a_unfocused_unpressed_max);
655     theme_a_unfocused_pressed_close =
656         appearance_copy(theme_a_unfocused_pressed_max);
657     theme_a_focused_unpressed_close =
658         appearance_copy(theme_a_focused_unpressed_max);
659     theme_a_focused_pressed_close =
660         appearance_copy(theme_a_focused_pressed_max);
661     theme_a_unfocused_unpressed_desk =
662         appearance_copy(theme_a_unfocused_unpressed_max);
663     theme_a_unfocused_pressed_desk =
664         appearance_copy(theme_a_unfocused_pressed_max);
665     theme_a_unfocused_pressed_set_desk =
666         appearance_copy(theme_a_unfocused_pressed_max);
667     theme_a_focused_unpressed_desk =
668         appearance_copy(theme_a_focused_unpressed_max);
669     theme_a_focused_pressed_desk =
670         appearance_copy(theme_a_focused_pressed_max);
671     theme_a_focused_pressed_set_desk =
672         appearance_copy(theme_a_focused_pressed_max);
673     theme_a_unfocused_unpressed_shade =
674         appearance_copy(theme_a_unfocused_unpressed_max);
675     theme_a_unfocused_pressed_shade =
676         appearance_copy(theme_a_unfocused_pressed_max);
677     theme_a_unfocused_pressed_set_shade =
678         appearance_copy(theme_a_unfocused_pressed_max);
679     theme_a_focused_unpressed_shade =
680         appearance_copy(theme_a_focused_unpressed_max);
681     theme_a_focused_pressed_shade =
682         appearance_copy(theme_a_focused_pressed_max);
683     theme_a_focused_pressed_set_shade =
684         appearance_copy(theme_a_focused_pressed_max);
685     theme_a_unfocused_unpressed_iconify =
686         appearance_copy(theme_a_unfocused_unpressed_max);
687     theme_a_unfocused_pressed_iconify =
688         appearance_copy(theme_a_unfocused_pressed_max);
689     theme_a_focused_unpressed_iconify =
690         appearance_copy(theme_a_focused_unpressed_max);
691     theme_a_focused_pressed_iconify =
692         appearance_copy(theme_a_focused_pressed_max);
693     theme_a_unfocused_pressed_set_max =
694         appearance_copy(theme_a_unfocused_pressed_max);
695     theme_a_focused_pressed_set_max =
696         appearance_copy(theme_a_focused_pressed_max);
697
698     theme_a_icon->surface.data.planar.grad = Background_ParentRelative;
699
700     /* set up the textures */
701     theme_a_focused_label->texture[0].type = 
702         theme_app_hilite_label->texture[0].type = Text;
703     theme_a_focused_label->texture[0].data.text.justify =
704         theme_app_hilite_label->texture[0].data.text.justify = winjust;
705     theme_a_focused_label->texture[0].data.text.font =
706         theme_app_hilite_label->texture[0].data.text.font = theme_winfont;
707     theme_a_focused_label->texture[0].data.text.shadow =
708         theme_app_hilite_label->texture[0].data.text.shadow =
709         theme_winfont_shadow;
710     theme_a_focused_label->texture[0].data.text.offset =
711         theme_app_hilite_label->texture[0].data.text.offset =
712         theme_winfont_shadow_offset;
713     theme_a_focused_label->texture[0].data.text.tint =
714         theme_app_hilite_label->texture[0].data.text.tint =
715         theme_winfont_shadow_tint;
716     theme_a_focused_label->texture[0].data.text.color =
717         theme_app_hilite_label->texture[0].data.text.color =
718         theme_title_focused_color;
719
720     theme_a_unfocused_label->texture[0].type =
721         theme_app_unhilite_label->texture[0].type = Text;
722     theme_a_unfocused_label->texture[0].data.text.justify =
723         theme_app_unhilite_label->texture[0].data.text.justify = winjust;
724     theme_a_unfocused_label->texture[0].data.text.font =
725         theme_app_unhilite_label->texture[0].data.text.font = theme_winfont;
726     theme_a_unfocused_label->texture[0].data.text.shadow =
727         theme_app_unhilite_label->texture[0].data.text.shadow =
728         theme_winfont_shadow;
729     theme_a_unfocused_label->texture[0].data.text.offset =
730         theme_app_unhilite_label->texture[0].data.text.offset =
731         theme_winfont_shadow_offset;
732     theme_a_unfocused_label->texture[0].data.text.tint =
733         theme_app_unhilite_label->texture[0].data.text.tint =
734         theme_winfont_shadow_tint;
735     theme_a_unfocused_label->texture[0].data.text.color =
736         theme_app_unhilite_label->texture[0].data.text.color =
737         theme_title_unfocused_color;
738
739     theme_a_focused_unpressed_max->texture[0].type = 
740         theme_a_focused_pressed_max->texture[0].type = 
741         theme_a_focused_pressed_set_max->texture[0].type =  
742         theme_a_unfocused_unpressed_max->texture[0].type = 
743         theme_a_unfocused_pressed_max->texture[0].type = 
744         theme_a_unfocused_pressed_set_max->texture[0].type = 
745         theme_a_focused_unpressed_close->texture[0].type = 
746         theme_a_focused_pressed_close->texture[0].type = 
747         theme_a_unfocused_unpressed_close->texture[0].type = 
748         theme_a_unfocused_pressed_close->texture[0].type = 
749         theme_a_focused_unpressed_desk->texture[0].type = 
750         theme_a_focused_pressed_desk->texture[0].type = 
751         theme_a_focused_pressed_set_desk->texture[0].type = 
752         theme_a_unfocused_unpressed_desk->texture[0].type = 
753         theme_a_unfocused_pressed_desk->texture[0].type = 
754         theme_a_unfocused_pressed_set_desk->texture[0].type = 
755         theme_a_focused_unpressed_shade->texture[0].type = 
756         theme_a_focused_pressed_shade->texture[0].type = 
757         theme_a_focused_pressed_set_shade->texture[0].type = 
758         theme_a_unfocused_unpressed_shade->texture[0].type = 
759         theme_a_unfocused_pressed_shade->texture[0].type = 
760         theme_a_unfocused_pressed_set_shade->texture[0].type = 
761         theme_a_focused_unpressed_iconify->texture[0].type = 
762         theme_a_focused_pressed_iconify->texture[0].type = 
763         theme_a_unfocused_unpressed_iconify->texture[0].type = 
764         theme_a_unfocused_pressed_iconify->texture[0].type = Bitmask;
765     theme_a_focused_unpressed_max->texture[0].data.mask.mask = 
766         theme_a_unfocused_unpressed_max->texture[0].data.mask.mask = 
767         theme_a_focused_pressed_max->texture[0].data.mask.mask = 
768         theme_a_unfocused_pressed_max->texture[0].data.mask.mask =
769         theme_max_unset_mask;
770     theme_a_focused_pressed_set_max->texture[0].data.mask.mask = 
771         theme_a_unfocused_pressed_set_max->texture[0].data.mask.mask =
772         theme_max_set_mask;
773     theme_a_focused_pressed_close->texture[0].data.mask.mask = 
774         theme_a_unfocused_pressed_close->texture[0].data.mask.mask =
775         theme_a_focused_unpressed_close->texture[0].data.mask.mask = 
776         theme_a_unfocused_unpressed_close->texture[0].data.mask.mask =
777         theme_close_mask;
778     theme_a_focused_unpressed_desk->texture[0].data.mask.mask = 
779         theme_a_unfocused_unpressed_desk->texture[0].data.mask.mask = 
780         theme_a_focused_pressed_desk->texture[0].data.mask.mask = 
781         theme_a_unfocused_pressed_desk->texture[0].data.mask.mask =
782         theme_desk_unset_mask;
783     theme_a_focused_pressed_set_desk->texture[0].data.mask.mask = 
784         theme_a_unfocused_pressed_set_desk->texture[0].data.mask.mask =
785         theme_desk_set_mask;
786     theme_a_focused_unpressed_shade->texture[0].data.mask.mask = 
787         theme_a_unfocused_unpressed_shade->texture[0].data.mask.mask = 
788         theme_a_focused_pressed_shade->texture[0].data.mask.mask = 
789         theme_a_unfocused_pressed_shade->texture[0].data.mask.mask =
790         theme_shade_unset_mask;
791     theme_a_focused_pressed_set_shade->texture[0].data.mask.mask = 
792         theme_a_unfocused_pressed_set_shade->texture[0].data.mask.mask =
793         theme_shade_set_mask;
794     theme_a_focused_unpressed_iconify->texture[0].data.mask.mask = 
795         theme_a_unfocused_unpressed_iconify->texture[0].data.mask.mask = 
796         theme_a_focused_pressed_iconify->texture[0].data.mask.mask = 
797         theme_a_unfocused_pressed_iconify->texture[0].data.mask.mask =
798         theme_iconify_mask;
799     theme_a_focused_unpressed_max->texture[0].data.mask.color = 
800         theme_a_focused_pressed_max->texture[0].data.mask.color = 
801         theme_a_focused_pressed_set_max->texture[0].data.mask.color = 
802         theme_a_focused_unpressed_close->texture[0].data.mask.color = 
803         theme_a_focused_pressed_close->texture[0].data.mask.color = 
804         theme_a_focused_unpressed_desk->texture[0].data.mask.color = 
805         theme_a_focused_pressed_desk->texture[0].data.mask.color = 
806         theme_a_focused_pressed_set_desk->texture[0].data.mask.color = 
807         theme_a_focused_unpressed_shade->texture[0].data.mask.color = 
808         theme_a_focused_pressed_shade->texture[0].data.mask.color = 
809         theme_a_focused_pressed_set_shade->texture[0].data.mask.color = 
810         theme_a_focused_unpressed_iconify->texture[0].data.mask.color = 
811         theme_a_focused_pressed_iconify->texture[0].data.mask.color =
812         theme_titlebut_focused_color;
813     theme_a_unfocused_unpressed_max->texture[0].data.mask.color = 
814         theme_a_unfocused_pressed_max->texture[0].data.mask.color = 
815         theme_a_unfocused_pressed_set_max->texture[0].data.mask.color = 
816         theme_a_unfocused_unpressed_close->texture[0].data.mask.color = 
817         theme_a_unfocused_pressed_close->texture[0].data.mask.color = 
818         theme_a_unfocused_unpressed_desk->texture[0].data.mask.color = 
819         theme_a_unfocused_pressed_desk->texture[0].data.mask.color = 
820         theme_a_unfocused_pressed_set_desk->texture[0].data.mask.color = 
821         theme_a_unfocused_unpressed_shade->texture[0].data.mask.color = 
822         theme_a_unfocused_pressed_shade->texture[0].data.mask.color = 
823         theme_a_unfocused_pressed_set_shade->texture[0].data.mask.color = 
824         theme_a_unfocused_unpressed_iconify->texture[0].data.mask.color = 
825         theme_a_unfocused_pressed_iconify->texture[0].data.mask.color =
826         theme_titlebut_unfocused_color;
827
828     XrmDestroyDatabase(db);
829
830     return loaded;
831 }