From 2f414a438b7b8759548a7c87b34a24c348231499 Mon Sep 17 00:00:00 2001 From: tokyo4j Date: Sat, 12 Apr 2025 04:20:02 +0900 Subject: [PATCH] rcxml: simplify the logic to traverse xml tree --- src/config/rcxml.c | 237 ++++++++------------------------------------- 1 file changed, 38 insertions(+), 199 deletions(-) diff --git a/src/config/rcxml.c b/src/config/rcxml.c index 7881e762..f545a9ef 100644 --- a/src/config/rcxml.c +++ b/src/config/rcxml.c @@ -38,35 +38,6 @@ #include "window-rules.h" #include "workspaces.h" -struct parser_state { - bool in_regions; - bool in_usable_area_override; - bool in_keybind; - bool in_mousebind; - bool in_touch; - bool in_libinput_category; - bool in_window_switcher_field; - bool in_window_rules; - bool in_action_query; - bool in_action_then_branch; - bool in_action_else_branch; - bool in_action_none_branch; - struct usable_area_override *current_usable_area_override; - struct keybind *current_keybind; - struct mousebind *current_mousebind; - struct touch_config_entry *current_touch; - struct libinput_category *current_libinput_category; - const char *current_mouse_context; - struct action *current_keybind_action; - struct action *current_mousebind_action; - struct region *current_region; - struct window_switcher_field *current_field; - struct window_rule *current_window_rule; - struct action *current_window_rule_action; - struct view_query *current_view_query; - struct action *current_child_action; -}; - /* for backward compatibility of */ static double mouse_scroll_factor = -1; @@ -1065,12 +1036,10 @@ set_tearing_mode(const char *str, enum tearing_mode *variable) } } -static void -entry(xmlNode *node, char *nodename, char *content, struct parser_state *state) +/* Returns true if the node's children should also be traversed */ +static bool +entry(xmlNode *node, char *nodename, char *content) { - if (!nodename) { - return; - } string_truncate_at_pattern(nodename, ".openbox_config"); string_truncate_at_pattern(nodename, ".labwc_config"); @@ -1078,81 +1047,45 @@ entry(xmlNode *node, char *nodename, char *content, struct parser_state *state) printf("%s: %s\n", nodename, content); } + /* handle nested nodes */ if (!strcasecmp(nodename, "margin")) { fill_usable_area_override(node); - return; - } - if (!strcasecmp(nodename, "keybind.keyboard")) { + } else if (!strcasecmp(nodename, "keybind.keyboard")) { fill_keybind(node); - return; - } - if (!strcasecmp(nodename, "context.mouse")) { + } else if (!strcasecmp(nodename, "context.mouse")) { fill_mouse_context(node); - return; - } - if (!strcasecmp(nodename, "touch")) { + } else if (!strcasecmp(nodename, "touch")) { fill_touch(node); - return; - } - if (!strcasecmp(nodename, "device.libinput")) { + } else if (!strcasecmp(nodename, "device.libinput")) { fill_libinput_category(node); - return; - } - if (!strcasecmp(nodename, "regions")) { + } else if (!strcasecmp(nodename, "regions")) { fill_regions(node); - return; - } - if (!strcasecmp(nodename, "fields.windowSwitcher")) { + } else if (!strcasecmp(nodename, "fields.windowSwitcher")) { fill_window_switcher_fields(node); - return; - } - if (!strcasecmp(nodename, "windowRules")) { + } else if (!strcasecmp(nodename, "windowRules")) { fill_window_rules(node); - return; - } - if (!strcasecmp(nodename, "font.theme")) { + } else if (!strcasecmp(nodename, "font.theme")) { fill_font(node); - return; - } - if (!strcasecmp(nodename, "map.tablet")) { + } else if (!strcasecmp(nodename, "map.tablet")) { fill_tablet_button_map(node); - return; - } /* handle nodes without content, e.g. */ - if (!strcmp(nodename, "default.keyboard")) { + } else if (!strcmp(nodename, "default.keyboard")) { load_default_key_bindings(); - return; - } - if (!strcmp(nodename, "devault.mouse") - || !strcmp(nodename, "default.mouse")) { + } else if (!strcmp(nodename, "default.mouse")) { load_default_mouse_bindings(); - return; - } + } else if (!strcasecmp(nodename, "prefix.desktops")) { + xstrdup_replace(rc.workspace_config.prefix, content); - if (!strcasecmp(nodename, "prefix.desktops")) { - xstrdup_replace(rc.workspace_config.prefix, content ? content : ""); - return; - } + } else if (!lab_xml_node_is_leaf(node)) { + /* parse children of nested nodes other than above */ + return true; - /* - * Nodenames where we want to honour !content have to be parsed above - * this point. An example of this is: - * - * - * - * - * - * In the case of the element having content, the node will be - * processed twice; first for the element itself (with no content) and - * then the content itself. In this situation xstrdup_replace() is - * called twice, but the end result is the right one. - */ - if (!content) { - return; - } + } else if (str_space_only(content)) { + /* ignore empty leaf nodes other than above */ - if (!strcmp(nodename, "decoration.core")) { + /* handle non-empty leaf nodes */ + } else if (!strcmp(nodename, "decoration.core")) { if (!strcmp(content, "client")) { rc.xdg_shell_server_side_deco = false; } else { @@ -1361,117 +1294,22 @@ entry(xmlNode *node, char *nodename, char *content, struct parser_state *state) } else if (!strcasecmp(nodename, "useFilter.magnifier")) { set_bool(content, &rc.mag_filter); } + + return false; } static void -process_node(xmlNode *node, struct parser_state *state) +traverse(xmlNode *node) { - char *content; - static char buffer[256]; - char *name; - - content = (char *)node->content; - if (xmlIsBlankNode(node)) { - return; - } - name = nodename(node, buffer, sizeof(buffer)); - entry(node, name, content, state); -} - -static void xml_tree_walk(xmlNode *node, struct parser_state *state); - -static void -traverse(xmlNode *n, struct parser_state *state) -{ - xmlAttr *attr; - - process_node(n, state); - for (attr = n->properties; attr; attr = attr->next) { - xml_tree_walk(attr->children, state); - } - xml_tree_walk(n->children, state); -} - -static void -xml_tree_walk(xmlNode *node, struct parser_state *state) -{ - for (xmlNode *n = node; n && n->name; n = n->next) { - if (!strcasecmp((char *)n->name, "comment")) { - continue; + xmlNode *child; + char *key, *content; + LAB_XML_FOR_EACH(node, child, key, content) { + (void)key; + char buffer[256]; + char *name = nodename(child, buffer, sizeof(buffer)); + if (entry(child, name, content)) { + traverse(child); } - if (!strcasecmp((char *)n->name, "margin")) { - state->in_usable_area_override = true; - traverse(n, state); - state->in_usable_area_override = false; - continue; - } - if (!strcasecmp((char *)n->name, "keybind")) { - state->in_keybind = true; - traverse(n, state); - state->in_keybind = false; - continue; - } - if (!strcasecmp((char *)n->name, "mousebind")) { - state->in_mousebind = true; - traverse(n, state); - state->in_mousebind = false; - continue; - } - if (!strcasecmp((char *)n->name, "touch")) { - state->in_touch = true; - traverse(n, state); - state->in_touch = false; - continue; - } - if (!strcasecmp((char *)n->name, "device")) { - state->in_libinput_category = true; - traverse(n, state); - state->in_libinput_category = false; - continue; - } - if (!strcasecmp((char *)n->name, "regions")) { - state->in_regions = true; - traverse(n, state); - state->in_regions = false; - continue; - } - if (!strcasecmp((char *)n->name, "fields")) { - state->in_window_switcher_field = true; - traverse(n, state); - state->in_window_switcher_field = false; - continue; - } - if (!strcasecmp((char *)n->name, "windowRules")) { - state->in_window_rules = true; - traverse(n, state); - state->in_window_rules = false; - continue; - } - if (!strcasecmp((char *)n->name, "query")) { - state->in_action_query = true; - traverse(n, state); - state->in_action_query = false; - continue; - } - if (!strcasecmp((char *)n->name, "then")) { - state->in_action_then_branch = true; - traverse(n, state); - state->in_action_then_branch = false; - continue; - } - if (!strcasecmp((char *)n->name, "else")) { - state->in_action_else_branch = true; - traverse(n, state); - state->in_action_else_branch = false; - continue; - } - if (!strcasecmp((char *)n->name, "none")) { - state->in_action_none_branch = true; - traverse(n, state); - state->in_action_none_branch = false; - continue; - } - traverse(n, state); } } @@ -1485,10 +1323,11 @@ rcxml_parse_xml(struct buf *b) wlr_log(WLR_ERROR, "error parsing config file"); return; } - struct parser_state init_state = {0}; xmlNode *root = xmlDocGetRootElement(d); + lab_xml_expand_dotted_attributes(root); - xml_tree_walk(root, &init_state); + traverse(root); + xmlFreeDoc(d); xmlCleanupParser(); }