1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 frame_default_config.c for the Openbox window manager
4 Copyright (c) 2006 Mikael Magnusson
5 Copyright (c) 2003-2007 Dana Jansens
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 See the COPYING file for a copy of the GNU General Public License.
20 #include "frame_concept2_config.h"
21 #include "frame_concept2_plugin.h"
23 #include "render/render.h"
24 #include "render/color.h"
25 #include "render/font.h"
26 #include "render/mask.h"
27 #include "render/icon.h"
28 #include "parser/parse.h"
36 static XrmDatabase loaddb(const gchar *name, gchar **path);
37 static gboolean read_int(XrmDatabase db, const gchar *rname, gint *value);
38 static gboolean read_string(XrmDatabase db, const gchar *rname, gchar **value);
39 static gboolean read_color(XrmDatabase db, const RrInstance *inst,
40 const gchar *rname, RrColor **value);
41 static gboolean read_mask(const RrInstance *inst, const gchar *path,
42 ObFrameThemeConfig *theme, const gchar *maskname, RrPixmapMask **value);
43 static gboolean read_appearance(XrmDatabase db, const RrInstance *inst,
44 const gchar *rname, RrAppearance *value, gboolean allow_trans);
45 static int parse_inline_number(const char *p);
46 static RrPixel32* read_c_image(gint width, gint height, const guint8 *data);
47 static void set_default_appearance(RrAppearance *a);
49 gint load_theme_config(const RrInstance *inst, const gchar *name,
50 const gchar * path, XrmDatabase db, RrFont *active_window_font,
51 RrFont *inactive_window_font, RrFont *menu_title_font,
52 RrFont *menu_item_font, RrFont *osd_font)
56 if (!read_int(db, "concept.border_width", &theme_config.border_width)) {
57 theme_config.border_width = 2;
59 if (!read_int(db, "concept.left_width", &theme_config.left_width)) {
60 theme_config.left_width = 15;
62 if (!read_color(db, inst, "concept.focus_border_color",
63 &theme_config.focus_border_color)) {
64 theme_config.focus_border_color = RrColorNew(inst, 0, 0, 0);
67 if (!read_color(db, inst, "concept.focus_corner_color",
68 &theme_config.focus_corner_color)) {
69 theme_config.focus_corner_color = RrColorNew(inst, 0, 0, 0);
72 if (!read_color(db, inst, "concept.unfocus_border_color",
73 &theme_config.unfocus_border_color)) {
74 theme_config.focus_border_color = RrColorNew(inst, 0, 0, 0);
77 if (!read_color(db, inst, "concept.unfocus_corner_color",
78 &theme_config.unfocus_corner_color)) {
79 theme_config.focus_corner_color = RrColorNew(inst, 0, 0, 0);
82 theme_config.inst = inst;
83 theme_config.name = g_strdup(name ? name : DEFAULT_THEME);
88 static XrmDatabase loaddb(const gchar *name, gchar **path)
91 XrmDatabase db = NULL;
95 s = g_build_filename(name, "openbox-3", "themerc", NULL);
96 if ((db = XrmGetFileDatabase(s)))
97 *path = g_path_get_dirname(s);
101 /* XXX backwards compatibility, remove me sometime later */
102 s = g_build_filename(g_get_home_dir(), ".themes", name, "openbox-3",
104 if ((db = XrmGetFileDatabase(s)))
105 *path = g_path_get_dirname(s);
108 for (it = parse_xdg_data_dir_paths(); !db && it; it = g_slist_next(it)) {
109 s = g_build_filename(it->data, "themes", name, "openbox-3",
111 if ((db = XrmGetFileDatabase(s)))
112 *path = g_path_get_dirname(s);
118 s = g_build_filename(name, "themerc", NULL);
119 if ((db = XrmGetFileDatabase(s)))
120 *path = g_path_get_dirname(s);
127 static gchar *create_class_name(const gchar *rname)
129 gchar *rclass = g_strdup(rname);
134 p = strchr(p+1, '.');
144 static gboolean read_int(XrmDatabase db, const gchar *rname, gint *value)
146 gboolean ret = FALSE;
147 gchar *rclass = create_class_name(rname);
148 gchar *rettype, *end;
151 if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) && retvalue.addr
153 *value = (gint)strtol(retvalue.addr, &end, 10);
154 if (end != retvalue.addr)
162 static gboolean read_string(XrmDatabase db, const gchar *rname, gchar **value)
164 gboolean ret = FALSE;
165 gchar *rclass = create_class_name(rname);
169 if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) && retvalue.addr
171 *value = retvalue.addr;
179 static gboolean read_color(XrmDatabase db, const RrInstance *inst,
180 const gchar *rname, RrColor **value)
182 gboolean ret = FALSE;
183 gchar *rclass = create_class_name(rname);
187 if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) && retvalue.addr
189 RrColor *c = RrColorParse(inst, retvalue.addr);
200 static gboolean read_mask(const RrInstance *inst, const gchar *path,
201 ObFrameThemeConfig *theme, const gchar *maskname, RrPixmapMask **value)
203 gboolean ret = FALSE;
205 gint hx, hy; /* ignored */
209 s = g_build_filename(path, maskname, NULL);
210 if (XReadBitmapFileData(s, &w, &h, &b, &hx, &hy) == BitmapSuccess) {
212 *value = RrPixmapMaskNew(inst, w, h, (gchar*)b);
220 static void parse_appearance(gchar *tex, RrSurfaceColorType *grad,
221 RrReliefType *relief, RrBevelType *bevel, gboolean *interlaced,
222 gboolean *border, gboolean allow_trans)
226 /* convert to all lowercase */
227 for (t = tex; *t != '\0'; ++t)
228 *t = g_ascii_tolower(*t);
230 if (allow_trans && strstr(tex, "parentrelative") != NULL) {
231 *grad = RR_SURFACE_PARENTREL;
234 if (strstr(tex, "gradient") != NULL) {
235 if (strstr(tex, "crossdiagonal") != NULL)
236 *grad = RR_SURFACE_CROSS_DIAGONAL;
237 else if (strstr(tex, "pyramid") != NULL)
238 *grad = RR_SURFACE_PYRAMID;
239 else if (strstr(tex, "mirrorhorizontal") != NULL)
240 *grad = RR_SURFACE_MIRROR_HORIZONTAL;
241 else if (strstr(tex, "horizontal") != NULL)
242 *grad = RR_SURFACE_HORIZONTAL;
243 else if (strstr(tex, "splitvertical") != NULL)
244 *grad = RR_SURFACE_SPLIT_VERTICAL;
245 else if (strstr(tex, "vertical") != NULL)
246 *grad = RR_SURFACE_VERTICAL;
248 *grad = RR_SURFACE_DIAGONAL;
251 *grad = RR_SURFACE_SOLID;
255 if (strstr(tex, "sunken") != NULL)
256 *relief = RR_RELIEF_SUNKEN;
257 else if (strstr(tex, "flat") != NULL)
258 *relief = RR_RELIEF_FLAT;
259 else if (strstr(tex, "raised") != NULL)
260 *relief = RR_RELIEF_RAISED;
262 *relief = (*grad == RR_SURFACE_PARENTREL) ? RR_RELIEF_FLAT
266 if (*relief == RR_RELIEF_FLAT) {
267 if (strstr(tex, "border") != NULL)
271 if (strstr(tex, "bevel2") != NULL)
277 if (strstr(tex, "interlaced") != NULL)
283 static gboolean read_appearance(XrmDatabase db, const RrInstance *inst,
284 const gchar *rname, RrAppearance *value, gboolean allow_trans)
286 gboolean ret = FALSE;
287 gchar *rclass = create_class_name(rname);
288 gchar *cname, *ctoname, *bcname, *icname, *hname, *sname;
289 gchar *csplitname, *ctosplitname;
294 cname = g_strconcat(rname, ".color", NULL);
295 ctoname = g_strconcat(rname, ".colorTo", NULL);
296 bcname = g_strconcat(rname, ".border.color", NULL);
297 icname = g_strconcat(rname, ".interlace.color", NULL);
298 hname = g_strconcat(rname, ".highlight", NULL);
299 sname = g_strconcat(rname, ".shadow", NULL);
300 csplitname = g_strconcat(rname, ".color.splitTo", NULL);
301 ctosplitname = g_strconcat(rname, ".colorTo.splitTo", NULL);
303 if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) && retvalue.addr
305 parse_appearance(retvalue.addr, &value->surface.grad,
306 &value->surface.relief, &value->surface.bevel,
307 &value->surface.interlaced, &value->surface.border, allow_trans);
308 if (!read_color(db, inst, cname, &value->surface.primary))
309 value->surface.primary = RrColorNew(inst, 0, 0, 0);
310 if (!read_color(db, inst, ctoname, &value->surface.secondary))
311 value->surface.secondary = RrColorNew(inst, 0, 0, 0);
312 if (value->surface.border)
313 if (!read_color(db, inst, bcname, &value->surface.border_color))
314 value->surface.border_color = RrColorNew(inst, 0, 0, 0);
315 if (value->surface.interlaced)
316 if (!read_color(db, inst, icname, &value->surface.interlace_color))
317 value->surface.interlace_color = RrColorNew(inst, 0, 0, 0);
318 if (read_int(db, hname, &i) && i >= 0)
319 value->surface.bevel_light_adjust = i;
320 if (read_int(db, sname, &i) && i >= 0 && i <= 256)
321 value->surface.bevel_dark_adjust = i;
323 if (value->surface.grad == RR_SURFACE_SPLIT_VERTICAL) {
326 if (!read_color(db, inst, csplitname, &value->surface.split_primary)) {
327 r = value->surface.primary->r;
329 g = value->surface.primary->g;
331 b = value->surface.primary->b;
339 value->surface.split_primary = RrColorNew(inst, r, g, b);
342 if (!read_color(db, inst, ctosplitname,
343 &value->surface.split_secondary)) {
344 r = value->surface.secondary->r;
346 g = value->surface.secondary->g;
348 b = value->surface.secondary->b;
356 value->surface.split_secondary = RrColorNew(inst, r, g, b);
363 g_free(ctosplitname);
375 static int parse_inline_number(const char *p)
383 for (; isdigit(*p); ++p)
384 res = res * 10 + *p - '0';
389 static void set_default_appearance(RrAppearance *a)
391 a->surface.grad = RR_SURFACE_SOLID;
392 a->surface.relief = RR_RELIEF_FLAT;
393 a->surface.bevel = RR_BEVEL_1;
394 a->surface.interlaced = FALSE;
395 a->surface.border = FALSE;
396 a->surface.primary = RrColorNew(a->inst, 0, 0, 0);
397 a->surface.secondary = RrColorNew(a->inst, 0, 0, 0);
400 /* Reads the output from gimp's C-Source file format into valid RGBA data for
402 static RrPixel32* read_c_image(gint width, gint height, const guint8 *data)
407 p = im = g_memdup(data, width * height * sizeof(RrPixel32));
409 for (i = 0; i < width * height; ++i) {
410 guchar a = ((*p >> 24) & 0xff);
411 guchar b = ((*p >> 16) & 0xff);
412 guchar g = ((*p >> 8) & 0xff);
413 guchar r = ((*p >> 0) & 0xff);
415 *p = ((r << RrDefaultRedOffset) + (g << RrDefaultGreenOffset) + (b
416 << RrDefaultBlueOffset) + (a << RrDefaultAlphaOffset));