mirror of
				https://github.com/labwc/labwc.git
				synced 2025-11-03 09:01:51 -05:00 
			
		
		
		
	action: add If and ForEach actions
Add If and ForEach actions as described in OpenBox specification. Limitations: - If and ForEach cannot contain nested If and ForEach.
This commit is contained in:
		
							parent
							
								
									12f6a8975a
								
							
						
					
					
						commit
						22e3be40e5
					
				
					 4 changed files with 307 additions and 3 deletions
				
			
		| 
						 | 
				
			
			@ -148,6 +148,56 @@ Actions are used in menus and keyboard/mouse bindings.
 | 
			
		|||
*<action name="None" />*
 | 
			
		||||
	If used as the only action for a binding: clear an earlier defined binding.
 | 
			
		||||
 | 
			
		||||
# CONDITIONAL ACTIONS
 | 
			
		||||
 | 
			
		||||
Actions that execute other actions. Used in keyboard/mouse bindings.
 | 
			
		||||
 | 
			
		||||
*<action name="If">*
 | 
			
		||||
	This action will execute one set of actions if the focused window
 | 
			
		||||
	matches the criteria, or another if it does not.
 | 
			
		||||
 | 
			
		||||
	The arguments are as follows:
 | 
			
		||||
 | 
			
		||||
	```
 | 
			
		||||
	<action name="If">
 | 
			
		||||
	  <query/>
 | 
			
		||||
	  <then><action/></then>
 | 
			
		||||
	  <else><action/></else>
 | 
			
		||||
	</action>
 | 
			
		||||
	```
 | 
			
		||||
 | 
			
		||||
	*query*
 | 
			
		||||
		Define a query with zero or more conditions. All conditions must
 | 
			
		||||
		be evaluated as true in order for the window to match this
 | 
			
		||||
		query. Multiple queries can be defined.
 | 
			
		||||
 | 
			
		||||
		Pattern matching is done according to glob(7) and is
 | 
			
		||||
		case-insensitive.
 | 
			
		||||
 | 
			
		||||
		Conditions are as follows:
 | 
			
		||||
 | 
			
		||||
		*identifier*
 | 
			
		||||
			XDG shell app_id for Wayland clients, WM_CLASS for
 | 
			
		||||
			XWayland clients.
 | 
			
		||||
 | 
			
		||||
		*title*
 | 
			
		||||
			XDG shell title for Wayland clients, WM_NAME for
 | 
			
		||||
			XWayland clients.
 | 
			
		||||
 | 
			
		||||
		This argument is optional.
 | 
			
		||||
	
 | 
			
		||||
	*then*
 | 
			
		||||
		A list of actions to be executed if the window matches any
 | 
			
		||||
		query. This argument is optional.
 | 
			
		||||
 | 
			
		||||
	*else*
 | 
			
		||||
		A list of actions to be executed if the window does not match
 | 
			
		||||
		any query. This argument is optional.
 | 
			
		||||
 | 
			
		||||
*<action name="ForEach">*
 | 
			
		||||
	Identical to "If" action, but applies to all windows, not just the
 | 
			
		||||
	focused one.
 | 
			
		||||
 | 
			
		||||
# SEE ALSO
 | 
			
		||||
 | 
			
		||||
labwc(1), labwc-config(5), labwc-theme(5)
 | 
			
		||||
labwc(1), labwc-config(5), labwc-theme(5), glob(7)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,6 +23,11 @@ struct action *action_create(const char *action_name);
 | 
			
		|||
bool action_is_valid(struct action *action);
 | 
			
		||||
 | 
			
		||||
void action_arg_add_str(struct action *action, const char *key, const char *value);
 | 
			
		||||
void action_arg_add_actionlist(struct action *action, const char *key);
 | 
			
		||||
void action_arg_add_querylist(struct action *action, const char *key);
 | 
			
		||||
 | 
			
		||||
struct wl_list *action_get_actionlist(struct action *action, const char *key);
 | 
			
		||||
struct wl_list *action_get_querylist(struct action *action, const char *key);
 | 
			
		||||
 | 
			
		||||
