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)
270 g_message("paths %s", paths);
271 while ((e = strchr(e + 1, ':'))) {
273 g_message("s %s", s);
275 list = g_slist_append(list, g_strdup(s));
279 list = g_slist_append(list, g_strdup(s));
284 void parse_paths_startup()
292 path = getenv("XDG_CONFIG_HOME");
293 if (path && path[0] != '\0') /* not unset or empty */
294 xdg_config_home_path = g_build_filename(path, NULL);
296 xdg_config_home_path = g_build_filename(g_get_home_dir(), ".config",
299 path = getenv("XDG_DATA_HOME");
300 if (path && path[0] != '\0') /* not unset or empty */
301 xdg_data_home_path = g_build_filename(path, NULL);
303 xdg_data_home_path = g_build_filename(g_get_home_dir(), ".local",
306 path = getenv("XDG_CONFIG_DIRS");
307 if (path && path[0] != '\0') /* not unset or empty */
308 xdg_config_dir_paths = split_paths(path);
310 xdg_config_dir_paths = g_slist_append(xdg_config_dir_paths,
313 "etc", "xdg", NULL));
314 xdg_config_dir_paths = g_slist_append(xdg_config_dir_paths,
315 g_strdup(CONFIGDIR));
317 xdg_config_dir_paths = g_slist_prepend(xdg_config_dir_paths,
318 xdg_config_home_path);
320 path = getenv("XDG_DATA_DIRS");
321 if (path && path[0] != '\0') /* not unset or empty */
322 xdg_data_dir_paths = split_paths(path);
324 xdg_data_dir_paths = g_slist_append(xdg_data_dir_paths,
327 "usr", "local", "share", NULL));
328 xdg_data_dir_paths = g_slist_append(xdg_data_dir_paths,
331 "usr", "share", NULL));
332 xdg_data_dir_paths = g_slist_append(xdg_data_dir_paths,
335 xdg_data_dir_paths = g_slist_prepend(xdg_data_dir_paths,
339 void parse_paths_shutdown()
347 for (it = xdg_config_dir_paths; it; it = g_slist_next(it))
349 g_slist_free(xdg_config_dir_paths);
350 xdg_config_dir_paths = NULL;
351 for (it = xdg_data_dir_paths; it; it = g_slist_next(it))
353 g_slist_free(xdg_data_dir_paths);
354 xdg_data_dir_paths = NULL;
357 gchar *parse_expand_tilde(const gchar *f)
364 spl = g_strsplit(f, "~", 0);
365 ret = g_strjoinv(g_get_home_dir(), spl);
370 void parse_mkdir_path(const gchar *path, gint mode)
374 g_assert(path[0] == '/');
378 while ((e = strchr(e + 1, '/'))) {
387 const gchar* parse_xdg_config_home_path()
389 return xdg_config_home_path;
392 const gchar* parse_xdg_data_home_path()
394 return xdg_data_home_path;
397 GSList* parse_xdg_config_dir_paths()
399 return xdg_config_dir_paths;
402 GSList* parse_xdg_data_dir_paths()
404 return xdg_data_dir_paths;