diff --git a/templates.cpp b/templates.cpp index ffca101..d8b2a0b 100644 --- a/templates.cpp +++ b/templates.cpp @@ -21,5 +21,3 @@ template class vector; template class vector; template class map; template class vector; -template class list; -template void std::list >::remove_if(bool (*)(int const&)); diff --git a/terminal.cpp b/terminal.cpp index 2097596..1b07660 100644 --- a/terminal.cpp +++ b/terminal.cpp @@ -152,15 +152,7 @@ void Emulator::debug_printout( int fd ) Cell *cell = fb.get_cell( y, x ); /* print renditions */ - screen.append( "\033[0" ); - char rendition[ 32 ]; - for ( std::list::iterator i = cell->renditions.begin(); - i != cell->renditions.end(); - i++ ) { - snprintf( rendition, 32, ";%d", *i ); - screen.append( rendition ); - } - screen.append( "m" ); + screen.append( cell->renditions.sgr() ); /* clear cell */ screen.append( "\033[X" ); diff --git a/terminal.hpp b/terminal.hpp index 8598047..dd7e2b0 100644 --- a/terminal.hpp +++ b/terminal.hpp @@ -16,12 +16,12 @@ namespace Terminal { private: bool initialized; Framebuffer last_frame; - std::list current_renditions; + std::string current_rendition_string; public: Display( int width, int height ) : initialized( false ), last_frame( width, height ), - current_renditions() + current_rendition_string() {} std::string new_frame( Framebuffer &f ); diff --git a/terminaldisplay.cpp b/terminaldisplay.cpp index e7f1f3a..5459ef6 100644 --- a/terminaldisplay.cpp +++ b/terminaldisplay.cpp @@ -39,11 +39,10 @@ std::string Display::new_frame( Framebuffer &f ) || (f.ds.get_width() != last_frame.ds.get_width()) || (f.ds.get_height() != last_frame.ds.get_height()) ) { /* clear screen */ - screen.append( "\033[0m;\033[H\033[2J" ); + screen.append( "\033[0m\033[H\033[2J" ); initialized = false; cursor_was_moved = true; - current_renditions.clear(); - current_renditions.push_back( 0 ); + current_rendition_string = "\033[0m"; } int cursor_x = -1, cursor_y = -1; @@ -69,23 +68,12 @@ std::string Display::new_frame( Framebuffer &f ) cursor_x = x; cursor_y = y; - std::list cell_print_renditions; - cell_print_renditions = cell->renditions; - cell_print_renditions.insert( cell_print_renditions.begin(), 0 ); + std::string rendition_str = cell->renditions.sgr(); - if ( cell_print_renditions != current_renditions ) { + if ( current_rendition_string != rendition_str ) { /* print renditions */ - screen.append( "\033[0" ); - char rendition[ 32 ]; - for ( std::list::iterator i = cell->renditions.begin(); - i != cell->renditions.end(); - i++ ) { - snprintf( rendition, 32, ";%d", *i ); - screen.append( rendition ); - } - screen.append( "m" ); - - current_renditions = cell_print_renditions; + screen.append( rendition_str ); + current_rendition_string = rendition_str; } if ( cell->contents.empty() ) { diff --git a/terminalframebuffer.cpp b/terminalframebuffer.cpp index d8ce303..286b6fe 100644 --- a/terminalframebuffer.cpp +++ b/terminalframebuffer.cpp @@ -9,8 +9,7 @@ void Cell::reset( void ) contents.clear(); fallback = false; width = 1; - renditions.clear(); - need_back_color_erase = true; + renditions = Renditions(); } DrawState::DrawState( int s_width, int s_height ) @@ -200,7 +199,6 @@ std::vector DrawState::get_tabs( void ) void Framebuffer::apply_renditions_to_current_cell( void ) { - get_cell()->need_back_color_erase = false; get_cell()->renditions = ds.get_renditions(); } @@ -297,7 +295,7 @@ void Framebuffer::soft_reset( void ) ds.cursor_visible = true; /* per xterm and gnome-terminal */ ds.application_mode_cursor_keys = false; ds.set_scrolling_region( 0, ds.get_height() - 1 ); - ds.clear_renditions(); + ds.add_rendition( 0 ); ds.clear_saved_cursor(); } @@ -344,21 +342,6 @@ void DrawState::resize( int s_width, int s_height ) } } -int DrawState::get_background_rendition( void ) -{ - int color = -1; - for ( std::list::iterator i = renditions.begin(); - i != renditions.end(); - i++ ) { - int r = *i; - if ( (40 <= r) && (r <= 49) ) { - color = r; - } - } - - return color; -} - void Framebuffer::back_color_erase( void ) { int bg_color = ds.get_background_rendition(); @@ -366,40 +349,65 @@ void Framebuffer::back_color_erase( void ) for ( int row = 0; row < ds.get_height(); row++ ) { for ( int col = 0; col < ds.get_width(); col++ ) { Cell *cell = get_cell( row, col ); - if ( cell->need_back_color_erase ) { - // assert( cell->renditions.empty() ); - if ( bg_color > 0 ) { - cell->renditions.push_back( bg_color ); - } - cell->need_back_color_erase = false; + if ( cell->renditions.background_color == -1 ) { + cell->renditions.background_color = bg_color; } } } } -static bool fg_colorval( const int &x ) { return (30 <= x) && (x <= 39); } -static bool bg_colorval( const int &x ) { return (40 <= x) && (x <= 49); } +Renditions::Renditions() + : bold( false ), underlined( false ), blink( false ), + inverse( false ), invisible( false ), foreground_color( 0 ), + background_color( -1 ) +{} -void DrawState::add_rendition( int x ) +void Renditions::set_rendition( int num ) { - /* Filter out older renditions that we know - will now be reset */ - - renditions.remove( x ); - - switch ( x ) { - case 1: case 22: renditions.remove( 1 ); renditions.remove( 22 ); break; /* bold */ - case 4: case 24: renditions.remove( 4 ); renditions.remove( 24 ); break; /* underlined */ - case 5: case 25: renditions.remove( 5 ); renditions.remove( 25 ); break; /* blink */ - case 7: case 27: renditions.remove( 7 ); renditions.remove( 27 ); break; /* inverse */ - case 8: case 28: renditions.remove( 8 ); renditions.remove( 28 ); break; /* invisible */ + if ( num == 0 ) { + bold = underlined = blink = inverse = invisible = false; + foreground_color = background_color = 0; + return; } - if ( (30 <= x) && (x <= 39) ) { /* foreground color */ - renditions.remove_if( fg_colorval ); - } else if ( (40 <= x) && (x <= 49) ) { /* background color */ - renditions.remove_if( bg_colorval ); + if ( (30 <= num) && (num <= 39) ) { /* foreground color */ + foreground_color = num; + return; + } else if ( (40 <= num) && (num <= 49) ) { /* background color */ + background_color = num; + return; } - renditions.push_back( x ); + switch ( num ) { + case 1: case 22: bold = (num == 1); break; + case 4: case 24: underlined = (num == 4); break; + case 5: case 25: blink = (num == 5); break; + case 7: case 27: inverse = (num == 7); break; + case 8: case 28: invisible = (num == 8); break; + } +} + +std::string Renditions::sgr( void ) +{ + std::string ret; + + ret.append( "\033[0" ); + if ( bold ) ret.append( ";1" ); + if ( underlined ) ret.append( ";4" ); + if ( blink ) ret.append( ";5" ); + if ( inverse ) ret.append( ";7" ); + if ( invisible ) ret.append( ";8" ); + if ( foreground_color ) { + char col[ 8 ]; + snprintf( col, 8, ";%d", foreground_color ); + ret.append( col ); + } + if ( background_color ) { + char col[ 8 ]; + snprintf( col, 8, ";%d", background_color ); + ret.append( col ); + } + ret.append( "m" ); + + return ret; } diff --git a/terminalframebuffer.hpp b/terminalframebuffer.hpp index 6747224..c4927bc 100644 --- a/terminalframebuffer.hpp +++ b/terminalframebuffer.hpp @@ -9,20 +9,41 @@ /* Terminal framebuffer */ namespace Terminal { + class Renditions { + public: + bool bold, underlined, blink, inverse, invisible; + int foreground_color; + int background_color; + + Renditions(); + void set_rendition( int num ); + std::string sgr( void ); + void back_color_erase( int num ) + { + if ( background_color == -1 ) background_color = num; + } + + bool operator==( const Renditions &x ) + { + return (bold == x.bold) && (underlined == x.underlined) + && (blink == x.blink) && (inverse == x.inverse) + && (invisible == x.invisible) && (foreground_color == x.foreground_color) + && (background_color == x.background_color); + } + }; + class Cell { public: std::vector contents; char fallback; /* first character is combining character */ int width; - std::list renditions; /* e.g., bold, blinking, etc. */ - bool need_back_color_erase; + Renditions renditions; Cell() : contents(), fallback( false ), width( 1 ), - renditions(), - need_back_color_erase( true ) + renditions() {} void reset( void ); @@ -51,7 +72,7 @@ namespace Terminal { class SavedCursor { public: int cursor_col, cursor_row; - std::list renditions; + Renditions renditions; /* character set shift state */ bool auto_wrap_mode; bool origin_mode; @@ -74,7 +95,7 @@ namespace Terminal { int scrolling_region_top_row, scrolling_region_bottom_row; - std::list renditions; + Renditions renditions; SavedCursor save; @@ -114,10 +135,9 @@ namespace Terminal { int limit_top( void ); int limit_bottom( void ); - void clear_renditions( void ) { renditions.clear(); } - void add_rendition( int x ); - const std::list get_renditions( void ) { return renditions; } - int get_background_rendition( void ); + void add_rendition( int x ) { renditions.set_rendition( x ); } + Renditions get_renditions( void ) { return renditions; } + int get_background_rendition( void ) { return renditions.background_color; } void save_cursor( void ); void restore_cursor( void ); diff --git a/terminalfunctions.cpp b/terminalfunctions.cpp index 5d1e5ee..590a553 100644 --- a/terminalfunctions.cpp +++ b/terminalfunctions.cpp @@ -322,11 +322,7 @@ void CSI_SGR( Framebuffer *fb, Dispatcher *dispatch ) bce = true; } - if ( rendition == 0 ) { - fb->ds.clear_renditions(); - } else { - fb->ds.add_rendition( rendition ); - } + fb->ds.add_rendition( rendition ); } }