summaryrefslogtreecommitdiff
path: root/openbox
diff options
context:
space:
mode:
Diffstat (limited to 'openbox')
-rw-r--r--openbox/Makefile.am25
-rw-r--r--openbox/config.c268
-rw-r--r--openbox/openbox.c2
-rw-r--r--openbox/parse.c267
-rw-r--r--openbox/parse.h56
-rw-r--r--openbox/parse.l45
-rw-r--r--openbox/parse.y146
7 files changed, 342 insertions, 467 deletions
diff --git a/openbox/Makefile.am b/openbox/Makefile.am
index 4c83005f..ecb72969 100644
--- a/openbox/Makefile.am
+++ b/openbox/Makefile.am
@@ -6,7 +6,7 @@ binary=openbox3
url=http://icculus.org/openbox
CPPFLAGS=$(X_CFLAGS) $(XFT_CFLAGS) $(GLIB_CFLAGS) $(GMODULE_CFLAGS) \
- $(LIBSN_CFLAGS) $(GL_CFLAGS) @CPPFLAGS@ \
+ $(LIBSN_CFLAGS) $(GL_CFLAGS) $(XML_CFLAGS) @CPPFLAGS@ \
-DLOCALEDIR=\"$(localedir)\" \
-DRCDIR=\"$(rcdir)\" \
-DPLUGINDIR=\"$(plugindir)\" \
@@ -16,38 +16,25 @@ CPPFLAGS=$(X_CFLAGS) $(XFT_CFLAGS) $(GLIB_CFLAGS) $(GMODULE_CFLAGS) \
INCLUDES=-I..
LIBS=$(X_LIBS) $(XFT_LIBS) $(XINERAMA_LIBS) $(XKB_LIBS) $(XRANDR_LIBS) \
$(VIDMODE_LIBS) $(XSHAPE_LIBS) $(GLIB_LIBS) $(GMODULE_LIBS) \
- $(LIBSN_LIBS) @LIBS@ @LIBINTL@
+ $(LIBSN_LIBS) $(XML_LIBS) @LIBS@ @LIBINTL@
bin_PROGRAMS=$(binary)
openbox3_LDADD=-lobrender -L../render
openbox3_LDFLAGS=-export-dynamic
-openbox3_SOURCES=parse.tab.c parse.lex.c action.c client.c config.c \
+openbox3_SOURCES=action.c client.c config.c parse.c \
extensions.c focus.c frame.c grab.c menu.c menu_render.c \
- openbox.c framerender.c parse.c plugin.c prop.c screen.c \
+ openbox.c framerender.c plugin.c prop.c screen.c \
stacking.c dispatch.c event.c group.c timer.c xerror.c \
moveresize.c startup.c popup.c dock.c window.c
noinst_HEADERS=action.h client.h config.h dispatch.h event.h extensions.h \
focus.h frame.h framerender.h geom.h gettext.h grab.h group.h \
- menu.h openbox.h parse.h parse.tab.h plugin.h prop.h screen.h \
+ menu.h openbox.h plugin.h prop.h screen.h \
stacking.h timer.h xerror.h moveresize.h startup.h popup.h \
- dock.h window.h
-
-# kill the implicit .c.y rule
-%.c: %.y
- @
-
-%.lex.c: %.l
- $(FLEX) -o$@ $<
-
-%.tab.c: %.y
- $(BISON) -d -o $@ $<
+ dock.h window.h parse.h
MAINTAINERCLEANFILES=Makefile.in
-clean-local:
- $(RM) parse.lex.c parse.tab.c parse.tab.h
-
distclean-local:
$(RM) *\~ *.orig *.rej .\#*
diff --git a/openbox/config.c b/openbox/config.c
index e751f32b..c3fa786c 100644
--- a/openbox/config.c
+++ b/openbox/config.c
@@ -23,182 +23,114 @@ gboolean config_dock_horz;
gboolean config_dock_hide;
guint config_dock_hide_timeout;
-static void parse_focus(char *name, ParseToken *value)
+static void parse_focus(xmlDocPtr doc, xmlNodePtr node, void *d)
{
- if (!g_ascii_strcasecmp(name, "focusnew")) {
- if (value->type != TOKEN_BOOL)
- yyerror("invalid value");
- else {
- config_focus_new = value->data.bool;
- }
- } else if (!g_ascii_strcasecmp(name, "followmouse")) {
- if (value->type != TOKEN_BOOL)
- yyerror("invalid value");
- else {
- config_focus_follow = value->data.bool;
- }
- } else if (!g_ascii_strcasecmp(name, "focuslast")) {
- if (value->type != TOKEN_BOOL)
- yyerror("invalid value");
- else {
- config_focus_last = value->data.bool;
- }
- } else if (!g_ascii_strcasecmp(name, "focuslastondesktop")) {
- if (value->type != TOKEN_BOOL)
- yyerror("invalid value");
- else {
- config_focus_last_on_desktop = value->data.bool;
- }
- } else if (!g_ascii_strcasecmp(name, "cyclingdialog")) {
- if (value->type != TOKEN_BOOL)
- yyerror("invalid value");
- else {
- config_focus_popup = value->data.bool;
- }
- } else
- yyerror("invalid option");
- parse_free_token(value);
+ xmlNodePtr n;
+
+ if ((n = parse_find_node("focusNew", node)))
+ config_focus_new = parse_bool(doc, n);
+ if ((n = parse_find_node("followMouse", node)))
+ config_focus_follow = parse_bool(doc, n);
+ if ((n = parse_find_node("focusLast", node)))
+ config_focus_last = parse_bool(doc, n);
+ if ((n = parse_find_node("focusLastOnDesktop", node)))
+ config_focus_last_on_desktop = parse_bool(doc, n);
+ if ((n = parse_find_node("cyclingDialog", node)))
+ config_focus_popup = parse_bool(doc, n);
}
-static void parse_theme(char *name, ParseToken *value)
+static void parse_theme(xmlDocPtr doc, xmlNodePtr node, void *d)
{
- if (!g_ascii_strcasecmp(name, "theme")) {
- if (value->type != TOKEN_STRING)
- yyerror("invalid value");
- else {
- g_free(config_theme);
- config_theme = g_strdup(value->data.string);
- }
- } else
- yyerror("invalid option");
- parse_free_token(value);
+ xmlNodePtr n;
+
+ if ((n = parse_find_node("theme", node))) {
+ g_free(config_theme);
+ config_theme = parse_string(doc, n);
+ }
}
-static void parse_desktops(char *name, ParseToken *value)
+static void parse_desktops(xmlDocPtr doc, xmlNodePtr node, void *d)
{
- GList *it;
-
- if (!g_ascii_strcasecmp(name, "number")) {
- if (value->type != TOKEN_INTEGER)
- yyerror("invalid value");
- else {
- config_desktops_num = value->data.integer;
- }
- } else if (!g_ascii_strcasecmp(name, "names")) {
- if (value->type == TOKEN_LIST) {
- for (it = value->data.list; it; it = it->next)
- if (((ParseToken*)it->data)->type != TOKEN_STRING) break;
- if (it == NULL) {
- /* build a string list */
- g_free(config_desktops_names);
- for (it = value->data.list; it; it = it->next)
- config_desktops_names =
- g_slist_append(config_desktops_names,
- g_strdup
- (((ParseToken*)it->data)->data.string));
- } else {
- yyerror("invalid string in names list");
- }
- } else {
- yyerror("syntax error (expected list of strings)");
- }
- } else
- yyerror("invalid option");
- parse_free_token(value);
+ xmlNodePtr n;
+
+ if ((n = parse_find_node("number", node)))
+ config_desktops_num = parse_int(doc, n);
+ if ((n = parse_find_node("names", node))) {
+ GSList *it;
+ xmlNodePtr nname;
+
+ for (it = config_desktops_names; it; it = it->next)
+ g_free(it->data);
+ g_slist_free(config_desktops_names);
+ config_desktops_names = NULL;
+
+ nname = parse_find_node("name", n->xmlChildrenNode);
+ while (nname) {
+ config_desktops_names = g_slist_append(config_desktops_names,
+ parse_string(doc, nname));
+ nname = parse_find_node("name", nname->next);
+ }
+ }
}
-static void parse_moveresize(char *name, ParseToken *value)
+static void parse_moveresize(xmlDocPtr doc, xmlNodePtr node, void *d)
{
- if (!g_ascii_strcasecmp(name, "opaque_move")) {
- if (value->type != TOKEN_BOOL)
- yyerror("invalid value");
- else {
- config_opaque_move = value->data.integer;
- }
- } else if (!g_ascii_strcasecmp(name, "opaque_resize")) {
- if (value->type != TOKEN_BOOL)
- yyerror("invalid value");
- else {
- config_opaque_resize = value->data.integer;
- }
- } else
- yyerror("invalid option");
- parse_free_token(value);
+ xmlNodePtr n;
+
+ if ((n = parse_find_node("opaqueMove", node)))
+ config_opaque_move = parse_bool(doc, n);
+ if ((n = parse_find_node("opaqueResize", node)))
+ config_opaque_resize = parse_bool(doc, n);
}
-static void parse_dock(char *name, ParseToken *value)
+static void parse_dock(xmlDocPtr doc, xmlNodePtr node, void *d)
{
- if (!g_ascii_strcasecmp(name, "stacking")) {
- if (value->type != TOKEN_STRING)
- yyerror("invalid value");
- else {
- if (!g_ascii_strcasecmp(value->data.string, "bottom"))
- config_dock_layer = Layer_Below;
- else if (!g_ascii_strcasecmp(value->data.string, "normal"))
- config_dock_layer = Layer_Normal;
- else if (!g_ascii_strcasecmp(value->data.string, "top"))
- config_dock_layer = Layer_Top;
- else
- yyerror("invalid layer");
- }
- } else if (!g_ascii_strcasecmp(name, "position")) {
- if (value->type != TOKEN_STRING)
- yyerror("invalid value");
- else {
- if (!g_ascii_strcasecmp(value->data.string, "topleft"))
- config_dock_pos = DockPos_TopLeft;
- else if (!g_ascii_strcasecmp(value->data.string, "top"))
- config_dock_pos = DockPos_Top;
- else if (!g_ascii_strcasecmp(value->data.string, "topright"))
- config_dock_pos = DockPos_TopRight;
- else if (!g_ascii_strcasecmp(value->data.string, "right"))
- config_dock_pos = DockPos_Right;
- else if (!g_ascii_strcasecmp(value->data.string, "bottomright"))
- config_dock_pos = DockPos_BottomRight;
- else if (!g_ascii_strcasecmp(value->data.string, "bottom"))
- config_dock_pos = DockPos_Bottom;
- else if (!g_ascii_strcasecmp(value->data.string, "bottomleft"))
- config_dock_pos = DockPos_BottomLeft;
- else if (!g_ascii_strcasecmp(value->data.string, "left"))
- config_dock_pos = DockPos_Left;
- else if (!g_ascii_strcasecmp(value->data.string, "floating"))
- config_dock_pos = DockPos_Floating;
- else
- yyerror("invalid position");
- }
- } else if (!g_ascii_strcasecmp(name, "floatingx")) {
- if (value->type != TOKEN_INTEGER)
- yyerror("invalid value");
- else {
- config_dock_x = value->data.integer;
- }
- } else if (!g_ascii_strcasecmp(name, "floatingy")) {
- if (value->type != TOKEN_INTEGER)
- yyerror("invalid value");
- else {
- config_dock_y = value->data.integer;
- }
- } else if (!g_ascii_strcasecmp(name, "horizontal")) {
- if (value->type != TOKEN_BOOL)
- yyerror("invalid value");
- else {
- config_dock_horz = value->data.bool;
- }
- } else if (!g_ascii_strcasecmp(name, "autohide")) {
- if (value->type != TOKEN_BOOL)
- yyerror("invalid value");
- else {
- config_dock_hide = value->data.bool;
- }
- } else if (!g_ascii_strcasecmp(name, "hidetimeout")) {
- if (value->type != TOKEN_INTEGER)
- yyerror("invalid value");
- else {
- config_dock_hide_timeout = value->data.integer;
- }
- } else
- yyerror("invalid option");
- parse_free_token(value);
+ xmlNodePtr n;
+
+ if ((n = parse_find_node("position", node))) {
+ if (parse_contains("TopLeft", doc, n))
+ config_dock_pos = DockPos_TopLeft;
+ else if (parse_contains("Top", doc, n))
+ config_dock_pos = DockPos_Top;
+ else if (parse_contains("TopRight", doc, n))
+ config_dock_pos = DockPos_TopRight;
+ else if (parse_contains("Right", doc, n))
+ config_dock_pos = DockPos_Right;
+ else if (parse_contains("BottomRight", doc, n))
+ config_dock_pos = DockPos_BottomRight;
+ else if (parse_contains("Bottom", doc, n))
+ config_dock_pos = DockPos_Bottom;
+ else if (parse_contains("BottomLeft", doc, n))
+ config_dock_pos = DockPos_BottomLeft;
+ else if (parse_contains("Left", doc, n))
+ config_dock_pos = DockPos_Left;
+ else if (parse_contains("Floating", doc, n))
+ config_dock_pos = DockPos_Floating;
+ }
+ if (config_dock_pos == DockPos_Floating) {
+ if ((n = parse_find_node("floatingX", node)))
+ config_dock_x = parse_int(doc, n);
+ if ((n = parse_find_node("floatingY", node)))
+ config_dock_y = parse_int(doc, n);
+ }
+ if ((n = parse_find_node("stacking", node))) {
+ if (parse_contains("top", doc, n))
+ config_dock_layer = Layer_Top;
+ else if (parse_contains("normal", doc, n))
+ config_dock_layer = Layer_Normal;
+ else if (parse_contains("bottom", doc, n))
+ config_dock_layer = Layer_Below;
+ }
+ if ((n = parse_find_node("direction", node))) {
+ if (parse_contains("horizontal", doc, n))
+ config_dock_horz = TRUE;
+ else if (parse_contains("vertical", doc, n))
+ config_dock_horz = FALSE;
+ }
+ if ((n = parse_find_node("autoHide", node)))
+ config_dock_hide = parse_bool(doc, n);
+ if ((n = parse_find_node("hideTimeout", node)))
+ config_dock_hide_timeout = parse_int(doc, n);
}
void config_startup()
@@ -209,21 +141,21 @@ void config_startup()
config_focus_last_on_desktop = TRUE;
config_focus_popup = TRUE;
- parse_reg_section("focus", NULL, parse_focus);
+ parse_register("focus", parse_focus, NULL);
config_theme = NULL;
- parse_reg_section("theme", NULL, parse_theme);
+ parse_register("theme", parse_theme, NULL);
config_desktops_num = 4;
config_desktops_names = NULL;
- parse_reg_section("desktops", NULL, parse_desktops);
+ parse_register("desktops", parse_desktops, NULL);
config_opaque_move = TRUE;
config_opaque_resize = TRUE;
- parse_reg_section("moveresize", NULL, parse_moveresize);
+ parse_register("moveresize", parse_moveresize, NULL);
config_dock_layer = Layer_Top;
config_dock_pos = DockPos_TopRight;
@@ -233,7 +165,7 @@ void config_startup()
config_dock_hide = FALSE;
config_dock_hide_timeout = 3000;
- parse_reg_section("dock", NULL, parse_dock);
+ parse_register("dock", parse_dock, NULL);
}
void config_shutdown()
diff --git a/openbox/openbox.c b/openbox/openbox.c
index 3b2a9991..2b4dddce 100644
--- a/openbox/openbox.c
+++ b/openbox/openbox.c
@@ -180,7 +180,7 @@ int main(int argc, char **argv)
/* set up the kernel config shit */
config_startup();
/* parse/load user options */
- parse_rc();
+ parse_config();
/* we're done with parsing now, kill it */
parse_shutdown();
diff --git a/openbox/parse.c b/openbox/parse.c
index ffb72c03..8f9c82fb 100644
--- a/openbox/parse.c
+++ b/openbox/parse.c
@@ -1,86 +1,243 @@
#include "parse.h"
+#include <glib.h>
-static GHashTable *reg = NULL;
+struct Callback {
+ char *tag;
+ ParseCallback func;
+ void *data;
+};
-struct Functions {
- ParseFunc f;
- AssignParseFunc af;
-} *funcs;
+static GHashTable *callbacks;
+static xmlDocPtr doc_config = NULL;
-void destshit(gpointer shit) { g_free(shit); }
+static void destfunc(struct Callback *c)
+{
+ g_free(c->tag);
+ g_free(c);
+}
void parse_startup()
{
- reg = g_hash_table_new_full(g_str_hash, g_str_equal, destshit, destshit);
- funcs = NULL;
+ callbacks = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
+ (GDestroyNotify)destfunc);
}
void parse_shutdown()
{
- g_hash_table_destroy(reg);
+ xmlFree(doc_config);
+ doc_config = NULL;
+
+ g_hash_table_destroy(callbacks);
}
-void parse_reg_section(char *section, ParseFunc func, AssignParseFunc afunc)
+void parse_register(const char *tag, ParseCallback func, void *data)
{
- struct Functions *f = g_new(struct Functions, 1);
- f->f = func;
- f->af = afunc;
- g_hash_table_insert(reg, g_ascii_strdown(section, -1), f);
+ struct Callback *c;
+
+ if ((c = g_hash_table_lookup(callbacks, tag))) {
+ g_warning("tag '%s' already registered", tag);
+ return;
+ }
+
+ c = g_new(struct Callback, 1);
+ c->tag = g_strdup(tag);
+ c->func = func;
+ c->data = data;
+ g_hash_table_insert(callbacks, c->tag, c);
}
-void parse_free_token(ParseToken *token)
+void parse_config()
{
- GList *it;
-
- switch (token->type) {
- case TOKEN_STRING:
- g_free(token->data.string);
- break;
- case TOKEN_IDENTIFIER:
- g_free(token->data.identifier);
- break;
- case TOKEN_LIST:
- for (it = token->data.list; it; it = it->next) {
- parse_free_token(it->data);
- g_free(it->data);
+ char *path;
+ xmlNodePtr node = NULL;
+
+ xmlLineNumbersDefault(1);
+
+ path = g_build_filename(g_get_home_dir(), ".openbox", "rc3", NULL);
+ if ((doc_config = xmlParseFile(path))) {
+ node = xmlDocGetRootElement(doc_config);
+ if (!node) {
+ xmlFreeDoc(doc_config);
+ doc_config = NULL;
+ g_warning("%s is an empty document", path);
+ } else {
+ if (xmlStrcasecmp(node->name, (const xmlChar*)"openbox_config")) {
+ xmlFreeDoc(doc_config);
+ doc_config = NULL;
+ g_warning("document %s is of wrong type. root node is "
+ "not 'openbox_config'", path);
+ }
+ }
+ }
+ g_free(path);
+ if (!doc_config) {
+ path = g_build_filename(RCDIR, "rc3", NULL);
+ if ((doc_config = xmlParseFile(path))) {
+ node = xmlDocGetRootElement(doc_config);
+ if (!node) {
+ xmlFreeDoc(doc_config);
+ doc_config = NULL;
+ g_warning("%s is an empty document", path);
+ } else {
+ if (xmlStrcasecmp(node->name,
+ (const xmlChar*)"openbox_config")) {
+ xmlFreeDoc(doc_config);
+ doc_config = NULL;
+ g_warning("document %s is of wrong type. root node is "
+ "not 'openbox_config'", path);
+ }
+ }
}
- g_list_free(token->data.list);
- break;
- case TOKEN_REAL:
- case TOKEN_INTEGER:
- case TOKEN_BOOL:
- case TOKEN_LBRACE:
- case TOKEN_RBRACE:
- case TOKEN_COMMA:
- case TOKEN_NEWLINE:
- break;
+ g_free(path);
}
+ if (!doc_config) {
+ g_message("unable to find a valid config file, using defaults");
+ } else {
+ parse_tree(doc_config, node->xmlChildrenNode, NULL);
+ }
+}
+
+void parse_tree(xmlDocPtr doc, xmlNodePtr node, void *nothing)
+{
+ while (node) {
+ struct Callback *c = g_hash_table_lookup(callbacks, node->name);
+
+ if (c)
+ c->func(doc, node->xmlChildrenNode, c->data);
+
+ node = node->next;
+ }
+}
+
+char *parse_string(xmlDocPtr doc, xmlNodePtr node)
+{
+ xmlChar *c = xmlNodeListGetString(doc, node->xmlChildrenNode, TRUE);
+ char *s = g_strdup((char*)c);
+ xmlFree(c);
+ return s;
}
-void parse_set_section(char *section)
+int parse_int(xmlDocPtr doc, xmlNodePtr node)
{
- char *sec;
- sec = g_ascii_strdown(section, -1);
- funcs = g_hash_table_lookup(reg, sec);
- g_free(sec);
+ xmlChar *c = xmlNodeListGetString(doc, node->xmlChildrenNode, TRUE);
+ int i = atoi((char*)c);
+ xmlFree(c);
+ return i;
}
-void parse_token(ParseToken *token)
+gboolean parse_bool(xmlDocPtr doc, xmlNodePtr node)
{
- if (funcs) {
- if (funcs->f)
- funcs->f(token);
- else if (token->type != TOKEN_NEWLINE)
- yyerror("syntax error");
+ xmlChar *c = xmlNodeListGetString(doc, node->xmlChildrenNode, TRUE);
+ gboolean b = FALSE;
+ if (!xmlStrcasecmp(c, (const xmlChar*) "true"))
+ b = TRUE;
+ else if (!xmlStrcasecmp(c, (const xmlChar*) "yes"))
+ b = TRUE;
+ else if (!xmlStrcasecmp(c, (const xmlChar*) "on"))
+ b = TRUE;
+ xmlFree(c);
+ return b;
+}
+
+gboolean parse_contains(const char *val, xmlDocPtr doc, xmlNodePtr node)
+{
+ xmlChar *c = xmlNodeListGetString(doc, node->xmlChildrenNode, TRUE);
+ gboolean r;
+ r = !xmlStrcasecmp(c, (const xmlChar*) val);
+ xmlFree(c);
+ return r;
+}
+
+xmlNodePtr parse_find_node(const char *tag, xmlNodePtr node)
+{
+ while (node) {
+ if (!xmlStrcasecmp(node->name, (const xmlChar*) tag))
+ return node;
+ node = node->next;
+ }
+ return NULL;
+}
+
+gboolean parse_attr_int(const char *name, xmlNodePtr node, int *value)
+{
+ xmlChar *c = xmlGetProp(node, (const xmlChar*) name);
+ gboolean r = FALSE;
+ if (c) {
+ *value = atoi((char*)c);
+ r = TRUE;
}
+ xmlFree(c);
+ return r;
}
-void parse_assign(char *name, ParseToken *value)
+gboolean parse_attr_string(const char *name, xmlNodePtr node, char **value)
{
- if (funcs) {
- if (funcs->af)
- funcs->af(name, value);
- else
- yyerror("syntax error");
+ xmlChar *c = xmlGetProp(node, (const xmlChar*) name);
+ gboolean r = FALSE;
+ if (c) {
+ *value = g_strdup((char*)c);
+ r = TRUE;
}
+ xmlFree(c);
+ return r;
+}
+
+Action *parse_action(xmlDocPtr doc, xmlNodePtr node)
+{
+ char *actname;
+ Action *act = NULL;
+ xmlNodePtr n;
+
+ if (parse_attr_string("name", node, &actname)) {
+ if ((act = action_from_string(actname))) {
+ if (act->func == action_execute || act->func == action_restart) {
+ if ((n = parse_find_node("execute", node->xmlChildrenNode)))
+ act->data.execute.path = parse_string(doc, n);
+ } else if (act->func == action_showmenu) {
+ if ((n = parse_find_node("menu", node->xmlChildrenNode)))
+ act->data.showmenu.name = parse_string(doc, n);
+ } else if (act->func == action_desktop) {
+ if ((n = parse_find_node("desktop", node->xmlChildrenNode)))
+ act->data.desktop.desk = parse_int(doc, n);
+ if (act->data.desktop.desk > 0) act->data.desktop.desk--;
+ } else if (act->func == action_send_to_desktop) {
+ if ((n = parse_find_node("desktop", node->xmlChildrenNode)))
+ act->data.sendto.desk = parse_int(doc, n);
+ if (act->data.sendto.desk > 0) act->data.sendto.desk--;
+ } else if (act->func == action_move_relative_horz ||
+ act->func == action_move_relative_vert ||
+ act->func == action_resize_relative_horz ||
+ act->func == action_resize_relative_vert) {
+ if ((n = parse_find_node("delta", node->xmlChildrenNode)))
+ act->data.relative.delta = parse_int(doc, n);
+ } else if (act->func == action_desktop_right ||
+ act->func == action_desktop_left ||
+ act->func == action_desktop_up ||
+ act->func == action_desktop_down) {
+ if ((n = parse_find_node("wrap", node->xmlChildrenNode))) {
+ g_message("WRAP %d", parse_bool(doc, n));
+ act->data.desktopdir.wrap = parse_bool(doc, n);
+ }
+ } else if (act->func == action_send_to_desktop_right ||
+ act->func == action_send_to_desktop_left ||
+ act->func == action_send_to_desktop_up ||
+ act->func == action_send_to_desktop_down) {
+ if ((n = parse_find_node("wrap", node->xmlChildrenNode)))
+ act->data.sendtodir.wrap = parse_bool(doc, n);
+ if ((n = parse_find_node("follow", node->xmlChildrenNode)))
+ act->data.sendtodir.follow = parse_bool(doc, n);
+ }
+ }
+ }
+ return act;
+}
+
+gboolean parse_attr_contains(const char *val, xmlNodePtr node,
+ const char *name)
+{
+ xmlChar *c = xmlGetProp(node, (const xmlChar*) name);
+ gboolean r;
+ r = !xmlStrcasecmp(c, (const xmlChar*) val);
+ xmlFree(c);
+ return r;
}
diff --git a/openbox/parse.h b/openbox/parse.h
index abd5bb2d..199e8104 100644
--- a/openbox/parse.h
+++ b/openbox/parse.h
@@ -1,48 +1,38 @@
#ifndef __parse_h
#define __parse_h
+#include "action.h"
+
+#include <libxml/parser.h>
#include <glib.h>
-#ifndef NO_TAB_H
-#include "parse.tab.h"
-#endif
-typedef enum {
- TOKEN_REAL = REAL,
- TOKEN_INTEGER = INTEGER,
- TOKEN_STRING = STRING,
- TOKEN_IDENTIFIER = IDENTIFIER,
- TOKEN_BOOL = BOOLEAN,
- TOKEN_LIST,
- TOKEN_LBRACE = '{',
- TOKEN_RBRACE = '}',
- TOKEN_COMMA = ',',
- TOKEN_NEWLINE = '\n'
-} ParseTokenType;
-
-typedef struct {
- ParseTokenType type;
- union ParseTokenData data;
-} ParseToken;
-
-typedef void (*ParseFunc)(ParseToken *token);
-typedef void (*AssignParseFunc)(char *name, ParseToken *value);
+typedef void (*ParseCallback)(xmlDocPtr doc, xmlNodePtr node, void *data);
void parse_startup();
void parse_shutdown();
-/* Parse the RC file
- found in parse.yacc
-*/
-void parse_rc();
+void parse_register(const char *tag, ParseCallback func, void *data);
+
+void parse_config();
+
+void parse_tree(xmlDocPtr doc, xmlNodePtr node, void *nothing);
+
+
+/* helpers */
+
+xmlNodePtr parse_find_node(const char *tag, xmlNodePtr node);
-void parse_reg_section(char *section, ParseFunc func, AssignParseFunc afunc);
+char *parse_string(xmlDocPtr doc, xmlNodePtr node);
+int parse_int(xmlDocPtr doc, xmlNodePtr node);
+gboolean parse_bool(xmlDocPtr doc, xmlNodePtr node);
+gboolean parse_contains(const char *val, xmlDocPtr doc, xmlNodePtr node);
+gboolean parse_attr_contains(const char *val, xmlNodePtr node,
+ const char *name);
-/* Free a parsed token's allocated memory */
-void parse_free_token(ParseToken *token);
+gboolean parse_attr_string(const char *name, xmlNodePtr node, char **value);
+gboolean parse_attr_int(const char *name, xmlNodePtr node, int *value);
-/* Display an error message while parsing.
- found in parse.yacc */
-void yyerror(char *err);
+Action *parse_action(xmlDocPtr doc, xmlNodePtr node);
#endif
diff --git a/openbox/parse.l b/openbox/parse.l
deleted file mode 100644
index a7cd6c63..00000000
--- a/openbox/parse.l
+++ /dev/null
@@ -1,45 +0,0 @@
-%{
-#include "parse.h"
-#ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-#endif
-
-extern int lineno;
-%}
-
-real [-0-9][0-9]*\.[0-9]+
-integer [-0-9][0-9]*
-string \"[^"\n]*\"
-identifier [a-zA-Z][-.a-zA-Z0-9_]*
-bool ([tT][rR][uU][eE]|[fF][aA][lL][sS][eE]|[yY][eE][sS]|[nN][oO]|[oO][nN]|[oO][fF][fF])
-
-%%
-
-^[ \t]*#.*\n /* comment */ { ++lineno; }
-^[ \t]*#.* /* comment */
-^[ \t]*\n /* empty lines */ { ++lineno; }
-[ \t] /* whitespace */
-{real} { yylval.real = atof(yytext); return REAL; }
-{integer} { yylval.integer = atoi(yytext); return INTEGER; }
-{string} { yylval.string = g_strdup(yytext+1); /* drop the left quote */
- if (yylval.string[yyleng-2] != '"')
- yyerror("improperly terminated string on line %d");
- else
- yylval.string[yyleng-2] = '\0';
- return STRING;
- }
-{bool} { yylval.bool = (!g_ascii_strcasecmp("true", yytext) ||
- !g_ascii_strcasecmp("yes", yytext) ||
- !g_ascii_strcasecmp("on", yytext));
- return BOOLEAN;
- }
-{identifier} { yylval.identifier = g_strdup(yytext); return IDENTIFIER; }
-[{}()\[\]=,] { yylval.character = *yytext; return *yytext; }
-\n { yylval.character = *yytext; return *yytext; }
-. { return INVALID; }
-
-%%
-
-int yywrap() {
- return 1;
-}
diff --git a/openbox/parse.y b/openbox/parse.y
deleted file mode 100644
index 7e92efd6..00000000
--- a/openbox/parse.y
+++ /dev/null
@@ -1,146 +0,0 @@
-%{
-#include <glib.h>
-#ifdef HAVE_STDIO_H
-# include <stdio.h>
-#endif
-
-%}
-
-%union ParseTokenData {
- float real;
- int integer;
- char *string;
- char *identifier;
- gboolean bool;
- char character;
- GList *list;
-}
-
-%{
-#define NO_TAB_H
-#include "parse.h"
-#undef NO_TAB_H
-
-extern int yylex();
-extern int yyparse();
-void yyerror(char *err);
-
-extern int lineno;
-extern FILE *yyin;
-
-static char *path;
-static ParseToken t;
-
-/* in parse.c */
-void parse_token(ParseToken *token);
-void parse_assign(char *name, ParseToken *token);
-void parse_set_section(char *section);
-%}
-
-%token <real> REAL
-%token <integer> INTEGER
-%token <string> STRING
-%token <identifier> IDENTIFIER
-%token <bool> BOOLEAN
-%token <character> '('
-%token <character> ')'
-%token <character> '{'
-%token <character> '}'
-%token <character> '='
-%token <character> ','
-%token <character> '\n'
-%token INVALID
-
-%type <list> list
-%type <list> listtokens
-
-%%
-
-sections:
- | sections '[' IDENTIFIER ']' { parse_set_section($3); } '\n'
- { ++lineno; } lines
- ;
-
-lines:
- | lines tokens { t.type='\n'; t.data.character='\n'; parse_token(&t); } '\n'
- { ++lineno; }
- | lines IDENTIFIER '=' listtoken { parse_assign($2, &t); } '\n'
- { ++lineno; }
- ;
-
-tokens:
- tokens token { parse_token(&t); }
- | token { parse_token(&t); }
- ;
-
-token:
- REAL { t.type = TOKEN_REAL; t.data.real = $1; }
- | INTEGER { t.type = TOKEN_INTEGER; t.data.integer = $1; }
- | STRING { t.type = TOKEN_STRING; t.data.string = $1; }
- | IDENTIFIER { t.type = TOKEN_IDENTIFIER; t.data.identifier = $1; }
- | BOOLEAN { t.type = TOKEN_BOOL; t.data.bool = $1; }
- | list { t.type = TOKEN_LIST; t.data.list = $1; }
- | '{' { t.type = $1; t.data.character = $1; }
- | '}' { t.type = $1; t.data.character = $1; }
- | ',' { t.type = $1; t.data.character = $1; }
- ;
-
-list:
- '(' listtokens ')' { $$ = $2; }
- ;
-
-listtokens:
- listtokens listtoken { ParseToken *nt = g_new(ParseToken, 1);
- nt->type = t.type;
- nt->data = t.data;
- $$ = g_list_append($1, nt);
- }
- | listtoken { ParseToken *nt = g_new(ParseToken, 1);
- nt->type = t.type;
- nt->data = t.data;
- $$ = g_list_append(NULL, nt);
- }
- ;
-
-listtoken:
- REAL { t.type = TOKEN_REAL; t.data.real = $1; }
- | INTEGER { t.type = TOKEN_INTEGER; t.data.integer = $1; }
- | STRING { t.type = TOKEN_STRING; t.data.string = $1; }
- | IDENTIFIER { t.type = TOKEN_IDENTIFIER; t.data.identifier = $1; }
- | BOOLEAN { t.type = TOKEN_BOOL; t.data.bool = $1; }
- | list { t.type = TOKEN_LIST; t.data.list = $1; }
- | '{' { t.type = $1; t.data.character = $1; }
- | '}' { t.type = $1; t.data.character = $1; }
- | ',' { t.type = $1; t.data.character = $1; }
- ;
-
-
-%%
-
-int lineno;
-
-void yyerror(char *err) {
- g_message("%s:%d: %s", path, lineno, err);
-}
-
-void parse_rc()
-{
- /* try the user's rc */
- path = g_build_filename(g_get_home_dir(), ".openbox", "rc3", NULL);
- if ((yyin = fopen(path, "r")) == NULL) {
- g_free(path);
- /* try the system wide rc */
- path = g_build_filename(RCDIR, "rc3", NULL);
- if ((yyin = fopen(path, "r")) == NULL) {
- g_warning("No rc2 file found!");
- g_free(path);
- return;
- }
- }
-
- lineno = 1;
-
- yyparse();
-
- g_free(path);
-}