From ca7a080a588cf40ff296da2481b08ac91d58287b Mon Sep 17 00:00:00 2001 From: Keith Winstein Date: Mon, 21 Feb 2011 01:57:45 -0500 Subject: [PATCH] Optimize output if two frames differ in a scroll of top region --- terminaldisplay.cpp | 63 ++++++++++++++++++++++++++++++++++++++++- terminalframebuffer.hpp | 9 ++++-- 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/terminaldisplay.cpp b/terminaldisplay.cpp index ccdee90..db96736 100644 --- a/terminaldisplay.cpp +++ b/terminaldisplay.cpp @@ -46,8 +46,69 @@ std::string Display::new_frame( Framebuffer &f ) current_rendition_string = "\033[0m"; } + /* shortcut -- has display moved up by a certain number of lines? */ + frame.y = 0; + + if ( initialized ) { + int lines_scrolled = 0; + int scroll_height = 0; + + for ( int row = 0; row < f.ds.get_height(); row++ ) { + if ( *(f.get_row( 0 )) == *(last_frame.get_row( row )) ) { + /* found a scroll */ + lines_scrolled = row; + scroll_height = 1; + + /* how big is the region that was scrolled? */ + for ( int region_height = 1; + lines_scrolled + region_height < f.ds.get_height(); + region_height++ ) { + if ( *(f.get_row( region_height )) + == *(last_frame.get_row( lines_scrolled + region_height )) ) { + scroll_height = region_height + 1; + } else { + break; + } + } + + break; + } + } + + if ( scroll_height ) { + frame.y = scroll_height; + + if ( lines_scrolled ) { + if ( cursor_y != f.ds.get_height() - 1 ) { + snprintf( tmp, 64, "\033[%d;%dH", f.ds.get_height(), 1 ); + frame.append( tmp ); + + cursor_y = f.ds.get_height() - 1; + cursor_x = 0; + } + + if ( current_rendition_string != "\033[0m" ) { + frame.append( "\033[0m" ); + current_rendition_string = "\033[0m"; + } + + for ( int i = 0; i < lines_scrolled; i++ ) { + frame.append( "\n" ); + } + + for ( int i = 0; i < f.ds.get_height(); i++ ) { + if ( i + lines_scrolled < f.ds.get_height() ) { + *(last_frame.get_row( i )) = *(last_frame.get_row( i + lines_scrolled )); + } else { + last_frame.get_row( i )->reset( 0 ); + } + } + } + } + } + /* iterate for every cell */ - for ( frame.y = 0; frame.y < f.ds.get_height(); frame.y++ ) { + for ( ; frame.y < f.ds.get_height(); frame.y++ ) { int last_x = 0; for ( frame.x = 0; frame.x < f.ds.get_width(); /* let put_cell() handle advance */ ) { diff --git a/terminalframebuffer.hpp b/terminalframebuffer.hpp index 14e87d4..a5f9e85 100644 --- a/terminalframebuffer.hpp +++ b/terminalframebuffer.hpp @@ -20,7 +20,7 @@ namespace Terminal { void set_rendition( int num ); std::string sgr( void ); - bool operator==( const Renditions &x ) + bool operator==( const Renditions &x ) const { return (bold == x.bold) && (underlined == x.underlined) && (blink == x.blink) && (inverse == x.inverse) @@ -45,7 +45,7 @@ namespace Terminal { void reset( int background_color ); - inline bool operator==( const Cell &x ) + bool operator==( const Cell &x ) const { return ( (contents == x.contents) && (fallback == x.fallback) @@ -67,6 +67,11 @@ namespace Terminal { void delete_cell( int col, int background_color ); void reset( int background_color ); + + bool operator==( const Row &x ) const + { + return ( (cells == x.cells) && (wrap == x.wrap) ); + } }; class SavedCursor {