move the openbox engine into librender and the kernel. the theme is loaded and stored...
[dana/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 *winjust_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     theme_winfont_shadow = FALSE;
472     theme_winfont_shadow_offset = 1;
473     theme_winfont_shadow_tint = 25;
474
475     theme_winfont = font_open(winfont_str);
476     theme_winfont_height = font_height(theme_winfont, theme_winfont_shadow,
477                                       theme_winfont_shadow_offset);
478
479     winjust = Justify_Left;
480     if (read_string(db, "window.justify", &winjust_str)) {
481         if (!g_ascii_strcasecmp(winjust_str, "right"))
482             winjust = Justify_Right;
483         else if (!g_ascii_strcasecmp(winjust_str, "center"))
484             winjust = Justify_Center;
485         g_free(winjust_str);
486     }
487
488     /* load the title layout */
489     theme_title_layout = g_strdup("NLIMC");
490
491     if (!read_int(db, "handleWidth", &theme_handle_height) ||
492         theme_handle_height < 0 || theme_handle_height > 100)
493         theme_handle_height = 6;
494     if (!read_int(db, "bevelWidth", &theme_bevel) ||
495         theme_bevel <= 0 || theme_bevel > 100) theme_bevel = 3;
496     if (!read_int(db, "borderWidth", &theme_bwidth) ||
497         theme_bwidth < 0 || theme_bwidth > 100) theme_bwidth = 1;
498     if (!read_int(db, "frameWidth", &theme_cbwidth) ||
499         theme_cbwidth < 0 || theme_cbwidth > 100) theme_cbwidth = theme_bevel;
500
501     if (!read_color(db, "borderColor", &theme_b_color))
502         theme_b_color = color_new(0, 0, 0);
503     if (!read_color(db, "window.frame.focusColor", &theme_cb_focused_color))
504         theme_cb_focused_color = color_new(0xff, 0xff, 0xff);
505     if (!read_color(db, "window.frame.unfocusColor", &theme_cb_unfocused_color))
506         theme_cb_unfocused_color = color_new(0xff, 0xff, 0xff);
507     if (!read_color(db, "window.label.focus.textColor",
508                     &theme_title_focused_color))
509         theme_title_focused_color = color_new(0x0, 0x0, 0x0);
510     if (!read_color(db, "window.label.unfocus.textColor",
511                     &theme_title_unfocused_color))
512         theme_title_unfocused_color = color_new(0xff, 0xff, 0xff);
513     if (!read_color(db, "window.button.focus.picColor",
514                     &theme_titlebut_focused_color))
515         theme_titlebut_focused_color = color_new(0, 0, 0);
516     if (!read_color(db, "window.button.unfocus.picColor",
517                     &theme_titlebut_unfocused_color))
518         theme_titlebut_unfocused_color = color_new(0xff, 0xff, 0xff);
519
520     if (read_mask(db, "window.button.max.mask", theme, &theme_max_unset_mask)){
521         if (!read_mask(db, "window.button.max.toggled.mask", theme,
522                        &theme_max_set_mask)) {
523             theme_max_set_mask = pixmap_mask_copy(theme_max_unset_mask);
524         }
525     } else {
526         {
527             char data[] = { 0x7f, 0x7f, 0x7f, 0x41, 0x41, 0x41, 0x7f };
528             theme_max_unset_mask = pixmap_mask_new(7, 7, data);
529         }
530         {
531             char data[] = { 0x7c, 0x44, 0x47, 0x47, 0x7f, 0x1f, 0x1f };
532             theme_max_set_mask = pixmap_mask_new(7, 7, data);
533         }
534     }
535
536     if (!read_mask(db, "window.button.icon.mask", theme,
537                    &theme_iconify_mask)) {
538         char data[] = { 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x7f };
539         theme_iconify_mask = pixmap_mask_new(7, 7, data);
540     }
541
542     if (read_mask(db, "window.button.stick.mask", theme,
543                    &theme_desk_unset_mask)) {
544         if (!read_mask(db, "window.button.stick.toggled.mask", theme,
545                        &theme_desk_set_mask)) {
546             theme_desk_set_mask =
547                 pixmap_mask_copy(theme_desk_unset_mask);
548         }
549     } else {
550         {
551             char data[] = { 0x63, 0x63, 0x00, 0x00, 0x00, 0x63, 0x63 };
552             theme_desk_unset_mask = pixmap_mask_new(7, 7, data);
553         }
554         {
555             char data[] = { 0x00, 0x36, 0x36, 0x08, 0x36, 0x36, 0x00 };
556             theme_desk_set_mask = pixmap_mask_new(7, 7, data);
557         }
558     }
559
560     if (read_mask(db, "window.button.shade.mask", theme,
561                    &theme_shade_unset_mask)) {
562         if (!read_mask(db, "window.button.shade.toggled.mask", theme,
563                        &theme_shade_set_mask)) {
564             theme_shade_set_mask =
565                 pixmap_mask_copy(theme_shade_unset_mask);
566         }
567     } else {
568         {
569             char data[] = { 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00 };
570             theme_shade_unset_mask = pixmap_mask_new(7, 7, data);
571         }
572         {
573             char data[] = { 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x7f };
574             theme_shade_set_mask = pixmap_mask_new(7, 7, data);
575         }
576     }
577
578     if (!read_mask(db, "window.button.close.mask", theme,
579                    &theme_close_mask)) {
580         char data[] = { 0x63, 0x77, 0x3e, 0x1c, 0x3e, 0x77, 0x63 };
581         theme_close_mask = pixmap_mask_new(7, 7, data);
582     }        
583
584     /* read the decoration textures */
585     if (!read_appearance(db, "window.title.focus", theme_a_focused_title))
586         set_default_appearance(theme_a_focused_title);
587     if (!read_appearance(db, "window.title.unfocus", theme_a_unfocused_title))
588         set_default_appearance(theme_a_unfocused_title);
589     if (!read_appearance(db, "window.label.focus", theme_a_focused_label))
590         set_default_appearance(theme_a_focused_label);
591     if (!read_appearance(db, "window.label.unfocus", theme_a_unfocused_label))
592         set_default_appearance(theme_a_unfocused_label);
593     if (!read_appearance(db, "window.handle.focus", theme_a_focused_handle))
594         set_default_appearance(theme_a_focused_handle);
595     if (!read_appearance(db, "window.handle.unfocus", theme_a_unfocused_handle))
596         set_default_appearance(theme_a_unfocused_handle);
597     if (!read_appearance(db, "window.grip.focus", theme_a_focused_grip))
598         set_default_appearance(theme_a_focused_grip);
599     if (!read_appearance(db, "window.grip.unfocus", theme_a_unfocused_grip))
600         set_default_appearance(theme_a_unfocused_grip);
601
602     /* read the appearances for rendering non-decorations. these cannot be
603        parent-relative */
604     if (theme_a_focused_label->surface.data.planar.grad !=
605         Background_ParentRelative) {
606         if (!read_appearance(db, "window.label.focus", theme_app_hilite_label))
607             set_default_appearance(theme_app_hilite_label);
608     } else {
609         if (!read_appearance(db, "window.title.focus", theme_app_hilite_label))
610             set_default_appearance(theme_app_hilite_label);
611     }
612     if (theme_a_unfocused_label->surface.data.planar.grad !=
613         Background_ParentRelative) {
614         if (!read_appearance(db, "window.label.unfocus",
615                              theme_app_unhilite_label))
616             set_default_appearance(theme_app_unhilite_label);
617     } else {
618         if (!read_appearance(db, "window.title.unfocus",
619                              theme_app_unhilite_label))
620             set_default_appearance(theme_app_unhilite_label);
621     }
622
623     /* read buttons textures */
624     if (!read_appearance(db, "window.button.pressed.focus",
625                          theme_a_focused_pressed_max))
626         if (!read_appearance(db, "window.button.pressed",
627                              theme_a_focused_pressed_max))
628             set_default_appearance(theme_a_focused_pressed_max);
629     if (!read_appearance(db, "window.button.pressed.unfocus",
630                          theme_a_unfocused_pressed_max))
631         if (!read_appearance(db, "window.button.pressed",
632                              theme_a_unfocused_pressed_max))
633             set_default_appearance(theme_a_unfocused_pressed_max);
634     if (!read_appearance(db, "window.button.focus",
635                          theme_a_focused_unpressed_max))
636         set_default_appearance(theme_a_focused_unpressed_max);
637     if (!read_appearance(db, "window.button.unfocus",
638                          theme_a_unfocused_unpressed_max))
639         set_default_appearance(theme_a_unfocused_unpressed_max);
640
641     theme_a_unfocused_unpressed_close =
642         appearance_copy(theme_a_unfocused_unpressed_max);
643     theme_a_unfocused_pressed_close =
644         appearance_copy(theme_a_unfocused_pressed_max);
645     theme_a_focused_unpressed_close =
646         appearance_copy(theme_a_focused_unpressed_max);
647     theme_a_focused_pressed_close =
648         appearance_copy(theme_a_focused_pressed_max);
649     theme_a_unfocused_unpressed_desk =
650         appearance_copy(theme_a_unfocused_unpressed_max);
651     theme_a_unfocused_pressed_desk =
652         appearance_copy(theme_a_unfocused_pressed_max);
653     theme_a_unfocused_pressed_set_desk =
654         appearance_copy(theme_a_unfocused_pressed_max);
655     theme_a_focused_unpressed_desk =
656         appearance_copy(theme_a_focused_unpressed_max);
657     theme_a_focused_pressed_desk =
658         appearance_copy(theme_a_focused_pressed_max);
659     theme_a_focused_pressed_set_desk =
660         appearance_copy(theme_a_focused_pressed_max);
661     theme_a_unfocused_unpressed_shade =
662         appearance_copy(theme_a_unfocused_unpressed_max);
663     theme_a_unfocused_pressed_shade =
664         appearance_copy(theme_a_unfocused_pressed_max);
665     theme_a_unfocused_pressed_set_shade =
666         appearance_copy(theme_a_unfocused_pressed_max);
667     theme_a_focused_unpressed_shade =
668         appearance_copy(theme_a_focused_unpressed_max);
669     theme_a_focused_pressed_shade =
670         appearance_copy(theme_a_focused_pressed_max);
671     theme_a_focused_pressed_set_shade =
672         appearance_copy(theme_a_focused_pressed_max);
673     theme_a_unfocused_unpressed_iconify =
674         appearance_copy(theme_a_unfocused_unpressed_max);
675     theme_a_unfocused_pressed_iconify =
676         appearance_copy(theme_a_unfocused_pressed_max);
677     theme_a_focused_unpressed_iconify =
678         appearance_copy(theme_a_focused_unpressed_max);
679     theme_a_focused_pressed_iconify =
680         appearance_copy(theme_a_focused_pressed_max);
681     theme_a_unfocused_pressed_set_max =
682         appearance_copy(theme_a_unfocused_pressed_max);
683     theme_a_focused_pressed_set_max =
684         appearance_copy(theme_a_focused_pressed_max);
685
686     theme_a_icon->surface.data.planar.grad = Background_ParentRelative;
687
688     /* set up the textures */
689     theme_a_focused_label->texture[0].type = 
690         theme_app_hilite_label->texture[0].type = Text;
691     theme_a_focused_label->texture[0].data.text.justify =
692         theme_app_hilite_label->texture[0].data.text.justify = winjust;
693     theme_a_focused_label->texture[0].data.text.font =
694         theme_app_hilite_label->texture[0].data.text.font = theme_winfont;
695     theme_a_focused_label->texture[0].data.text.shadow =
696         theme_app_hilite_label->texture[0].data.text.shadow =
697         theme_winfont_shadow;
698     theme_a_focused_label->texture[0].data.text.offset =
699         theme_app_hilite_label->texture[0].data.text.offset =
700         theme_winfont_shadow_offset;
701     theme_a_focused_label->texture[0].data.text.tint =
702         theme_app_hilite_label->texture[0].data.text.tint =
703         theme_winfont_shadow_tint;
704     theme_a_focused_label->texture[0].data.text.color =
705         theme_app_hilite_label->texture[0].data.text.color =
706         theme_title_focused_color;
707
708     theme_a_unfocused_label->texture[0].type =
709         theme_app_unhilite_label->texture[0].type = Text;
710     theme_a_unfocused_label->texture[0].data.text.justify =
711         theme_app_unhilite_label->texture[0].data.text.justify = winjust;
712     theme_a_unfocused_label->texture[0].data.text.font =
713         theme_app_unhilite_label->texture[0].data.text.font = theme_winfont;
714     theme_a_unfocused_label->texture[0].data.text.shadow =
715         theme_app_unhilite_label->texture[0].data.text.shadow =
716         theme_winfont_shadow;
717     theme_a_unfocused_label->texture[0].data.text.offset =
718         theme_app_unhilite_label->texture[0].data.text.offset =
719         theme_winfont_shadow_offset;
720     theme_a_unfocused_label->texture[0].data.text.tint =
721         theme_app_unhilite_label->texture[0].data.text.tint =
722         theme_winfont_shadow_tint;
723     theme_a_unfocused_label->texture[0].data.text.color =
724         theme_app_unhilite_label->texture[0].data.text.color =
725         theme_title_unfocused_color;
726
727     theme_a_focused_unpressed_max->texture[0].type = 
728         theme_a_focused_pressed_max->texture[0].type = 
729         theme_a_focused_pressed_set_max->texture[0].type =  
730         theme_a_unfocused_unpressed_max->texture[0].type = 
731         theme_a_unfocused_pressed_max->texture[0].type = 
732         theme_a_unfocused_pressed_set_max->texture[0].type = 
733         theme_a_focused_unpressed_close->texture[0].type = 
734         theme_a_focused_pressed_close->texture[0].type = 
735         theme_a_unfocused_unpressed_close->texture[0].type = 
736         theme_a_unfocused_pressed_close->texture[0].type = 
737         theme_a_focused_unpressed_desk->texture[0].type = 
738         theme_a_focused_pressed_desk->texture[0].type = 
739         theme_a_focused_pressed_set_desk->texture[0].type = 
740         theme_a_unfocused_unpressed_desk->texture[0].type = 
741         theme_a_unfocused_pressed_desk->texture[0].type = 
742         theme_a_unfocused_pressed_set_desk->texture[0].type = 
743         theme_a_focused_unpressed_shade->texture[0].type = 
744         theme_a_focused_pressed_shade->texture[0].type = 
745         theme_a_focused_pressed_set_shade->texture[0].type = 
746         theme_a_unfocused_unpressed_shade->texture[0].type = 
747         theme_a_unfocused_pressed_shade->texture[0].type = 
748         theme_a_unfocused_pressed_set_shade->texture[0].type = 
749         theme_a_focused_unpressed_iconify->texture[0].type = 
750         theme_a_focused_pressed_iconify->texture[0].type = 
751         theme_a_unfocused_unpressed_iconify->texture[0].type = 
752         theme_a_unfocused_pressed_iconify->texture[0].type = Bitmask;
753     theme_a_focused_unpressed_max->texture[0].data.mask.mask = 
754         theme_a_unfocused_unpressed_max->texture[0].data.mask.mask = 
755         theme_a_focused_pressed_max->texture[0].data.mask.mask = 
756         theme_a_unfocused_pressed_max->texture[0].data.mask.mask =
757         theme_max_unset_mask;
758     theme_a_focused_pressed_set_max->texture[0].data.mask.mask = 
759         theme_a_unfocused_pressed_set_max->texture[0].data.mask.mask =
760         theme_max_set_mask;
761     theme_a_focused_pressed_close->texture[0].data.mask.mask = 
762         theme_a_unfocused_pressed_close->texture[0].data.mask.mask =
763         theme_a_focused_unpressed_close->texture[0].data.mask.mask = 
764         theme_a_unfocused_unpressed_close->texture[0].data.mask.mask =
765         theme_close_mask;
766     theme_a_focused_unpressed_desk->texture[0].data.mask.mask = 
767         theme_a_unfocused_unpressed_desk->texture[0].data.mask.mask = 
768         theme_a_focused_pressed_desk->texture[0].data.mask.mask = 
769         theme_a_unfocused_pressed_desk->texture[0].data.mask.mask =
770         theme_desk_unset_mask;
771     theme_a_focused_pressed_set_desk->texture[0].data.mask.mask = 
772         theme_a_unfocused_pressed_set_desk->texture[0].data.mask.mask =
773         theme_desk_set_mask;
774     theme_a_focused_unpressed_shade->texture[0].data.mask.mask = 
775         theme_a_unfocused_unpressed_shade->texture[0].data.mask.mask = 
776         theme_a_focused_pressed_shade->texture[0].data.mask.mask = 
777         theme_a_unfocused_pressed_shade->texture[0].data.mask.mask =
778         theme_shade_unset_mask;
779     theme_a_focused_pressed_set_shade->texture[0].data.mask.mask = 
780         theme_a_unfocused_pressed_set_shade->texture[0].data.mask.mask =
781         theme_shade_set_mask;
782     theme_a_focused_unpressed_iconify->texture[0].data.mask.mask = 
783         theme_a_unfocused_unpressed_iconify->texture[0].data.mask.mask = 
784         theme_a_focused_pressed_iconify->texture[0].data.mask.mask = 
785         theme_a_unfocused_pressed_iconify->texture[0].data.mask.mask =
786         theme_iconify_mask;
787     theme_a_focused_unpressed_max->texture[0].data.mask.color = 
788         theme_a_focused_pressed_max->texture[0].data.mask.color = 
789         theme_a_focused_pressed_set_max->texture[0].data.mask.color = 
790         theme_a_focused_unpressed_close->texture[0].data.mask.color = 
791         theme_a_focused_pressed_close->texture[0].data.mask.color = 
792         theme_a_focused_unpressed_desk->texture[0].data.mask.color = 
793         theme_a_focused_pressed_desk->texture[0].data.mask.color = 
794         theme_a_focused_pressed_set_desk->texture[0].data.mask.color = 
795         theme_a_focused_unpressed_shade->texture[0].data.mask.color = 
796         theme_a_focused_pressed_shade->texture[0].data.mask.color = 
797         theme_a_focused_pressed_set_shade->texture[0].data.mask.color = 
798         theme_a_focused_unpressed_iconify->texture[0].data.mask.color = 
799         theme_a_focused_pressed_iconify->texture[0].data.mask.color =
800         theme_titlebut_focused_color;
801     theme_a_unfocused_unpressed_max->texture[0].data.mask.color = 
802         theme_a_unfocused_pressed_max->texture[0].data.mask.color = 
803         theme_a_unfocused_pressed_set_max->texture[0].data.mask.color = 
804         theme_a_unfocused_unpressed_close->texture[0].data.mask.color = 
805         theme_a_unfocused_pressed_close->texture[0].data.mask.color = 
806         theme_a_unfocused_unpressed_desk->texture[0].data.mask.color = 
807         theme_a_unfocused_pressed_desk->texture[0].data.mask.color = 
808         theme_a_unfocused_pressed_set_desk->texture[0].data.mask.color = 
809         theme_a_unfocused_unpressed_shade->texture[0].data.mask.color = 
810         theme_a_unfocused_pressed_shade->texture[0].data.mask.color = 
811         theme_a_unfocused_pressed_set_shade->texture[0].data.mask.color = 
812         theme_a_unfocused_unpressed_iconify->texture[0].data.mask.color = 
813         theme_a_unfocused_pressed_iconify->texture[0].data.mask.color =
814         theme_titlebut_unfocused_color;
815
816     XrmDestroyDatabase(db);
817
818     return loaded;
819 }