Implement scrolling region
This commit is contained in:
+2
-1
@@ -88,7 +88,8 @@ void Emulator::print( Parser::Print *act )
|
|||||||
fb.ds.move_col( 1, true, true );
|
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 );
|
combining_cell->contents.push_back( act->ch );
|
||||||
}
|
}
|
||||||
act->handled = true;
|
act->handled = true;
|
||||||
|
|||||||
+43
-10
@@ -57,6 +57,7 @@ DrawState::DrawState( int s_width, int s_height )
|
|||||||
: width( s_width ), height( s_height ),
|
: width( s_width ), height( s_height ),
|
||||||
cursor_col( 0 ), cursor_row( 0 ),
|
cursor_col( 0 ), cursor_row( 0 ),
|
||||||
combining_char_col( 0 ), combining_char_row( 0 ), tabs( s_width ),
|
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 )
|
next_print_will_wrap( false ), origin_mode( false ), auto_wrap_mode( true )
|
||||||
{
|
{
|
||||||
for ( int i = 0; i < width; i++ ) {
|
for ( int i = 0; i < width; i++ ) {
|
||||||
@@ -72,16 +73,16 @@ void Framebuffer::scroll( int N )
|
|||||||
{
|
{
|
||||||
if ( N >= 0 ) {
|
if ( N >= 0 ) {
|
||||||
for ( int i = 0; i < N; i++ ) {
|
for ( int i = 0; i < N; i++ ) {
|
||||||
rows.pop_front();
|
rows.erase( rows.begin() + ds.limit_top() );
|
||||||
rows.push_back( Row( ds.get_width() ) );
|
rows.insert( rows.begin() + ds.limit_bottom(), Row( ds.get_width() ) );
|
||||||
ds.move_row( -1, true );
|
ds.move_row( -1, true );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
N = -N;
|
N = -N;
|
||||||
|
|
||||||
for ( int i = 0; i < N; i++ ) {
|
for ( int i = 0; i < N; i++ ) {
|
||||||
rows.pop_back();
|
rows.erase( rows.begin() + ds.limit_bottom() );
|
||||||
rows.push_front( Row( ds.get_width() ) );
|
rows.insert( rows.begin() + ds.limit_top(), Row( ds.get_width() ) );
|
||||||
ds.move_row( 1, true );
|
ds.move_row( 1, true );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,8 +96,8 @@ void DrawState::new_grapheme( void )
|
|||||||
|
|
||||||
void DrawState::snap_cursor_to_border( void )
|
void DrawState::snap_cursor_to_border( void )
|
||||||
{
|
{
|
||||||
if ( cursor_row < 0 ) cursor_row = 0;
|
if ( cursor_row < limit_top() ) cursor_row = limit_top();
|
||||||
if ( cursor_row >= height ) cursor_row = height - 1;
|
if ( cursor_row > limit_bottom() ) cursor_row = limit_bottom();
|
||||||
if ( cursor_col < 0 ) cursor_col = 0;
|
if ( cursor_col < 0 ) cursor_col = 0;
|
||||||
if ( cursor_col >= width ) cursor_col = width - 1;
|
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 )
|
void Framebuffer::move_rows_autoscroll( int rows )
|
||||||
{
|
{
|
||||||
if ( ds.get_cursor_row() + rows >= ds.get_height() ) {
|
if ( ds.get_cursor_row() + rows > ds.limit_bottom() ) {
|
||||||
scroll( ds.get_height() - ds.get_cursor_row() - rows + 1 );
|
scroll( ds.get_cursor_row() + rows - ds.limit_bottom() );
|
||||||
} else if ( ds.get_cursor_row() + rows < 0 ) {
|
} else if ( ds.get_cursor_row() + rows < ds.limit_top() ) {
|
||||||
scroll( ds.get_cursor_row() + rows );
|
scroll( ds.get_cursor_row() + rows - ds.limit_top() );
|
||||||
}
|
}
|
||||||
|
|
||||||
ds.move_row( rows, true );
|
ds.move_row( rows, true );
|
||||||
@@ -203,3 +204,35 @@ int DrawState::get_next_tab( void )
|
|||||||
}
|
}
|
||||||
return -1;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ namespace Terminal {
|
|||||||
|
|
||||||
std::vector<bool> tabs;
|
std::vector<bool> tabs;
|
||||||
|
|
||||||
|
int scrolling_region_top_row, scrolling_region_bottom_row;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool next_print_will_wrap;
|
bool next_print_will_wrap;
|
||||||
bool origin_mode;
|
bool origin_mode;
|
||||||
@@ -63,6 +65,11 @@ namespace Terminal {
|
|||||||
void clear_tab( int col );
|
void clear_tab( int col );
|
||||||
int get_next_tab( void );
|
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 );
|
DrawState( int s_width, int s_height );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -177,8 +177,12 @@ static Function func_CSI_TBC( CSI, "g", CSI_TBC );
|
|||||||
static bool *get_DEC_mode( int param, Framebuffer *fb ) {
|
static bool *get_DEC_mode( int param, Framebuffer *fb ) {
|
||||||
switch ( param ) {
|
switch ( param ) {
|
||||||
case 3: /* 80/132 */
|
case 3: /* 80/132 */
|
||||||
|
/* clear screen */
|
||||||
fb->ds.move_row( 0 );
|
fb->ds.move_row( 0 );
|
||||||
fb->ds.move_col( 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;
|
return NULL;
|
||||||
case 6: /* origin */
|
case 6: /* origin */
|
||||||
fb->ds.move_row( 0 );
|
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_DECSM( CSI, "?h", CSI_DECSM );
|
||||||
static Function func_CSI_DECRM( CSI, "?l", CSI_DECRM );
|
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 );
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user