merge the C branch into HEAD
[openbox.git] / engines / openbox / theme.c
blob2c96224f34821e4606da5dc0f96837a4202ad73e
1 #include "openbox.h"
2 #include "../../kernel/themerc.h"
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
17 static XrmDatabase loaddb(char *theme)
19 XrmDatabase db;
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);
28 if (db == NULL) {
29 char *s = g_build_filename(THEMEDIR, theme, NULL);
30 db = XrmGetFileDatabase(s);
31 g_free(s);
33 return db;
36 static char *create_class_name(char *rname)
38 char *rclass = g_strdup(rname);
39 char *p = rclass;
41 while (TRUE) {
42 *p = toupper(*p);
43 p = strchr(p+1, '.');
44 if (p == NULL) break;
45 ++p;
46 if (*p == '\0') break;
48 return rclass;
51 gboolean read_bool(XrmDatabase db, char *rname, gboolean *value)
53 gboolean ret = FALSE;
54 char *rclass = create_class_name(rname);
55 char *rettype;
56 XrmValue retvalue;
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;
67 g_free(rclass);
68 return ret;
71 gboolean read_int(XrmDatabase db, char *rname, int *value)
73 gboolean ret = FALSE;
74 char *rclass = create_class_name(rname);
75 char *rettype, *end;
76 XrmValue retvalue;
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;
85 g_free(rclass);
86 return ret;
89 gboolean read_string(XrmDatabase db, char *rname, char **value)
91 gboolean ret = FALSE;
92 char *rclass = create_class_name(rname);
93 char *rettype;
94 XrmValue retvalue;
96 if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) &&
97 retvalue.addr != NULL) {
98 *value = retvalue.addr;
99 ret = TRUE;
102 g_free(rclass);
103 return ret;
106 gboolean read_color(XrmDatabase db, char *rname, color_rgb **value)
108 gboolean ret = FALSE;
109 char *rclass = create_class_name(rname);
110 char *rettype;
111 XrmValue retvalue;
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;
122 g_free(rclass);
123 return ret;
126 static void parse_appearance(char *tex, SurfaceColorType *grad,
127 ReliefType *relief, BevelType *bevel,
128 gboolean *interlaced, gboolean *border)
130 char *t;
132 /* convert to all lowercase */
133 for (t = tex; *t != '\0'; ++t)
134 *t = g_ascii_tolower(*t);
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;
160 if (strstr(tex, "sunken") != NULL)
161 *relief = Sunken;
162 else if (strstr(tex, "flat") != NULL)
163 *relief = Flat;
164 else
165 *relief = Raised;
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;
178 if (strstr(tex, "interlaced") != NULL)
179 *interlaced = TRUE;
180 else
181 *interlaced = FALSE;
186 gboolean read_appearance(XrmDatabase db, char *rname, Appearance *value)
188 gboolean ret = FALSE;
189 char *rclass = create_class_name(rname), *cname, *ctoname, *bcname;
190 char *rettype;
191 XrmValue retvalue;
193 cname = g_strconcat(rname, ".color", NULL);
194 ctoname = g_strconcat(rname, ".colorTo", NULL);
195 bcname = g_strconcat(rname, ".borderColor", NULL);
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;
216 g_free(bcname);
217 g_free(ctoname);
218 g_free(cname);
219 g_free(rclass);
220 return ret;
223 void set_default_appearance(Appearance *a)
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);
234 gboolean load()
236 XrmDatabase db = NULL;
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);
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;
253 /* XXX load the font, not from the theme file tho, its in themerc_font */
254 s_font_height = 10;
256 if (!read_int(db, "handleWidth", &s_handle_height) ||
257 s_handle_height < 0 || s_handle_height > 100) s_handle_height = 6;
258 if (!read_int(db, "bevelWidth", &s_bevel) ||
259 s_bevel <= 0 || s_bevel > 100) s_bevel = 3;
260 if (!read_int(db, "borderWidth", &s_bwidth) ||
261 s_bwidth < 0 || s_bwidth > 100) s_bwidth = 1;
262 if (!read_int(db, "frameWidth", &s_cbwidth) ||
263 s_cbwidth < 0 || s_cbwidth > 100) s_cbwidth = s_bevel;
265 if (!read_color(db, "borderColor", &s_b_color))
266 s_b_color = color_new(0, 0, 0);
267 if (!read_color(db, "window.frame.focusColor", &s_cb_focused_color))
268 s_cb_focused_color = color_new(0xff, 0xff, 0xff);
269 if (!read_color(db, "window.frame.unfocusColor", &s_cb_unfocused_color))
270 s_cb_unfocused_color = color_new(0xff, 0xff, 0xff);
272 if (!read_appearance(db, "window.title.focus", a_focused_title))
273 set_default_appearance(a_focused_title);
274 if (!read_appearance(db, "window.title.unfocus", a_unfocused_title))
275 set_default_appearance(a_unfocused_title);
276 if (!read_appearance(db, "window.label.focus", a_focused_label))
277 set_default_appearance(a_focused_label);
278 if (!read_appearance(db, "window.label.unfocus", a_unfocused_label))
279 set_default_appearance(a_unfocused_label);
280 if (!read_appearance(db, "window.handle.focus", a_focused_handle))
281 set_default_appearance(a_focused_handle);
282 if (!read_appearance(db, "window.handle.unfocus", a_unfocused_handle))
283 set_default_appearance(a_unfocused_handle);
284 if (!read_appearance(db, "window.grip.focus", a_focused_grip))
285 set_default_appearance(a_focused_grip);
286 if (!read_appearance(db, "window.grip.unfocus", a_unfocused_grip))
287 set_default_appearance(a_unfocused_grip);
289 if (!read_appearance(db, "window.button.pressed.focus",
290 a_focused_pressed_max))
291 if (!read_appearance(db, "window.button.pressed",
292 a_focused_pressed_max))
293 set_default_appearance(a_focused_pressed_max);
294 if (!read_appearance(db, "window.button.pressed.unfocus",
295 a_unfocused_pressed_max))
296 if (!read_appearance(db, "window.button.pressed",
297 a_unfocused_pressed_max))
298 set_default_appearance(a_unfocused_pressed_max);
299 if (!read_appearance(db, "window.button.focus",
300 a_focused_unpressed_max))
301 set_default_appearance(a_focused_unpressed_max);
302 if (!read_appearance(db, "window.button.unfocus",
303 a_unfocused_unpressed_max))
304 set_default_appearance(a_unfocused_unpressed_max);
306 a_unfocused_unpressed_close = appearance_copy(a_unfocused_unpressed_max);
307 a_unfocused_pressed_close = appearance_copy(a_unfocused_pressed_max);
308 a_focused_unpressed_close = appearance_copy(a_focused_unpressed_max);
309 a_focused_pressed_close = appearance_copy(a_focused_pressed_max);
310 a_unfocused_unpressed_desk = appearance_copy(a_unfocused_unpressed_max);
311 a_unfocused_pressed_desk = appearance_copy(a_unfocused_pressed_max);
312 a_focused_unpressed_desk = appearance_copy(a_focused_unpressed_max);
313 a_focused_pressed_desk = appearance_copy(a_focused_pressed_max);
314 a_unfocused_unpressed_iconify = appearance_copy(a_unfocused_unpressed_max);
315 a_unfocused_pressed_iconify = appearance_copy(a_unfocused_pressed_max);
316 a_focused_unpressed_iconify = appearance_copy(a_focused_unpressed_max);
317 a_focused_pressed_iconify = appearance_copy(a_focused_pressed_max);
319 a_icon->surface.data.planar.grad = Background_ParentRelative;
321 /* XXX load the button masks */
323 XrmDestroyDatabase(db);
324 return TRUE;