From b8d67c54f3f124a16e72e6e46e5050e38e2f9f08 Mon Sep 17 00:00:00 2001 From: Keith Winstein Date: Sat, 22 Jan 2011 16:35:02 -0500 Subject: [PATCH] Handles DEC alignment and intermediate chars, sends "unhandled" acts to debug fd --- parseraction.cpp | 12 +++++++++++- parseraction.hpp | 11 ++++++++--- terminal.cpp | 41 +++++++++++++++++++++++++++++++++++------ terminal.hpp | 8 ++++++-- terminalcsi.cpp | 11 +++++++++++ 5 files changed, 71 insertions(+), 12 deletions(-) diff --git a/parseraction.cpp b/parseraction.cpp index 794b47d..f958456 100644 --- a/parseraction.cpp +++ b/parseraction.cpp @@ -15,7 +15,7 @@ void Execute::act_on_terminal( Terminal::Emulator *emu ) void Clear::act_on_terminal( Terminal::Emulator *emu ) { - emu->clear(); + emu->clear( this ); } void Param::act_on_terminal( Terminal::Emulator *emu ) @@ -23,7 +23,17 @@ void Param::act_on_terminal( Terminal::Emulator *emu ) emu->param( this ); } +void Collect::act_on_terminal( Terminal::Emulator *emu ) +{ + emu->collect( this ); +} + void CSI_Dispatch::act_on_terminal( Terminal::Emulator *emu ) { emu->CSI_dispatch( this ); } + +void Esc_Dispatch::act_on_terminal( Terminal::Emulator *emu ) +{ + emu->Esc_dispatch( this ); +} diff --git a/parseraction.hpp b/parseraction.hpp index 631bac1..2c00ea6 100644 --- a/parseraction.hpp +++ b/parseraction.hpp @@ -13,12 +13,13 @@ namespace Parser { public: bool char_present; wchar_t ch; + bool handled; virtual std::string name( void ) = 0; virtual void act_on_terminal( Terminal::Emulator * ) {}; - Action() : char_present( false ), ch( -1 ) {}; + Action() : char_present( false ), ch( -1 ), handled( false ) {}; virtual ~Action() {}; }; @@ -41,7 +42,9 @@ namespace Parser { void act_on_terminal( Terminal::Emulator *emu ); }; class Collect : public Action { - public: std::string name( void ) { return std::string( "Collect" ); } + public: + std::string name( void ) { return std::string( "Collect" ); } + void act_on_terminal( Terminal::Emulator *emu ); }; class Param : public Action { public: @@ -49,7 +52,9 @@ namespace Parser { void act_on_terminal( Terminal::Emulator *emu ); }; class Esc_Dispatch : public Action { - public: std::string name( void ) { return std::string( "Esc_Dispatch" ); } + public: + std::string name( void ) { return std::string( "Esc_Dispatch" ); } + void act_on_terminal( Terminal::Emulator *emu ); }; class CSI_Dispatch : public Action { public: diff --git a/terminal.cpp b/terminal.cpp index 55c2537..2e62c9a 100644 --- a/terminal.cpp +++ b/terminal.cpp @@ -63,7 +63,9 @@ std::string Emulator::input( char c, int actfd ) i++ ) { Parser::Action *act = *i; - if ( (actfd > 0) && (typeid(*act) != typeid(Parser::Print)) ) { + act->act_on_terminal( this ); + + if ( (actfd > 0) && ( !act->handled ) ) { char actsum[ 32 ]; if ( act->char_present ) { if ( isprint( act->ch ) ) { @@ -81,8 +83,6 @@ std::string Emulator::input( char c, int actfd ) swrite( actfd, actsum ); } - act->act_on_terminal( this ); - delete act; } @@ -124,16 +124,19 @@ void Emulator::execute( Parser::Execute *act ) case 0x0a: /* LF */ cursor_row++; autoscroll(); + act->handled = true; break; case 0x0d: /* CR */ cursor_col = 0; + act->handled = true; break; case 0x08: /* BS */ if ( cursor_col > 0 ) { cursor_col--; newgrapheme(); /* this is not xterm's behavior */ + act->handled = true; } break; } @@ -177,11 +180,14 @@ void Emulator::print( Parser::Print *act ) } cursor_col += chwidth; + act->handled = true; break; case 0: /* combining character */ if ( rows[ combining_char_row ].cells[ combining_char_col ].contents.size() < 16 ) { /* seems like a reasonable limit on combining character */ rows[ combining_char_row ].cells[ combining_char_col ].contents.push_back( act->ch ); } + act->handled = true; + break; case -1: /* unprintable character */ break; default: @@ -240,6 +246,7 @@ void Emulator::param( Parser::Param *act ) if ( params.length() < 100 ) { /* enough for 16 five-char params plus 15 semicolons */ params.push_back( act->ch ); + act->handled = true; } } @@ -247,15 +254,17 @@ void Emulator::collect( Parser::Collect *act ) { assert( act->char_present ); if ( ( dispatch_chars.length() < 8 ) /* never should need more than 2 */ - && ( act->ch <= 255 ) ) { /* ignore non-8-bit */ + && ( act->ch <= 255 ) ) { /* ignore non-8-bit */ dispatch_chars.push_back( act->ch ); + act->handled = true; } } -void Emulator::clear( void ) +void Emulator::clear( Parser::Clear *act ) { params.clear(); dispatch_chars.clear(); + act->handled = true; } void Emulator::CSI_dispatch( Parser::CSI_Dispatch *act ) @@ -269,16 +278,36 @@ void Emulator::CSI_dispatch( Parser::CSI_Dispatch *act ) if ( dispatch_chars == "K" ) { CSI_EL(); + act->handled = true; } else if ( dispatch_chars == "J" ) { CSI_ED(); + act->handled = true; } else if ( (dispatch_chars == "A") || (dispatch_chars == "B") || (dispatch_chars == "C") || (dispatch_chars == "D") - || (dispatch_chars == "H") ) { + || (dispatch_chars == "H") + || (dispatch_chars == "f") ) { CSI_cursormove(); + act->handled = true; } else if ( dispatch_chars == "c" ) { CSI_DA(); + act->handled = true; + } +} + +void Emulator::Esc_dispatch( Parser::Esc_Dispatch *act ) +{ + /* add final char to dispatch key */ + assert( act->char_present ); + Parser::Collect act2; + act2.char_present = true; + act2.ch = act->ch; + collect( &act2 ); + + if ( dispatch_chars == "#8" ) { + Esc_DECALN(); + act->handled = true; } } diff --git a/terminal.hpp b/terminal.hpp index 52b6d95..7860409 100644 --- a/terminal.hpp +++ b/terminal.hpp @@ -35,7 +35,9 @@ namespace Terminal { friend void Parser::Execute::act_on_terminal( Emulator * ); friend void Parser::Clear::act_on_terminal( Emulator * ); friend void Parser::Param::act_on_terminal( Emulator * ); + friend void Parser::Collect::act_on_terminal( Emulator * ); friend void Parser::CSI_Dispatch::act_on_terminal( Emulator * ); + friend void Parser::Esc_Dispatch::act_on_terminal( Emulator * ); private: Parser::UTF8Parser parser; @@ -56,8 +58,9 @@ namespace Terminal { void execute( Parser::Execute *act ); void param( Parser::Param *act ); void collect( Parser::Collect *act ); - void clear( void ); + void clear( Parser::Clear *act ); void CSI_dispatch( Parser::CSI_Dispatch *act ); + void Esc_dispatch( Parser::Esc_Dispatch *act ); void scroll( int N ); void autoscroll( void ); @@ -67,11 +70,12 @@ namespace Terminal { std::vector parsed_params; int getparam( size_t N, int defaultval ); - /* CSI methods */ + /* CSI and Escape methods */ void CSI_EL( void ); void CSI_ED( void ); void CSI_cursormove( void ); void CSI_DA( void ); + void Esc_DECALN( void ); public: Emulator( size_t s_width, size_t s_height ); diff --git a/terminalcsi.cpp b/terminalcsi.cpp index a9c0fce..cba3d54 100644 --- a/terminalcsi.cpp +++ b/terminalcsi.cpp @@ -70,6 +70,7 @@ void Emulator::CSI_cursormove( void ) cursor_col -= num; break; case 'H': + case 'f': int x = getparam( 0, 1 ); int y = getparam( 1, 1 ); cursor_row = x - 1; @@ -88,3 +89,13 @@ void Emulator::CSI_DA( void ) { terminal_to_host.append( "\033[?1;0c" ); } + +void Emulator::Esc_DECALN( void ) +{ + for ( int y = 0; y < height; y++ ) { + for ( int x = 0; x < width; x++ ) { + rows[ y ].cells[ x ].reset(); + rows[ y ].cells[ x ].contents.push_back( L'E' ); + } + } +}