]>
Dogcows Code - chaz/openbox/blob - obt/xml.c
1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 obt/xml.c for the Openbox window manager
4 Copyright (c) 2003-2007 Dana 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.
20 #include "obt/paths.h"
27 #ifdef HAVE_SYS_STAT_H
28 # include <sys/stat.h>
30 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>
46 GHashTable
*callbacks
;
52 static void destfunc(struct Callback
*c
)
55 g_slice_free(struct Callback
, c
);
58 ObtXmlInst
* obt_xml_instance_new(void)
60 ObtXmlInst
*i
= g_slice_new(ObtXmlInst
);
62 i
->xdg_paths
= obt_paths_new();
63 i
->callbacks
= g_hash_table_new_full(g_str_hash
, g_str_equal
, NULL
,
64 (GDestroyNotify
)destfunc
);
71 void obt_xml_instance_ref(ObtXmlInst
*i
)
76 void obt_xml_instance_unref(ObtXmlInst
*i
)
78 if (i
&& --i
->ref
== 0) {
79 obt_paths_unref(i
->xdg_paths
);
80 g_hash_table_destroy(i
->callbacks
);
81 g_slice_free(ObtXmlInst
, i
);
85 xmlDocPtr
obt_xml_doc(ObtXmlInst
*i
)
87 g_assert(i
->doc
); /* a doc is open? */
91 xmlNodePtr
obt_xml_root(ObtXmlInst
*i
)
93 g_assert(i
->doc
); /* a doc is open? */
97 void obt_xml_register(ObtXmlInst
*i
, const gchar
*tag
,
98 ObtXmlCallback func
, gpointer data
)
102 if (g_hash_table_lookup(i
->callbacks
, tag
)) {
103 g_error("Tag '%s' already registered", tag
);
107 c
= g_slice_new(struct Callback
);
108 c
->tag
= g_strdup(tag
);
111 g_hash_table_insert(i
->callbacks
, c
->tag
, c
);
114 static gboolean
load_file(ObtXmlInst
*i
,
116 const gchar
*filename
,
117 const gchar
*root_node
,
123 g_assert(i
->doc
== NULL
); /* another doc isn't open already? */
125 for (it
= paths
; !r
&& it
; it
= g_slist_next(it
)) {
129 if (!domain
&& !filename
) /* given a full path to the file */
130 path
= g_strdup(it
->data
);
132 path
= g_build_filename(it
->data
, domain
, filename
, NULL
);
134 if (stat(path
, &s
) >= 0) {
135 /* XML_PARSE_BLANKS is needed apparently, or the tree can end up
136 with extra nodes in it. */
137 i
->doc
= xmlReadFile(path
, NULL
, (XML_PARSE_NOBLANKS
|
139 XML_PARSE_XINCLUDE
));
141 i
->root
= xmlDocGetRootElement(i
->doc
);
145 g_message("%s is an empty XML document", path
);
147 else if (xmlStrcmp(i
->root
->name
,
148 (const xmlChar
*)root_node
)) {
152 g_message("XML document %s is of wrong type. Root "
153 "node is not '%s'", path
, root_node
);
156 i
->path
= g_strdup(path
);
168 gboolean
obt_xml_load_file(ObtXmlInst
*i
,
170 const gchar
*root_node
)
175 paths
= g_slist_append(NULL
, g_strdup(path
));
177 r
= load_file(i
, NULL
, NULL
, root_node
, paths
);
181 paths
= g_slist_delete_link(paths
, paths
);
186 gboolean
obt_xml_load_config_file(ObtXmlInst
*i
,
188 const gchar
*filename
,
189 const gchar
*root_node
)
191 GSList
*it
, *paths
= NULL
;
194 for (it
= obt_paths_config_dirs(i
->xdg_paths
); it
; it
= g_slist_next(it
))
195 paths
= g_slist_append(paths
, g_strdup(it
->data
));
197 r
= load_file(i
, domain
, filename
, root_node
, paths
);
201 paths
= g_slist_delete_link(paths
, paths
);
206 gboolean
obt_xml_load_data_file(ObtXmlInst
*i
,
208 const gchar
*filename
,
209 const gchar
*root_node
)
211 GSList
*it
, *paths
= NULL
;
214 for (it
= obt_paths_data_dirs(i
->xdg_paths
); it
; it
= g_slist_next(it
))
215 paths
= g_slist_append(paths
, g_strdup(it
->data
));
217 r
= load_file(i
, domain
, filename
, root_node
, paths
);
221 paths
= g_slist_delete_link(paths
, paths
);
226 gboolean
obt_xml_load_theme_file(ObtXmlInst
*i
,
229 const gchar
*filename
,
230 const gchar
*root_node
)
232 GSList
*it
, *paths
= NULL
;
235 /* use ~/.themes for backwards compatibility */
236 paths
= g_slist_append
237 (paths
, g_build_filename(g_get_home_dir(), ".themes", theme
, NULL
));
239 for (it
= obt_paths_data_dirs(i
->xdg_paths
); it
; it
= g_slist_next(it
))
240 paths
= g_slist_append
241 (paths
, g_build_filename(it
->data
, "themes", theme
, NULL
));
243 r
= load_file(i
, domain
, filename
, root_node
, paths
);
247 paths
= g_slist_delete_link(paths
, paths
);
253 gboolean
obt_xml_load_mem(ObtXmlInst
*i
,
254 gpointer data
, guint len
, const gchar
*root_node
)
258 g_assert(i
->doc
== NULL
); /* another doc isn't open already? */
260 i
->doc
= xmlParseMemory(data
, len
);
262 i
->root
= xmlDocGetRootElement(i
->doc
);
266 g_message("Given memory is an empty document");
268 else if (xmlStrcmp(i
->root
->name
, (const xmlChar
*)root_node
)) {
272 g_message("XML Document in given memory is of wrong "
273 "type. Root node is not '%s'\n", root_node
);
281 gboolean
obt_xml_save_file(ObtXmlInst
*inst
,
285 return xmlSaveFormatFile(path
, inst
->doc
, pretty
) != -1;
288 void obt_xml_close(ObtXmlInst
*i
)
299 void obt_xml_tree(ObtXmlInst
*i
, xmlNodePtr node
)
301 g_assert(i
->doc
); /* a doc is open? */
305 struct Callback
*c
= g_hash_table_lookup(i
->callbacks
, node
->name
);
306 if (c
) c
->func(node
, c
->data
);
312 void obt_xml_tree_from_root(ObtXmlInst
*i
)
314 obt_xml_tree(i
, i
->root
->children
);
317 gchar
*obt_xml_node_string(xmlNodePtr node
)
319 xmlChar
*c
= xmlNodeGetContent(node
);
321 if (c
) g_strstrip((char*)c
); /* strip leading/trailing whitespace */
322 s
= g_strdup(c
? (gchar
*)c
: "");
327 gint
obt_xml_node_int(xmlNodePtr node
)
329 xmlChar
*c
= xmlNodeGetContent(node
);
331 if (c
) g_strstrip((char*)c
); /* strip leading/trailing whitespace */
332 i
= c
? atoi((gchar
*)c
) : 0;
337 gboolean
obt_xml_node_bool(xmlNodePtr node
)
339 xmlChar
*c
= xmlNodeGetContent(node
);
341 if (c
) g_strstrip((char*)c
); /* strip leading/trailing whitespace */
342 if (c
&& !xmlStrcasecmp(c
, (const xmlChar
*) "true"))
344 else if (c
&& !xmlStrcasecmp(c
, (const xmlChar
*) "yes"))
346 else if (c
&& !xmlStrcasecmp(c
, (const xmlChar
*) "on"))
352 gboolean
obt_xml_node_contains(xmlNodePtr node
, const gchar
*val
)
354 xmlChar
*c
= xmlNodeGetContent(node
);
356 if (c
) g_strstrip((char*)c
); /* strip leading/trailing whitespace */
357 r
= !xmlStrcasecmp(c
, (const xmlChar
*) val
);
362 xmlNodePtr
obt_xml_find_node(xmlNodePtr node
, const gchar
*tag
)
365 if (!xmlStrcmp(node
->name
, (const xmlChar
*) tag
))
372 gboolean
obt_xml_attr_bool(xmlNodePtr node
, const gchar
*name
,
375 xmlChar
*c
= xmlGetProp(node
, (const xmlChar
*) name
);
378 g_strstrip((char*)c
); /* strip leading/trailing whitespace */
379 if (!xmlStrcasecmp(c
, (const xmlChar
*) "true"))
380 *value
= TRUE
, r
= TRUE
;
381 else if (!xmlStrcasecmp(c
, (const xmlChar
*) "yes"))
382 *value
= TRUE
, r
= TRUE
;
383 else if (!xmlStrcasecmp(c
, (const xmlChar
*) "on"))
384 *value
= TRUE
, r
= TRUE
;
385 else if (!xmlStrcasecmp(c
, (const xmlChar
*) "false"))
386 *value
= FALSE
, r
= TRUE
;
387 else if (!xmlStrcasecmp(c
, (const xmlChar
*) "no"))
388 *value
= FALSE
, r
= TRUE
;
389 else if (!xmlStrcasecmp(c
, (const xmlChar
*) "off"))
390 *value
= FALSE
, r
= TRUE
;
396 gboolean
obt_xml_attr_int(xmlNodePtr node
, const gchar
*name
, gint
*value
)
398 xmlChar
*c
= xmlGetProp(node
, (const xmlChar
*) name
);
401 g_strstrip((char*)c
); /* strip leading/trailing whitespace */
402 *value
= atoi((gchar
*)c
);
409 gboolean
obt_xml_attr_string(xmlNodePtr node
, const gchar
*name
,
412 xmlChar
*c
= xmlGetProp(node
, (const xmlChar
*) name
);
415 g_strstrip((char*)c
); /* strip leading/trailing whitespace */
416 *value
= g_strdup((gchar
*)c
);
423 gboolean
obt_xml_attr_contains(xmlNodePtr node
, const gchar
*name
,
426 xmlChar
*c
= xmlGetProp(node
, (const xmlChar
*) name
);
429 g_strstrip((char*)c
); /* strip leading/trailing whitespace */
430 r
= !xmlStrcasecmp(c
, (const xmlChar
*) val
);
This page took 0.057227 seconds and 4 git commands to generate.