From c15d3d0c4802384e2c8662e5798b3c02edb3915f Mon Sep 17 00:00:00 2001 From: Keith Winstein Date: Mon, 16 Apr 2012 03:44:07 -0400 Subject: [PATCH] Use "ANSI-mode" cursor keys only on actual cursor keys (A through D). Fixes #161. --- src/terminal/terminaluserinput.cc | 52 +++++++++++++++++++++++-------- src/terminal/terminaluserinput.h | 13 ++++++-- 2 files changed, 49 insertions(+), 16 deletions(-) diff --git a/src/terminal/terminaluserinput.cc b/src/terminal/terminaluserinput.cc index 1caa20f..597c552 100644 --- a/src/terminal/terminaluserinput.cc +++ b/src/terminal/terminaluserinput.cc @@ -16,33 +16,59 @@ along with this program. If not, see . */ +#include #include "terminaluserinput.h" using namespace Terminal; +using namespace std; -std::string UserInput::input( const Parser::UserByte *act, - bool application_mode_cursor_keys ) +string UserInput::input( const Parser::UserByte *act, + bool application_mode_cursor_keys ) { - char translated_str[ 2 ] = { act->c, 0 }; + act->handled = true; /* The user will always be in application mode. If stm is not in application mode, convert user's cursor control function to an ANSI cursor control sequence */ - /* We don't need lookahead to do this for 7-bit. */ + /* We need to look ahead one byte in the SS3 state to see if + the next byte will be A, B, C, or D (cursor control keys). */ - if ( (!application_mode_cursor_keys) - && (last_byte == 0x1b) /* ESC */ - && (act->c == 'O') ) { /* ESC O = 7-bit SS3 = application mode */ - translated_str[ 0 ] = '['; + switch ( state ) { + case Ground: + if ( act->c == 0x1b ) { /* ESC */ + state = ESC; + } + return string( &act->c, 1 ); + break; + + case ESC: + if ( act->c == 'O' ) { /* ESC O = 7-bit SS3 */ + state = SS3; + return string(); + } else { + state = Ground; + return string( &act->c, 1 ); + } + break; + + case SS3: + state = Ground; + if ( (!application_mode_cursor_keys) + && (act->c >= 'A') + && (act->c <= 'D') ) { + char translated_cursor[ 2 ] = { '[', act->c }; + return string( translated_cursor, 2 ); + } else { + char original_cursor[ 2 ] = { 'O', act->c }; + return string( original_cursor, 2 ); + } + break; } /* This doesn't handle the 8-bit SS3 C1 control, which would be two octets in UTF-8. Fortunately nobody seems to send this. */ - last_byte = act->c; - - act->handled = true; - - return std::string( translated_str, 1 ); + assert( false ); + return string(); } diff --git a/src/terminal/terminaluserinput.h b/src/terminal/terminaluserinput.h index 5ae1496..465508c 100644 --- a/src/terminal/terminaluserinput.h +++ b/src/terminal/terminaluserinput.h @@ -24,18 +24,25 @@ namespace Terminal { class UserInput { + public: + enum UserInputState { + Ground, + ESC, + SS3 + }; + private: - wchar_t last_byte; + UserInputState state; public: UserInput() - : last_byte( -1 ) + : state( Ground ) {} std::string input( const Parser::UserByte *act, bool application_mode_cursor_keys ); - bool operator==( const UserInput &x ) const { return last_byte == x.last_byte; } + bool operator==( const UserInput &x ) const { return state == x.state; } }; }