/* 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; } }
/* 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; } }
/* 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); }