Exemple #1
0
/* Executes keys from the start of key sequence or at some offset in it.
 * Returns error code. */
static int
dispatch_keys(const wchar_t keys[], keys_info_t *keys_info, int no_remap,
		int prev_count)
{
	key_info_t key_info;
	int result;

	if(fill_key_info(&keys, &key_info, prev_count, &result) != 0)
	{
		return result;
	}

	result = KEYS_UNKNOWN;
	if(!no_remap)
	{
		result = dispatch_keys_at_root(keys, keys_info,
				&user_cmds_root[vle_mode_get()], key_info, no_remap);
	}

	if(result == KEYS_UNKNOWN)
	{
		result = dispatch_keys_at_root(keys, keys_info,
				&builtin_cmds_root[vle_mode_get()], key_info, no_remap);
	}

	return result;
}
Exemple #2
0
void
vle_keys_suggest(const wchar_t keys[], vle_keys_list_cb cb, int custom_only,
		int fold_subkeys)
{
	keys_suggest(&user_cmds_root[vle_mode_get()], keys, L"key: ", cb,
			custom_only, fold_subkeys);
	keys_suggest(&builtin_cmds_root[vle_mode_get()], keys, L"key: ", cb,
			custom_only, fold_subkeys);
}
Exemple #3
0
/* Updates hardware cursor to be on currently active area of the interface,
 * which depends mainly on current mode.. */
static void
update_hardware_cursor(void)
{
	if(ui_sb_multiline())
	{
		checked_wmove(status_bar, 0, 0);
		ui_refresh_win(status_bar);
		return;
	}

	switch(vle_mode_get())
	{
		case MENU_MODE:
		case FILE_INFO_MODE:
		case MORE_MODE: ui_refresh_win(menu_win);       break;
		case CHANGE_MODE:
		case ATTR_MODE: ui_refresh_win(change_win);     break;
		case MSG_MODE:  ui_refresh_win(error_win);      break;
		case VIEW_MODE: ui_refresh_win(curr_view->win); break;
		case SORT_MODE: ui_refresh_win(sort_win);       break;

		case NORMAL_MODE:
		case VISUAL_MODE:
			if(should_check_views_for_changes())
			{
				ui_refresh_win(curr_view->win);
			}
			break;
	}
}
Exemple #4
0
void
clear_input_bar(void)
{
	if(uses_input_bar[vle_mode_get()] && !vle_mode_is(VISUAL_MODE))
	{
		clear_num_window();
	}
}
Exemple #5
0
/* Executes keys from the start of key sequence or at some offset in it.
 * Returns error code. */
static int
dispatch_keys(const wchar_t keys[], keys_info_t *keys_info, int no_remap,
		int prev_count)
{
	key_info_t key_info;
	int result;

	keys = get_reg(keys, &key_info.reg);
	if(keys == NULL)
	{
		return KEYS_WAIT;
	}
	if(key_info.reg == L'\x1b' || key_info.reg == L'\x03')
	{
		return 0;
	}

	keys = get_count(keys, &key_info.count);
	key_info.count = combine_counts(key_info.count, prev_count);
	key_info.multi = L'\0';

	if(!no_remap)
	{
		key_chunk_t *const root = keys_info->selector
		                        ? &selectors_root[vle_mode_get()]
		                        : &user_cmds_root[vle_mode_get()];
		result = dispatch_keys_at_root(keys, keys_info, root, key_info, no_remap);
	}
	else
	{
		result = KEYS_UNKNOWN;
	}

	if(result == KEYS_UNKNOWN && !keys_info->selector)
	{
		result = dispatch_keys_at_root(keys, keys_info,
				&builtin_cmds_root[vle_mode_get()], key_info, no_remap);
	}

	return result;
}
Exemple #6
0
/* Checks keys for a count.  Returns non-zero if there is count in the current
 * position. */
