diff options
Diffstat (limited to 'crawl-ref/source/macro.cc')
-rw-r--r-- | crawl-ref/source/macro.cc | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/crawl-ref/source/macro.cc b/crawl-ref/source/macro.cc index 712cd8c39d..c983f203d4 100644 --- a/crawl-ref/source/macro.cc +++ b/crawl-ref/source/macro.cc @@ -67,6 +67,11 @@ static macromap *all_maps[] = &Keymaps[KC_LEVELMAP], &Keymaps[KC_TARGETING], &Keymaps[KC_CONFIRM], + +#ifdef USE_TILE + &Keymaps[KC_TILE], +#endif + &Macros, }; @@ -77,6 +82,38 @@ static std::vector<std::string> userfunctions; static std::vector<key_recorder*> recorders; +typedef std::map<std::string, int> name_to_cmd_map; +typedef std::map<int, std::string> cmd_to_name_map; + +struct command_name +{ + command_type cmd; + const char* name; +}; + +static command_name _command_name_list[] = { +#include "cmd-name.h" +}; + +static name_to_cmd_map _names_to_cmds; +static cmd_to_name_map _cmds_to_names; + +struct default_binding +{ + int key; + command_type cmd; +}; + +static default_binding _default_binding_list[] = { +#include "cmd-keys.h" +}; + +typedef std::map<int, int> key_to_cmd_map; +typedef std::map<int, int> cmd_to_key_map; + +static key_to_cmd_map _keys_to_cmds[KC_CONTEXT_COUNT]; +static cmd_to_key_map _cmds_to_keys[KC_CONTEXT_COUNT]; + inline int userfunc_index(int key) { int index = (key <= USERFUNCBASE? USERFUNCBASE - key : -1); @@ -992,3 +1029,161 @@ int get_macro_buf_size() { return (Buffer.size()); } + +/////////////////////////////////////////////////////////////// +// Keybinding stuff + +#define VALID_BIND_COMMAND(cmd) (cmd > CMD_NO_CMD && cmd < CMD_MIN_SYNTHETIC) + +void init_keybindings() +{ + int i; + + for (i = 0; _command_name_list[i].cmd != CMD_NO_CMD + && _command_name_list[i].name != NULL; i++) + { + command_name &data = _command_name_list[i]; + + ASSERT(VALID_BIND_COMMAND(data.cmd)); + ASSERT(_names_to_cmds.find(data.name) == _names_to_cmds.end()); + ASSERT(_cmds_to_names.find(data.cmd) == _cmds_to_names.end()); + + _names_to_cmds[data.name] = data.cmd; + _cmds_to_names[data.cmd] = data.name; + } + + ASSERT(i >= 130); + + for (i = 0; _default_binding_list[i].cmd != CMD_NO_CMD + && _default_binding_list[i].key != '\0'; i++) + { + default_binding &data = _default_binding_list[i]; + ASSERT(VALID_BIND_COMMAND(data.cmd)); + + KeymapContext context = context_for_command(data.cmd); + + ASSERT(context < KC_CONTEXT_COUNT); + + key_to_cmd_map &key_map = _keys_to_cmds[context]; + cmd_to_key_map &cmd_map = _cmds_to_keys[context]; + + // Only one command per key, but it's okay to have several + // keys map to the same command. + ASSERT(key_map.find(data.key) == key_map.end()); + + key_map[data.key] = data.cmd; + cmd_map[data.cmd] = data.key; + } + + ASSERT(i >= 130); +} + +command_type name_to_command(std::string name) +{ + name_to_cmd_map::iterator it = _names_to_cmds.find(name); + + if (it == _names_to_cmds.end()) + return (CMD_NO_CMD); + + return static_cast<command_type>(it->second); +} + +std::string command_to_name(command_type cmd) +{ + cmd_to_name_map::iterator it = _cmds_to_names.find(cmd); + + if (it == _cmds_to_names.end()) + return ("CMD_NO_CMD"); + + return (it->second); +} + +command_type key_to_command(int key, KeymapContext context) +{ + key_to_cmd_map &key_map = _keys_to_cmds[context]; + key_to_cmd_map::iterator it = key_map.find(key); + + if (it == key_map.end()) + return CMD_NO_CMD; + + command_type cmd = static_cast<command_type>(it->second); + + ASSERT(context_for_command(cmd) == context); + + return cmd; +} + +int command_to_key(command_type cmd) +{ + KeymapContext context = context_for_command(cmd); + + if (context == KC_NONE) + return ('\0'); + + cmd_to_key_map &cmd_map = _cmds_to_keys[context]; + cmd_to_key_map::iterator it = cmd_map.find(cmd); + + if (it == cmd_map.end()) + return ('\0'); + + return (it->second); +} + +KeymapContext context_for_command(command_type cmd) +{ +#ifdef USE_TILE + if (cmd >= CMD_MIN_TILE && cmd <= CMD_MAX_TILE) + return KC_TILE; +#endif + + if (cmd > CMD_NO_CMD && cmd <= CMD_MAX_NORMAL) + return KC_DEFAULT; + + if (cmd >= CMD_MIN_OVERMAP && cmd <= CMD_MAX_OVERMAP) + return KC_LEVELMAP; + + if (cmd >= CMD_MIN_TARGET && cmd <= CMD_MAX_TARGET) + return KC_TARGETING; + + return KC_NONE; +} + +void bind_command_to_key(command_type cmd, int key) +{ + KeymapContext context = context_for_command(cmd); + std::string command_name = command_to_name(cmd); + + if (context == KC_NONE || command_name == "CMD_NO_CMD" + || !VALID_BIND_COMMAND(cmd)) + { + if (command_name == "CMD_NO_CMD") + { + mprf(MSGCH_ERROR, "Cannot bind command #%d to a key.", + (int) cmd); + return; + } + + mprf(MSGCH_ERROR, "Cannot bind command '%s' to a key.", + command_name.c_str()); + return; + } + + if (is_userfunction(key)) + { + mpr("Cannot bind user function keys to a command.", MSGCH_ERROR); + return; + } + + if (is_synthetic_key(key)) + { + mpr("Cannot bind synthetic keys to a command.", MSGCH_ERROR); + return; + } + + // We're good. + key_to_cmd_map &key_map = _keys_to_cmds[context]; + cmd_to_key_map &cmd_map = _cmds_to_keys[context]; + + key_map[key] = cmd; + cmd_map[cmd] = key; +} |