]> Dogcows Code - chaz/openbox/blob - parser/parse.c
make openbox base-dir spec compliant, and change the theme dir structure, so that...
[chaz/openbox] / parser / parse.c
1 #include "parse.h"
2 #include <glib.h>
3 #include <string.h>
4 #include <sys/stat.h>
5 #include <sys/types.h>
6
7 static gboolean xdg_start;
8 static gchar *xdg_config_home_path;
9 static gchar *xdg_data_home_path;
10 static GSList *xdg_config_dir_paths;
11 static GSList *xdg_data_dir_paths;
12
13 struct Callback {
14 char *tag;
15 ParseCallback func;
16 void *data;
17 };
18
19 struct _ObParseInst {
20 GHashTable *callbacks;
21 };
22
23 static void destfunc(struct Callback *c)
24 {
25 g_free(c->tag);
26 g_free(c);
27 }
28
29 ObParseInst* parse_startup()
30 {
31 ObParseInst *i = g_new(ObParseInst, 1);
32 i->callbacks = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
33 (GDestroyNotify)destfunc);
34 return i;
35 }
36
37 void parse_shutdown(ObParseInst *i)
38 {
39 if (i) {
40 g_hash_table_destroy(i->callbacks);
41 g_free(i);
42 }
43 }
44
45 void parse_register(ObParseInst *i, const char *tag,
46 ParseCallback func, void *data)
47 {
48 struct Callback *c;
49
50 if ((c = g_hash_table_lookup(i->callbacks, tag))) {
51 g_warning("tag '%s' already registered", tag);
52 return;
53 }
54
55 c = g_new(struct Callback, 1);
56 c->tag = g_strdup(tag);
57 c->func = func;
58 c->data = data;
59 g_hash_table_insert(i->callbacks, c->tag, c);
60 }
61
62 gboolean parse_load_rc(xmlDocPtr *doc, xmlNodePtr *root)
63 {
64 GSList *it;
65 gchar *path;
66 gboolean r = FALSE;
67
68 for (it = xdg_config_dir_paths; !r && it; it = g_slist_next(it)) {
69 path = g_build_filename(it->data, "openbox", "rc.xml", NULL);
70 r = parse_load(path, "openbox_config", doc, root);
71 g_free(path);
72 }
73 if (!r)
74 g_warning("unable to find a valid config file, using defaults");
75 return r;
76 }
77
78 gboolean parse_load_menu(const gchar *file, xmlDocPtr *doc, xmlNodePtr *root)
79 {
80 GSList *it;
81 gchar *path;
82 gboolean r = FALSE;
83
84 if (file[0] == '/') {
85 r = parse_load(file, "openbox_menu", doc, root);
86 } else {
87 for (it = xdg_config_dir_paths; !r && it; it = g_slist_next(it)) {
88 path = g_build_filename(it->data, "openbox", file, NULL);
89 r = parse_load(path, "openbox_menu", doc, root);
90 g_free(path);
91 }
92 }
93 if (!r)
94 g_warning("unable to find a valid menu file '%s'", file);
95 return r;
96 }
97
98 gboolean parse_load(const char *path, const char *rootname,
99 xmlDocPtr *doc, xmlNodePtr *root)
100 {
101 if ((*doc = xmlParseFile(path))) {
102 *root = xmlDocGetRootElement(*doc);
103 if (!*root) {
104 xmlFreeDoc(*doc);
105 *doc = NULL;
106 g_warning("%s is an empty document", path);
107 } else {
108 if (xmlStrcasecmp((*root)->name, (const xmlChar*)rootname)) {
109 xmlFreeDoc(*doc);
110 *doc = NULL;
111 g_warning("document %s is of wrong type. root node is "
112 "not '%s'", path, rootname);
113 }
114 }
115 }
116 if (!*doc)
117 return FALSE;
118 return TRUE;
119 }
120
121 gboolean parse_load_mem(gpointer data, guint len, const char *rootname,
122 xmlDocPtr *doc, xmlNodePtr *root)
123 {
124 if ((*doc = xmlParseMemory(data, len))) {
125 *root = xmlDocGetRootElement(*doc);
126 if (!*root) {
127 xmlFreeDoc(*doc);
128 *doc = NULL;
129 g_warning("Given memory is an empty document");
130 } else {
131 if (xmlStrcasecmp((*root)->name, (const xmlChar*)rootname)) {
132 xmlFreeDoc(*doc);
133 *doc = NULL;
134 g_warning("document in given memory is of wrong type. root "
135 "node is not '%s'", rootname);
136 }
137 }
138 }
139 if (!*doc)
140 return FALSE;
141 return TRUE;
142 }
143
144 void parse_close(xmlDocPtr doc)
145 {
146 xmlFree(doc);
147 }
148
149 void parse_tree(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
150 {
151 while (node) {
152 struct Callback *c = g_hash_table_lookup(i->callbacks, node->name);
153
154 if (c)
155 c->func(i, doc, node, c->data);
156
157 node = node->next;
158 }
159 }
160
161 char *parse_string(xmlDocPtr doc, xmlNodePtr node)
162 {
163 xmlChar *c = xmlNodeListGetString(doc, node->children, TRUE);
164 char *s = g_strdup(c ? (char*)c : "");
165 xmlFree(c);
166 return s;
167 }
168
169 int parse_int(xmlDocPtr doc, xmlNodePtr node)
170 {
171 xmlChar *c = xmlNodeListGetString(doc, node->children, TRUE);
172 int i = atoi((char*)c);
173 xmlFree(c);
174 return i;
175 }
176
177 gboolean parse_bool(xmlDocPtr doc, xmlNodePtr node)
178 {
179 xmlChar *c = xmlNodeListGetString(doc, node->children, TRUE);
180 gboolean b = FALSE;
181 if (!xmlStrcasecmp(c, (const xmlChar*) "true"))
182 b = TRUE;
183 else if (!xmlStrcasecmp(c, (const xmlChar*) "yes"))
184 b = TRUE;
185 else if (!xmlStrcasecmp(c, (const xmlChar*) "on"))
186 b = TRUE;
187 xmlFree(c);
188 return b;
189 }
190
191 gboolean parse_contains(const char *val, xmlDocPtr doc, xmlNodePtr node)
192 {
193 xmlChar *c = xmlNodeListGetString(doc, node->children, TRUE);
194 gboolean r;
195 r = !xmlStrcasecmp(c, (const xmlChar*) val);
196 xmlFree(c);
197 return r;
198 }
199
200 xmlNodePtr parse_find_node(const char *tag, xmlNodePtr node)
201 {
202 while (node) {
203 if (!xmlStrcasecmp(node->name, (const xmlChar*) tag))
204 return node;
205 node = node->next;
206 }
207 return NULL;
208 }
209
210 gboolean parse_attr_int(const char *name, xmlNodePtr node, int *value)
211 {
212 xmlChar *c = xmlGetProp(node, (const xmlChar*) name);
213 gboolean r = FALSE;
214 if (c) {
215 *value = atoi((char*)c);
216 r = TRUE;
217 }
218 xmlFree(c);
219 return r;
220 }
221
222 gboolean parse_attr_string(const char *name, xmlNodePtr node, char **value)
223 {
224 xmlChar *c = xmlGetProp(node, (const xmlChar*) name);
225 gboolean r = FALSE;
226 if (c) {
227 *value = g_strdup((char*)c);
228 r = TRUE;
229 }
230 xmlFree(c);
231 return r;
232 }
233
234 gboolean parse_attr_contains(const char *val, xmlNodePtr node,
235 const char *name)
236 {
237 xmlChar *c = xmlGetProp(node, (const xmlChar*) name);
238 gboolean r;
239 r = !xmlStrcasecmp(c, (const xmlChar*) val);
240 xmlFree(c);
241 return r;
242 }
243
244 static GSList* split_paths(const gchar *paths)
245 {
246 GSList *list = NULL;
247 gchar *c, *e, *s;
248
249 c = g_strdup(paths);
250 s = c;
251 e = c - 1;
252 g_message("paths %s", paths);
253 while ((e = strchr(e + 1, ':'))) {
254 *e = '\0';
255 g_message("s %s", s);
256 if (s[0] != '\0')
257 list = g_slist_append(list, g_strdup(s));
258 s = e + 1;
259 }
260 if (s[0] != '\0')
261 list = g_slist_append(list, g_strdup(s));
262 g_free(c);
263 return list;
264 }
265
266 void parse_paths_startup()
267 {
268 gchar *path;
269
270 if (xdg_start)
271 return;
272 xdg_start = TRUE;
273
274 path = getenv("XDG_CONFIG_HOME");
275 if (path && path[0] != '\0') /* not unset or empty */
276 xdg_config_home_path = g_build_filename(path, NULL);
277 else
278 xdg_config_home_path = g_build_filename(g_get_home_dir(), ".config",
279 NULL);
280
281 path = getenv("XDG_DATA_HOME");
282 if (path && path[0] != '\0') /* not unset or empty */
283 xdg_data_home_path = g_build_filename(path, NULL);
284 else
285 xdg_data_home_path = g_build_filename(g_get_home_dir(), ".local",
286 "share", NULL);
287
288 path = getenv("XDG_CONFIG_DIRS");
289 if (path && path[0] != '\0') /* not unset or empty */
290 xdg_config_dir_paths = split_paths(path);
291 else {
292 xdg_config_dir_paths = g_slist_append(xdg_config_dir_paths,
293 g_build_filename
294 (G_DIR_SEPARATOR_S,
295 "etc", "xdg", NULL));
296 xdg_config_dir_paths = g_slist_append(xdg_config_dir_paths,
297 g_strdup(CONFIGDIR));
298 }
299 xdg_config_dir_paths = g_slist_prepend(xdg_config_dir_paths,
300 xdg_config_home_path);
301
302 path = getenv("XDG_DATA_DIRS");
303 if (path && path[0] != '\0') /* not unset or empty */
304 xdg_data_dir_paths = split_paths(path);
305 else {
306 xdg_data_dir_paths = g_slist_append(xdg_data_dir_paths,
307 g_build_filename
308 (G_DIR_SEPARATOR_S,
309 "usr", "local", "share", NULL));
310 xdg_data_dir_paths = g_slist_append(xdg_data_dir_paths,
311 g_build_filename
312 (G_DIR_SEPARATOR_S,
313 "usr", "share", NULL));
314 xdg_config_dir_paths = g_slist_append(xdg_config_dir_paths,
315 g_strdup(DATADIR));
316 }
317 xdg_data_dir_paths = g_slist_prepend(xdg_data_dir_paths,
318 xdg_data_home_path);
319 }
320
321 void parse_paths_shutdown()
322 {
323 GSList *it;
324
325 if (!xdg_start)
326 return;
327 xdg_start = FALSE;
328
329 for (it = xdg_config_dir_paths; it; it = g_slist_next(it))
330 g_free(it->data);
331 g_slist_free(xdg_config_dir_paths);
332 xdg_config_dir_paths = NULL;
333 }
334
335 gchar *parse_expand_tilde(const gchar *f)
336 {
337 gchar **spl;
338 gchar *ret;
339
340 if (!f)
341 return NULL;
342 spl = g_strsplit(f, "~", 0);
343 ret = g_strjoinv(g_get_home_dir(), spl);
344 g_strfreev(spl);
345 return ret;
346 }
347
348 void parse_mkdir_path(const gchar *path, gint mode)
349 {
350 gchar *c, *e;
351
352 g_assert(path[0] == '/');
353
354 c = g_strdup(path);
355 e = c;
356 while ((e = strchr(e + 1, '/'))) {
357 *e = '\0';
358 mkdir(c, mode);
359 *e = '/';
360 }
361 mkdir(c, mode);
362 g_free(c);
363 }
364
365 const gchar* parse_xdg_config_home_path()
366 {
367 return xdg_config_home_path;
368 }
369
370 const gchar* parse_xdg_data_home_path()
371 {
372 return xdg_data_home_path;
373 }
374
375 GSList* parse_xdg_config_dir_paths()
376 {
377 return xdg_config_dir_paths;
378 }
379
380 GSList* parse_xdg_data_dir_paths()
381 {
382 return xdg_data_dir_paths;
383 }
This page took 0.0523 seconds and 4 git commands to generate.