mirror of
				https://github.com/labwc/labwc.git
				synced 2025-10-29 05:40:24 -04:00 
			
		
		
		
	rcxml: rewrite action parser
This commit rewrites the nested action parser into append_actions() which is used by following commits. At this point, it's not used yet and parsing "If" action is temporarily disabled.
This commit is contained in:
		
							parent
							
								
									8881841098
								
							
						
					
					
						commit
						9462457cc2
					
				
					 1 changed files with 128 additions and 127 deletions
				
			
		|  | @ -432,112 +432,141 @@ fill_region(char *nodename, char *content, struct parser_state *state) | |||
| } | ||||
| 
 | ||||
| static void | ||||
| fill_action_query(char *nodename, char *content, struct action *action, struct parser_state *state) | ||||
| fill_action_query(struct action *action, xmlNode *node, struct view_query *query) | ||||
| { | ||||
| 	if (!action) { | ||||
| 		wlr_log(WLR_ERROR, "No parent action for query: %s=%s", nodename, content); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	string_truncate_at_pattern(nodename, ".keybind.keyboard"); | ||||
| 	string_truncate_at_pattern(nodename, ".mousebind.context.mouse"); | ||||
| 
 | ||||
| 	if (!strcasecmp(nodename, "query.action")) { | ||||
| 		state->current_view_query = NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	string_truncate_at_pattern(nodename, ".query.action"); | ||||
| 
 | ||||
| 	if (!content) { | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	if (!state->current_view_query) { | ||||
| 		struct wl_list *queries = action_get_querylist(action, "query"); | ||||
| 		if (!queries) { | ||||
| 			action_arg_add_querylist(action, "query"); | ||||
| 			queries = action_get_querylist(action, "query"); | ||||
| 	xmlNode *child; | ||||
| 	char *key, *content; | ||||
| 	LAB_XML_FOR_EACH(node, child, key, content) { | ||||
| 		if (!strcasecmp(key, "identifier")) { | ||||
| 			xstrdup_replace(query->identifier, content); | ||||
| 		} else if (!strcasecmp(key, "title")) { | ||||
| 			xstrdup_replace(query->title, content); | ||||
| 		} else if (!strcmp(key, "type")) { | ||||
| 			query->window_type = parse_window_type(content); | ||||
| 		} else if (!strcasecmp(key, "sandboxEngine")) { | ||||
| 			xstrdup_replace(query->sandbox_engine, content); | ||||
| 		} else if (!strcasecmp(key, "sandboxAppId")) { | ||||
| 			xstrdup_replace(query->sandbox_app_id, content); | ||||
| 		} else if (!strcasecmp(key, "shaded")) { | ||||
| 			query->shaded = parse_three_state(content); | ||||
| 		} else if (!strcasecmp(key, "maximized")) { | ||||
| 			query->maximized = view_axis_parse(content); | ||||
| 		} else if (!strcasecmp(key, "iconified")) { | ||||
| 			query->iconified = parse_three_state(content); | ||||
| 		} else if (!strcasecmp(key, "focused")) { | ||||
| 			query->focused = parse_three_state(content); | ||||
| 		} else if (!strcasecmp(key, "omnipresent")) { | ||||
| 			query->omnipresent = parse_three_state(content); | ||||
| 		} else if (!strcasecmp(key, "tiled")) { | ||||
| 			query->tiled = view_edge_parse(content); | ||||
| 		} else if (!strcasecmp(key, "tiled_region")) { | ||||
| 			xstrdup_replace(query->tiled_region, content); | ||||
| 		} else if (!strcasecmp(key, "desktop")) { | ||||
| 			xstrdup_replace(query->desktop, content); | ||||
| 		} else if (!strcasecmp(key, "decoration")) { | ||||
| 			query->decoration = ssd_mode_parse(content); | ||||
| 		} else if (!strcasecmp(key, "monitor")) { | ||||
| 			xstrdup_replace(query->monitor, content); | ||||
| 		} | ||||
| 		state->current_view_query = view_query_create(); | ||||
| 		wl_list_append(queries, &state->current_view_query->link); | ||||
| 	} | ||||
| 
 | ||||
| 	if (!strcasecmp(nodename, "identifier")) { | ||||
| 		xstrdup_replace(state->current_view_query->identifier, content); | ||||
| 	} else if (!strcasecmp(nodename, "title")) { | ||||
| 		xstrdup_replace(state->current_view_query->title, content); | ||||
| 	} else if (!strcmp(nodename, "type")) { | ||||
| 		state->current_view_query->window_type = parse_window_type(content); | ||||
| 	} else if (!strcasecmp(nodename, "sandboxEngine")) { | ||||
| 		xstrdup_replace(state->current_view_query->sandbox_engine, content); | ||||
| 	} else if (!strcasecmp(nodename, "sandboxAppId")) { | ||||
| 		xstrdup_replace(state->current_view_query->sandbox_app_id, content); | ||||
| 	} else if (!strcasecmp(nodename, "shaded")) { | ||||
| 		state->current_view_query->shaded = parse_three_state(content); | ||||
| 	} else if (!strcasecmp(nodename, "maximized")) { | ||||
| 		state->current_view_query->maximized = view_axis_parse(content); | ||||
| 	} else if (!strcasecmp(nodename, "iconified")) { | ||||
| 		state->current_view_query->iconified = parse_three_state(content); | ||||
| 	} else if (!strcasecmp(nodename, "focused")) { | ||||
| 		state->current_view_query->focused = parse_three_state(content); | ||||
| 	} else if (!strcasecmp(nodename, "omnipresent")) { | ||||
| 		state->current_view_query->omnipresent = parse_three_state(content); | ||||
| 	} else if (!strcasecmp(nodename, "tiled")) { | ||||
| 		state->current_view_query->tiled = view_edge_parse(content); | ||||
| 	} else if (!strcasecmp(nodename, "tiled_region")) { | ||||
| 		xstrdup_replace(state->current_view_query->tiled_region, content); | ||||
| 	} else if (!strcasecmp(nodename, "desktop")) { | ||||
| 		xstrdup_replace(state->current_view_query->desktop, content); | ||||
| 	} else if (!strcasecmp(nodename, "decoration")) { | ||||
| 		state->current_view_query->decoration = ssd_mode_parse(content); | ||||
| 	} else if (!strcasecmp(nodename, "monitor")) { | ||||
| 		xstrdup_replace(state->current_view_query->monitor, content); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void append_actions(xmlNode *node, struct wl_list *list); | ||||
| 
 | ||||
| static void | ||||
| fill_child_action(char *nodename, char *content, struct action *parent, | ||||
| 	const char *branch_name, struct parser_state *state) | ||||
| parse_action_args(xmlNode *node, struct action *action) | ||||
| { | ||||
| 	if (!parent) { | ||||
| 		wlr_log(WLR_ERROR, "No parent action for branch: %s=%s", nodename, content); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	string_truncate_at_pattern(nodename, ".keybind.keyboard"); | ||||
| 	string_truncate_at_pattern(nodename, ".mousebind.context.mouse"); | ||||
| 	string_truncate_at_pattern(nodename, ".then.action"); | ||||
| 	string_truncate_at_pattern(nodename, ".else.action"); | ||||
| 	string_truncate_at_pattern(nodename, ".none.action"); | ||||
| 
 | ||||
| 	if (!strcasecmp(nodename, "action")) { | ||||
| 		state->current_child_action = NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	if (!content) { | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	struct wl_list *siblings = action_get_actionlist(parent, branch_name); | ||||
| 	if (!siblings) { | ||||
| 		action_arg_add_actionlist(parent, branch_name); | ||||
| 		siblings = action_get_actionlist(parent, branch_name); | ||||
| 	} | ||||
| 
 | ||||
| 	if (!strcasecmp(nodename, "name.action")) { | ||||
| 		if (!strcasecmp(content, "If") || !strcasecmp(content, "ForEach")) { | ||||
| 			wlr_log(WLR_ERROR, "action '%s' cannot be a child action", content); | ||||
| 			return; | ||||
| 	xmlNode *child; | ||||
| 	char *key, *content; | ||||
| 	LAB_XML_FOR_EACH(node, child, key, content) { | ||||
| 		if (!strcasecmp(key, "query")) { | ||||
| 			struct wl_list *querylist = | ||||
| 				action_get_querylist(action, "query"); | ||||
| 			if (!querylist) { | ||||
| 				action_arg_add_querylist(action, "query"); | ||||
| 				querylist = action_get_querylist(action, "query"); | ||||
| 			} | ||||
| 			struct view_query *query = view_query_create(); | ||||
| 			fill_action_query(action, child, query); | ||||
| 			wl_list_append(querylist, &query->link); | ||||
| 		} else if (!strcasecmp(key, "then")) { | ||||
| 			struct wl_list *actions = | ||||
| 				action_get_actionlist(action, "then"); | ||||
| 			if (!actions) { | ||||
| 				action_arg_add_actionlist(action, "then"); | ||||
| 				actions = action_get_actionlist(action, "then"); | ||||
| 			} | ||||
| 			append_actions(child, actions); | ||||
| 		} else if (!strcasecmp(key, "else")) { | ||||
| 			struct wl_list *actions = | ||||
| 				action_get_actionlist(action, "else"); | ||||
| 			if (!actions) { | ||||
| 				action_arg_add_actionlist(action, "else"); | ||||
| 				actions = action_get_actionlist(action, "else"); | ||||
| 			} | ||||
| 			append_actions(child, actions); | ||||
| 		} else if (!strcasecmp(key, "none")) { | ||||
| 			struct wl_list *actions = | ||||
| 				action_get_actionlist(action, "none"); | ||||
| 			if (!actions) { | ||||
| 				action_arg_add_actionlist(action, "none"); | ||||
| 				actions = action_get_actionlist(action, "none"); | ||||
| 			} | ||||
| 			append_actions(child, actions); | ||||
| 		} else if (!strcasecmp(key, "name")) { | ||||
| 			/* Ignore <action name=""> */ | ||||
| 		} else if (lab_xml_node_is_leaf(child)) { | ||||
| 			/* Handle normal action args */ | ||||
| 			char buffer[256]; | ||||
| 			char *node_name = nodename(child, buffer, sizeof(buffer)); | ||||
| 			action_arg_from_xml_node(action, node_name, content); | ||||
| 		} else { | ||||
| 			/* Handle nested args like <position><x> in ShowMenu */ | ||||
| 			parse_action_args(child, action); | ||||
| 		} | ||||
| 		state->current_child_action = action_create(content); | ||||
| 		if (state->current_child_action) { | ||||
| 			wl_list_append(siblings, &state->current_child_action->link); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static struct action * | ||||
| parse_action(xmlNode *node) | ||||
| { | ||||
| 	char name[256]; | ||||
| 	struct action *action = NULL; | ||||
| 
 | ||||
| 	if (lab_xml_get_string(node, "name", name, sizeof(name))) { | ||||
| 		action = action_create(name); | ||||
| 	} | ||||
| 	if (!action) { | ||||
| 		return NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	parse_action_args(node, action); | ||||
| 	return action; | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| append_actions(xmlNode *node, struct wl_list *list) | ||||
| { | ||||
| 	xmlNode *child; | ||||
| 	char *key, *content; | ||||
| 	LAB_XML_FOR_EACH(node, child, key, content) { | ||||
| 		if (strcasecmp(key, "action")) { | ||||
| 			continue; | ||||
| 		} | ||||
| 		if (lab_xml_node_is_leaf(child)) { | ||||
| 			/*
 | ||||
| 			 * A mousebind contains two types of "action" nodes: | ||||
| 			 *   <mousebind button="Left" action="Click"> | ||||
| 			 *     <action name="Close" /> | ||||
| 			 *   </mousebind> | ||||
| 			 * The first node (action="Click") is skipped. | ||||
| 			 */ | ||||
| 			continue; | ||||
| 		} | ||||
| 		struct action *action = parse_action(child); | ||||
| 		if (action) { | ||||
| 			wl_list_append(list, &action->link); | ||||
| 		} | ||||
| 	} else if (!state->current_child_action) { | ||||
| 		wlr_log(WLR_ERROR, "expect <action name=\"\"> element first. " | ||||
| 			"nodename: '%s' content: '%s'", nodename, content); | ||||
| 	} else { | ||||
| 		action_arg_from_xml_node(state->current_child_action, nodename, content); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -1055,38 +1084,10 @@ entry(xmlNode *node, char *nodename, char *content, struct parser_state *state) | |||
| 		fill_usable_area_override(nodename, content, state); | ||||
| 	} | ||||
| 	if (state->in_keybind) { | ||||
| 		if (state->in_action_query) { | ||||
| 			fill_action_query(nodename, content, | ||||
| 				state->current_keybind_action, state); | ||||
| 		} else if (state->in_action_then_branch) { | ||||
| 			fill_child_action(nodename, content, | ||||
| 				state->current_keybind_action, "then", state); | ||||
| 		} else if (state->in_action_else_branch) { | ||||
| 			fill_child_action(nodename, content, | ||||
| 				state->current_keybind_action, "else", state); | ||||
| 		} else if (state->in_action_none_branch) { | ||||
| 			fill_child_action(nodename, content, | ||||
| 				state->current_keybind_action, "none", state); | ||||
| 		} else { | ||||
| 			fill_keybind(nodename, content, state); | ||||
| 		} | ||||
| 		fill_keybind(nodename, content, state); | ||||
| 	} | ||||
| 	if (state->in_mousebind) { | ||||
| 		if (state->in_action_query) { | ||||
| 			fill_action_query(nodename, content, | ||||
| 				state->current_mousebind_action, state); | ||||
| 		} else if (state->in_action_then_branch) { | ||||
| 			fill_child_action(nodename, content, | ||||
| 				state->current_mousebind_action, "then", state); | ||||
| 		} else if (state->in_action_else_branch) { | ||||
| 			fill_child_action(nodename, content, | ||||
| 				state->current_mousebind_action, "else", state); | ||||
| 		} else if (state->in_action_none_branch) { | ||||
| 			fill_child_action(nodename, content, | ||||
| 				state->current_mousebind_action, "none", state); | ||||
| 		} else { | ||||
| 			fill_mousebind(nodename, content, state); | ||||
| 		} | ||||
| 		fill_mousebind(nodename, content, state); | ||||
| 	} | ||||
| 	if (state->in_touch) { | ||||
| 		fill_touch(nodename, content, state); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 tokyo4j
						tokyo4j