summaryrefslogtreecommitdiffstats
path: root/src/frontend/terminaloverlay.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend/terminaloverlay.cc')
-rw-r--r--src/frontend/terminaloverlay.cc794
1 files changed, 377 insertions, 417 deletions
diff --git a/src/frontend/terminaloverlay.cc b/src/frontend/terminaloverlay.cc
index d8a3872..38f71b2 100644
--- a/src/frontend/terminaloverlay.cc
+++ b/src/frontend/terminaloverlay.cc
@@ -40,11 +40,9 @@
using namespace Overlay;
-void ConditionalOverlayCell::apply( Framebuffer &fb, uint64_t confirmed_epoch, int row, bool flag ) const
+void ConditionalOverlayCell::apply( Framebuffer& fb, uint64_t confirmed_epoch, int row, bool flag ) const
{
- if ( (!active)
- || (row >= fb.ds.get_height())
- || (col >= fb.ds.get_width()) ) {
+ if ( ( !active ) || ( row >= fb.ds.get_height() ) || ( col >= fb.ds.get_width() ) ) {
return;
}
@@ -58,33 +56,33 @@ void ConditionalOverlayCell::apply( Framebuffer &fb, uint64_t confirmed_epoch, i
if ( unknown ) {
if ( flag && ( col != fb.ds.get_width() - 1 ) ) {
- fb.get_mutable_cell( row, col )->get_renditions().set_attribute(Renditions::underlined, true);
+ fb.get_mutable_cell( row, col )->get_renditions().set_attribute( Renditions::underlined, true );
}
return;
}
if ( *fb.get_cell( row, col ) != replacement ) {
- *(fb.get_mutable_cell( row, col )) = replacement;
+ *( fb.get_mutable_cell( row, col ) ) = replacement;
if ( flag ) {
fb.get_mutable_cell( row, col )->get_renditions().set_attribute( Renditions::underlined, true );
}
}
}
-Validity ConditionalOverlayCell::get_validity( const Framebuffer &fb, int row,
- uint64_t early_ack __attribute__((unused)),
- uint64_t late_ack ) const
+Validity ConditionalOverlayCell::get_validity( const Framebuffer& fb,
+ int row,
+ uint64_t early_ack __attribute__( ( unused ) ),
+ uint64_t late_ack ) const
{
if ( !active ) {
return Inactive;
}
- if ( (row >= fb.ds.get_height())
- || (col >= fb.ds.get_width()) ) {
+ if ( ( row >= fb.ds.get_height() ) || ( col >= fb.ds.get_width() ) ) {
return IncorrectOrExpired;
}
- const Cell &current = *( fb.get_cell( row, col ) );
+ const Cell& current = *( fb.get_cell( row, col ) );
/* see if it hasn't been updated yet */
if ( late_ack < expiration_frame ) {
@@ -103,7 +101,7 @@ Validity ConditionalOverlayCell::get_validity( const Framebuffer &fb, int row,
std::vector<Cell>::const_iterator it = original_contents.begin();
for ( ; it != original_contents.end(); it++ ) {
if ( it->contents_match( replacement ) )
- break;
+ break;
}
if ( it == original_contents.end() ) {
return Correct;
@@ -113,23 +111,21 @@ Validity ConditionalOverlayCell::get_validity( const Framebuffer &fb, int row,
return IncorrectOrExpired;
}
-Validity ConditionalCursorMove::get_validity( const Framebuffer &fb,
- uint64_t early_ack __attribute((unused)),
- uint64_t late_ack ) const
+Validity ConditionalCursorMove::get_validity( const Framebuffer& fb,
+ uint64_t early_ack __attribute( ( unused ) ),
+ uint64_t late_ack ) const
{
if ( !active ) {
return Inactive;
}
- if ( (row >= fb.ds.get_height())
- || (col >= fb.ds.get_width()) ) {
+ if ( ( row >= fb.ds.get_height() ) || ( col >= fb.ds.get_width() ) ) {
// fprintf( stderr, "Crazy cursor (%d,%d)!\n", row, col );
return IncorrectOrExpired;
}
if ( late_ack >= expiration_frame ) {
- if ( (fb.ds.get_cursor_col() == col)
- && (fb.ds.get_cursor_row() == row) ) {
+ if ( ( fb.ds.get_cursor_col() == col ) && ( fb.ds.get_cursor_row() == row ) ) {
return Correct;
}
return IncorrectOrExpired;
@@ -138,7 +134,7 @@ Validity ConditionalCursorMove::get_validity( const Framebuffer &fb,
return Pending;
}
-void ConditionalCursorMove::apply( Framebuffer &fb, uint64_t confirmed_epoch ) const
+void ConditionalCursorMove::apply( Framebuffer& fb, uint64_t confirmed_epoch ) const
{
if ( !active ) {
return;
@@ -157,29 +153,24 @@ void ConditionalCursorMove::apply( Framebuffer &fb, uint64_t confirmed_epoch ) c
}
NotificationEngine::NotificationEngine()
- : last_word_from_server( timestamp() ),
- last_acked_state( timestamp() ),
- escape_key_string(),
- message(),
- message_is_network_error( false ),
- message_expiration( -1 ),
- show_quit_keystroke( true )
+ : last_word_from_server( timestamp() ), last_acked_state( timestamp() ), escape_key_string(), message(),
+ message_is_network_error( false ), message_expiration( -1 ), show_quit_keystroke( true )
{}
-static std::string human_readable_duration( int num_seconds, const std::string &seconds_abbr ) {
- char tmp[ 128 ];
+static std::string human_readable_duration( int num_seconds, const std::string& seconds_abbr )
+{
+ char tmp[128];
if ( num_seconds < 60 ) {
snprintf( tmp, 128, "%d %s", num_seconds, seconds_abbr.c_str() );
} else if ( num_seconds < 3600 ) {
snprintf( tmp, 128, "%d:%02d", num_seconds / 60, num_seconds % 60 );
} else {
- snprintf( tmp, 128, "%d:%02d:%02d", num_seconds / 3600,
- (num_seconds / 60) % 60, num_seconds % 60 );
+ snprintf( tmp, 128, "%d:%02d:%02d", num_seconds / 3600, ( num_seconds / 60 ) % 60, num_seconds % 60 );
}
return tmp;
}
-void NotificationEngine::apply( Framebuffer &fb ) const
+void NotificationEngine::apply( Framebuffer& fb ) const
{
uint64_t now = timestamp();
@@ -204,55 +195,60 @@ void NotificationEngine::apply( Framebuffer &fb ) const
notification_bar.append( 0x20 );
for ( int i = 0; i < fb.ds.get_width(); i++ ) {
- *(fb.get_mutable_cell( 0, i )) = notification_bar;
+ *( fb.get_mutable_cell( 0, i ) ) = notification_bar;
}
/* write message */
- wchar_t tmp[ 128 ];
+ wchar_t tmp[128];
/* We want to prefer the "last contact" message if we simply haven't
heard from the server in a while, but print the "last reply" message
if the problem is uplink-only. */
- double since_heard = (double)(now - last_word_from_server) / 1000.0;
- double since_ack = (double)(now - last_acked_state) / 1000.0;
+ double since_heard = (double)( now - last_word_from_server ) / 1000.0;
+ double since_ack = (double)( now - last_acked_state ) / 1000.0;
const char server_message[] = "contact";
const char reply_message[] = "reply";
double time_elapsed = since_heard;
- const char *explanation = server_message;
+ const char* explanation = server_message;
- if ( reply_late( now ) && (!server_late( now )) ) {
+ if ( reply_late( now ) && ( !server_late( now ) ) ) {
time_elapsed = since_ack;
explanation = reply_message;
}
const static char blank[] = "";
- const char *keystroke_str = show_quit_keystroke ? escape_key_string.c_str() : blank;
+ const char* keystroke_str = show_quit_keystroke ? escape_key_string.c_str() : blank;
- if ( message.empty() && (!time_expired) ) {
+ if ( message.empty() && ( !time_expired ) ) {
return;
}
if ( message.empty() && time_expired ) {
- swprintf( tmp, 128, L"mosh: Last %s %s ago.%s", explanation,
- human_readable_duration( static_cast<int>( time_elapsed ),
- "seconds" ).c_str(),
- keystroke_str );
- } else if ( (!message.empty()) && (!time_expired) ) {
+ swprintf( tmp,
+ 128,
+ L"mosh: Last %s %s ago.%s",
+ explanation,
+ human_readable_duration( static_cast<int>( time_elapsed ), "seconds" ).c_str(),
+ keystroke_str );
+ } else if ( ( !message.empty() ) && ( !time_expired ) ) {
swprintf( tmp, 128, L"mosh: %ls%s", message.c_str(), keystroke_str );
} else {
- swprintf( tmp, 128, L"mosh: %ls (%s without %s.)%s", message.c_str(),
- human_readable_duration( static_cast<int>( time_elapsed ),
- "s" ).c_str(),
- explanation, keystroke_str );
+ swprintf( tmp,
+ 128,
+ L"mosh: %ls (%s without %s.)%s",
+ message.c_str(),
+ human_readable_duration( static_cast<int>( time_elapsed ), "s" ).c_str(),
+ explanation,
+ keystroke_str );
}
std::wstring string_to_draw( tmp );
int overlay_col = 0;
- Cell *combining_cell = fb.get_mutable_cell( 0, 0 );
+ Cell* combining_cell = fb.get_mutable_cell( 0, 0 );
/* We unfortunately duplicate the terminal's logic for how to render a Unicode sequence into graphemes */
for ( std::wstring::const_iterator i = string_to_draw.begin(); i != string_to_draw.end(); i++ ) {
@@ -262,42 +258,42 @@ void NotificationEngine::apply( Framebuffer &fb ) const
wchar_t ch = *i;
int chwidth = ch == L'\0' ? -1 : wcwidth( ch );
- Cell *this_cell = 0;
+ Cell* this_cell = 0;
switch ( chwidth ) {
- case 1: /* normal character */
- case 2: /* wide character */
- this_cell = fb.get_mutable_cell( 0, overlay_col );
- fb.reset_cell( this_cell );
- this_cell->get_renditions().set_attribute(Renditions::bold, true);
- this_cell->get_renditions().set_foreground_color( 7 );
- this_cell->get_renditions().set_background_color( 4 );
-
- this_cell->append( ch );
- this_cell->set_wide( chwidth == 2 );
- combining_cell = this_cell;
-
- overlay_col += chwidth;
- break;
- case 0: /* combining character */
- if ( !combining_cell ) {
- break;
- }
-
- if ( combining_cell->empty() ) {
- assert( !combining_cell->get_wide() );
- combining_cell->set_fallback( true );
- overlay_col++;
- }
-
- if ( !combining_cell->full() ) {
- combining_cell->append( ch );
- }
- break;
- case -1: /* unprintable character */
- break;
- default:
- assert( !"unexpected character width from wcwidth()" );
+ case 1: /* normal character */
+ case 2: /* wide character */
+ this_cell = fb.get_mutable_cell( 0, overlay_col );
+ fb.reset_cell( this_cell );
+ this_cell->get_renditions().set_attribute( Renditions::bold, true );
+ this_cell->get_renditions().set_foreground_color( 7 );
+ this_cell->get_renditions().set_background_color( 4 );
+
+ this_cell->append( ch );
+ this_cell->set_wide( chwidth == 2 );
+ combining_cell = this_cell;
+
+ overlay_col += chwidth;
+ break;
+ case 0: /* combining character */
+ if ( !combining_cell ) {
+ break;
+ }
+
+ if ( combining_cell->empty() ) {
+ assert( !combining_cell->get_wide() );
+ combining_cell->set_fallback( true );
+ overlay_col++;
+ }
+
+ if ( !combining_cell->full() ) {
+ combining_cell->append( ch );
+ }
+ break;
+ case -1: /* unprintable character */
+ break;
+ default:
+ assert( !"unexpected character width from wcwidth()" );
}
}
}
@@ -306,7 +302,7 @@ void NotificationEngine::adjust_message( void )
{
if ( timestamp() >= message_expiration ) {
message.clear();
- }
+ }
}
int NotificationEngine::wait_time( void ) const
@@ -330,7 +326,7 @@ int NotificationEngine::wait_time( void ) const
return next_expiry;
}
-void OverlayManager::apply( Framebuffer &fb )
+void OverlayManager::apply( Framebuffer& fb )
{
predictions.cull( fb );
predictions.apply( fb );
@@ -339,67 +335,54 @@ void OverlayManager::apply( Framebuffer &fb )
title.apply( fb );
}
-void TitleEngine::set_prefix( const std::wstring &s )
+void TitleEngine::set_prefix( const std::wstring& s )
{
prefix = Terminal::Framebuffer::title_type( s.begin(), s.end() );
}
-void ConditionalOverlayRow::apply( Framebuffer &fb, uint64_t confirmed_epoch, bool flag ) const
+void ConditionalOverlayRow::apply( Framebuffer& fb, uint64_t confirmed_epoch, bool flag ) const
{
- for ( overlay_cells_type::const_iterator it = overlay_cells.begin();
- it != overlay_cells.end();
- it++ ) {
+ for ( overlay_cells_type::const_iterator it = overlay_cells.begin(); it != overlay_cells.end(); it++ ) {
it->apply( fb, confirmed_epoch, row_num, flag );
}
}
-void PredictionEngine::apply( Framebuffer &fb ) const
+void PredictionEngine::apply( Framebuffer& fb ) const
{
- if ( (display_preference == Never) || !( srtt_trigger
- || glitch_trigger
- || (display_preference == Always)
- || (display_preference == Experimental) ) ){
+ if ( ( display_preference == Never )
+ || !( srtt_trigger || glitch_trigger || ( display_preference == Always )
+ || ( display_preference == Experimental ) ) ) {
return;
}
- for ( cursors_type::const_iterator it = cursors.begin();
- it != cursors.end();
- it++ ) {
+ for ( cursors_type::const_iterator it = cursors.begin(); it != cursors.end(); it++ ) {
it->apply( fb, confirmed_epoch );
}
- for ( overlays_type::const_iterator it = overlays.begin();
- it != overlays.end();
- it++ ) {
+ for ( overlays_type::const_iterator it = overlays.begin(); it != overlays.end(); it++ ) {
it->apply( fb, confirmed_epoch, flagging );
}
}
-void PredictionEngine::kill_epoch( uint64_t epoch, const Framebuffer &fb )
+void PredictionEngine::kill_epoch( uint64_t epoch, const Framebuffer& fb )
{
- for( cursors_type::iterator it = cursors.begin(); it != cursors.end(); ) {
+ for ( cursors_type::iterator it = cursors.begin(); it != cursors.end(); ) {
cursors_type::iterator it_next = it;
it_next++;
- if ( it->tentative( epoch - 1 )) {
+ if ( it->tentative( epoch - 1 ) ) {
cursors.erase( it );
}
it = it_next;
}
- cursors.push_back( ConditionalCursorMove( local_frame_sent + 1,
- fb.ds.get_cursor_row(),
- fb.ds.get_cursor_col(),
- prediction_epoch ) );
+ cursors.push_back( ConditionalCursorMove(
+ local_frame_sent + 1, fb.ds.get_cursor_row(), fb.ds.get_cursor_col(), prediction_epoch ) );
cursor().active = true;
- for ( overlays_type::iterator i = overlays.begin();
- i != overlays.end();
- i++ ) {
- for ( overlay_cells_type::iterator j = i->overlay_cells.begin();
- j != i->overlay_cells.end();
- j++ ) {
+ for ( overlays_type::iterator i = overlays.begin(); i != overlays.end(); i++ ) {
+ for ( overlay_cells_type::iterator j = i->overlay_cells.begin(); j != i->overlay_cells.end(); j++ ) {
if ( j->tentative( epoch - 1 ) ) {
- j->reset();
+ j->reset();
}
}
}
@@ -416,35 +399,30 @@ void PredictionEngine::reset( void )
// fprintf( stderr, "RESETTING\n" );
}
-void PredictionEngine::init_cursor( const Framebuffer &fb )
+void PredictionEngine::init_cursor( const Framebuffer& fb )
{
if ( cursors.empty() ) {
/* initialize new cursor prediction */
-
- cursors.push_back( ConditionalCursorMove( local_frame_sent + 1,
- fb.ds.get_cursor_row(),
- fb.ds.get_cursor_col(),
- prediction_epoch ) );
+
+ cursors.push_back( ConditionalCursorMove(
+ local_frame_sent + 1, fb.ds.get_cursor_row(), fb.ds.get_cursor_col(), prediction_epoch ) );
cursor().active = true;
} else if ( cursor().tentative_until_epoch != prediction_epoch ) {
- cursors.push_back( ConditionalCursorMove( local_frame_sent + 1,
- cursor().row,
- cursor().col,
- prediction_epoch ) );
+ cursors.push_back(
+ ConditionalCursorMove( local_frame_sent + 1, cursor().row, cursor().col, prediction_epoch ) );
cursor().active = true;
}
}
-void PredictionEngine::cull( const Framebuffer &fb )
+void PredictionEngine::cull( const Framebuffer& fb )
{
if ( display_preference == Never ) {
return;
}
- if ( (last_height != fb.ds.get_height())
- || (last_width != fb.ds.get_width()) ) {
+ if ( ( last_height != fb.ds.get_height() ) || ( last_width != fb.ds.get_width() ) ) {
last_height = fb.ds.get_height();
last_width = fb.ds.get_width();
reset();
@@ -455,9 +433,8 @@ void PredictionEngine::cull( const Framebuffer &fb )
/* control srtt_trigger with hysteresis */
if ( send_interval > SRTT_TRIGGER_HIGH ) {
srtt_trigger = true;
- } else if ( srtt_trigger &&
- (send_interval <= SRTT_TRIGGER_LOW) /* 20 ms is current minimum value */
- && (!active()) ) { /* only turn off when no predictions being shown */
+ } else if ( srtt_trigger && ( send_interval <= SRTT_TRIGGER_LOW ) /* 20 ms is current minimum value */
+ && ( !active() ) ) { /* only turn off when no predictions being shown */
srtt_trigger = false;
}
@@ -479,113 +456,107 @@ void PredictionEngine::cull( const Framebuffer &fb )
while ( i != overlays.end() ) {
overlays_type::iterator inext = i;
inext++;
- if ( (i->row_num < 0) || (i->row_num >= fb.ds.get_height()) ) {
+ if ( ( i->row_num < 0 ) || ( i->row_num >= fb.ds.get_height() ) ) {
overlays.erase( i );
i = inext;
continue;
}
- for ( overlay_cells_type::iterator j = i->overlay_cells.begin();
- j != i->overlay_cells.end();
- j++ ) {
- switch ( j->get_validity( fb, i->row_num,
- local_frame_acked, local_frame_late_acked ) ) {
- case IncorrectOrExpired:
- if ( j->tentative( confirmed_epoch ) ) {
-
- /*
- fprintf( stderr, "Bad tentative prediction in row %d, col %d (think %lc, actually %lc)\n",
- i->row_num, j->col,
- j->replacement.debug_contents(),
- fb.get_cell( i->row_num, j->col )->debug_contents()
- );
- */
-
- if ( display_preference == Experimental ) {
- j->reset();
- } else {
- kill_epoch( j->tentative_until_epoch, fb );
- }
- /*
- if ( j->display_time != uint64_t(-1) ) {
- fprintf( stderr, "TIMING %ld - %ld (TENT)\n", time(NULL), now - j->display_time );
- }
- */
- } else {
- /*
- fprintf( stderr, "[%d=>%d] Killing prediction in row %d, col %d (think %lc, actually %lc)\n",
- (int)local_frame_acked, (int)j->expiration_frame,
- i->row_num, j->col,
- j->replacement.debug_contents(),
- fb.get_cell( i->row_num, j->col )->debug_contents() );
- */
- /*
- if ( j->display_time != uint64_t(-1) ) {
- fprintf( stderr, "TIMING %ld - %ld\n", time(NULL), now - j->display_time );
- }
- */
-
- if ( display_preference == Experimental ) {
- j->reset();
- } else {
- reset();
- return;
- }
- }
- break;
- case Correct:
- /*
- if ( j->display_time != uint64_t(-1) ) {
- fprintf( stderr, "TIMING %ld + %ld\n", now, now - j->display_time );
- }
- */
-
- if ( j->tentative_until_epoch > confirmed_epoch ) {
- confirmed_epoch = j->tentative_until_epoch;
-
- /*
- fprintf( stderr, "%lc in (%d,%d) confirms epoch %lu (predicting in epoch %lu)\n",
- j->replacement.debug_contents(), i->row_num, j->col,
- confirmed_epoch, prediction_epoch );
- */
-
- }
-
- /* When predictions come in quickly, slowly take away the glitch trigger. */
- if ( now - j->prediction_time < GLITCH_THRESHOLD
- && ( glitch_trigger > 0 && now - GLITCH_REPAIR_MININTERVAL >= last_quick_confirmation ) ) {
- glitch_trigger--;
- last_quick_confirmation = now;
- }
-
- /* match rest of row to the actual renditions */
- {
- const Renditions &actual_renditions = fb.get_cell( i->row_num, j->col )->get_renditions();
- for ( overlay_cells_type::iterator k = j;
- k != i->overlay_cells.end();
- k++ ) {
- k->replacement.get_renditions() = actual_renditions;
- }
- }
-
- /* fallthrough */
- case CorrectNoCredit:
- j->reset();
-
- break;
- case Pending:
- /* When a prediction takes a long time to be confirmed, we
- activate the predictions even if SRTT is low */
- if ( (now - j->prediction_time) >= GLITCH_FLAG_THRESHOLD ) {
- glitch_trigger = GLITCH_REPAIR_COUNT * 2; /* display and underline */
- } else if ( ((now - j->prediction_time) >= GLITCH_THRESHOLD)
- && (glitch_trigger < GLITCH_REPAIR_COUNT) ) {
- glitch_trigger = GLITCH_REPAIR_COUNT; /* just display */
- }
-
- break;
- default:
- break;
+ for ( overlay_cells_type::iterator j = i->overlay_cells.begin(); j != i->overlay_cells.end(); j++ ) {
+ switch ( j->get_validity( fb, i->row_num, local_frame_acked, local_frame_late_acked ) ) {
+ case IncorrectOrExpired:
+ if ( j->tentative( confirmed_epoch ) ) {
+
+ /*
+ fprintf( stderr, "Bad tentative prediction in row %d, col %d (think %lc, actually %lc)\n",
+ i->row_num, j->col,
+ j->replacement.debug_contents(),
+ fb.get_cell( i->row_num, j->col )->debug_contents()
+ );
+ */
+
+ if ( display_preference == Experimental ) {
+ j->reset();
+ } else {
+ kill_epoch( j->tentative_until_epoch, fb );
+ }
+ /*
+ if ( j->display_time != uint64_t(-1) ) {
+ fprintf( stderr, "TIMING %ld - %ld (TENT)\n", time(NULL), now - j->display_time );
+ }
+ */
+ } else {
+ /*
+ fprintf( stderr, "[%d=>%d] Killing prediction in row %d, col %d (think %lc, actually %lc)\n",
+ (int)local_frame_acked, (int)j->expiration_frame,
+ i->row_num, j->col,
+ j->replacement.debug_contents(),
+ fb.get_cell( i->row_num, j->col )->debug_contents() );
+ */
+ /*
+ if ( j->display_time != uint64_t(-1) ) {
+ fprintf( stderr, "TIMING %ld - %ld\n", time(NULL), now - j->display_time );
+ }
+ */
+
+ if ( display_preference == Experimental ) {
+ j->reset();
+ } else {
+ reset();
+ return;
+ }
+ }
+ break;
+ case Correct:
+ /*
+ if ( j->display_time != uint64_t(-1) ) {
+ fprintf( stderr, "TIMING %ld + %ld\n", now, now - j->display_time );
+ }
+ */
+
+ if ( j->tentative_until_epoch > confirmed_epoch ) {
+ confirmed_epoch = j->tentative_until_epoch;
+
+ /*
+ fprintf( stderr, "%lc in (%d,%d) confirms epoch %lu (predicting in epoch %lu)\n",
+ j->replacement.debug_contents(), i->row_num, j->col,
+ confirmed_epoch, prediction_epoch );
+ */
+ }
+
+ /* When predictions come in quickly, slowly take away the glitch trigger. */
+ if ( now - j->prediction_time < GLITCH_THRESHOLD
+ && ( glitch_trigger > 0 && now - GLITCH_REPAIR_MININTERVAL >= last_quick_confirmation ) ) {
+ glitch_trigger--;
+ last_quick_confirmation = now;
+ }
+
+ /* match rest of row to the actual renditions */
+ {
+ const Renditions& actual_renditions = fb.get_cell( i->row_num, j->col )->get_renditions();
+ for ( overlay_cells_type::iterator k = j; k != i->overlay_cells.end(); k++ ) {
+ k->replacement.get_renditions() = actual_renditions;
+ }
+ }
+
+ /* fallthrough */
+ case CorrectNoCredit:
+ j->reset();
+
+ break;
+ case Pending:
+ /* When a prediction takes a long time to be confirmed, we
+ activate the predictions even if SRTT is low */
+ if ( ( now - j->prediction_time ) >= GLITCH_FLAG_THRESHOLD ) {
+ glitch_trigger = GLITCH_REPAIR_COUNT * 2; /* display and underline */
+ } else if ( ( ( now - j->prediction_time ) >= GLITCH_THRESHOLD )
+ && ( glitch_trigger < GLITCH_REPAIR_COUNT ) ) {
+ glitch_trigger = GLITCH_REPAIR_COUNT; /* just display */
+ }
+
+ break;
+ default:
+ break;
}
}
@@ -593,9 +564,8 @@ void PredictionEngine::cull( const Framebuffer &fb )
}
/* go through cursor predictions */
- if ( !cursors.empty()
- && cursor().get_validity( fb,
- local_frame_acked, local_frame_late_acked ) == IncorrectOrExpired ) {
+ if ( !cursors.empty()
+ && cursor().get_validity( fb, local_frame_acked, local_frame_late_acked ) == IncorrectOrExpired ) {
/*
fprintf( stderr, "Sadly, we're predicting (%d,%d) vs. (%d,%d) [tau: %ld, expiration_time=%ld, now=%ld]\n",
cursor().row, cursor().col,
@@ -615,8 +585,7 @@ void PredictionEngine::cull( const Framebuffer &fb )
/* NB: switching from list to another STL container could break this code.
So we don't use the cursors_type typedef. */
- for ( std::list<ConditionalCursorMove>::iterator it = cursors.begin();
- it != cursors.end(); ) {
+ for ( std::list<ConditionalCursorMove>::iterator it = cursors.begin(); it != cursors.end(); ) {
if ( it->get_validity( fb, local_frame_acked, local_frame_late_acked ) != Pending ) {
it = cursors.erase( it );
} else {
@@ -625,7 +594,7 @@ void PredictionEngine::cull( const Framebuffer &fb )
}
}
-ConditionalOverlayRow & PredictionEngine::get_or_make_row( int row_num, int num_cols )
+ConditionalOverlayRow& PredictionEngine::get_or_make_row( int row_num, int num_cols )
{
overlays_type::iterator it;
@@ -643,13 +612,13 @@ ConditionalOverlayRow & PredictionEngine::get_or_make_row( int row_num, int num_
r.overlay_cells.reserve( num_cols );
for ( int i = 0; i < num_cols; i++ ) {
r.overlay_cells.push_back( ConditionalOverlayCell( 0, i, prediction_epoch ) );
- assert( r.overlay_cells[ i ].col == i );
+ assert( r.overlay_cells[i].col == i );
}
overlays.push_back( r );
return overlays.back();
}
-void PredictionEngine::new_user_byte( char the_byte, const Framebuffer &fb )
+void PredictionEngine::new_user_byte( char the_byte, const Framebuffer& fb )
{
if ( display_preference == Never ) {
return;
@@ -663,8 +632,7 @@ void PredictionEngine::new_user_byte( char the_byte, const Framebuffer &fb )
uint64_t now = timestamp();
/* translate application-mode cursor control function to ANSI cursor control sequence */
- if ( (last_byte == 0x1b)
- && (the_byte == 'O') ) {
+ if ( ( last_byte == 0x1b ) && ( the_byte == 'O' ) ) {
the_byte = '[';
}
last_byte = the_byte;
@@ -672,14 +640,12 @@ void PredictionEngine::new_user_byte( char the_byte, const Framebuffer &fb )
Parser::Actions actions;
parser.input( the_byte, actions );
- for ( Parser::Actions::iterator it = actions.begin();
- it != actions.end();
- it++ ) {
+ for ( Parser::Actions::iterator it = actions.begin(); it != actions.end(); it++ ) {
Parser::Action& act = **it;
/*
fprintf( stderr, "Action: %s (%lc)\n",
- act->name().c_str(), act->char_present ? act->ch : L'_' );
+ act->name().c_str(), act->char_present ? act->ch : L'_' );
*/
const std::type_info& type_act = typeid( act );
@@ -694,174 +660,174 @@ void PredictionEngine::new_user_byte( char the_byte, const Framebuffer &fb )
/* XXX handle wide characters */
if ( ch == 0x7f ) { /* backspace */
- // fprintf( stderr, "Backspace.\n" );
- ConditionalOverlayRow &the_row = get_or_make_row( cursor().row, fb.ds.get_width() );
-
- if ( cursor().col > 0 ) {
- cursor().col--;
- cursor().expire( local_frame_sent + 1, now );
-
- if ( predict_overwrite ) {
- ConditionalOverlayCell &cell = the_row.overlay_cells[ cursor().col ];
- cell.reset_with_orig();
- cell.active = true;
- cell.tentative_until_epoch = prediction_epoch;
- cell.expire( local_frame_sent + 1, now );
- const Cell orig_cell = *fb.get_cell();
- cell.original_contents.push_back( orig_cell );
- cell.replacement = orig_cell;
- cell.replacement.clear();
- cell.replacement.append(' ');
- } else {
- for ( int i = cursor().col; i < fb.ds.get_width(); i++ ) {
- ConditionalOverlayCell &cell = the_row.overlay_cells[ i ];
-
- cell.reset_with_orig();
- cell.active = true;
- cell.tentative_until_epoch = prediction_epoch;
- cell.expire( local_frame_sent + 1, now );
- cell.original_contents.push_back( *fb.get_cell( cursor().row, i ) );
-
- if ( i + 2 < fb.ds.get_width() ) {
- ConditionalOverlayCell &next_cell = the_row.overlay_cells[ i + 1 ];
- const Cell *next_cell_actual = fb.get_cell( cursor().row, i + 1 );
-
- if ( next_cell.active ) {
- if ( next_cell.unknown ) {
- cell.unknown = true;
- } else {
- cell.unknown = false;
- cell.replacement = next_cell.replacement;
- }
- } else {
- cell.unknown = false;
- cell.replacement = *next_cell_actual;
- }
- } else {
- cell.unknown = true;
- }
- }
- }
- }
- } else if ( (ch < 0x20) || (wcwidth( ch ) != 1) ) {
- /* unknown print */
- become_tentative();
- // fprintf( stderr, "Unknown print 0x%x\n", ch );
+ // fprintf( stderr, "Backspace.\n" );
+ ConditionalOverlayRow& the_row = get_or_make_row( cursor().row, fb.ds.get_width() );
+
+ if ( cursor().col > 0 ) {
+ cursor().col--;
+ cursor().expire( local_frame_sent + 1, now );
+
+ if ( predict_overwrite ) {
+ ConditionalOverlayCell& cell = the_row.overlay_cells[cursor().col];
+ cell.reset_with_orig();
+ cell.active = true;
+ cell.tentative_until_epoch = prediction_epoch;
+ cell.expire( local_frame_sent + 1, now );
+ const Cell orig_cell = *fb.get_cell();
+ cell.original_contents.push_back( orig_cell );
+ cell.replacement = orig_cell;
+ cell.replacement.clear();
+ cell.replacement.append( ' ' );
+ } else {
+ for ( int i = cursor().col; i < fb.ds.get_width(); i++ ) {
+ ConditionalOverlayCell& cell = the_row.overlay_cells[i];
+
+ cell.reset_with_orig();
+ cell.active = true;
+ cell.tentative_until_epoch = prediction_epoch;
+ cell.expire( local_frame_sent + 1, now );
+ cell.original_contents.push_back( *fb.get_cell( cursor().row, i ) );
+
+ if ( i + 2 < fb.ds.get_width() ) {
+ ConditionalOverlayCell& next_cell = the_row.overlay_cells[i + 1];
+ const Cell* next_cell_actual = fb.get_cell( cursor().row, i + 1 );
+
+ if ( next_cell.active ) {
+ if ( next_cell.unknown ) {
+ cell.unknown = true;
+ } else {
+ cell.unknown = false;
+ cell.replacement = next_cell.replacement;
+ }
+ } else {
+ cell.unknown = false;
+ cell.replacement = *next_cell_actual;
+ }
+ } else {
+ cell.unknown = true;
+ }
+ }
+ }
+ }
+ } else if ( ( ch < 0x20 ) || ( wcwidth( ch ) != 1 ) ) {
+ /* unknown print */
+ become_tentative();
+ // fprintf( stderr, "Unknown print 0x%x\n", ch );
} else {
- assert( cursor().row >= 0 );
- assert( cursor().col >= 0 );
- assert( cursor().row < fb.ds.get_height() );
- assert( cursor().col < fb.ds.get_width() );
-
- ConditionalOverlayRow &the_row = get_or_make_row( cursor().row, fb.ds.get_width() );
-
- if ( cursor().col + 1 >= fb.ds.get_width() ) {
- /* prediction in the last column is tricky */
- /* e.g., emacs will show wrap character, shell will just put the character there */
- become_tentative();
- }
-
- /* do the insert */
- int rightmost_column = predict_overwrite ? cursor().col : fb.ds.get_width() - 1;
- for ( int i = rightmost_column; i > cursor().col; i-- ) {
- ConditionalOverlayCell &cell = the_row.overlay_cells[ i ];
- cell.reset_with_orig();
- cell.active = true;
- cell.tentative_until_epoch = prediction_epoch;
- cell.expire( local_frame_sent + 1, now );
- cell.original_contents.push_back( *fb.get_cell( cursor().row, i ) );
-
- ConditionalOverlayCell &prev_cell = the_row.overlay_cells[ i - 1 ];
- const Cell *prev_cell_actual = fb.get_cell( cursor().row, i - 1 );
-
- if ( i == fb.ds.get_width() - 1 ) {
- cell.unknown = true;
- } else if ( prev_cell.active ) {
- if ( prev_cell.unknown ) {
- cell.unknown = true;
- } else {
- cell.unknown = false;
- cell.replacement = prev_cell.replacement;
- }
- } else {
- cell.unknown = false;
- cell.replacement = *prev_cell_actual;
- }
- }
-
- ConditionalOverlayCell &cell = the_row.overlay_cells[ cursor().col ];
- cell.reset_with_orig();
- cell.active = true;
- cell.tentative_until_epoch = prediction_epoch;
- cell.expire( local_frame_sent + 1, now );
- cell.replacement.get_renditions() = fb.ds.get_renditions();
-
- /* heuristic: match renditions of character to the left */
- if ( cursor().col > 0 ) {
- ConditionalOverlayCell &prev_cell = the_row.overlay_cells[ cursor().col - 1 ];
- const Cell *prev_cell_actual = fb.get_cell( cursor().row, cursor().col - 1 );
- if ( prev_cell.active && (!prev_cell.unknown) ) {
- cell.replacement.get_renditions() = prev_cell.replacement.get_renditions();
- } else {
- cell.replacement.get_renditions() = prev_cell_actual->get_renditions();
- }
- }
-
- cell.replacement.clear();
- cell.replacement.append( ch );
- cell.original_contents.push_back( *fb.get_cell( cursor().row, cursor().col ) );
-
- /*
- fprintf( stderr, "[%d=>%d] Predicting %lc in row %d, col %d [tue: %lu]\n",
- (int)local_frame_acked, (int)cell.expiration_frame,
- ch, cursor().row, cursor().col,
- cell.tentative_until_epoch );
- */
-
- cursor().expire( local_frame_sent + 1, now );
-
- /* do we need to wrap? */
- if ( cursor().col < fb.ds.get_width() - 1 ) {
- cursor().col++;
- } else {
- become_tentative();
- newline_carriage_return( fb );
- }
+ assert( cursor().row >= 0 );
+ assert( cursor().col >= 0 );
+ assert( cursor().row < fb.ds.get_height() );
+ assert( cursor().col < fb.ds.get_width() );
+
+ ConditionalOverlayRow& the_row = get_or_make_row( cursor().row, fb.ds.get_width() );
+
+ if ( cursor().col + 1 >= fb.ds.get_width() ) {
+ /* prediction in the last column is tricky */
+ /* e.g., emacs will show wrap character, shell will just put the character there */
+ become_tentative();
+ }
+
+ /* do the insert */
+ int rightmost_column = predict_overwrite ? cursor().col : fb.ds.get_width() - 1;
+ for ( int i = rightmost_column; i > cursor().col; i-- ) {
+ ConditionalOverlayCell& cell = the_row.overlay_cells[i];
+ cell.reset_with_orig();
+ cell.active = true;
+ cell.tentative_until_epoch = prediction_epoch;
+ cell.expire( local_frame_sent + 1, now );
+ cell.original_contents.push_back( *fb.get_cell( cursor().row, i ) );
+
+ ConditionalOverlayCell& prev_cell = the_row.overlay_cells[i - 1];
+ const Cell* prev_cell_actual = fb.get_cell( cursor().row, i - 1 );
+
+ if ( i == fb.ds.get_width() - 1 ) {
+ cell.unknown = true;
+ } else if ( prev_cell.active ) {
+ if ( prev_cell.unknown ) {
+ cell.unknown = true;
+ } else {
+ cell.unknown = false;
+ cell.replacement = prev_cell.replacement;
+ }
+ } else {
+ cell.unknown = false;
+ cell.replacement = *prev_cell_actual;
+ }
+ }
+
+ ConditionalOverlayCell& cell = the_row.overlay_cells[cursor().col];
+ cell.reset_with_orig();
+ cell.active = true;
+ cell.tentative_until_epoch = prediction_epoch;
+ cell.expire( local_frame_sent + 1, now );
+ cell.replacement.get_renditions() = fb.ds.get_renditions();
+
+ /* heuristic: match renditions of character to the left */
+ if ( cursor().col > 0 ) {
+ ConditionalOverlayCell& prev_cell = the_row.overlay_cells[cursor().col - 1];
+ const Cell* prev_cell_actual = fb.get_cell( cursor().row, cursor().col - 1 );
+ if ( prev_cell.active && ( !prev_cell.unknown ) ) {
+ cell.replacement.get_renditions() = prev_cell.replacement.get_renditions();
+ } else {
+ cell.replacement.get_renditions() = prev_cell_actual->get_renditions();
+ }
+ }
+
+ cell.replacement.clear();
+ cell.replacement.append( ch );
+ cell.original_contents.push_back( *fb.get_cell( cursor().row, cursor().col ) );
+
+ /*
+ fprintf( stderr, "[%d=>%d] Predicting %lc in row %d, col %d [tue: %lu]\n",