diff --git a/src/input.cpp b/src/input.cpp index 7c2eb123c22306ff7f1d4ae9691c4a257444111e..1bb9ce84010e2307a518cd349b06d869c2e2b948 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -510,10 +510,18 @@ void input_manager::init_keycode_mapping() add_keyboard_char_keycode_pair( KEY_END, translate_marker_context( "key name", "END" ) ); add_keyboard_char_keycode_pair( '\n', translate_marker_context( "key name", "RETURN" ) ); + for( int c = 0; IS_CTRL_CHAR( c ); c++ ) { + // Some codes fall into this range but have more common names we'd prefer to use. + if( !IS_NAMED_CTRL_CHAR( c ) ) { + // These are directly translated in `get_keyname()` + // NOLINTNEXTLINE(cata-translate-string-literal) + add_keyboard_char_keycode_pair( c, string_format( "CTRL+%c", c + 64 ) ); + } + } + // function keys, as defined by ncurses for( int i = F_KEY_NUM_BEG; i <= F_KEY_NUM_END; i++ ) { - // not marked for translation here, but specially handled in get_keyname so - // it gets properly translated. + // These are directly translated in `get_keyname()` // NOLINTNEXTLINE(cata-translate-string-literal) add_keyboard_char_keycode_pair( KEY_F( i ), string_format( "F%d", i ) ); } @@ -689,6 +697,12 @@ std::string input_manager::get_keyname( int ch, input_event_t inp_type, bool por } else { return string_format( pgettext( "function key name", "F%d" ), F_KEY_NUM( ch ) ); } + } else if( IS_CTRL_CHAR( ch ) && !IS_NAMED_CTRL_CHAR( ch ) ) { + if( portable ) { + return it->second; + } else { + return string_format( pgettext( "control key name", "CTRL+%c" ), ch + 64 ); + } } else if( ch >= char_key_beg && ch <= char_key_end && ch != ' ' ) { // character keys except space need no translation return it->second; @@ -928,7 +942,8 @@ void input_context::register_action( const std::string &action_descriptor ) register_action( action_descriptor, translation() ); } -void input_context::register_action( const std::string &action_descriptor, const translation &name ) +void input_context::register_action( const std::string &action_descriptor, + const translation &name ) { if( action_descriptor == "ANY_INPUT" ) { registered_any_input = true; @@ -1694,7 +1709,8 @@ std::string input_context::press_x( const std::string &action_id, const std::str } // TODO: merge this with input_context::get_desc -std::string input_context::press_x( const std::string &action_id, const std::string &key_bound_pre, +std::string input_context::press_x( const std::string &action_id, + const std::string &key_bound_pre, const std::string &key_bound_suf, const std::string &key_unbound ) const { if( action_id == "ANY_INPUT" ) { diff --git a/src/input.h b/src/input.h index a0a9413985cbc79de61a760263686737efb3ea85..9c0a0de64972c2b365cd16215c9fa4ea97ef5dcc 100644 --- a/src/input.h +++ b/src/input.h @@ -60,6 +60,17 @@ inline constexpr bool IS_F_KEY( const int key ) { return key >= KEY_F( F_KEY_NUM_BEG ) && key <= KEY_F( F_KEY_NUM_END ); } +/** @return true if the given character is in the range of basic ASCII control characters */ +inline constexpr bool IS_CTRL_CHAR( const int key ) +{ + // https://en.wikipedia.org/wiki/C0_and_C1_control_codes#Basic_ASCII_control_codes + return key >= 0 && key < ' '; +} +/** @return true if the given character is an ASCII control char but should not be rendered with "CTRL+" */ +inline constexpr bool IS_NAMED_CTRL_CHAR( const int key ) +{ + return key == '\t' || key == '\n' || key == KEY_ESCAPE || key == KEY_BACKSPACE; +} inline constexpr int KEY_NUM( const int n ) { return 0x30 + n; /* Numbers 0, 1, ..., 9 */