void action_arg_from_xml_node(struct action *action, const char *nodename, const char *content);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										128
									
								
								src/action.c
									
										
									
									
									
								
							
							
						
						
									
										128
									
								
								src/action.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -7,6 +7,7 @@
 | 
			
		|||
#include <unistd.h>
 | 
			
		||||
#include <wlr/util/log.h>
 | 
			
		||||
#include "action.h"
 | 
			
		||||
#include "common/array-size.h"
 | 
			
		||||
#include "common/list.h"
 | 
			
		||||
#include "common/mem.h"
 | 
			
		||||
#include "common/parse-bool.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -24,6 +25,8 @@ enum action_arg_type {
 | 
			
		|||
	LAB_ACTION_ARG_STR = 0,
 | 
			
		||||
	LAB_ACTION_ARG_BOOL,
 | 
			
		||||
	LAB_ACTION_ARG_INT,
 | 
			
		||||
	LAB_ACTION_ARG_QUERY_LIST,
 | 
			
		||||
	LAB_ACTION_ARG_ACTION_LIST,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct action_arg {
 | 
			
		||||
| 
						 | 
				
			
			@ -48,6 +51,11 @@ struct action_arg_int {
 | 
			
		|||
	int value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct action_arg_list {
 | 
			
		||||
	struct action_arg base;
 | 
			
		||||
	struct wl_list value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum action_type {
 | 
			
		||||
	ACTION_TYPE_INVALID = 0,
 | 
			
		||||
	ACTION_TYPE_NONE,
 | 
			
		||||
| 
						 | 
				
			
			@ -82,6 +90,8 @@ enum action_type {
 | 
			
		|||
	ACTION_TYPE_SNAP_TO_REGION,
 | 
			
		||||
	ACTION_TYPE_TOGGLE_KEYBINDS,
 | 
			
		||||
	ACTION_TYPE_FOCUS_OUTPUT,
 | 
			
		||||
	ACTION_TYPE_IF,
 | 
			
		||||
	ACTION_TYPE_FOR_EACH,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const char *action_names[] = {
 | 
			
		||||
| 
						 | 
				
			
			@ -118,6 +128,8 @@ const char *action_names[] = {
 | 
			
		|||
	"SnapToRegion",
 | 
			
		||||
	"ToggleKeybinds",
 | 
			
		||||
	"FocusOutput",
 | 
			
		||||
	"If",
 | 
			
		||||
	"ForEach",
 | 
			
		||||
	NULL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -158,6 +170,30 @@ action_arg_add_int(struct action *action, const char *key, int value)
 | 
			
		|||
	wl_list_append(&action->args, &arg->base.link);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
action_arg_add_list(struct action *action, const char *key, enum action_arg_type type)
 | 
			
		||||
{
 | 
			
		||||
	assert(action);
 | 
			
		||||
	assert(key);
 | 
			
		||||
	struct action_arg_list *arg = znew(*arg);
 | 
			
		||||
	arg->base.type = type;
 | 
			
		||||
	arg->base.key = xstrdup(key);
 | 
			
		||||
	wl_list_init(&arg->value);
 | 
			
		||||
	wl_list_append(&action->args, &arg->base.link);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
action_arg_add_querylist(struct action *action, const char *key)
 | 
			
		||||
{
 | 
			
		||||
	action_arg_add_list(action, key, LAB_ACTION_ARG_QUERY_LIST);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
action_arg_add_actionlist(struct action *action, const char *key)
 | 
			
		||||
{
 | 
			
		||||
	action_arg_add_list(action, key, LAB_ACTION_ARG_ACTION_LIST);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void *
 | 
			
		||||
action_get_arg(struct action *action, const char *key, enum action_arg_type type)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -193,6 +229,20 @@ action_get_int(struct action *action, const char *key, int default_value)
 | 
			
		|||
	return arg ? arg->value : default_value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct wl_list *
 | 
			
		||||
action_get_querylist(struct action *action, const char *key)
 | 
			
		||||
{
 | 
			
		||||
	struct action_arg_list *arg = action_get_arg(action, key, LAB_ACTION_ARG_QUERY_LIST);
 | 
			
		||||
	return arg ? &arg->value : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct wl_list *
 | 
			
		||||
action_get_actionlist(struct action *action, const char *key)
 | 
			
		||||
{
 | 
			
		||||
	struct action_arg_list *arg = action_get_arg(action, key, LAB_ACTION_ARG_ACTION_LIST);
 | 
			
		||||
	return arg ? &arg->value : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
action_arg_from_xml_node(struct action *action, const char *nodename, const char *content)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -327,6 +377,20 @@ actions_contain_toggle_keybinds(struct wl_list *action_list)
 | 
			
		|||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool
 | 
			
		||||
action_list_is_valid(struct wl_list *actions)
 | 
			
		||||
{
 | 
			
		||||
	assert(actions);
 | 
			
		||||
 | 
			
		||||
	struct action *action;
 | 
			
		||||
	wl_list_for_each(action, actions, link) {
 | 
			
		||||
		if (!action_is_valid(action)) {
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Checks for *required* arguments */
 | 
			
		||||
bool
 | 
			
		||||
action_is_valid(struct action *action)
 | 
			
		||||
| 
						 | 
				
			
			@ -356,6 +420,19 @@ action_is_valid(struct action *action)
 | 
			
		|||
	case ACTION_TYPE_FOCUS_OUTPUT:
 | 
			
		||||
		arg_name = "output";
 | 
			
		||||
		break;
 | 
			
		||||
	case ACTION_TYPE_IF:
 | 
			
		||||
	case ACTION_TYPE_FOR_EACH:
 | 
			
		||||
		; /* works around "a label can only be part of a statement" */
 | 
			
		||||
		static const char * const branches[] = { "then", "else" };
 | 
			
		||||
		for (size_t i = 0; i < ARRAY_SIZE(branches); i++) {
 | 
			
		||||
			struct wl_list *children = action_get_actionlist(action, branches[i]);
 | 
			
		||||
			if (children && !action_list_is_valid(children)) {
 | 
			
		||||
				wlr_log(WLR_ERROR, "Invalid action in %s '%s' branch",
 | 
			
		||||
					action_names[action->type], branches[i]);
 | 
			
		||||
				return false;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return true;
 | 
			
		||||
	default:
 | 
			
		||||
		/* No arguments required */
 | 
			
		||||
		return true;
 | 
			
		||||
| 
						 | 
				
			
			@ -381,6 +458,15 @@ action_free(struct action *action)
 | 
			
		|||
		if (arg->type == LAB_ACTION_ARG_STR) {
 | 
			
		||||
			struct action_arg_str *str_arg = (struct action_arg_str *)arg;
 | 
			
		||||
			zfree(str_arg->value);
 | 
			
		||||
		} else if (arg->type == LAB_ACTION_ARG_ACTION_LIST) {
 | 
			
		||||
			struct action_arg_list *list_arg = (struct action_arg_list *)arg;
 | 
			
		||||
			action_list_free(&list_arg->value);
 | 
			
		||||
		} else if (arg->type == LAB_ACTION_ARG_QUERY_LIST) {
 | 
			
		||||
			struct action_arg_list *list_arg = (struct action_arg_list *)arg;
 | 
			
		||||
			struct view_query *elm, *next;
 | 
			
		||||
			wl_list_for_each_safe(elm, next, &list_arg->value, link) {
 | 
			
		||||
				view_query_free(elm);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		zfree(arg);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -466,6 +552,31 @@ view_for_action(struct view *activator, struct server *server,
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
run_if_action(struct view *view, struct server *server, struct action *action)
 | 
			
		||||
{
 | 
			
		||||
	struct view_query *query;
 | 
			
		||||
	struct wl_list *queries, *actions;
 | 
			
		||||
	const char *branch = "then";
 | 
			
		||||
 | 
			
		||||
	queries = action_get_querylist(action, "query");
 | 
			
		||||
	if (queries) {
 | 
			
		||||
		branch = "else";
 | 
			
		||||
		/* All queries are OR'ed */
 | 
			
		||||
		wl_list_for_each(query, queries, link) {
 | 
			
		||||
			if (view_matches_query(view, query)) {
 | 
			
		||||
				branch = "then";
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	actions = action_get_actionlist(action, branch);
 | 
			
		||||
	if (actions) {
 | 
			
		||||
		actions_run(view, server, actions, 0);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
actions_run(struct view *activator, struct server *server,
 | 
			
		||||
	struct wl_list *actions, uint32_t resize_edges)
 | 
			
		||||
| 
						 | 
				
			
			@ -693,6 +804,23 @@ actions_run(struct view *activator, struct server *server,
 | 
			
		|||
				desktop_focus_output(output_from_name(server, output_name));
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		case ACTION_TYPE_IF:
 | 
			
		||||
			if (view) {
 | 
			
		||||
				run_if_action(view, server, action);
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		case ACTION_TYPE_FOR_EACH:
 | 
			
		||||
			{
 | 
			
		||||
				struct wl_array views;
 | 
			
		||||
				struct view **item;
 | 
			
		||||
				wl_array_init(&views);
 | 
			
		||||
				view_array_append(server, &views, LAB_VIEW_CRITERIA_NONE);
 | 
			
		||||
				wl_array_for_each(item, &views) {
 | 
			
		||||
					run_if_action(*item, server, action);
 | 
			
		||||
				}
 | 
			
		||||
				wl_array_release(&views);
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		case ACTION_TYPE_INVALID:
 | 
			
		||||
			wlr_log(WLR_ERROR, "Not executing unknown action");
 | 
			
		||||
			break;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,6 +27,7 @@
 | 
			
		|||
#include "config/rcxml.h"
 | 
			
		||||
#include "labwc.h"
 | 
			
		||||
#include "regions.h"
 | 
			
		||||
#include "view.h"
 | 
			
		||||
#include "window-rules.h"
 | 
			
		||||
#include "workspaces.h"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -37,6 +38,9 @@ static bool in_mousebind;
 | 
			
		|||
static bool in_libinput_category;
 | 
			
		||||
static bool in_window_switcher_field;
 | 
			
		||||
static bool in_window_rules;
 | 
			
		||||
static bool in_action_query;
 | 
			
		||||
static bool in_action_then_branch;
 | 
			
		||||
static bool in_action_else_branch;
 | 
			
		||||
 | 
			
		||||
static struct usable_area_override *current_usable_area_override;
 | 
			
		||||
static struct keybind *current_keybind;
 | 
			
		||||
| 
						 | 
				
			
			@ -49,6 +53,8 @@ static struct region *current_region;
 | 
			
		|||
static struct window_switcher_field *current_field;
 | 
			
		||||
static struct window_rule *current_window_rule;
 | 
			
		||||
static struct action *current_window_rule_action;
 | 
			
		||||
static struct view_query *current_view_query;
 | 
			
		||||
static struct action *current_child_action;
 | 
			
		||||
 | 
			
		||||
enum font_place {
 | 
			
		||||
	FONT_PLACE_NONE = 0,
 | 
			
		||||
| 
						 | 
				
			
			@ -246,6 +252,79 @@ fill_region(char *nodename, char *content)
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
fill_action_query(char *nodename, char *content, struct action *action)
 | 
			
		||||
{
 | 
			
		||||
	string_truncate_at_pattern(nodename, ".keybind.keyboard");
 | 
			
		||||
	string_truncate_at_pattern(nodename, ".mousebind.context.mouse");
 | 
			
		||||
 | 
			
		||||
	if (!strcasecmp(nodename, "query.action")) {
 | 
			
		||||
		current_view_query = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	string_truncate_at_pattern(nodename, ".query.action");
 | 
			
		||||
 | 
			
		||||
	if (!content) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!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");
 | 
			
		||||
		}
 | 
			
		||||
		current_view_query = znew(*current_view_query);
 | 
			
		||||
		wl_list_append(queries, ¤t_view_query->link);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!strcasecmp(nodename, "identifier")) {
 | 
			
		||||
		current_view_query->identifier = xstrdup(content);
 | 
			
		||||
	} else if (!strcasecmp(nodename, "title")) {
 | 
			
		||||
		current_view_query->title = xstrdup(content);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
fill_child_action(char *nodename, char *content, struct action *parent,
 | 
			
		||||
	const char *branch_name)
 | 
			
		||||
{
 | 
			
		||||
	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");
 | 
			
		||||
 | 
			
		||||
	if (!strcasecmp(nodename, "action")) {
 | 
			
		||||
		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;
 | 
			
		||||
		}
 | 
			
		||||
		current_child_action = action_create(content);
 | 
			
		||||
		if (current_child_action) {
 | 
			
		||||
			wl_list_append(siblings, ¤t_child_action->link);
 | 
			
		||||
		}
 | 
			
		||||
	} else if (!current_child_action) {
 | 
			
		||||
		wlr_log(WLR_ERROR, "expect <action name=\"\"> element first. "
 | 
			
		||||
			"nodename: '%s' content: '%s'", nodename, content);
 | 
			
		||||
	} else {
 | 
			
		||||
		action_arg_from_xml_node(current_child_action, nodename, content);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
fill_keybind(char *nodename, char *content)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -539,11 +618,33 @@ entry(xmlNode *node, char *nodename, char *content)
 | 
			
		|||
		fill_usable_area_override(nodename, content);
 | 
			
		||||
	}
 | 
			
		||||
	if (in_keybind) {
 | 
			
		||||
		if (in_action_query) {
 | 
			
		||||
			fill_action_query(nodename, content,
 | 
			
		||||
				current_keybind_action);
 | 
			
		||||
		} else if (in_action_then_branch) {
 | 
			
		||||
			fill_child_action(nodename, content,
 | 
			
		||||
				current_keybind_action, "then");
 | 
			
		||||
		} else if (in_action_else_branch) {
 | 
			
		||||
			fill_child_action(nodename, content,
 | 
			
		||||
				current_keybind_action, "else");
 | 
			
		||||
		} else {
 | 
			
		||||
			fill_keybind(nodename, content);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (in_mousebind) {
 | 
			
		||||
		if (in_action_query) {
 | 
			
		||||
			fill_action_query(nodename, content,
 | 
			
		||||
				current_mousebind_action);
 | 
			
		||||
		} else if (in_action_then_branch) {
 | 
			
		||||
			fill_child_action(nodename, content,
 | 
			
		||||
				current_mousebind_action, "then");
 | 
			
		||||
		} else if (in_action_else_branch) {
 | 
			
		||||
			fill_child_action(nodename, content,
 | 
			
		||||
				current_mousebind_action, "else");
 | 
			
		||||
		} else {
 | 
			
		||||
			fill_mousebind(nodename, content);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (in_libinput_category) {
 | 
			
		||||
		fill_libinput_category(nodename, content);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -771,6 +872,24 @@ xml_tree_walk(xmlNode *node)
 | 
			
		|||
			in_window_rules = false;
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		if (!strcasecmp((char *)n->name, "query")) {
 | 
			
		||||
			in_action_query = true;
 | 
			
		||||
			traverse(n);
 | 
			
		||||
			in_action_query = false;
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		if (!strcasecmp((char *)n->name, "then")) {
 | 
			
		||||
			in_action_then_branch = true;
 | 
			
		||||
			traverse(n);
 | 
			
		||||
			in_action_then_branch = false;
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		if (!strcasecmp((char *)n->name, "else")) {
 | 
			
		||||
			in_action_else_branch = true;
 | 
			
		||||
			traverse(n);
 | 
			
		||||
			in_action_else_branch = false;
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		traverse(n);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1366,6 +1485,8 @@ rcxml_finish(void)
 | 
			
		|||
	current_mouse_context = NULL;
 | 
			
		||||
	current_keybind_action = NULL;
 | 
			
		||||
	current_mousebind_action = NULL;
 | 
			
		||||
	current_child_action = NULL;
 | 
			
		||||
	current_view_query = NULL;
 | 
			
		||||
	current_region = NULL;
 | 
			
		||||
	current_field = NULL;
 | 
			
		||||
	current_window_rule = NULL;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue