diff --git a/parseraction.cpp b/parseraction.cpp index a234e98..d329247 100644 --- a/parseraction.cpp +++ b/parseraction.cpp @@ -68,5 +68,6 @@ void OSC_End::act_on_terminal( Terminal::Emulator *emu ) void UserByte::act_on_terminal( Terminal::Emulator *emu ) { - emu->dispatch.terminal_to_host.append( emu->user.input( this ) ); + emu->dispatch.terminal_to_host.append( emu->user.input( this, + emu->fb.ds.application_mode_cursor_keys ) ); } diff --git a/termemu.cpp b/termemu.cpp index 8b9e1ad..43f3e94 100644 --- a/termemu.cpp +++ b/termemu.cpp @@ -127,28 +127,32 @@ void emulate_terminal( int fd, int debug_fd ) pollfds[ 1 ].fd = fd; pollfds[ 1 ].events = POLLIN; + swrite( STDOUT_FILENO, terminal.open().c_str() ); + while ( 1 ) { int active_fds = poll( pollfds, 2, -1 ); if ( active_fds <= 0 ) { perror( "poll" ); - return; + break; } if ( pollfds[ 0 ].revents & POLLIN ) { if ( termemu( fd, STDIN_FILENO, true, debug_fd, &parser, &terminal ) < 0 ) { - return; + break; } } else if ( pollfds[ 1 ].revents & POLLIN ) { if ( termemu( fd, fd, false, debug_fd, &parser, &terminal ) < 0 ) { - return; + break; } } else if ( (pollfds[ 0 ].revents | pollfds[ 1 ].revents) & (POLLERR | POLLHUP | POLLNVAL) ) { - return; + break; } else { fprintf( stderr, "poll mysteriously woken up\n" ); } } + + swrite( STDOUT_FILENO, terminal.close().c_str() ); } int termemu( int host_fd, int src_fd, bool user, int debug_fd, diff --git a/terminal.cpp b/terminal.cpp index 55218c5..711b4b3 100644 --- a/terminal.cpp +++ b/terminal.cpp @@ -183,3 +183,15 @@ void Emulator::debug_printout( int fd ) swrite( fd, screen.c_str() ); } + +std::string Emulator::open( void ) +{ + char appmode[ 6 ] = { 0x1b, '[', '?', '1', 'h', 0 }; + return std::string( appmode ); +} + +std::string Emulator::close( void ) +{ + char ansimode[ 6 ] = { 0x1b, '[', '?', '1', 'l', 0 }; + return std::string( ansimode ); +} diff --git a/terminal.hpp b/terminal.hpp index 5877d85..fa838df 100644 --- a/terminal.hpp +++ b/terminal.hpp @@ -43,6 +43,9 @@ namespace Terminal { std::string read_octets_to_host( void ); void debug_printout( int fd ); + + std::string open( void ); /* put user cursor keys in application mode */ + std::string close( void ); /* restore user cursor keys */ }; } diff --git a/terminalframebuffer.cpp b/terminalframebuffer.cpp index 4ea7a88..17f1a07 100644 --- a/terminalframebuffer.cpp +++ b/terminalframebuffer.cpp @@ -47,7 +47,7 @@ DrawState::DrawState( int s_width, int s_height ) scrolling_region_top_row( 0 ), scrolling_region_bottom_row( height - 1 ), renditions(), save(), next_print_will_wrap( false ), origin_mode( false ), auto_wrap_mode( true ), - insert_mode( false ), cursor_visible( true ) + insert_mode( false ), cursor_visible( true ), application_mode_cursor_keys( false ) { for ( int i = 0; i < width; i++ ) { tabs[ i ] = ( (i % 8) == 0 ); @@ -346,6 +346,8 @@ void Framebuffer::soft_reset( void ) { ds.insert_mode = false; ds.origin_mode = false; + ds.cursor_visible = true; /* per xterm and gnome-terminal */ + ds.application_mode_cursor_keys = false; ds.set_scrolling_region( 0, ds.get_height() - 1 ); ds.clear_renditions(); ds.clear_saved_cursor(); diff --git a/terminalframebuffer.hpp b/terminalframebuffer.hpp index e141309..99509a1 100644 --- a/terminalframebuffer.hpp +++ b/terminalframebuffer.hpp @@ -70,6 +70,8 @@ namespace Terminal { bool insert_mode; bool cursor_visible; + bool application_mode_cursor_keys; + /* bold, etc. */ void move_row( int N, bool relative = false ); diff --git a/terminalfunctions.cpp b/terminalfunctions.cpp index 2c59b25..186c587 100644 --- a/terminalfunctions.cpp +++ b/terminalfunctions.cpp @@ -208,6 +208,8 @@ static Function func_CSI_TBC( CSI, "g", CSI_TBC ); static bool *get_DEC_mode( int param, Framebuffer *fb ) { switch ( param ) { + case 1: /* cursor key mode */ + return &(fb->ds.application_mode_cursor_keys); case 3: /* 80/132 */ /* clear screen */ fb->ds.move_row( 0 ); diff --git a/terminaluserinput.cpp b/terminaluserinput.cpp index a858f93..e59d100 100644 --- a/terminaluserinput.cpp +++ b/terminaluserinput.cpp @@ -2,7 +2,8 @@ using namespace Terminal; -std::string UserInput::input( Parser::UserByte *act ) +std::string UserInput::input( Parser::UserByte *act, + bool application_mode_cursor_keys ) { char translated_str[ 2 ] = { act->c, 0 }; @@ -12,7 +13,7 @@ std::string UserInput::input( Parser::UserByte *act ) /* We don't need lookahead to do this for 7-bit. */ - if ( (!application_mode_cursor) + if ( (!application_mode_cursor_keys) && (last_byte == 0x1b) /* ESC */ && (act->c == 'O') ) { /* ESC O = 7-bit SS3 = application mode */ translated_str[ 0 ] = '['; @@ -21,6 +22,8 @@ std::string UserInput::input( Parser::UserByte *act ) /* 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 ); diff --git a/terminaluserinput.hpp b/terminaluserinput.hpp index 37cec66..6672408 100644 --- a/terminaluserinput.hpp +++ b/terminaluserinput.hpp @@ -7,17 +7,15 @@ namespace Terminal { class UserInput { private: - bool last_byte; - bool application_mode_cursor; + short last_byte; public: UserInput() - : last_byte( 0 ), - application_mode_cursor( false ) + : last_byte( -1 ) {} - std::string input( Parser::UserByte *act ); - void set_cursor_application_mode( bool mode ) { application_mode_cursor = mode; } + std::string input( Parser::UserByte *act, + bool application_mode_cursor_keys ); }; }