X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=parser%2Fparse.c;h=e79eec6e6be3679b041e1d7a5ae06588feb82cd9;hb=c1b2fc5324522f74a14a5cfa210c95e1509a6e7f;hp=72643652e9ce588f5905a8c4a750d581517c9f67;hpb=0e69ae2b96fb4dd7435ebe15645d1384d11a3ef7;p=chaz%2Fopenbox diff --git a/parser/parse.c b/parser/parse.c index 72643652..e79eec6e 100644 --- a/parser/parse.c +++ b/parser/parse.c @@ -1,5 +1,14 @@ #include "parse.h" #include +#include +#include +#include + +static gboolean xdg_start; +static gchar *xdg_config_home_path; +static gchar *xdg_data_home_path; +static GSList *xdg_config_dir_paths; +static GSList *xdg_data_dir_paths; struct Callback { char *tag; @@ -7,7 +16,9 @@ struct Callback { void *data; }; -static GHashTable *callbacks; +struct _ObParseInst { + GHashTable *callbacks; +}; static void destfunc(struct Callback *c) { @@ -15,22 +26,28 @@ static void destfunc(struct Callback *c) g_free(c); } -void parse_startup() +ObParseInst* parse_startup() { - callbacks = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, - (GDestroyNotify)destfunc); + ObParseInst *i = g_new(ObParseInst, 1); + i->callbacks = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, + (GDestroyNotify)destfunc); + return i; } -void parse_shutdown() +void parse_shutdown(ObParseInst *i) { - g_hash_table_destroy(callbacks); + if (i) { + g_hash_table_destroy(i->callbacks); + g_free(i); + } } -void parse_register(const char *tag, ParseCallback func, void *data) +void parse_register(ObParseInst *i, const char *tag, + ParseCallback func, void *data) { struct Callback *c; - if ((c = g_hash_table_lookup(callbacks, tag))) { + if ((c = g_hash_table_lookup(i->callbacks, tag))) { g_warning("tag '%s' already registered", tag); return; } @@ -39,36 +56,48 @@ void parse_register(const char *tag, ParseCallback func, void *data) c->tag = g_strdup(tag); c->func = func; c->data = data; - g_hash_table_insert(callbacks, c->tag, c); + g_hash_table_insert(i->callbacks, c->tag, c); } gboolean parse_load_rc(xmlDocPtr *doc, xmlNodePtr *root) { - char *path; + GSList *it; + gchar *path; gboolean r = FALSE; - path = g_build_filename(g_get_home_dir(), ".openbox", "rc3", NULL); - if (parse_load(path, "openbox_config", doc, root)) { - r = TRUE; - } else { + for (it = xdg_config_dir_paths; !r && it; it = g_slist_next(it)) { + path = g_build_filename(it->data, "openbox", "rc.xml", NULL); + r = parse_load(path, "openbox_config", doc, root); g_free(path); - path = g_build_filename(RCDIR, "rc3", NULL); - if (parse_load(path, "openbox_config", doc, root)) { - r = TRUE; + } + if (!r) + g_warning("unable to find a valid config file, using defaults"); + return r; +} + +gboolean parse_load_menu(const gchar *file, xmlDocPtr *doc, xmlNodePtr *root) +{ + GSList *it; + gchar *path; + gboolean r = FALSE; + + if (file[0] == '/') { + r = parse_load(file, "openbox_menu", doc, root); + } else { + for (it = xdg_config_dir_paths; !r && it; it = g_slist_next(it)) { + path = g_build_filename(it->data, "openbox", file, NULL); + r = parse_load(path, "openbox_menu", doc, root); + g_free(path); } } - g_free(path); if (!r) - g_message("unable to find a valid config file, using defaults"); + g_warning("unable to find a valid menu file '%s'", file); return r; } gboolean parse_load(const char *path, const char *rootname, xmlDocPtr *doc, xmlNodePtr *root) { - - xmlLineNumbersDefault(1); - if ((*doc = xmlParseFile(path))) { *root = xmlDocGetRootElement(*doc); if (!*root) { @@ -79,8 +108,31 @@ gboolean parse_load(const char *path, const char *rootname, if (xmlStrcasecmp((*root)->name, (const xmlChar*)rootname)) { xmlFreeDoc(*doc); *doc = NULL; - g_warning("document %s is of wrong type. root *root is " - "not 'openbox_config'", path); + g_warning("document %s is of wrong type. root node is " + "not '%s'", path, rootname); + } + } + } + if (!*doc) + return FALSE; + return TRUE; +} + +gboolean parse_load_mem(gpointer data, guint len, const char *rootname, + xmlDocPtr *doc, xmlNodePtr *root) +{ + if ((*doc = xmlParseMemory(data, len))) { + *root = xmlDocGetRootElement(*doc); + if (!*root) { + xmlFreeDoc(*doc); + *doc = NULL; + g_warning("Given memory is an empty document"); + } else { + if (xmlStrcasecmp((*root)->name, (const xmlChar*)rootname)) { + xmlFreeDoc(*doc); + *doc = NULL; + g_warning("document in given memory is of wrong type. root " + "node is not '%s'", rootname); } } } @@ -94,13 +146,13 @@ void parse_close(xmlDocPtr doc) xmlFree(doc); } -void parse_tree(xmlDocPtr doc, xmlNodePtr node, void *nothing) +void parse_tree(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node) { while (node) { - struct Callback *c = g_hash_table_lookup(callbacks, node->name); + struct Callback *c = g_hash_table_lookup(i->callbacks, node->name); if (c) - c->func(doc, node, c->data); + c->func(i, doc, node, c->data); node = node->next; } @@ -108,15 +160,15 @@ void parse_tree(xmlDocPtr doc, xmlNodePtr node, void *nothing) char *parse_string(xmlDocPtr doc, xmlNodePtr node) { - xmlChar *c = xmlNodeListGetString(doc, node->xmlChildrenNode, TRUE); - char *s = g_strdup((char*)c); + xmlChar *c = xmlNodeListGetString(doc, node->children, TRUE); + char *s = g_strdup(c ? (char*)c : ""); xmlFree(c); return s; } int parse_int(xmlDocPtr doc, xmlNodePtr node) { - xmlChar *c = xmlNodeListGetString(doc, node->xmlChildrenNode, TRUE); + xmlChar *c = xmlNodeListGetString(doc, node->children, TRUE); int i = atoi((char*)c); xmlFree(c); return i; @@ -124,7 +176,7 @@ int parse_int(xmlDocPtr doc, xmlNodePtr node) gboolean parse_bool(xmlDocPtr doc, xmlNodePtr node) { - xmlChar *c = xmlNodeListGetString(doc, node->xmlChildrenNode, TRUE); + xmlChar *c = xmlNodeListGetString(doc, node->children, TRUE); gboolean b = FALSE; if (!xmlStrcasecmp(c, (const xmlChar*) "true")) b = TRUE; @@ -138,7 +190,7 @@ gboolean parse_bool(xmlDocPtr doc, xmlNodePtr node) gboolean parse_contains(const char *val, xmlDocPtr doc, xmlNodePtr node) { - xmlChar *c = xmlNodeListGetString(doc, node->xmlChildrenNode, TRUE); + xmlChar *c = xmlNodeListGetString(doc, node->children, TRUE); gboolean r; r = !xmlStrcasecmp(c, (const xmlChar*) val); xmlFree(c); @@ -188,3 +240,144 @@ gboolean parse_attr_contains(const char *val, xmlNodePtr node, xmlFree(c); return r; } + +static GSList* split_paths(const gchar *paths) +{ + GSList *list = NULL; + gchar *c, *e, *s; + + c = g_strdup(paths); + s = c; + e = c - 1; + g_message("paths %s", paths); + while ((e = strchr(e + 1, ':'))) { + *e = '\0'; + g_message("s %s", s); + if (s[0] != '\0') + list = g_slist_append(list, g_strdup(s)); + s = e + 1; + } + if (s[0] != '\0') + list = g_slist_append(list, g_strdup(s)); + g_free(c); + return list; +} + +void parse_paths_startup() +{ + gchar *path; + + if (xdg_start) + return; + xdg_start = TRUE; + + path = getenv("XDG_CONFIG_HOME"); + if (path && path[0] != '\0') /* not unset or empty */ + xdg_config_home_path = g_build_filename(path, NULL); + else + xdg_config_home_path = g_build_filename(g_get_home_dir(), ".config", + NULL); + + path = getenv("XDG_DATA_HOME"); + if (path && path[0] != '\0') /* not unset or empty */ + xdg_data_home_path = g_build_filename(path, NULL); + else + xdg_data_home_path = g_build_filename(g_get_home_dir(), ".local", + "share", NULL); + + path = getenv("XDG_CONFIG_DIRS"); + if (path && path[0] != '\0') /* not unset or empty */ + xdg_config_dir_paths = split_paths(path); + else { + xdg_config_dir_paths = g_slist_append(xdg_config_dir_paths, + g_build_filename + (G_DIR_SEPARATOR_S, + "etc", "xdg", NULL)); + xdg_config_dir_paths = g_slist_append(xdg_config_dir_paths, + g_strdup(CONFIGDIR)); + } + xdg_config_dir_paths = g_slist_prepend(xdg_config_dir_paths, + xdg_config_home_path); + + path = getenv("XDG_DATA_DIRS"); + if (path && path[0] != '\0') /* not unset or empty */ + xdg_data_dir_paths = split_paths(path); + else { + xdg_data_dir_paths = g_slist_append(xdg_data_dir_paths, + g_build_filename + (G_DIR_SEPARATOR_S, + "usr", "local", "share", NULL)); + xdg_data_dir_paths = g_slist_append(xdg_data_dir_paths, + g_build_filename + (G_DIR_SEPARATOR_S, + "usr", "share", NULL)); + xdg_config_dir_paths = g_slist_append(xdg_config_dir_paths, + g_strdup(DATADIR)); + } + xdg_data_dir_paths = g_slist_prepend(xdg_data_dir_paths, + xdg_data_home_path); +} + +void parse_paths_shutdown() +{ + GSList *it; + + if (!xdg_start) + return; + xdg_start = FALSE; + + for (it = xdg_config_dir_paths; it; it = g_slist_next(it)) + g_free(it->data); + g_slist_free(xdg_config_dir_paths); + xdg_config_dir_paths = NULL; +} + +gchar *parse_expand_tilde(const gchar *f) +{ + gchar **spl; + gchar *ret; + + if (!f) + return NULL; + spl = g_strsplit(f, "~", 0); + ret = g_strjoinv(g_get_home_dir(), spl); + g_strfreev(spl); + return ret; +} + +void parse_mkdir_path(const gchar *path, gint mode) +{ + gchar *c, *e; + + g_assert(path[0] == '/'); + + c = g_strdup(path); + e = c; + while ((e = strchr(e + 1, '/'))) { + *e = '\0'; + mkdir(c, mode); + *e = '/'; + } + mkdir(c, mode); + g_free(c); +} + +const gchar* parse_xdg_config_home_path() +{ + return xdg_config_home_path; +} + +const gchar* parse_xdg_data_home_path() +{ + return xdg_data_home_path; +} + +GSList* parse_xdg_config_dir_paths() +{ + return xdg_config_dir_paths; +} + +GSList* parse_xdg_data_dir_paths() +{ + return xdg_data_dir_paths; +}