10 static GHashTable
*callbacks
;
11 static xmlDocPtr doc_config
= NULL
;
13 static void destfunc(struct Callback
*c
)
21 callbacks
= g_hash_table_new_full(g_str_hash
, g_str_equal
, NULL
,
22 (GDestroyNotify
)destfunc
);
30 g_hash_table_destroy(callbacks
);
33 void parse_register(const char *tag
, ParseCallback func
, void *data
)
37 if ((c
= g_hash_table_lookup(callbacks
, tag
))) {
38 g_warning("tag '%s' already registered", tag
);
42 c
= g_new(struct Callback
, 1);
43 c
->tag
= g_strdup(tag
);
46 g_hash_table_insert(callbacks
, c
->tag
, c
);
52 xmlNodePtr node
= NULL
;
54 xmlLineNumbersDefault(1);
56 path
= g_build_filename(g_get_home_dir(), ".openbox", "rc3", NULL
);
57 if ((doc_config
= xmlParseFile(path
))) {
58 node
= xmlDocGetRootElement(doc_config
);
60 xmlFreeDoc(doc_config
);
62 g_warning("%s is an empty document", path
);
64 if (xmlStrcasecmp(node
->name
, (const xmlChar
*)"openbox_config")) {
65 xmlFreeDoc(doc_config
);
67 g_warning("document %s is of wrong type. root node is "
68 "not 'openbox_config'", path
);
74 path
= g_build_filename(RCDIR
, "rc3", NULL
);
75 if ((doc_config
= xmlParseFile(path
))) {
76 node
= xmlDocGetRootElement(doc_config
);
78 xmlFreeDoc(doc_config
);
80 g_warning("%s is an empty document", path
);
82 if (xmlStrcasecmp(node
->name
,
83 (const xmlChar
*)"openbox_config")) {
84 xmlFreeDoc(doc_config
);
86 g_warning("document %s is of wrong type. root node is "
87 "not 'openbox_config'", path
);
94 g_message("unable to find a valid config file, using defaults");
96 parse_tree(doc_config
, node
->xmlChildrenNode
, NULL
);
100 void parse_tree(xmlDocPtr doc
, xmlNodePtr node
, void *nothing
)
103 struct Callback
*c
= g_hash_table_lookup(callbacks
, node
->name
);
106 c
->func(doc
, node
->xmlChildrenNode
, c
->data
);
112 char *parse_string(xmlDocPtr doc
, xmlNodePtr node
)
114 xmlChar
*c
= xmlNodeListGetString(doc
, node
->xmlChildrenNode
, TRUE
);
115 char *s
= g_strdup((char*)c
);
120 int parse_int(xmlDocPtr doc
, xmlNodePtr node
)
122 xmlChar
*c
= xmlNodeListGetString(doc
, node
->xmlChildrenNode
, TRUE
);
123 int i
= atoi((char*)c
);
128 gboolean
parse_bool(xmlDocPtr doc
, xmlNodePtr node
)
130 xmlChar
*c
= xmlNodeListGetString(doc
, node
->xmlChildrenNode
, TRUE
);
132 if (!xmlStrcasecmp(c
, (const xmlChar
*) "true"))
134 else if (!xmlStrcasecmp(c
, (const xmlChar
*) "yes"))
136 else if (!xmlStrcasecmp(c
, (const xmlChar
*) "on"))
142 gboolean
parse_contains(const char *val
, xmlDocPtr doc
, xmlNodePtr node
)
144 xmlChar
*c
= xmlNodeListGetString(doc
, node
->xmlChildrenNode
, TRUE
);
146 r
= !xmlStrcasecmp(c
, (const xmlChar
*) val
);
151 xmlNodePtr
parse_find_node(const char *tag
, xmlNodePtr node
)
154 if (!xmlStrcasecmp(node
->name
, (const xmlChar
*) tag
))
161 gboolean
parse_attr_int(const char *name
, xmlNodePtr node
, int *value
)
163 xmlChar
*c
= xmlGetProp(node
, (const xmlChar
*) name
);
166 *value
= atoi((char*)c
);
173 gboolean
parse_attr_string(const char *name
, xmlNodePtr node
, char **value
)
175 xmlChar
*c
= xmlGetProp(node
, (const xmlChar
*) name
);
178 *value
= g_strdup((char*)c
);
185 Action
*parse_action(xmlDocPtr doc
, xmlNodePtr node
)
191 if (parse_attr_string("name", node
, &actname
)) {
192 if ((act
= action_from_string(actname
))) {
193 if (act
->func
== action_execute
|| act
->func
== action_restart
) {
194 if ((n
= parse_find_node("execute", node
->xmlChildrenNode
)))
195 act
->data
.execute
.path
= parse_string(doc
, n
);
196 } else if (act
->func
== action_showmenu
) {
197 if ((n
= parse_find_node("menu", node
->xmlChildrenNode
)))
198 act
->data
.showmenu
.name
= parse_string(doc
, n
);
199 } else if (act
->func
== action_desktop
) {
200 if ((n
= parse_find_node("desktop", node
->xmlChildrenNode
)))
201 act
->data
.desktop
.desk
= parse_int(doc
, n
);
202 if (act
->data
.desktop
.desk
> 0) act
->data
.desktop
.desk
--;
203 } else if (act
->func
== action_send_to_desktop
) {
204 if ((n
= parse_find_node("desktop", node
->xmlChildrenNode
)))
205 act
->data
.sendto
.desk
= parse_int(doc
, n
);
206 if (act
->data
.sendto
.desk
> 0) act
->data
.sendto
.desk
--;
207 } else if (act
->func
== action_move_relative_horz
||
208 act
->func
== action_move_relative_vert
||
209 act
->func
== action_resize_relative_horz
||
210 act
->func
== action_resize_relative_vert
) {
211 if ((n
= parse_find_node("delta", node
->xmlChildrenNode
)))
212 act
->data
.relative
.delta
= parse_int(doc
, n
);
213 } else if (act
->func
== action_desktop_right
||
214 act
->func
== action_desktop_left
||
215 act
->func
== action_desktop_up
||
216 act
->func
== action_desktop_down
) {
217 if ((n
= parse_find_node("wrap", node
->xmlChildrenNode
))) {
218 g_message("WRAP %d", parse_bool(doc
, n
));
219 act
->data
.desktopdir
.wrap
= parse_bool(doc
, n
);
221 } else if (act
->func
== action_send_to_desktop_right
||
222 act
->func
== action_send_to_desktop_left
||
223 act
->func
== action_send_to_desktop_up
||
224 act
->func
== action_send_to_desktop_down
) {
225 if ((n
= parse_find_node("wrap", node
->xmlChildrenNode
)))
226 act
->data
.sendtodir
.wrap
= parse_bool(doc
, n
);
227 if ((n
= parse_find_node("follow", node
->xmlChildrenNode
)))
228 act
->data
.sendtodir
.follow
= parse_bool(doc
, n
);
235 gboolean
parse_attr_contains(const char *val
, xmlNodePtr node
,
238 xmlChar
*c
= xmlGetProp(node
, (const xmlChar
*) name
);
240 r
= !xmlStrcasecmp(c
, (const xmlChar
*) val
);