static int
is_at_count(const wchar_t keys[])
{
	if((mode_flags[vle_mode_get()] & MF_USES_COUNT) != 0)
	{
		if(keys[0] != L'0' && iswdigit(keys[0]))
		{
			return 1;
		}
	}
	return 0;
}
Exemple #7
0
void
modupd_input_bar(wchar_t *str)
{
	if(vle_mode_is(VISUAL_MODE))
	{
		clear_input_bar();
	}

	if(uses_input_bar[vle_mode_get()])
	{
		update_input_bar(str);
	}
}
Exemple #8
0
static int
execute_keys_general(const wchar_t keys[], int timed_out, int mapped,
		int no_remap)
{
	int result;
	keys_info_t keys_info;

	if(keys[0] == L'\0')
	{
		return KEYS_UNKNOWN;
	}

	init_keys_info(&keys_info, mapped);
	keys_info.after_wait = timed_out;
	result = dispatch_keys(keys, &keys_info, no_remap, NO_COUNT_GIVEN);
	if(result == KEYS_UNKNOWN && def_handlers[vle_mode_get()] != NULL)
	{
		result = def_handlers[vle_mode_get()](keys[0]);
		execute_keys_general(keys + 1, 0, mapped, no_remap);
	}
	return result;
}
Exemple #9
0
/* Enters the mode, which won't be left until one of expected results specified
 * by the mask is picked by the user. */
static void
enter(int result_mask)
{
	accept_mask = result_mask;
	prev_use_input_bar = curr_stats.use_input_bar;
	curr_stats.use_input_bar = 0;

	prev_mode = vle_mode_get();
	vle_mode_set(MSG_MODE, VMT_SECONDARY);

	quit = 0;
	event_loop(&quit);
}
Exemple #10
0
/* Handles the rest of the keys after first one has been determined (in curr).
 * These can be: <nothing> (empty line), selector, multikey argument.  Returns
 * error code. */
static int
execute_next_keys(key_chunk_t *curr, const wchar_t keys[], key_info_t *key_info,
		keys_info_t *keys_info, int has_duplicate, int no_remap)
{
	const key_conf_t *const conf = &curr->conf;

	if(*keys == L'\0')
	{
		int wait_point = (conf->type == BUILTIN_WAIT_POINT);
		wait_point = wait_point || (conf->type == USER_CMD &&
				conf->followed != FOLLOWED_BY_NONE);

		if(wait_point)
		{
			const int with_input = (mode_flags[vle_mode_get()] & MF_USES_INPUT);
			if(!keys_info->after_wait)
			{
				return (with_input || has_duplicate) ? KEYS_WAIT_SHORT : KEYS_WAIT;
			}
		}
		else if(conf->data.handler == NULL || conf->followed != FOLLOWED_BY_NONE)
		{
			return KEYS_UNKNOWN;
		}
	}
	else if(conf->type != USER_CMD)
	{
		int result;

		if(conf->followed == FOLLOWED_BY_MULTIKEY)
		{
			key_info->multi = keys[0];
			return dispatch_key(*key_info, keys_info, curr, keys + 1);
		}

		keys_info->selector = 1;
		result = dispatch_keys(keys, keys_info, no_remap, key_info->count);
		keys_info->selector = 0;

		if(IS_KEYS_RET_CODE(result))
		{
			return result;
		}

		/* We used this count in selector, so don't pass it to command. */
		key_info->count = NO_COUNT_GIVEN;
	}

	return dispatch_key(*key_info, keys_info, curr, keys);
}
Exemple #11
0
static const wchar_t *
get_reg(const wchar_t *keys, int *reg)
{
	*reg = NO_REG_GIVEN;
	if((mode_flags[vle_mode_get()] & MF_USES_REGS) == 0)
	{
		return keys;
	}
	if(keys[0] == L'"')
	{
		if(keys[1] == L'\0')
		{
			return NULL;
		}
		*reg = keys[1];
		keys += 2;
	}

	return keys;
}
Exemple #12
0
/* Handles the rest of the keys after first one has been determined (in curr).
 * These can be: <nothing> (empty line), selector, multikey argument.  Returns
 * error code. */
static int
execute_next_keys(key_chunk_t *curr, const wchar_t keys[], key_info_t *key_info,
		keys_info_t *keys_info, int has_duplicate, int no_remap)
{
	const key_conf_t *const conf = &curr->conf;

	if(*keys == L'\0')
	{
		int wait_point = (curr->type == BUILTIN_WAIT_POINT);
		wait_point = wait_point || (curr->type == USER_CMD &&
				conf->followed != FOLLOWED_BY_NONE);

		if(wait_point)
		{
			const int with_input = (mode_flags[vle_mode_get()] & MF_USES_INPUT);
			if(!keys_info->after_wait)
			{
				return (with_input || has_duplicate) ? KEYS_WAIT_SHORT : KEYS_WAIT;
			}
		}
		else if(conf->data.handler == NULL || conf->followed != FOLLOWED_BY_NONE)
		{
			return KEYS_UNKNOWN;
		}
	}
	else if(curr->type != USER_CMD)
	{
		if(conf->followed == FOLLOWED_BY_MULTIKEY)
		{
			key_info->multi = keys[0];
			return dispatch_key(*key_info, keys_info, curr, keys + 1);
		}

		keys_info->selector = 1;
		return dispatch_selector(keys, keys_info, *key_info, curr, no_remap);
	}

	return dispatch_key(*key_info, keys_info, curr, keys);
}
Exemple #13
0
/* Gets default handler of active mode.  Returns the handler, which is NULL when
 * not set for active mode. */
