diff --git a/Makefile b/Makefile index c29ff78..0e941c4 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ proto = userinput.proto -source = parse.cpp parserstate.cpp parser.cpp templates.cpp terminal.cpp termemu.cpp parseraction.cpp terminalfunctions.cpp swrite.cpp terminalframebuffer.cpp terminaldispatcher.cpp terminaluserinput.cpp terminaldisplay.cpp network.cpp ntester.cpp ocb.cpp base64.cpp encrypt.cpp decrypt.cpp crypto.cpp networktransport.cpp networkinstruction.cpp user.cpp userinput.pb.cc -objects = parserstate.o parser.o templates.o terminal.o parseraction.o terminalfunctions.o swrite.o terminalframebuffer.o terminaldispatcher.o terminaluserinput.o terminaldisplay.o network.o ocb.o base64.o crypto.o networktransport.o networkinstruction.o user.o userinput.pb.o +source = parse.cpp parserstate.cpp parser.cpp templates.cpp terminal.cpp termemu.cpp parseraction.cpp terminalfunctions.cpp swrite.cpp terminalframebuffer.cpp terminaldispatcher.cpp terminaluserinput.cpp terminaldisplay.cpp network.cpp ntester.cpp ocb.cpp base64.cpp encrypt.cpp decrypt.cpp crypto.cpp networktransport.cpp networkinstruction.cpp user.cpp userinput.pb.cc completeterminal.cpp +objects = parserstate.o parser.o templates.o terminal.o parseraction.o terminalfunctions.o swrite.o terminalframebuffer.o terminaldispatcher.o terminaluserinput.o terminaldisplay.o network.o ocb.o base64.o crypto.o networktransport.o networkinstruction.o user.o userinput.pb.o completeterminal.o repos = templates.rpo executables = parse termemu ntester encrypt decrypt diff --git a/parseraction.cpp b/parseraction.cpp index 3a66845..b5425df 100644 --- a/parseraction.cpp +++ b/parseraction.cpp @@ -16,57 +16,57 @@ std::string Action::str( void ) return name() + std::string( thechar ); } -void Print::act_on_terminal( Terminal::Emulator *emu ) +void Print::act_on_terminal( Terminal::Emulator *emu ) const { emu->print( this ); } -void Execute::act_on_terminal( Terminal::Emulator *emu ) +void Execute::act_on_terminal( Terminal::Emulator *emu ) const { emu->execute( this ); } -void Clear::act_on_terminal( Terminal::Emulator *emu ) +void Clear::act_on_terminal( Terminal::Emulator *emu ) const { emu->dispatch.clear( this ); } -void Param::act_on_terminal( Terminal::Emulator *emu ) +void Param::act_on_terminal( Terminal::Emulator *emu ) const { emu->dispatch.newparamchar( this ); } -void Collect::act_on_terminal( Terminal::Emulator *emu ) +void Collect::act_on_terminal( Terminal::Emulator *emu ) const { emu->dispatch.collect( this ); } -void CSI_Dispatch::act_on_terminal( Terminal::Emulator *emu ) +void CSI_Dispatch::act_on_terminal( Terminal::Emulator *emu ) const { emu->CSI_dispatch( this ); } -void Esc_Dispatch::act_on_terminal( Terminal::Emulator *emu ) +void Esc_Dispatch::act_on_terminal( Terminal::Emulator *emu ) const { emu->Esc_dispatch( this ); } -void OSC_Put::act_on_terminal( Terminal::Emulator *emu ) +void OSC_Put::act_on_terminal( Terminal::Emulator *emu ) const { emu->dispatch.OSC_put( this ); } -void OSC_Start::act_on_terminal( Terminal::Emulator *emu ) +void OSC_Start::act_on_terminal( Terminal::Emulator *emu ) const { emu->dispatch.OSC_start( this ); } -void OSC_End::act_on_terminal( Terminal::Emulator *emu ) +void OSC_End::act_on_terminal( Terminal::Emulator *emu ) const { emu->OSC_end( this ); } -void UserByte::act_on_terminal( Terminal::Emulator *emu ) +void UserByte::act_on_terminal( Terminal::Emulator *emu ) const { emu->dispatch.terminal_to_host.append( emu->user.input( this, emu->fb.ds.application_mode_cursor_keys ) ); @@ -77,7 +77,7 @@ void UserByte::act_on_terminal( Terminal::Emulator *emu ) */ } -void Resize::act_on_terminal( Terminal::Emulator *emu ) +void Resize::act_on_terminal( Terminal::Emulator *emu ) const { emu->resize( width, height ); handled = true; diff --git a/parseraction.hpp b/parseraction.hpp index 7709b69..34414c5 100644 --- a/parseraction.hpp +++ b/parseraction.hpp @@ -13,13 +13,13 @@ namespace Parser { public: bool char_present; wchar_t ch; - bool handled; + mutable bool handled; std::string str( void ); virtual std::string name( void ) = 0; - virtual void act_on_terminal( Terminal::Emulator * ) {}; + virtual void act_on_terminal( Terminal::Emulator * ) const {}; Action() : char_present( false ), ch( -1 ), handled( false ) {}; virtual ~Action() {}; @@ -33,37 +33,37 @@ namespace Parser { class Print : public Action { public: std::string name( void ) { return std::string( "Print" ); } - void act_on_terminal( Terminal::Emulator *emu ); + void act_on_terminal( Terminal::Emulator *emu ) const; }; class Execute : public Action { public: std::string name( void ) { return std::string( "Execute" ); } - void act_on_terminal( Terminal::Emulator *emu ); + void act_on_terminal( Terminal::Emulator *emu ) const; }; class Clear : public Action { public: std::string name( void ) { return std::string( "Clear" ); } - void act_on_terminal( Terminal::Emulator *emu ); + void act_on_terminal( Terminal::Emulator *emu ) const; }; class Collect : public Action { public: std::string name( void ) { return std::string( "Collect" ); } - void act_on_terminal( Terminal::Emulator *emu ); + void act_on_terminal( Terminal::Emulator *emu ) const; }; class Param : public Action { public: std::string name( void ) { return std::string( "Param" ); } - void act_on_terminal( Terminal::Emulator *emu ); + void act_on_terminal( Terminal::Emulator *emu ) const; }; class Esc_Dispatch : public Action { public: std::string name( void ) { return std::string( "Esc_Dispatch" ); } - void act_on_terminal( Terminal::Emulator *emu ); + void act_on_terminal( Terminal::Emulator *emu ) const; }; class CSI_Dispatch : public Action { public: std::string name( void ) { return std::string( "CSI_Dispatch" ); } - void act_on_terminal( Terminal::Emulator *emu ); + void act_on_terminal( Terminal::Emulator *emu ) const; }; class Hook : public Action { public: std::string name( void ) { return std::string( "Hook" ); } @@ -77,17 +77,17 @@ namespace Parser { class OSC_Start : public Action { public: std::string name( void ) { return std::string( "OSC_Start" ); } - void act_on_terminal( Terminal::Emulator *emu ); + void act_on_terminal( Terminal::Emulator *emu ) const; }; class OSC_Put : public Action { public: std::string name( void ) { return std::string( "OSC_Put" ); } - void act_on_terminal( Terminal::Emulator *emu ); + void act_on_terminal( Terminal::Emulator *emu ) const; }; class OSC_End : public Action { public: std::string name( void ) { return std::string( "OSC_End" ); } - void act_on_terminal( Terminal::Emulator *emu ); + void act_on_terminal( Terminal::Emulator *emu ) const; }; class UserByte : public Action { @@ -96,7 +96,7 @@ namespace Parser { char c; /* The user-source byte. We don't try to interpret the charset */ std::string name( void ) { return std::string( "UserByte" ); } - void act_on_terminal( Terminal::Emulator *emu ); + void act_on_terminal( Terminal::Emulator *emu ) const; UserByte( int s_c ) : c( s_c ) {} @@ -112,7 +112,7 @@ namespace Parser { size_t width, height; std::string name( void ) { return std::string( "Resize" ); } - void act_on_terminal( Terminal::Emulator *emu ); + void act_on_terminal( Terminal::Emulator *emu ) const; Resize( size_t s_width, size_t s_height ) : width( s_width ), diff --git a/termemu.cpp b/termemu.cpp index d3d9eca..ff8dfbb 100644 --- a/termemu.cpp +++ b/termemu.cpp @@ -22,7 +22,7 @@ #include #include "parser.hpp" -#include "terminal.hpp" +#include "completeterminal.hpp" #include "swrite.hpp" const size_t buf_size = 16384; @@ -122,7 +122,7 @@ int main( void ) } /* Print a frame if the last frame was more than 1/50 seconds ago */ -bool tick( Terminal::Emulator *e, Terminal::Display *d, Terminal::Framebuffer &state ) +bool tick( Terminal::Framebuffer &state, const Terminal::Framebuffer &new_frame ) { static bool initialized = false; static struct timeval last_time; @@ -138,9 +138,9 @@ bool tick( Terminal::Emulator *e, Terminal::Display *d, Terminal::Framebuffer &s if ( (!initialized) || (diff >= 0.02) ) { - std::string update = d->new_frame( initialized, state, e->get_fb() ); + std::string update = Terminal::Display::new_frame( initialized, state, new_frame ); swrite( STDOUT_FILENO, update.c_str() ); - state = e->get_fb(); + state = new_frame; initialized = true; last_time = this_time; @@ -198,9 +198,7 @@ void emulate_terminal( int fd ) } /* open parser and terminal */ - Parser::UTF8Parser parser; - Terminal::Emulator terminal( window_size.ws_col, window_size.ws_row ); - Terminal::Display display; + Terminal::Complete complete( window_size.ws_col, window_size.ws_row ); Terminal::Framebuffer state( window_size.ws_col, window_size.ws_row ); struct pollfd pollfds[ 3 ]; @@ -214,7 +212,7 @@ void emulate_terminal( int fd ) pollfds[ 2 ].fd = winch_fd; pollfds[ 2 ].events = POLLIN; - swrite( STDOUT_FILENO, terminal.open().c_str() ); + swrite( STDOUT_FILENO, complete.open().c_str() ); int poll_timeout = -1; @@ -226,11 +224,43 @@ void emulate_terminal( int fd ) } if ( pollfds[ 0 ].revents & POLLIN ) { - if ( termemu( fd, STDIN_FILENO, true, &parser, &terminal ) < 0 ) { + /* input from user */ + char buf[ buf_size ]; + + /* fill buffer if possible */ + ssize_t bytes_read = read( pollfds[ 0 ].fd, buf, buf_size ); + if ( bytes_read == 0 ) { /* EOF */ + return; + } else if ( bytes_read < 0 ) { + perror( "read" ); + return; + } + + std::string terminal_to_host; + + for ( int i = 0; i < bytes_read; i++ ) { + Parser::UserByte ub( buf[ i ] ); + terminal_to_host += complete.act( &ub ); + } + + if ( swrite( fd, terminal_to_host.c_str(), terminal_to_host.length() ) < 0 ) { break; } } else if ( pollfds[ 1 ].revents & POLLIN ) { - if ( termemu( fd, fd, false, &parser, &terminal ) < 0 ) { + /* input from host */ + char buf[ buf_size ]; + + /* fill buffer if possible */ + ssize_t bytes_read = read( pollfds[ 1 ].fd, buf, buf_size ); + if ( bytes_read == 0 ) { /* EOF */ + return; + } else if ( bytes_read < 0 ) { + perror( "read" ); + return; + } + + std::string terminal_to_host = complete.act( std::string( buf, bytes_read ) ); + if ( swrite( fd, terminal_to_host.c_str(), terminal_to_host.length() ) < 0 ) { break; } } else if ( pollfds[ 2 ].revents & POLLIN ) { @@ -247,7 +277,7 @@ void emulate_terminal( int fd ) /* tell emulator */ Parser::Resize r( window_size.ws_col, window_size.ws_row ); - r.act_on_terminal( &terminal ); + complete.act( &r ); /* tell child process */ if ( ioctl( fd, TIOCSWINSZ, &window_size ) < 0 ) { @@ -259,17 +289,17 @@ void emulate_terminal( int fd ) break; } - if ( tick( &terminal, &display, state ) ) { /* there was a frame */ + if ( tick( state, complete.get_fb()) ) { /* there was a frame */ poll_timeout = -1; } else { poll_timeout = 20; } } - std::string update = display.new_frame( true, state, terminal.get_fb() ); + std::string update = Terminal::Display::new_frame( true, state, complete.get_fb() ); swrite( STDOUT_FILENO, update.c_str() ); - swrite( STDOUT_FILENO, terminal.close().c_str() ); + swrite( STDOUT_FILENO, complete.close().c_str() ); } int termemu( int host_fd, int src_fd, bool user, diff --git a/terminal.cpp b/terminal.cpp index 9414e8d..a56b7d4 100644 --- a/terminal.cpp +++ b/terminal.cpp @@ -20,13 +20,13 @@ std::string Emulator::read_octets_to_host( void ) return ret; } -void Emulator::execute( Parser::Execute *act ) +void Emulator::execute( const Parser::Execute *act ) { fb.ds.next_print_will_wrap = false; dispatch.dispatch( CONTROL, act, &fb ); } -void Emulator::print( Parser::Print *act ) +void Emulator::print( const Parser::Print *act ) { assert( act->char_present ); @@ -109,28 +109,28 @@ void Emulator::print( Parser::Print *act ) } } -void Emulator::CSI_dispatch( Parser::CSI_Dispatch *act ) +void Emulator::CSI_dispatch( const Parser::CSI_Dispatch *act ) { fb.ds.next_print_will_wrap = false; dispatch.dispatch( CSI, act, &fb ); } -void Emulator::OSC_end( Parser::OSC_End *act ) +void Emulator::OSC_end( const Parser::OSC_End *act ) { fb.ds.next_print_will_wrap = false; dispatch.OSC_dispatch( act, &fb ); } -void Emulator::Esc_dispatch( Parser::Esc_Dispatch *act ) +void Emulator::Esc_dispatch( const Parser::Esc_Dispatch *act ) { fb.ds.next_print_will_wrap = false; /* handle 7-bit ESC-encoding of C1 control characters */ if ( (dispatch.get_dispatch_chars().size() == 0) && (0x40 <= act->ch) && (act->ch <= 0x5F) ) { - act->ch += 0x40; - dispatch.dispatch( CONTROL, act, &fb ); - act->ch -= 0x40; + Parser::Esc_Dispatch act2 = *act; + act2.ch += 0x40; + dispatch.dispatch( CONTROL, &act2, &fb ); } else { dispatch.dispatch( ESCAPE, act, &fb ); } diff --git a/terminal.hpp b/terminal.hpp index 2ff5789..b90763c 100644 --- a/terminal.hpp +++ b/terminal.hpp @@ -14,19 +14,19 @@ namespace Terminal { class Emulator { - friend void Parser::Print::act_on_terminal( Emulator * ); - 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 * ); - friend void Parser::OSC_Start::act_on_terminal( Emulator * ); - friend void Parser::OSC_Put::act_on_terminal( Emulator * ); - friend void Parser::OSC_End::act_on_terminal( Emulator * ); + friend void Parser::Print::act_on_terminal( Emulator * ) const; + friend void Parser::Execute::act_on_terminal( Emulator * ) const; + friend void Parser::Clear::act_on_terminal( Emulator * ) const; + friend void Parser::Param::act_on_terminal( Emulator * ) const; + friend void Parser::Collect::act_on_terminal( Emulator * ) const; + friend void Parser::CSI_Dispatch::act_on_terminal( Emulator * ) const; + friend void Parser::Esc_Dispatch::act_on_terminal( Emulator * ) const; + friend void Parser::OSC_Start::act_on_terminal( Emulator * ) const; + friend void Parser::OSC_Put::act_on_terminal( Emulator * ) const; + friend void Parser::OSC_End::act_on_terminal( Emulator * ) const; - friend void Parser::UserByte::act_on_terminal( Emulator * ); - friend void Parser::Resize::act_on_terminal( Emulator * ); + friend void Parser::UserByte::act_on_terminal( Emulator * ) const; + friend void Parser::Resize::act_on_terminal( Emulator * ) const; private: Framebuffer fb; @@ -34,11 +34,11 @@ namespace Terminal { UserInput user; /* action methods */ - void print( Parser::Print *act ); - void execute( Parser::Execute *act ); - void CSI_dispatch( Parser::CSI_Dispatch *act ); - void Esc_dispatch( Parser::Esc_Dispatch *act ); - void OSC_end( Parser::OSC_End *act ); + void print( const Parser::Print *act ); + void execute( const Parser::Execute *act ); + void CSI_dispatch( const Parser::CSI_Dispatch *act ); + void Esc_dispatch( const Parser::Esc_Dispatch *act ); + void OSC_end( const Parser::OSC_End *act ); void resize( size_t s_width, size_t s_height ); public: diff --git a/terminaldispatcher.cpp b/terminaldispatcher.cpp index 6fadf4d..1d3d35b 100644 --- a/terminaldispatcher.cpp +++ b/terminaldispatcher.cpp @@ -12,7 +12,7 @@ Dispatcher::Dispatcher() OSC_string(), terminal_to_host() {} -void Dispatcher::newparamchar( Parser::Param *act ) +void Dispatcher::newparamchar( const Parser::Param *act ) { assert( act->char_present ); assert( (act->ch == ';') || ( (act->ch >= '0') && (act->ch <= '9') ) ); @@ -24,7 +24,7 @@ void Dispatcher::newparamchar( Parser::Param *act ) parsed = false; } -void Dispatcher::collect( Parser::Collect *act ) +void Dispatcher::collect( const Parser::Collect *act ) { assert( act->char_present ); if ( ( dispatch_chars.length() < 8 ) /* never should need more than 2 */ @@ -34,7 +34,7 @@ void Dispatcher::collect( Parser::Collect *act ) } } -void Dispatcher::clear( Parser::Clear *act ) +void Dispatcher::clear( const Parser::Clear *act ) { params.clear(); dispatch_chars.clear(); @@ -141,7 +141,7 @@ Function::Function( Function_Type type, std::string dispatch_chars, register_function( type, dispatch_chars, *this ); } -void Dispatcher::dispatch( Function_Type type, Parser::Action *act, Framebuffer *fb ) +void Dispatcher::dispatch( Function_Type type, const Parser::Action *act, Framebuffer *fb ) { /* add final char to dispatch key */ if ( (type == ESCAPE) || (type == CSI) ) { @@ -175,7 +175,7 @@ void Dispatcher::dispatch( Function_Type type, Parser::Action *act, Framebuffer } } -void Dispatcher::OSC_put( Parser::OSC_Put *act ) +void Dispatcher::OSC_put( const Parser::OSC_Put *act ) { assert( act->char_present ); if ( OSC_string.size() < 256 ) { /* should be a long enough window title */ @@ -184,7 +184,7 @@ void Dispatcher::OSC_put( Parser::OSC_Put *act ) } } -void Dispatcher::OSC_start( Parser::OSC_Start *act ) +void Dispatcher::OSC_start( const Parser::OSC_Start *act ) { OSC_string.clear(); act->handled = true; diff --git a/terminaldispatcher.hpp b/terminaldispatcher.hpp index 37447f9..205b299 100644 --- a/terminaldispatcher.hpp +++ b/terminaldispatcher.hpp @@ -63,19 +63,19 @@ namespace Terminal { int getparam( size_t N, int defaultval ); int param_count( void ); - void newparamchar( Parser::Param *act ); - void collect( Parser::Collect *act ); - void clear( Parser::Clear *act ); + void newparamchar( const Parser::Param *act ); + void collect( const Parser::Collect *act ); + void clear( const Parser::Clear *act ); std::string str( void ); - void dispatch( Function_Type type, Parser::Action *act, Framebuffer *fb ); + void dispatch( Function_Type type, const Parser::Action *act, Framebuffer *fb ); std::string get_dispatch_chars( void ) { return dispatch_chars; } std::vector get_OSC_string( void ) { return OSC_string; } - void OSC_put( Parser::OSC_Put *act ); - void OSC_start( Parser::OSC_Start *act ); - void OSC_dispatch( Parser::OSC_End *act, Framebuffer *fb ); + void OSC_put( const Parser::OSC_Put *act ); + void OSC_start( const Parser::OSC_Start *act ); + void OSC_dispatch( const Parser::OSC_End *act, Framebuffer *fb ); }; } diff --git a/terminaldisplay.hpp b/terminaldisplay.hpp index 1014751..97417aa 100644 --- a/terminaldisplay.hpp +++ b/terminaldisplay.hpp @@ -21,12 +21,10 @@ namespace Terminal { class Display { private: - void put_cell( bool initialized, FrameState &frame, const Framebuffer &f ); + static void put_cell( bool initialized, FrameState &frame, const Framebuffer &f ); public: - Display() {} - - std::string new_frame( bool initialized, const Framebuffer &last, const Framebuffer &f ); + static std::string new_frame( bool initialized, const Framebuffer &last, const Framebuffer &f ); }; } diff --git a/terminalfunctions.cpp b/terminalfunctions.cpp index 7d9c464..ebcb581 100644 --- a/terminalfunctions.cpp +++ b/terminalfunctions.cpp @@ -461,7 +461,7 @@ void CSI_DECSTR( Framebuffer *fb, Dispatcher *dispatch __attribute((unused)) ) static Function func_CSI_DECSTR( CSI, "!p", CSI_DECSTR ); /* xterm uses an Operating System Command to set the window title */ -void Dispatcher::OSC_dispatch( Parser::OSC_End *act, Framebuffer *fb ) +void Dispatcher::OSC_dispatch( const Parser::OSC_End *act, Framebuffer *fb ) { if ( OSC_string.size() >= 2 ) { if ( (OSC_string[ 0 ] == L'0') diff --git a/terminaluserinput.cpp b/terminaluserinput.cpp index feed3d4..e5088b1 100644 --- a/terminaluserinput.cpp +++ b/terminaluserinput.cpp @@ -2,7 +2,7 @@ using namespace Terminal; -std::string UserInput::input( Parser::UserByte *act, +std::string UserInput::input( const Parser::UserByte *act, bool application_mode_cursor_keys ) { char translated_str[ 2 ] = { act->c, 0 }; diff --git a/terminaluserinput.hpp b/terminaluserinput.hpp index 6672408..e7f02c0 100644 --- a/terminaluserinput.hpp +++ b/terminaluserinput.hpp @@ -14,7 +14,7 @@ namespace Terminal { : last_byte( -1 ) {} - std::string input( Parser::UserByte *act, + std::string input( const Parser::UserByte *act, bool application_mode_cursor_keys ); }; }