1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 parse.c for the Openbox window manager
4 Copyright (c) 2003 Ben Jansens
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 See the COPYING file for a copy of the GNU General Public License.
23 #include <sys/types.h>
25 static gboolean xdg_start;
26 static gchar *xdg_config_home_path;
27 static gchar *xdg_data_home_path;
28 static GSList *xdg_config_dir_paths;
29 static GSList *xdg_data_dir_paths;
38 GHashTable *callbacks;
41 static void destfunc(struct Callback *c)
47 ObParseInst* parse_startup()
49 ObParseInst *i = g_new(ObParseInst, 1);
50 i->callbacks = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
51 (GDestroyNotify)destfunc);
55 void parse_shutdown(ObParseInst *i)
58 g_hash_table_destroy(i->callbacks);
63 void parse_register(ObParseInst *i, const char *tag,
64 ParseCallback func, void *data)
68 if ((c = g_hash_table_lookup(i->callbacks, tag))) {
69 g_warning("tag '%s' already registered", tag);
73 c = g_new(struct Callback, 1);
74 c->tag = g_strdup(tag);
77 g_hash_table_insert(i->callbacks, c->tag, c);
80 gboolean parse_load_rc(xmlDocPtr *doc, xmlNodePtr *root)
86 for (it = xdg_config_dir_paths; !r && it; it = g_slist_next(it)) {
87 path = g_build_filename(it->data, "openbox", "rc.xml", NULL);
88 r = parse_load(path, "openbox_config", doc, root);
92 g_warning("unable to find a valid config file, using defaults");
96 gboolean parse_load_menu(const gchar *file, xmlDocPtr *doc, xmlNodePtr *root)
102 if (file[0] == '/') {
103 r = parse_load(file, "openbox_menu", doc, root);
105 for (it = xdg_config_dir_paths; !r && it; it = g_slist_next(it)) {
106 path = g_build_filename(it->data, "openbox", file, NULL);
107 r = parse_load(path, "openbox_menu", doc, root);
112 g_warning("unable to find a valid menu file '%s'", file);
116 gboolean parse_load(const char *path, const char *rootname,
117 xmlDocPtr *doc, xmlNodePtr *root)
119 if ((*doc = xmlParseFile(path))) {
120 *root = xmlDocGetRootElement(*doc);
124 g_warning("%s is an empty document", path);
126 if (xmlStrcasecmp((*root)->name, (const xmlChar*)rootname)) {
129 g_warning("document %s is of wrong type. root node is "
130 "not '%s'", path, rootname);
139 gboolean parse_load_mem(gpointer data, guint len, const char *rootname,
140 xmlDocPtr *doc, xmlNodePtr *root)
142 if ((*doc = xmlParseMemory(data, len))) {
143 *root = xmlDocGetRootElement(*doc);
147 g_warning("Given memory is an empty document");
149 if (xmlStrcasecmp((*root)->name, (const xmlChar*)rootname)) {
152 g_warning("document in given memory is of wrong type. root "
153 "node is not '%s'", rootname);
162 void parse_close(xmlDocPtr doc)
167 void parse_tree(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
170 struct Callback *c = g_hash_table_lookup(i->callbacks, node->name);
173 c->func(i, doc, node, c->data);
179 char *parse_string(xmlDocPtr doc, xmlNodePtr node)
181 xmlChar *c = xmlNodeListGetString(doc, node->children, TRUE);
182 char *s = g_strdup(c ? (char*)c : "");
187 int parse_int(xmlDocPtr doc, xmlNodePtr node)
189 xmlChar *c = xmlNodeListGetString(doc, node->children, TRUE);
190 int i = atoi((char*)c);
195 gboolean parse_bool(xmlDocPtr doc, xmlNodePtr node)
197 xmlChar *c = xmlNodeListGetString(doc, node->children, TRUE);
199 if (!xmlStrcasecmp(c, (const xmlChar*) "true"))
201 else if (!xmlStrcasecmp(c, (const xmlChar*) "yes"))
203 else if (!xmlStrcasecmp(c, (const xmlChar*) "on"))
209 gboolean parse_contains(const char *val, xmlDocPtr doc, xmlNodePtr node)
211 xmlChar *c = xmlNodeListGetString(doc, node->children, TRUE);
213 r = !xmlStrcasecmp(c, (const xmlChar*) val);
218 xmlNodePtr parse_find_node(const char *tag, xmlNodePtr node)
221 if (!xmlStrcasecmp(node->name, (const xmlChar*) tag))
228 gboolean parse_attr_int(const char *name, xmlNodePtr node, int *value)
230 xmlChar *c = xmlGetProp(node, (const xmlChar*) name);
233 *value = atoi((char*)c);
240 gboolean parse_attr_string(const char *name, xmlNodePtr node, char **value)
242 xmlChar *c = xmlGetProp(node, (const xmlChar*) name);
245 *value = g_strdup((char*)c);
252 gboolean parse_attr_contains(const char *val, xmlNodePtr node,
255 xmlChar *c = xmlGetProp(node, (const xmlChar*) name);
257 r = !xmlStrcasecmp(c, (const xmlChar*) val);
262 static GSList* split_paths(const gchar *paths)
269 spl = g_strsplit(paths, ":", -1);
270 for (it = spl; *it; ++it)
271 list = g_slist_append(list, *it);
276 void parse_paths_startup()
284 path = getenv("XDG_CONFIG_HOME");
285 if (path && path[0] != '\0') /* not unset or empty */
286 xdg_config_home_path = g_build_filename(path, NULL);
288 xdg_config_home_path = g_build_filename(g_get_home_dir(), ".config",
291 path = getenv("XDG_DATA_HOME");
292 if (path && path[0] != '\0') /* not unset or empty */
293 xdg_data_home_path = g_build_filename(path, NULL);
295 xdg_data_home_path = g_build_filename(g_get_home_dir(), ".local",
298 path = getenv("XDG_CONFIG_DIRS");
299 if (path && path[0] != '\0') /* not unset or empty */
300 xdg_config_dir_paths = split_paths(path);
302 xdg_config_dir_paths = g_slist_append(xdg_config_dir_paths,
305 "etc", "xdg", NULL));
306 xdg_config_dir_paths = g_slist_append(xdg_config_dir_paths,
307 g_strdup(CONFIGDIR));
309 xdg_config_dir_paths = g_slist_prepend(xdg_config_dir_paths,
310 xdg_config_home_path);
312 path = getenv("XDG_DATA_DIRS");
313 if (path && path[0] != '\0') /* not unset or empty */
314 xdg_data_dir_paths = split_paths(path);
316 xdg_data_dir_paths = g_slist_append(xdg_data_dir_paths,
319 "usr", "local", "share", NULL));
320 xdg_data_dir_paths = g_slist_append(xdg_data_dir_paths,
323 "usr", "share", NULL));
324 xdg_data_dir_paths = g_slist_append(xdg_data_dir_paths,
327 xdg_data_dir_paths = g_slist_prepend(xdg_data_dir_paths,
331 void parse_paths_shutdown()
339 for (it = xdg_config_dir_paths; it; it = g_slist_next(it))
341 g_slist_free(xdg_config_dir_paths);
342 xdg_config_dir_paths = NULL;
343 for (it = xdg_data_dir_paths; it; it = g_slist_next(it))
345 g_slist_free(xdg_data_dir_paths);
346 xdg_data_dir_paths = NULL;
349 gchar *parse_expand_tilde(const gchar *f)
356 spl = g_strsplit(f, "~", 0);
357 ret = g_strjoinv(g_get_home_dir(), spl);
362 void parse_mkdir_path(const gchar *path, gint mode)
366 g_assert(path[0] == '/');
370 while ((e = strchr(e + 1, '/'))) {
379 const gchar* parse_xdg_config_home_path()
381 return xdg_config_home_path;
384 const gchar* parse_xdg_data_home_path()
386 return xdg_data_home_path;
389 GSList* parse_xdg_config_dir_paths()
391 return xdg_config_dir_paths;
394 GSList* parse_xdg_data_dir_paths()
396 return xdg_data_dir_paths;