Пример #1
0
/* Performs action associated with the key (in curr), if any.  Returns error
 * code. */
static int
dispatch_key(key_info_t key_info, keys_info_t *keys_info, key_chunk_t *curr,
		const wchar_t keys[])
{
	const key_conf_t *const conf = &curr->conf;

	if(curr->type != USER_CMD)
	{
		const int result = execute_mapping_handler(conf, key_info, keys_info);
		const int finish_dispatching = result != 0
		                            || *keys == L'\0'
		                            || conf->followed != FOLLOWED_BY_MULTIKEY;
		if(finish_dispatching)
		{
			return result;
		}

		/* Process the rest of the input after a command followed by multikey. */
		return execute_keys_general_wrapper(keys, keys_info->after_wait, 0,
				curr->no_remap);
	}
	else
	{
		if(curr->silent)
		{
			silence_ui(1);
		}

		int result = has_def_handler() ? 0 : KEYS_UNKNOWN;

		/* Protect chunk from deletion while it's in use. */
		enter_chunk(curr);

		if(curr->enters == 1)
		{
			result = execute_after_remapping(conf->data.cmd, keys, *keys_info,
					key_info, curr);
		}
		else if(has_def_handler())
		{
			result = def_handler()(curr->key);

			if(result == 0)
			{
				result = execute_keys_general(keys, keys_info->after_wait, 0,
						curr->no_remap);
			}
		}

		if(result == KEYS_UNKNOWN && has_def_handler())
		{
			if(curr->enters == 1)
			{
				result = def_handler()(conf->data.cmd[0]);
				enter_chunk(curr);
				execute_keys_general(conf->data.cmd + 1, 0, 1, curr->no_remap);
				leave_chunk(curr);
			}
			else
			{
				int i;
				for(i = 0; conf->data.cmd[i] != '\0'; i++)
				{
					result = def_handler()(conf->data.cmd[i]);
				}
			}
		}

		if(curr->silent)
		{
			silence_ui(0);
		}

		/* Release the chunk, this will free it if deletion was attempted. */
		leave_chunk(curr);

		return result;
	}
}
Пример #2
0
Файл: keys.c Проект: jubalh/vifm
/* Performs action associated with the key (in curr), if any.  Returns error
 * code. */
static int
dispatch_key(key_info_t key_info, keys_info_t *keys_info, key_chunk_t *curr,
		const wchar_t keys[])
{
	const key_conf_t *const conf = &curr->conf;

	if(conf->type != USER_CMD && conf->type != BUILTIN_CMD)
	{
		const int result = execute_mapping_handler(conf, key_info, keys_info);
		const int finish_dispatching = result != 0
		                            || *keys == L'\0'
		                            || conf->followed != FOLLOWED_BY_MULTIKEY;
		if(finish_dispatching)
		{
			return result;
		}

		/* Process the rest of the input after a command followed by multikey. */
		return execute_keys_general_wrapper(keys, keys_info->after_wait, 0,
				curr->no_remap);
	}
	else
	{
		int result = has_def_handler() ? 0 : KEYS_UNKNOWN;

		if(curr->enters == 0)
		{
			result = execute_after_remapping(conf->data.cmd, keys, *keys_info,
					key_info, curr);
		}
		else if(has_def_handler())
		{
			result = def_handler()(curr->key);

			if(result == 0)
			{
				result = execute_keys_general(keys, keys_info->after_wait, 0,
						curr->no_remap);
			}
		}

		if(result == KEYS_UNKNOWN && has_def_handler())
		{
			/* curr shouldn't be freed here as if it was result would be 0. */
			if(curr->enters == 0)
			{
				result = def_handler()(conf->data.cmd[0]);
				enter_chunk(curr);
				execute_keys_general(conf->data.cmd + 1, 0, 1, curr->no_remap);
				leave_chunk(curr);
			}
			else
			{
				int i;
				for(i = 0; conf->data.cmd[i] != '\0'; i++)
				{
					result = def_handler()(conf->data.cmd[i]);
				}
			}
		}

		return result;
	}
}
Пример #3
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);
}