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