From feb352c8098ae6985ef8977fec2d625386e6f686 Mon Sep 17 00:00:00 2001 From: Keith Winstein Date: Mon, 16 Apr 2012 07:46:18 -0400 Subject: [PATCH] Optional verifier for round-trippability, and fix wrapping and tab bugs. --- src/network/transportsender.cc | 9 ++++++ src/statesync/completeterminal.cc | 23 +++++++++++++++ src/statesync/completeterminal.h | 2 ++ src/statesync/user.h | 2 ++ src/terminal/terminaldisplay.cc | 30 +++++++++++--------- src/terminal/terminalframebuffer.cc | 44 +++++++++++++++++++++++++---- src/terminal/terminalframebuffer.h | 2 ++ 7 files changed, 93 insertions(+), 19 deletions(-) diff --git a/src/network/transportsender.cc b/src/network/transportsender.cc index 6beb797..3f822ab 100644 --- a/src/network/transportsender.cc +++ b/src/network/transportsender.cc @@ -143,6 +143,15 @@ void TransportSender::tick( void ) string diff = current_state.diff_from( assumed_receiver_state->state ); + /* verify diff has round-trip identity (modulo Unicode fallback rendering) */ + /* + MyState newstate( assumed_receiver_state->state ); + newstate.apply_string( diff ); + if ( current_state.compare( newstate ) ) { + fprintf( stderr, "Diff: %s\n", diff.c_str() ); + } + */ + if ( diff.empty() && (now >= next_ack_time) ) { send_empty_ack(); return; diff --git a/src/statesync/completeterminal.cc b/src/statesync/completeterminal.cc index c9203d3..5e13109 100644 --- a/src/statesync/completeterminal.cc +++ b/src/statesync/completeterminal.cc @@ -153,3 +153,26 @@ int Complete::wait_time( uint64_t now ) const return next_echo_ack_time - now; } } + +bool Complete::compare( const Complete &other ) const +{ + bool ret = false; + for ( int x = 0; x < terminal.get_fb().ds.get_width(); x++ ) { + for ( int y = 0; y < terminal.get_fb().ds.get_height(); y++ ) { + if ( terminal.get_fb().get_cell( y, x )->compare( *other.terminal.get_fb().get_cell( y, x ) ) ) { + fprintf( stderr, "Cell (%d, %d) differs.\n", y, x ); + ret = true; + } + } + } + + if ( (terminal.get_fb().ds.get_cursor_row() != other.terminal.get_fb().ds.get_cursor_row()) + || (terminal.get_fb().ds.get_cursor_col() != other.terminal.get_fb().ds.get_cursor_col()) ) { + fprintf( stderr, "Cursor mismatch: (%d, %d) vs. (%d, %d).\n", + terminal.get_fb().ds.get_cursor_row(), terminal.get_fb().ds.get_cursor_col(), + other.terminal.get_fb().ds.get_cursor_row(), other.terminal.get_fb().ds.get_cursor_col() ); + ret = true; + } + + return ret; +} diff --git a/src/statesync/completeterminal.h b/src/statesync/completeterminal.h index c76f4a9..e849057 100644 --- a/src/statesync/completeterminal.h +++ b/src/statesync/completeterminal.h @@ -60,6 +60,8 @@ namespace Terminal { std::string diff_from( const Complete &existing ) const; void apply_string( std::string diff ); bool operator==( const Complete &x ) const; + + bool compare( const Complete &other ) const; }; } diff --git a/src/statesync/user.h b/src/statesync/user.h index 51384d2..84cb497 100644 --- a/src/statesync/user.h +++ b/src/statesync/user.h @@ -77,6 +77,8 @@ namespace Network { string diff_from( const UserStream &existing ) const; void apply_string( string diff ); bool operator==( const UserStream &x ) const { return actions == x.actions; } + + bool compare( const UserStream & ) const { return false; } }; } diff --git a/src/terminal/terminaldisplay.cc b/src/terminal/terminaldisplay.cc index 58d6697..42bd39f 100644 --- a/src/terminal/terminaldisplay.cc +++ b/src/terminal/terminaldisplay.cc @@ -193,20 +193,22 @@ std::string Display::new_frame( bool initialized, const Framebuffer &last, const frame.x < f.ds.get_width(); /* let put_cell() handle advance */ ) { last_x = frame.x; put_cell( initialized, frame, f ); + } - /* To hint that a word-select should group the end of one line - with the beginning of the next, we let the real cursor - actually wrap around in cases where it wrapped around for us. */ + /* To hint that a word-select should group the end of one line + with the beginning of the next, we let the real cursor + actually wrap around in cases where it wrapped around for us. */ - if ( (frame.cursor_x >= f.ds.get_width()) - && (frame.y < f.ds.get_height() - 1) - && f.get_row( frame.y )->get_wrap() - && (!initialized || !frame.last_frame.get_row( frame.y )->get_wrap()) ) { - /* next write will wrap */ - frame.cursor_x = 0; - frame.cursor_y++; - frame.force_next_put = true; - } + if ( (frame.y < f.ds.get_height() - 1) + && f.get_row( frame.y )->get_wrap() ) { + frame.x = last_x; + frame.force_next_put = true; + put_cell( initialized, frame, f ); + + /* next write will wrap */ + frame.cursor_x = 0; + frame.cursor_y++; + frame.force_next_put = true; } /* Turn off wrap */ @@ -301,8 +303,10 @@ void Display::put_cell( bool initialized, FrameState &frame, const Framebuffer & if ( frame.force_next_put ) { frame.append( " " ); - frame.append_silent_move( frame.y, frame.x ); + frame.cursor_x++; + frame.x++; frame.force_next_put = false; + return; } /* can we go to the end of the line? */ diff --git a/src/terminal/terminalframebuffer.cc b/src/terminal/terminalframebuffer.cc index 12c3a59..1a8a06c 100644 --- a/src/terminal/terminalframebuffer.cc +++ b/src/terminal/terminalframebuffer.cc @@ -366,7 +366,7 @@ void DrawState::resize( int s_width, int s_height ) snap_cursor_to_border(); - tabs.resize( width ); + tabs.clear(); /* saved cursor will be snapped to border on restore */ @@ -482,11 +482,6 @@ std::string Renditions::sgr( void ) const /* Reduce 256 "standard" colors to the 8 ANSI colors. */ -/* We could do something fancy like find the nearest system color in - the deltaE(2000) sense, but for "business graphics," the colorimetric - intent is probably less important than just having separate colors - be separate as much as possible. */ - /* Terminal emulators generally agree on the (R',G',B') values of the "standard" 256-color pallette beyond #15, but for the first 16 colors there is disagreement. Most terminal emulators are roughly @@ -573,3 +568,40 @@ wchar_t Cell::debug_contents( void ) const return contents.front(); } } + +bool Cell::compare( const Cell &other ) const +{ + bool ret = false; + + if ( !contents_match( other ) ) { + ret = true; + fprintf( stderr, "Contents: %lc vs. %lc\n", + debug_contents(), other.debug_contents() ); + } + + if ( fallback != other.fallback ) { + ret = true; + fprintf( stderr, "fallback: %d vs. %d\n", + fallback, other.fallback ); + } + + if ( width != other.width ) { + ret = true; + fprintf( stderr, "width: %d vs. %d\n", + width, other.width ); + } + + if ( !(renditions == other.renditions) ) { + ret = true; + fprintf( stderr, "renditions: %s vs. %s\n", + renditions.sgr().c_str(), other.renditions.sgr().c_str() ); + } + + if ( wrap != other.wrap ) { + ret = true; + fprintf( stderr, "wrap: %d vs. %d\n", + wrap, other.wrap ); + } + + return ret; +} diff --git a/src/terminal/terminalframebuffer.h b/src/terminal/terminalframebuffer.h index 46d7aad..bd1b09b 100644 --- a/src/terminal/terminalframebuffer.h +++ b/src/terminal/terminalframebuffer.h @@ -102,6 +102,8 @@ namespace Terminal { return ( is_blank() && other.is_blank() ) || ( contents == other.contents ); } + + bool compare( const Cell &other ) const; }; class Row {