will draw fonts when stop segging
[mikachu/openbox.git] / engines / openbox / theme.c
1 #include "openbox.h"
2 #include "../../kernel/themerc.h"
3
4 #include <glib.h>
5 #include <X11/Xlib.h>
6 #include <X11/Xresource.h>
7 #ifdef HAVE_STDLIB_H
8 #  include <stdlib.h>
9 #endif
10 #ifdef HAVE_CTYPE_H
11 #  include <ctype.h>
12 #endif
13 #ifdef HAVE_STRING_H
14 #  include <string.h>
15 #endif
16
17 static XrmDatabase loaddb(char *theme)
18 {
19     XrmDatabase db;
20
21     db = XrmGetFileDatabase(theme);
22     if (db == NULL) {
23         char *s = g_build_filename(g_get_home_dir(), ".openbox", "themes",
24                                    "openbox", theme, NULL);
25         db = XrmGetFileDatabase(s);
26         g_free(s);
27     }
28     if (db == NULL) {
29         char *s = g_build_filename(THEMEDIR, theme, NULL);
30         db = XrmGetFileDatabase(s);
31         g_free(s);
32     }
33     return db;
34 }
35
36 static char *create_class_name(char *rname)
37 {
38     char *rclass = g_strdup(rname);
39     char *p = rclass;
40
41     while (TRUE) {
42         *p = toupper(*p);
43         p = strchr(p+1, '.');
44         if (p == NULL) break;
45         ++p;
46         if (*p == '\0') break;
47     }
48     return rclass;
49 }
50
51 gboolean read_bool(XrmDatabase db, char *rname, gboolean *value)
52 {
53     gboolean ret = FALSE;
54     char *rclass = create_class_name(rname);
55     char *rettype;
56     XrmValue retvalue;
57   
58     if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
59         retvalue.addr != NULL) {
60         if (!g_ascii_strcasecmp(retvalue.addr, "true"))
61             *value = TRUE;
62         else
63             *value = FALSE;
64         ret = TRUE;
65     }
66
67     g_free(rclass);
68     return ret;
69 }
70
71 gboolean read_int(XrmDatabase db, char *rname, int *value)
72 {
73     gboolean ret = FALSE;
74     char *rclass = create_class_name(rname);
75     char *rettype, *end;
76     XrmValue retvalue;
77   
78     if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
79         retvalue.addr != NULL) {
80         *value = (int)strtol(retvalue.addr, &end, 10);
81         if (end != retvalue.addr)
82             ret = TRUE;
83     }
84
85     g_free(rclass);
86     return ret;
87 }
88
89 gboolean read_string(XrmDatabase db, char *rname, char **value)
90 {
91     gboolean ret = FALSE;
92     char *rclass = create_class_name(rname);
93     char *rettype;
94     XrmValue retvalue;
95   
96     if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
97         retvalue.addr != NULL) {
98         *value = retvalue.addr;
99         ret = TRUE;
100     }
101
102     g_free(rclass);
103     return ret;
104 }
105
106 gboolean read_color(XrmDatabase db, char *rname, color_rgb **value)
107 {
108     gboolean ret = FALSE;
109     char *rclass = create_class_name(rname);
110     char *rettype;
111     XrmValue retvalue;
112   
113     if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
114         retvalue.addr != NULL) {
115         color_rgb *c = color_parse(retvalue.addr);
116         if (c != NULL) {
117             *value = c;
118             ret = TRUE;
119         }
120     }
121
122     g_free(rclass);
123     return ret;
124 }
125
126 static void parse_appearance(char *tex, SurfaceColorType *grad,
127                           ReliefType *relief, BevelType *bevel,
128                           gboolean *interlaced, gboolean *border)
129 {
130     char *t;
131
132     /* convert to all lowercase */
133     for (t = tex; *t != '\0'; ++t)
134         *t = g_ascii_tolower(*t);
135
136     if (strstr(tex, "parentrelative") != NULL) {
137         *grad = Background_ParentRelative;
138     } else {
139         if (strstr(tex, "gradient") != NULL) {
140             if (strstr(tex, "crossdiagonal") != NULL)
141                 *grad = Background_CrossDiagonal;
142             else if (strstr(tex, "rectangle") != NULL)
143                 *grad = Background_Rectangle;
144             else if (strstr(tex, "pyramid") != NULL)
145                 *grad = Background_Pyramid;
146             else if (strstr(tex, "pipecross") != NULL)
147                 *grad = Background_PipeCross;
148             else if (strstr(tex, "elliptic") != NULL)
149                 *grad = Background_Elliptic;
150             else if (strstr(tex, "horizontal") != NULL)
151                 *grad = Background_Horizontal;
152             else if (strstr(tex, "vertical") != NULL)
153                 *grad = Background_Vertical;
154             else
155                 *grad = Background_Diagonal;
156         } else {
157             *grad = Background_Solid;
158         }
159
160         if (strstr(tex, "sunken") != NULL)
161             *relief = Sunken;
162         else if (strstr(tex, "flat") != NULL)
163             *relief = Flat;
164         else
165             *relief = Raised;
166         
167         *border = FALSE;
168         if (*relief == Flat) {
169             if (strstr(tex, "border") != NULL)
170                 *border = TRUE;
171         } else {
172             if (strstr(tex, "bevel2") != NULL)
173                 *bevel = Bevel2;
174             else
175                 *bevel = Bevel1;
176         }
177
178         if (strstr(tex, "interlaced") != NULL)
179             *interlaced = TRUE;
180         else
181             *interlaced = FALSE;
182     }
183 }
184
185
186 gboolean read_appearance(XrmDatabase db, char *rname, Appearance *value)
187 {
188     gboolean ret = FALSE;
189     char *rclass = create_class_name(rname), *cname, *ctoname, *bcname;
190     char *rettype;
191     XrmValue retvalue;
192
193     cname = g_strconcat(rname, ".color", NULL);
194     ctoname = g_strconcat(rname, ".colorTo", NULL);
195     bcname = g_strconcat(rname, ".borderColor", NULL);
196
197     if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
198         retvalue.addr != NULL) {
199         parse_appearance(retvalue.addr,
200                          &value->surface.data.planar.grad,
201                          &value->surface.data.planar.relief,
202                          &value->surface.data.planar.bevel,
203                          &value->surface.data.planar.interlaced,
204                          &value->surface.data.planar.border);
205         if (!read_color(db, cname, &value->surface.data.planar.primary))
206             value->surface.data.planar.primary = color_new(0, 0, 0);
207         if (!read_color(db, ctoname, &value->surface.data.planar.secondary))
208             value->surface.data.planar.secondary = color_new(0, 0, 0);
209         if (value->surface.data.planar.border)
210             if (!read_color(db, bcname,
211                             &value->surface.data.planar.border_color))
212                 value->surface.data.planar.border_color = color_new(0, 0, 0);
213         ret = TRUE;
214     }
215
216     g_free(bcname);
217     g_free(ctoname);
218     g_free(cname);
219     g_free(rclass);
220     return ret;
221 }
222
223 void set_default_appearance(Appearance *a)
224 {
225     a->surface.data.planar.grad = Background_Solid;
226     a->surface.data.planar.relief = Flat;
227     a->surface.data.planar.bevel = Bevel1;
228     a->surface.data.planar.interlaced = FALSE;
229     a->surface.data.planar.border = FALSE;
230     a->surface.data.planar.primary = color_new(0, 0, 0);
231     a->surface.data.planar.secondary = color_new(0, 0, 0);
232 }
233
234 gboolean load()
235 {
236     XrmDatabase db = NULL;
237
238     if (themerc_theme != NULL) {
239         db = loaddb(themerc_theme);
240         if (db == NULL) {
241             g_warning("Failed to load the theme '%s'", themerc_theme);
242             g_message("Falling back to the default: '%s'", DEFAULT_THEME);
243         }
244     }
245     if (db == NULL) {
246         db = loaddb(DEFAULT_THEME);
247         if (db == NULL) {
248             g_warning("Failed to load the theme '%s'.", DEFAULT_THEME);
249             return FALSE;
250         }
251     }
252
253     /* load the font, not from the theme file tho, its in themerc_font */
254     s_winfont_shadow = 1; /* XXX read from themrc */
255     s_winfont_shadow_offset = 2; /* XXX read from themerc */
256     s_winfont = font_open(themerc_font);
257     s_winfont_height = font_height(s_winfont, s_winfont_shadow,
258                                    s_winfont_shadow_offset);
259
260     if (!read_int(db, "handleWidth", &s_handle_height) ||
261         s_handle_height < 0 || s_handle_height > 100) s_handle_height = 6;
262     if (!read_int(db, "bevelWidth", &s_bevel) ||
263         s_bevel <= 0 || s_bevel > 100) s_bevel = 3;
264     if (!read_int(db, "borderWidth", &s_bwidth) ||
265         s_bwidth < 0 || s_bwidth > 100) s_bwidth = 1;
266     if (!read_int(db, "frameWidth", &s_cbwidth) ||
267         s_cbwidth < 0 || s_cbwidth > 100) s_cbwidth = s_bevel;
268
269     if (!read_color(db, "borderColor", &s_b_color))
270         s_b_color = color_new(0, 0, 0);
271     if (!read_color(db, "window.frame.focusColor", &s_cb_focused_color))
272         s_cb_focused_color = color_new(0xff, 0xff, 0xff);
273     if (!read_color(db, "window.frame.unfocusColor", &s_cb_unfocused_color))
274         s_cb_unfocused_color = color_new(0xff, 0xff, 0xff);
275     if (!read_color(db, "window.label.focus.textColor",
276                     &s_title_focused_color))
277         s_title_focused_color = color_new(0xff, 0xff, 0xff);
278     if (!read_color(db, "window.label.unfocus.textColor",
279                     &s_title_unfocused_color))
280         s_title_unfocused_color = color_new(0xff, 0xff, 0xff);
281
282     if (!read_appearance(db, "window.title.focus", a_focused_title))
283         set_default_appearance(a_focused_title);
284     if (!read_appearance(db, "window.title.unfocus", a_unfocused_title))
285         set_default_appearance(a_unfocused_title);
286     if (!read_appearance(db, "window.label.focus", a_focused_label))
287         set_default_appearance(a_focused_label);
288     if (!read_appearance(db, "window.label.unfocus", a_unfocused_label))
289         set_default_appearance(a_unfocused_label);
290     if (!read_appearance(db, "window.handle.focus", a_focused_handle))
291         set_default_appearance(a_focused_handle);
292     if (!read_appearance(db, "window.handle.unfocus", a_unfocused_handle))
293         set_default_appearance(a_unfocused_handle);
294     if (!read_appearance(db, "window.grip.focus", a_focused_grip))
295         set_default_appearance(a_focused_grip);
296     if (!read_appearance(db, "window.grip.unfocus", a_unfocused_grip))
297         set_default_appearance(a_unfocused_grip);
298
299     if (!read_appearance(db, "window.button.pressed.focus",
300                          a_focused_pressed_max))
301         if (!read_appearance(db, "window.button.pressed",
302                              a_focused_pressed_max))
303             set_default_appearance(a_focused_pressed_max);
304     if (!read_appearance(db, "window.button.pressed.unfocus",
305                          a_unfocused_pressed_max))
306         if (!read_appearance(db, "window.button.pressed",
307                              a_unfocused_pressed_max))
308             set_default_appearance(a_unfocused_pressed_max);
309     if (!read_appearance(db, "window.button.focus",
310                          a_focused_unpressed_max))
311             set_default_appearance(a_focused_unpressed_max);
312     if (!read_appearance(db, "window.button.unfocus",
313                          a_unfocused_unpressed_max))
314             set_default_appearance(a_unfocused_unpressed_max);
315
316     a_unfocused_unpressed_close = appearance_copy(a_unfocused_unpressed_max);
317     a_unfocused_pressed_close = appearance_copy(a_unfocused_pressed_max);
318     a_focused_unpressed_close = appearance_copy(a_focused_unpressed_max);
319     a_focused_pressed_close = appearance_copy(a_focused_pressed_max);
320     a_unfocused_unpressed_desk = appearance_copy(a_unfocused_unpressed_max);
321     a_unfocused_pressed_desk = appearance_copy(a_unfocused_pressed_max);
322     a_focused_unpressed_desk = appearance_copy(a_focused_unpressed_max);
323     a_focused_pressed_desk = appearance_copy(a_focused_pressed_max);
324     a_unfocused_unpressed_iconify = appearance_copy(a_unfocused_unpressed_max);
325     a_unfocused_pressed_iconify = appearance_copy(a_unfocused_pressed_max);
326     a_focused_unpressed_iconify = appearance_copy(a_focused_unpressed_max);
327     a_focused_pressed_iconify = appearance_copy(a_focused_pressed_max);
328
329     a_icon->surface.data.planar.grad = Background_ParentRelative;
330
331
332     /* XXX load the button masks */
333
334     XrmDestroyDatabase(db);
335     return TRUE;
336 }
337
338