static default_handler
def_handler(void)
{
	return def_handlers[vle_mode_get()];
}
Exemple #14
0
/* Dispatches keys passed in using a tree of shortcuts registered in the root.
 * Returns error code. */
static int
dispatch_keys_at_root(const wchar_t keys[], keys_info_t *keys_info,
		key_chunk_t *root, key_info_t key_info, int no_remap)
{
	key_chunk_t *curr;
	const wchar_t *keys_start = keys;
	int has_duplicate;
	int result;

	/* The loop finds longest match of the input (keys) amoung registered
	 * shortcuts. */
	curr = root;
	while(*keys != L'\0')
	{
		key_chunk_t *p;
		int number_in_the_middle = 0;

		p = curr->child;
		while(p != NULL && p->key < *keys)
		{
			if(p->conf.type == BUILTIN_NIM_KEYS)
			{
				number_in_the_middle = 1;
			}
			p = p->next;
		}

		if(p == NULL || p->key != *keys)
		{
			if(curr == root)
				return KEYS_UNKNOWN;

			while(p != NULL)
			{
				if(p->conf.type == BUILTIN_NIM_KEYS)
				{
					number_in_the_middle = 1;
				}
				p = p->next;
			}

			if(curr->conf.followed != FOLLOWED_BY_NONE &&
					(!number_in_the_middle || !is_at_count(keys)))
			{
				break;
			}

			if(number_in_the_middle)
			{
				int count;
				const wchar_t *new_keys = get_count(keys, &count);
				if(new_keys != keys)
				{
					key_info.count = combine_counts(key_info.count, count);
					keys = new_keys;
					continue;
				}
			}

			if(curr->conf.type == BUILTIN_WAIT_POINT)
			{
				return KEYS_UNKNOWN;
			}

			has_duplicate = root == &user_cmds_root[vle_mode_get()] &&
					contains_chain(&builtin_cmds_root[vle_mode_get()], keys_start, keys);
			result = execute_next_keys(curr, curr->conf.type == USER_CMD ? keys : L"",
					&key_info, keys_info, has_duplicate, no_remap);
			if(curr->conf.type == USER_CMD)
				return result;
			if(IS_KEYS_RET_CODE(result))
			{
				if(result == KEYS_WAIT_SHORT)
					return KEYS_UNKNOWN;

				return result;
			}
			inc_counter(keys_info, keys - keys_start);
			return execute_keys_general(keys, 0, keys_info->mapped, no_remap);
		}
		keys++;
		curr = p;
	}

	if(*keys == '\0' && curr->conf.type != BUILTIN_WAIT_POINT &&
			curr->children_count > 0 && curr->conf.data.handler != NULL &&
			!keys_info->after_wait)
	{
		return KEYS_WAIT_SHORT;
	}

	has_duplicate = root == &user_cmds_root[vle_mode_get()] &&
			contains_chain(&builtin_cmds_root[vle_mode_get()], keys_start, keys);
	result = execute_next_keys(curr, keys, &key_info, keys_info, has_duplicate,
			no_remap);
	if(!IS_KEYS_RET_CODE(result))
	{
		inc_counter(keys_info, keys - keys_start);
	}
	else if(*keys == '\0' && result == KEYS_UNKNOWN && curr->children_count > 0)
	{
		return keys_info->after_wait ? KEYS_UNKNOWN : KEYS_WAIT_SHORT;
	}
	return result;
}
Exemple #15
0
/* Dispatches keys passed in as a selector followed by arbitrary other keys.
 * Returns error code. */
