From 2471c4a68eea8813473a5f44303e11cb7b1fb203 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Mon, 11 Aug 2014 14:23:19 +0400 Subject: [PATCH] Add a new API for converting between interface_key and string characters. It's necessary now that the simple linear arrangement is broken. --- Lua API.rst | 11 +++++++++++ library/LuaApi.cpp | 24 ++++++++++++++++++++++++ library/include/modules/Screen.h | 5 +++++ library/modules/Screen.cpp | 29 ++++++++++++++++++++++++++--- plugins/command-prompt.cpp | 6 +++--- plugins/search.cpp | 16 ++++++++-------- plugins/uicommon.h | 8 +++----- plugins/zone.cpp | 7 +++---- 8 files changed, 83 insertions(+), 23 deletions(-) diff --git a/Lua API.rst b/Lua API.rst index 663f2779c..800b3f011 100644 --- a/Lua API.rst +++ b/Lua API.rst @@ -1591,6 +1591,17 @@ Basic painting functions: Returns the string that should be used to represent the given logical keybinding on the screen in texts like "press Key to ...". +* ``dfhack.screen.keyToChar(key)`` + + Returns the integer character code of the string input + character represented by the given logical keybinding, + or *nil* if not a string input key. + +* ``dfhack.screen.charToKey(charcode)`` + + Returns the keybinding representing the given string input + character, or *nil* if impossible. + The "pen" argument used by functions above may be represented by a table with the following possible fields: diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index 711e0e38a..53f4b08e6 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -1924,6 +1924,28 @@ static int screen_doSimulateInput(lua_State *L) return 0; } +static int screen_keyToChar(lua_State *L) +{ + auto keycode = (df::interface_key)luaL_checkint(L, 1); + int charcode = Screen::keyToChar(keycode); + if (charcode >= 0) + lua_pushinteger(L, charcode); + else + lua_pushnil(L); + return 1; +} + +static int screen_charToKey(lua_State *L) +{ + auto charcode = (char)luaL_checkint(L, 1); + df::interface_key keycode = Screen::charToKey(charcode); + if (keycode) + lua_pushinteger(L, keycode); + else + lua_pushnil(L); + return 1; +} + } static const luaL_Reg dfhack_screen_funcs[] = { @@ -1938,6 +1960,8 @@ static const luaL_Reg dfhack_screen_funcs[] = { { "dismiss", screen_dismiss }, { "isDismissed", screen_isDismissed }, { "_doSimulateInput", screen_doSimulateInput }, + { "keyToChar", screen_keyToChar }, + { "charToKey", screen_charToKey }, { NULL, NULL } }; diff --git a/library/include/modules/Screen.h b/library/include/modules/Screen.h index bfc393734..205a0ed3f 100644 --- a/library/include/modules/Screen.h +++ b/library/include/modules/Screen.h @@ -195,6 +195,11 @@ namespace DFHack /// Retrieve the string representation of the bound key. DFHACK_EXPORT std::string getKeyDisplay(df::interface_key key); + /// Return the character represented by this key, or -1 + DFHACK_EXPORT int keyToChar(df::interface_key key); + /// Return the key code matching this character, or NONE + DFHACK_EXPORT df::interface_key charToKey(char code); + /// A painter class that implements a clipping area and cursor/pen state struct DFHACK_EXPORT Painter : ViewRect { df::coord2d gcursor; diff --git a/library/modules/Screen.cpp b/library/modules/Screen.cpp index 782bb317d..c0e857922 100644 --- a/library/modules/Screen.cpp +++ b/library/modules/Screen.cpp @@ -413,6 +413,29 @@ string Screen::getKeyDisplay(df::interface_key key) return "?"; } +int Screen::keyToChar(df::interface_key key) +{ + if (key < interface_key::STRING_A000 || + key > interface_key::STRING_A255) + return -1; + + if (key < interface_key::STRING_A128) + return key - interface_key::STRING_A000; + + return key - interface_key::STRING_A128 + 128; +} + +df::interface_key Screen::charToKey(char code) +{ + int val = (unsigned char)code; + if (val < 127) + return df::interface_key(interface_key::STRING_A000 + val); + else if (val == 127) + return interface_key::NONE; + else + return df::interface_key(interface_key::STRING_A128 + (val-128)); +} + /* * Base DFHack viewscreen. */ @@ -654,10 +677,10 @@ int dfhack_lua_viewscreen::do_input(lua_State *L) lua_pushboolean(L, true); lua_rawset(L, -3); - if (key >= interface_key::STRING_A000 && - key <= interface_key::STRING_A255) + int charval = Screen::keyToChar(key); + if (charval >= 0) { - lua_pushinteger(L, key - interface_key::STRING_A000); + lua_pushinteger(L, charval); lua_setfield(L, -2, "_STRING"); } } diff --git a/plugins/command-prompt.cpp b/plugins/command-prompt.cpp index f9a3f80bf..30be625b7 100644 --- a/plugins/command-prompt.cpp +++ b/plugins/command-prompt.cpp @@ -238,10 +238,10 @@ void viewscreen_commandpromptst::feed(std::set *events) cursor_pos = entry.size(); continue; } - if (key >= interface_key::STRING_A000 && - key <= interface_key::STRING_A255) + int charcode = Screen::keyToChar(key); + if (charcode > 0) { - entry.insert(cursor_pos, 1, char(key - interface_key::STRING_A000)); + entry.insert(cursor_pos, 1, char(charcode)); cursor_pos++; set_entry(entry); return; diff --git a/plugins/search.cpp b/plugins/search.cpp index 7bb5cbd62..848c65eaf 100644 --- a/plugins/search.cpp +++ b/plugins/search.cpp @@ -130,7 +130,8 @@ public: this->cursor_pos = get_viewscreen_cursor(); this->primary_list = get_primary_list(); this->select_key = get_search_select_key(); - select_token = (df::interface_key) (ascii_to_enum_offset + select_key); + select_token = Screen::charToKey(select_key); + shift_select_token = Screen::charToKey(select_key + 'A' - 'a'); valid = true; do_post_init(); } @@ -185,10 +186,11 @@ public: return false; } df::interface_key last_token = *input->rbegin(); - if (last_token >= interface_key::STRING_A032 && last_token <= interface_key::STRING_A126) + int charcode = Screen::keyToChar(last_token); + if (charcode >= 32 && charcode <= 126) { // Standard character - search_string += last_token - ascii_to_enum_offset; + search_string += char(charcode); do_search(); } else if (last_token == interface_key::STRING_A000) @@ -219,7 +221,7 @@ public: // Hotkey pressed, enter typing mode start_entry_mode(); } - else if (input->count((df::interface_key) (select_token + shift_offset))) + else if (input->count(shift_select_token)) { // Shift + Hotkey pressed, clear query clear_search(); @@ -246,7 +248,7 @@ protected: virtual int32_t *get_viewscreen_cursor() = 0; virtual vector *get_primary_list() = 0; - search_generic() : ascii_to_enum_offset(interface_key::STRING_A048 - '0'), shift_offset('A' - 'a') + search_generic() { reset_all(); } @@ -412,9 +414,7 @@ private: bool entry_mode; df::interface_key select_token; - const int ascii_to_enum_offset; - const int shift_offset; - + df::interface_key shift_select_token; }; template search_generic *search_generic ::lock = NULL; diff --git a/plugins/uicommon.h b/plugins/uicommon.h index 0ea0da861..6854c7b19 100644 --- a/plugins/uicommon.h +++ b/plugins/uicommon.h @@ -143,8 +143,6 @@ void OutputToggleString(int &x, int &y, const char *text, const char *hotkey, bo OutputString(COLOR_GREY, x, y, "Off", newline, left_margin); } -const int ascii_to_enum_offset = interface_key::STRING_A048 - '0'; - inline string int_to_string(const int n) { return static_cast( &(ostringstream() << n) )->str(); @@ -792,11 +790,11 @@ public: { // Search query typing mode always on df::interface_key last_token = *input->rbegin(); - if ((last_token >= interface_key::STRING_A096 && last_token <= interface_key::STRING_A123) || - last_token == interface_key::STRING_A032) + int charcode = Screen::keyToChar(last_token); + if ((charcode >= 96 && charcode <= 123) || charcode == 32) { // Standard character - search_string += last_token - ascii_to_enum_offset; + search_string += char(charcode); filterDisplay(); centerSelection(); } diff --git a/plugins/zone.cpp b/plugins/zone.cpp index 5690ec29d..e631021d0 100644 --- a/plugins/zone.cpp +++ b/plugins/zone.cpp @@ -4087,8 +4087,6 @@ using df::global::ui_building_assign_items; using df::global::ui_building_in_assign; -static const int ascii_to_enum_offset = interface_key::STRING_A048 - '0'; - void OutputString(int8_t color, int &x, int y, const std::string &text) { Screen::paintString(Screen::Pen(' ', color, 0), x, y, text); @@ -4241,10 +4239,11 @@ public: } df::interface_key last_token = *input->rbegin(); - if (last_token >= interface_key::STRING_A032 && last_token <= interface_key::STRING_A126) + int charcode = Screen::keyToChar(last_token); + if (charcode >= 32 && charcode <= 126) { // Standard character - search_string += last_token - ascii_to_enum_offset; + search_string += char(charcode); apply_filters(); } else if (last_token == interface_key::STRING_A000)