diff --git a/terminal.cpp b/terminal.cpp index 29114e8..eeaf71e 100644 --- a/terminal.cpp +++ b/terminal.cpp @@ -88,7 +88,8 @@ void Emulator::print( Parser::Print *act ) fb.ds.move_col( 1, true, true ); } - if ( combining_cell->contents.size() < 16 ) { /* seems like a reasonable limit on combining characters */ + if ( combining_cell->contents.size() < 16 ) { + /* seems like a reasonable limit on combining characters */ combining_cell->contents.push_back( act->ch ); } act->handled = true; diff --git a/terminalframebuffer.cpp b/terminalframebuffer.cpp index 68c17f7..1f79ab1 100644 --- a/terminalframebuffer.cpp +++ b/terminalframebuffer.cpp @@ -57,6 +57,7 @@ DrawState::DrawState( int s_width, int s_height ) : width( s_width ), height( s_height ), cursor_col( 0 ), cursor_row( 0 ), combining_char_col( 0 ), combining_char_row( 0 ), tabs( s_width ), + scrolling_region_top_row( 0 ), scrolling_region_bottom_row( height - 1 ), next_print_will_wrap( false ), origin_mode( false ), auto_wrap_mode( true ) { for ( int i = 0; i < width; i++ ) { @@ -72,16 +73,16 @@ void Framebuffer::scroll( int N ) { if ( N >= 0 ) { for ( int i = 0; i < N; i++ ) { - rows.pop_front(); - rows.push_back( Row( ds.get_width() ) ); + rows.erase( rows.begin() + ds.limit_top() ); + rows.insert( rows.begin() + ds.limit_bottom(), Row( ds.get_width() ) ); ds.move_row( -1, true ); } } else { N = -N; for ( int i = 0; i < N; i++ ) { - rows.pop_back(); - rows.push_front( Row( ds.get_width() ) ); + rows.erase( rows.begin() + ds.limit_bottom() ); + rows.insert( rows.begin() + ds.limit_top(), Row( ds.get_width() ) ); ds.move_row( 1, true ); } } @@ -95,8 +96,8 @@ void DrawState::new_grapheme( void ) void DrawState::snap_cursor_to_border( void ) { - if ( cursor_row < 0 ) cursor_row = 0; - if ( cursor_row >= height ) cursor_row = height - 1; + if ( cursor_row < limit_top() ) cursor_row = limit_top(); + if ( cursor_row > limit_bottom() ) cursor_row = limit_bottom(); if ( cursor_col < 0 ) cursor_col = 0; if ( cursor_col >= width ) cursor_col = width - 1; } @@ -139,10 +140,10 @@ void DrawState::move_col( int N, bool relative, bool implicit ) void Framebuffer::move_rows_autoscroll( int rows ) { - if ( ds.get_cursor_row() + rows >= ds.get_height() ) { - scroll( ds.get_height() - ds.get_cursor_row() - rows + 1 ); - } else if ( ds.get_cursor_row() + rows < 0 ) { - scroll( ds.get_cursor_row() + rows ); + if ( ds.get_cursor_row() + rows > ds.limit_bottom() ) { + scroll( ds.get_cursor_row() + rows - ds.limit_bottom() ); + } else if ( ds.get_cursor_row() + rows < ds.limit_top() ) { + scroll( ds.get_cursor_row() + rows - ds.limit_top() ); } ds.move_row( rows, true ); @@ -203,3 +204,35 @@ int DrawState::get_next_tab( void ) } return -1; } + +void DrawState::set_scrolling_region( int top, int bottom ) +{ + if ( height < 1 ) { + return; + } + + scrolling_region_top_row = top; + scrolling_region_bottom_row = bottom; + + if ( scrolling_region_top_row < 0 ) scrolling_region_top_row = 0; + if ( scrolling_region_bottom_row >= height ) scrolling_region_bottom_row = height - 1; + + if ( scrolling_region_bottom_row < scrolling_region_top_row ) + scrolling_region_bottom_row = scrolling_region_top_row; + /* real rule requires TWO-line scrolling region */ + + if ( origin_mode ) { + snap_cursor_to_border(); + new_grapheme(); + } +} + +int DrawState::limit_top( void ) +{ + return origin_mode ? scrolling_region_top_row : 0; +} + +int DrawState::limit_bottom( void ) +{ + return origin_mode ? scrolling_region_bottom_row : height - 1; +} diff --git a/terminalframebuffer.hpp b/terminalframebuffer.hpp index 26fc150..3190e7d 100644 --- a/terminalframebuffer.hpp +++ b/terminalframebuffer.hpp @@ -42,6 +42,8 @@ namespace Terminal { std::vector tabs; + int scrolling_region_top_row, scrolling_region_bottom_row; + public: bool next_print_will_wrap; bool origin_mode; @@ -63,6 +65,11 @@ namespace Terminal { void clear_tab( int col ); int get_next_tab( void ); + void set_scrolling_region( int top, int bottom ); + + int limit_top( void ); + int limit_bottom( void ); + DrawState( int s_width, int s_height ); }; diff --git a/terminalfunctions.cpp b/terminalfunctions.cpp index cb7105d..9ccafa4 100644 --- a/terminalfunctions.cpp +++ b/terminalfunctions.cpp @@ -177,8 +177,12 @@ static Function func_CSI_TBC( CSI, "g", CSI_TBC ); static bool *get_DEC_mode( int param, Framebuffer *fb ) { switch ( param ) { case 3: /* 80/132 */ + /* clear screen */ fb->ds.move_row( 0 ); fb->ds.move_col( 0 ); + for ( int y = 0; y < fb->ds.get_height(); y++ ) { + clearline( fb, y, 0, fb->ds.get_width() - 1 ); + } return NULL; case 6: /* origin */ fb->ds.move_row( 0 ); @@ -212,3 +216,19 @@ void CSI_DECRM( Framebuffer *fb, Dispatcher *dispatch ) static Function func_CSI_DECSM( CSI, "?h", CSI_DECSM ); static Function func_CSI_DECRM( CSI, "?l", CSI_DECRM ); + +void CSI_DECSTBM( Framebuffer *fb, Dispatcher *dispatch ) +{ + int top = dispatch->getparam( 0, 1 ); + int bottom = dispatch->getparam( 1, fb->ds.get_height() ); + + fb->ds.set_scrolling_region( top - 1, bottom - 1 ); +} + +static Function func_CSI_DECSTMB( CSI, "r", CSI_DECSTBM ); + +void Ctrl_BEL( Framebuffer *fb __attribute((unused)), Dispatcher *dispatch __attribute((unused)) ) +{} + +static Function func_Ctrl_BEL( CONTROL, "\x07", Ctrl_BEL ); +