static int
dispatch_selector(const wchar_t keys[], keys_info_t *keys_info,
		key_info_t master_key_info, key_chunk_t *master_curr, int no_remap)
{
	const wchar_t *keys_start = keys;
	key_chunk_t *curr = &selectors_root[vle_mode_get()];
	key_info_t key_info;
	int result;

	if(fill_key_info(&keys, &key_info, master_key_info.count, &result) != 0)
	{
		return result;
	}

	/* The loop finds longest match of the input (keys) among registered
	 * shortcuts. */
	while(*keys != L'\0')
	{
		key_chunk_t *p;

		for(p = curr->child; p != NULL && p->key < *keys; p = p->next)
		{
			/* Advance. */
		}
		if(p == NULL || p->key != *keys)
		{
			break;
		}
		++keys;
		curr = p;
	}

	/* Handle ambiguous selector. */
	if(*keys == '\0' && curr->type != BUILTIN_WAIT_POINT &&
			curr->children_count > 0 && curr->conf.data.handler != NULL &&
			!keys_info->after_wait)
	{
		return KEYS_WAIT_SHORT;
	}

	/* Execute the selector. */
	if(curr->conf.followed == FOLLOWED_BY_MULTIKEY && keys[0] != L'\0')
	{
		const wchar_t mk[] = { keys[0], L'\0' };
		result = execute_next_keys(curr, mk, &key_info, keys_info, 0, no_remap);
		++keys;
	}
	else
	{
		result = keys[0] == L'\0'
		       ? execute_next_keys(curr, L"", &key_info, keys_info, 0, no_remap)
		       : dispatch_key(key_info, keys_info, curr, L"");
	}
	if(IS_KEYS_RET_CODE(result))
	{
		return result;
	}

	/* We used this count in selector, so don't pass it to command. */
	master_key_info.count = NO_COUNT_GIVEN;

	/* Execute command that requested the selector. */
	result = execute_mapping_handler(&master_curr->conf, master_key_info,
			keys_info);
	if(IS_KEYS_RET_CODE(result))
	{
		return result;
	}

	inc_counter(keys_info, keys - keys_start);

	/* execute_keys_general() treats empty input as an error. */
	if(keys[0] == L'\0')
	{
		return 0;
	}
	/* Process the rest of the line. */
	return execute_keys_general(keys, keys_info->after_wait, 0, no_remap);
}
Exemple #16
0
/* Looks up possible continuations of keys for the given root and calls cb on
 * them. */
static void
keys_suggest(const key_chunk_t *root, const wchar_t keys[],
		const wchar_t prefix[], vle_keys_list_cb cb, int custom_only,
		int fold_subkeys)
{
	const key_chunk_t *curr = root;

	while(*keys != L'\0')
	{
		const key_chunk_t *p;
		int number_in_the_middle = 0;

		/* Look up current key among children of current node (might be root), while
		 * inspecting NIM as well. */
		for(p = curr->child; p != NULL && p->key < *keys; p = p->next)
		{
			if(p->type == BUILTIN_NIM_KEYS)
			{
				number_in_the_middle = 1;
			}
		}

		/* Go to the next character if a match found. */
		if(p != NULL && p->key == *keys)
		{
			++keys;
			curr = p;
			continue;
		}

		/* No match for the first character is fatal for the lookup. */
		if(curr == root)
		{
			return;
		}

		/* Need to inspect all children for NIM. */
		for(; p != NULL && !number_in_the_middle; p = p->next)
		{
			if(p->type == BUILTIN_NIM_KEYS)
			{
				number_in_the_middle = 1;
			}
		}

		/* Give up if this isn't one of cases where next character is not presented
		 * in the tree by design. */
		if(curr->conf.followed != FOLLOWED_BY_NONE &&
				(!number_in_the_middle || !is_at_count(keys)))
		{
			break;
		}

		/* Skip over number in the middle, if any. */
		if(number_in_the_middle)
		{
			int count;
			const wchar_t *new_keys = get_count(keys, &count);
			if(new_keys != keys)
			{
				keys = new_keys;
				continue;
			}
		}

		break;
	}

	if(!custom_only && *keys == L'\0')
	{
		suggest_children(curr, prefix, cb, fold_subkeys);
	}

	if(curr->type == BUILTIN_WAIT_POINT)
	{
		if(curr->conf.followed == FOLLOWED_BY_SELECTOR)
		{
			/* Suggest selectors. */
			keys_suggest(&selectors_root[vle_mode_get()], keys, L"sel: ", cb,
					custom_only, fold_subkeys);
		}
		else if(curr->conf.followed == FOLLOWED_BY_MULTIKEY)
		{
			/* Invoke optional external function to provide suggestions. */
			if(curr->conf.suggest != NULL)
			{
				curr->conf.suggest(cb);
			}
		}
	}
}