Abstract cursor movement
This commit is contained in:
+64
-75
@@ -45,24 +45,18 @@ void Emulator::execute( Parser::Execute *act )
|
|||||||
|
|
||||||
switch ( act->ch ) {
|
switch ( act->ch ) {
|
||||||
case 0x0a: /* LF */
|
case 0x0a: /* LF */
|
||||||
fb.cursor_row++;
|
fb.move_rows_autoscroll( 1 );
|
||||||
fb.autoscroll();
|
|
||||||
fb.newgrapheme();
|
|
||||||
act->handled = true;
|
act->handled = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0d: /* CR */
|
case 0x0d: /* CR */
|
||||||
fb.cursor_col = 0;
|
fb.ds.move_col( 0 );
|
||||||
fb.newgrapheme();
|
|
||||||
act->handled = true;
|
act->handled = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x08: /* BS */
|
case 0x08: /* BS */
|
||||||
if ( fb.cursor_col > 0 ) {
|
fb.ds.move_col( -1, true );
|
||||||
fb.cursor_col--;
|
|
||||||
fb.newgrapheme(); /* this is not xterm's behavior */
|
|
||||||
act->handled = true;
|
act->handled = true;
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,56 +65,47 @@ void Emulator::print( Parser::Print *act )
|
|||||||
{
|
{
|
||||||
assert( act->char_present );
|
assert( act->char_present );
|
||||||
|
|
||||||
if ( (fb.width == 0) || (fb.height == 0) ) {
|
int chwidth = act->ch == L'\0' ? -1 : wcwidth( act->ch );
|
||||||
|
|
||||||
|
Cell *this_cell = fb.get_cell();
|
||||||
|
|
||||||
|
if ( !this_cell ) { /* zero-size framebuffer */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert( fb.cursor_row < fb.height ); /* must be on screen */
|
Cell *combining_cell = fb.get_combining_cell();
|
||||||
assert( fb.cursor_col <= fb.width + 1 ); /* two off is ok */
|
|
||||||
assert( fb.combining_char_row < fb.height );
|
|
||||||
assert( fb.combining_char_col < fb.width );
|
|
||||||
|
|
||||||
int chwidth = act->ch == L'\0' ? -1 : wcwidth( act->ch );
|
|
||||||
|
|
||||||
Cell *this_cell;
|
|
||||||
|
|
||||||
switch ( chwidth ) {
|
switch ( chwidth ) {
|
||||||
case 1: /* normal character */
|
case 1: /* normal character */
|
||||||
case 2: /* wide character */
|
case 2: /* wide character */
|
||||||
if ( fb.cursor_col >= fb.width ) { /* wrap */
|
if ( fb.ds.next_print_will_wrap ) {
|
||||||
fb.cursor_col = 0;
|
fb.ds.move_col( 0 );
|
||||||
fb.cursor_row++;
|
fb.move_rows_autoscroll( 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
fb.autoscroll();
|
this_cell = fb.get_cell();
|
||||||
fb.newgrapheme();
|
|
||||||
|
|
||||||
this_cell = &fb.rows[ fb.cursor_row ].cells[ fb.cursor_col ];
|
|
||||||
this_cell->reset();
|
this_cell->reset();
|
||||||
this_cell->contents.push_back( act->ch );
|
this_cell->contents.push_back( act->ch );
|
||||||
|
this_cell->width = chwidth;
|
||||||
|
|
||||||
if ( (fb.cursor_col < fb.width - 1) && (chwidth == 2) ) {
|
fb.claim_overlap( fb.ds.get_cursor_row(), fb.ds.get_cursor_col() );
|
||||||
Cell *next_cell = &fb.rows[ fb.cursor_row ].cells[ fb.cursor_col + 1 ];
|
|
||||||
this_cell->overlapped_cells.push_back( next_cell );
|
fb.ds.move_col( chwidth, true, true );
|
||||||
next_cell->overlapping_cell = this_cell;
|
|
||||||
}
|
|
||||||
|
|
||||||
fb.cursor_col += chwidth;
|
|
||||||
act->handled = true;
|
act->handled = true;
|
||||||
break;
|
break;
|
||||||
case 0: /* combining character */
|
case 0: /* combining character */
|
||||||
if ( fb.rows[ fb.combining_char_row ].cells[ fb.combining_char_col ].contents.size() == 0 ) {
|
if ( combining_cell->contents.size() == 0 ) {
|
||||||
/* cell starts with combining character */
|
/* cell starts with combining character */
|
||||||
fb.rows[ fb.combining_char_row ].cells[ fb.combining_char_col ].fallback = true;
|
assert( this_cell == combining_cell );
|
||||||
assert( fb.cursor_col == fb.combining_char_col );
|
assert( combining_cell->width == 1 );
|
||||||
assert( fb.cursor_row == fb.combining_char_row );
|
combining_cell->fallback = true;
|
||||||
assert( fb.cursor_col < fb.width );
|
fb.ds.move_col( 1, true, true );
|
||||||
fb.cursor_col++;
|
|
||||||
/* a combining character should never be able to wrap us */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( fb.rows[ fb.combining_char_row ].cells[ fb.combining_char_col ].contents.size() < 16 ) { /* seems like a reasonable limit on combining character */
|
if ( combining_cell->contents.size() < 16 ) { /* seems like a reasonable limit on combining characters */
|
||||||
fb.rows[ fb.combining_char_row ].cells[ fb.combining_char_col ].contents.push_back( act->ch );
|
combining_cell->contents.push_back( act->ch );
|
||||||
}
|
}
|
||||||
act->handled = true;
|
act->handled = true;
|
||||||
break;
|
break;
|
||||||
@@ -131,42 +116,6 @@ void Emulator::print( Parser::Print *act )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Emulator::debug_printout( int fd )
|
|
||||||
{
|
|
||||||
std::string screen;
|
|
||||||
screen.append( "\033[H\033[2J" );
|
|
||||||
|
|
||||||
for ( int y = 0; y < fb.height; y++ ) {
|
|
||||||
for ( int x = 0; x < fb.width; x++ ) {
|
|
||||||
char curmove[ 32 ];
|
|
||||||
snprintf( curmove, 32, "\033[%d;%dH", y + 1, x + 1 );
|
|
||||||
screen.append( curmove );
|
|
||||||
Cell *cell = &fb.rows[ y ].cells[ x ];
|
|
||||||
if ( cell->overlapping_cell ) continue;
|
|
||||||
|
|
||||||
if ( cell->fallback ) {
|
|
||||||
char utf8[ 8 ];
|
|
||||||
snprintf( utf8, 8, "%lc", 0xA0 );
|
|
||||||
screen.append( utf8 );
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( std::vector<wchar_t>::iterator i = cell->contents.begin();
|
|
||||||
i != cell->contents.end();
|
|
||||||
i++ ) {
|
|
||||||
char utf8[ 8 ];
|
|
||||||
snprintf( utf8, 8, "%lc", *i );
|
|
||||||
screen.append( utf8 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char curmove[ 32 ];
|
|
||||||
snprintf( curmove, 32, "\033[%d;%dH", fb.cursor_row + 1, fb.cursor_col + 1 );
|
|
||||||
screen.append( curmove );
|
|
||||||
|
|
||||||
swrite( fd, screen.c_str() );
|
|
||||||
}
|
|
||||||
|
|
||||||
void Emulator::CSI_dispatch( Parser::CSI_Dispatch *act )
|
void Emulator::CSI_dispatch( Parser::CSI_Dispatch *act )
|
||||||
{
|
{
|
||||||
/* add final char to dispatch key */
|
/* add final char to dispatch key */
|
||||||
@@ -212,3 +161,43 @@ void Emulator::Esc_dispatch( Parser::Esc_Dispatch *act )
|
|||||||
act->handled = true;
|
act->handled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Emulator::debug_printout( int fd )
|
||||||
|
{
|
||||||
|
std::string screen;
|
||||||
|
screen.append( "\033[H\033[2J" );
|
||||||
|
|
||||||
|
for ( int y = 0; y < fb.ds.get_height(); y++ ) {
|
||||||
|
for ( int x = 0; x < fb.ds.get_width(); x++ ) {
|
||||||
|
char curmove[ 32 ];
|
||||||
|
snprintf( curmove, 32, "\033[%d;%dH", y + 1, x + 1 );
|
||||||
|
screen.append( curmove );
|
||||||
|
Cell *cell = fb.get_cell( y, x );
|
||||||
|
if ( cell->overlapping_cell ) continue;
|
||||||
|
|
||||||
|
assert( (cell->overlapped_cells.size() + 1 == (size_t)cell->width)
|
||||||
|
|| (x == fb.ds.get_width() - 1) );
|
||||||
|
|
||||||
|
if ( cell->fallback ) {
|
||||||
|
char utf8[ 8 ];
|
||||||
|
snprintf( utf8, 8, "%lc", 0xA0 );
|
||||||
|
screen.append( utf8 );
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( std::vector<wchar_t>::iterator i = cell->contents.begin();
|
||||||
|
i != cell->contents.end();
|
||||||
|
i++ ) {
|
||||||
|
char utf8[ 8 ];
|
||||||
|
snprintf( utf8, 8, "%lc", *i );
|
||||||
|
screen.append( utf8 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char curmove[ 32 ];
|
||||||
|
snprintf( curmove, 32, "\033[%d;%dH", fb.ds.get_cursor_row() + 1,
|
||||||
|
fb.ds.get_cursor_col() + 1 );
|
||||||
|
screen.append( curmove );
|
||||||
|
|
||||||
|
swrite( fd, screen.c_str() );
|
||||||
|
}
|
||||||
|
|||||||
+33
-47
@@ -4,49 +4,42 @@
|
|||||||
|
|
||||||
using namespace Terminal;
|
using namespace Terminal;
|
||||||
|
|
||||||
|
static void clearline( Framebuffer *fb, int row, int start, int end )
|
||||||
|
{
|
||||||
|
for ( int col = start; col <= end; col++ ) {
|
||||||
|
fb->get_cell( row, col )->reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Emulator::CSI_EL( void )
|
void Emulator::CSI_EL( void )
|
||||||
{
|
{
|
||||||
|
/* default: active position to end of line, inclusive */
|
||||||
|
int start = fb.ds.get_cursor_col(), end = fb.ds.get_width() - 1;
|
||||||
|
|
||||||
if ( as.params == "1" ) { /* start of screen to active position, inclusive */
|
if ( as.params == "1" ) { /* start of screen to active position, inclusive */
|
||||||
for ( int x = 0; x <= fb.cursor_col; x++ ) {
|
start = 0;
|
||||||
if ( x < fb.width ) {
|
end = fb.ds.get_cursor_col();
|
||||||
fb.rows[ fb.cursor_row ].cells[ x ].reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if ( as.params == "2" ) { /* all of line */
|
} else if ( as.params == "2" ) { /* all of line */
|
||||||
fb.rows[ fb.cursor_row ] = Row( fb.width );
|
start = 0;
|
||||||
} else { /* active position to end of line, inclusive */
|
|
||||||
for ( int x = fb.cursor_col; x < fb.width; x++ ) {
|
|
||||||
fb.rows[ fb.cursor_row ].cells[ x ].reset();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clearline( &fb, -1, start, end );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Emulator::CSI_ED( void ) {
|
void Emulator::CSI_ED( void ) {
|
||||||
if ( as.params == "1" ) { /* start of screen to active position, inclusive */
|
if ( as.params == "1" ) { /* start of screen to active position, inclusive */
|
||||||
for ( int y = 0; y < fb.cursor_row; y++ ) {
|
for ( int y = 0; y < fb.ds.get_cursor_row(); y++ ) {
|
||||||
for ( int x = 0; x < fb.width; x++ ) {
|
clearline( &fb, y, 0, fb.ds.get_width() - 1 );
|
||||||
fb.rows[ y ].cells[ x ].reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for ( int x = 0; x <= fb.cursor_col; x++ ) {
|
|
||||||
if ( x < fb.width ) {
|
|
||||||
fb.rows[ fb.cursor_row ].cells[ x ].reset();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
clearline( &fb, -1, 0, fb.ds.get_cursor_col() );
|
||||||
} else if ( as.params == "2" ) { /* entire screen */
|
} else if ( as.params == "2" ) { /* entire screen */
|
||||||
for ( int y = 0; y < fb.height; y++ ) {
|
for ( int y = 0; y < fb.ds.get_height(); y++ ) {
|
||||||
for ( int x = 0; x < fb.width; x++ ) {
|
clearline( &fb, y, 0, fb.ds.get_width() - 1 );
|
||||||
fb.rows[ y ].cells[ x ].reset();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else { /* active position to end of screen, inclusive */
|
} else { /* active position to end of screen, inclusive */
|
||||||
for ( int x = fb.cursor_col; x < fb.width; x++ ) {
|
clearline( &fb, -1, fb.ds.get_cursor_col(), fb.ds.get_width() - 1 );
|
||||||
fb.rows[ fb.cursor_row ].cells[ x ].reset();
|
for ( int y = fb.ds.get_cursor_row() + 1; y < fb.ds.get_height(); y++ ) {
|
||||||
}
|
clearline( &fb, y, 0, fb.ds.get_width() - 1 );
|
||||||
for ( int y = fb.cursor_row + 1; y < fb.height; y++ ) {
|
|
||||||
for ( int x = 0; x < fb.width; x++ ) {
|
|
||||||
fb.rows[ y ].cells[ x ].reset();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -57,31 +50,24 @@ void Emulator::CSI_cursormove( void )
|
|||||||
|
|
||||||
switch ( as.dispatch_chars[ 0 ] ) {
|
switch ( as.dispatch_chars[ 0 ] ) {
|
||||||
case 'A':
|
case 'A':
|
||||||
fb.cursor_row -= num;
|
fb.ds.move_row( -num, true );
|
||||||
break;
|
break;
|
||||||
case 'B':
|
case 'B':
|
||||||
fb.cursor_row += num;
|
fb.ds.move_row( num, true );
|
||||||
break;
|
break;
|
||||||
case 'C':
|
case 'C':
|
||||||
fb.cursor_col += num;
|
fb.ds.move_col( num, true );
|
||||||
break;
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
fb.cursor_col -= num;
|
fb.ds.move_col( -num, true );
|
||||||
break;
|
break;
|
||||||
case 'H':
|
case 'H':
|
||||||
case 'f':
|
case 'f':
|
||||||
int x = as.getparam( 0, 1 );
|
int x = as.getparam( 0, 1 );
|
||||||
int y = as.getparam( 1, 1 );
|
int y = as.getparam( 1, 1 );
|
||||||
fb.cursor_row = x - 1;
|
fb.ds.move_row( x - 1 );
|
||||||
fb.cursor_col = y - 1;
|
fb.ds.move_col( y - 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( fb.cursor_row < 0 ) fb.cursor_row = 0;
|
|
||||||
if ( fb.cursor_row >= fb.height ) fb.cursor_row = fb.height - 1;
|
|
||||||
if ( fb.cursor_col < 0 ) fb.cursor_col = 0;
|
|
||||||
if ( fb.cursor_col >= fb.width ) fb.cursor_col = fb.width - 1;
|
|
||||||
|
|
||||||
fb.newgrapheme();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Emulator::CSI_DA( void )
|
void Emulator::CSI_DA( void )
|
||||||
@@ -91,10 +77,10 @@ void Emulator::CSI_DA( void )
|
|||||||
|
|
||||||
void Emulator::Esc_DECALN( void )
|
void Emulator::Esc_DECALN( void )
|
||||||
{
|
{
|
||||||
for ( int y = 0; y < fb.height; y++ ) {
|
for ( int y = 0; y < fb.ds.get_height(); y++ ) {
|
||||||
for ( int x = 0; x < fb.width; x++ ) {
|
for ( int x = 0; x < fb.ds.get_width(); x++ ) {
|
||||||
fb.rows[ y ].cells[ x ].reset();
|
fb.get_cell( y, x )->reset();
|
||||||
fb.rows[ y ].cells[ x ].contents.push_back( L'E' );
|
fb.get_cell( y, x )->contents.push_back( L'E' );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+98
-11
@@ -8,14 +8,16 @@ Cell::Cell()
|
|||||||
: overlapping_cell( NULL ),
|
: overlapping_cell( NULL ),
|
||||||
contents(),
|
contents(),
|
||||||
overlapped_cells(),
|
overlapped_cells(),
|
||||||
fallback( false )
|
fallback( false ),
|
||||||
|
width( 1 )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
Cell::Cell( const Cell &x )
|
Cell::Cell( const Cell &x )
|
||||||
: overlapping_cell( x.overlapping_cell ),
|
: overlapping_cell( x.overlapping_cell ),
|
||||||
contents( x.contents ),
|
contents( x.contents ),
|
||||||
overlapped_cells( x.overlapped_cells ),
|
overlapped_cells( x.overlapped_cells ),
|
||||||
fallback( x.fallback )
|
fallback( x.fallback ),
|
||||||
|
width( 1 )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
Cell & Cell::operator=( const Cell &x )
|
Cell & Cell::operator=( const Cell &x )
|
||||||
@@ -36,6 +38,7 @@ void Cell::reset( void )
|
|||||||
{
|
{
|
||||||
contents.clear();
|
contents.clear();
|
||||||
fallback = false;
|
fallback = false;
|
||||||
|
width = 1;
|
||||||
|
|
||||||
if ( overlapping_cell ) {
|
if ( overlapping_cell ) {
|
||||||
assert( overlapped_cells.size() == 0 );
|
assert( overlapped_cells.size() == 0 );
|
||||||
@@ -50,11 +53,15 @@ void Cell::reset( void )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Framebuffer::Framebuffer( int s_width, int s_height )
|
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 ),
|
combining_char_col( 0 ), combining_char_row( 0 ),
|
||||||
rows( height, Row( width ) )
|
next_print_will_wrap( false )
|
||||||
|
{}
|
||||||
|
|
||||||
|
Framebuffer::Framebuffer( int s_width, int s_height )
|
||||||
|
: rows( s_height, Row( s_width ) ), ds( s_width, s_height )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void Framebuffer::scroll( int N )
|
void Framebuffer::scroll( int N )
|
||||||
@@ -63,22 +70,102 @@ void Framebuffer::scroll( int N )
|
|||||||
|
|
||||||
for ( int i = 0; i < N; i++ ) {
|
for ( int i = 0; i < N; i++ ) {
|
||||||
rows.pop_front();
|
rows.pop_front();
|
||||||
rows.push_back( Row( width ) );
|
rows.push_back( Row( ds.get_width() ) );
|
||||||
cursor_row--;
|
ds.move_row( -1, true );
|
||||||
combining_char_row--;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Framebuffer::newgrapheme( void )
|
void DrawState::new_grapheme( void )
|
||||||
{
|
{
|
||||||
combining_char_col = cursor_col;
|
combining_char_col = cursor_col;
|
||||||
combining_char_row = cursor_row;
|
combining_char_row = cursor_row;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Framebuffer::autoscroll( void )
|
void DrawState::snap_cursor_to_border( void )
|
||||||
{
|
{
|
||||||
if ( cursor_row >= height ) { /* scroll */
|
if ( cursor_row < 0 ) cursor_row = 0;
|
||||||
scroll( cursor_row - height + 1 );
|
if ( cursor_row >= height ) cursor_row = height - 1;
|
||||||
|
if ( cursor_col < 0 ) cursor_col = 0;
|
||||||
|
if ( cursor_col >= width ) cursor_col = width - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawState::move_row( int N, bool relative )
|
||||||
|
{
|
||||||
|
if ( relative ) {
|
||||||
|
cursor_row += N;
|
||||||
|
} else {
|
||||||
|
cursor_row = N;
|
||||||
|
}
|
||||||
|
|
||||||
|
snap_cursor_to_border();
|
||||||
|
new_grapheme();
|
||||||
|
next_print_will_wrap = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawState::move_col( int N, bool relative, bool implicit )
|
||||||
|
{
|
||||||
|
if ( implicit ) {
|
||||||
|
new_grapheme();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( relative ) {
|
||||||
|
cursor_col += N;
|
||||||
|
} else {
|
||||||
|
cursor_col = N;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( implicit && (cursor_col >= width) ) {
|
||||||
|
next_print_will_wrap = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
snap_cursor_to_border();
|
||||||
|
if ( !implicit ) {
|
||||||
|
new_grapheme();
|
||||||
|
next_print_will_wrap = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 );
|
||||||
|
}
|
||||||
|
|
||||||
|
ds.move_row( rows, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
Cell *Framebuffer::get_cell( void )
|
||||||
|
{
|
||||||
|
if ( (ds.get_width() == 0) || (ds.get_height() == 0) ) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &rows[ ds.get_cursor_row() ].cells[ ds.get_cursor_col() ];
|
||||||
|
}
|
||||||
|
|
||||||
|
Cell *Framebuffer::get_cell( int row, int col )
|
||||||
|
{
|
||||||
|
if ( row == -1 ) row = ds.get_cursor_row();
|
||||||
|
if ( col == -1 ) col = ds.get_cursor_col();
|
||||||
|
|
||||||
|
return &rows[ row ].cells[ col ];
|
||||||
|
}
|
||||||
|
|
||||||
|
Cell *Framebuffer::get_combining_cell( void )
|
||||||
|
{
|
||||||
|
return &rows[ ds.get_combining_char_row() ].cells[ ds.get_combining_char_col() ];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Framebuffer::claim_overlap( int row, int col )
|
||||||
|
{
|
||||||
|
Cell *the_cell = &rows[ row ].cells[ col ];
|
||||||
|
|
||||||
|
for ( int i = col + 1; i < col + the_cell->width; i++ ) {
|
||||||
|
if ( i < ds.get_width() ) {
|
||||||
|
Cell *next_cell = get_cell( row, i );
|
||||||
|
next_cell->reset();
|
||||||
|
the_cell->overlapped_cells.push_back( next_cell );
|
||||||
|
next_cell->overlapping_cell = the_cell;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+37
-4
@@ -13,6 +13,7 @@ namespace Terminal {
|
|||||||
std::vector<wchar_t> contents;
|
std::vector<wchar_t> contents;
|
||||||
std::vector<Cell *> overlapped_cells;
|
std::vector<Cell *> overlapped_cells;
|
||||||
char fallback; /* first character is combining character */
|
char fallback; /* first character is combining character */
|
||||||
|
int width;
|
||||||
|
|
||||||
Cell();
|
Cell();
|
||||||
|
|
||||||
@@ -29,19 +30,51 @@ namespace Terminal {
|
|||||||
Row( size_t s_width );
|
Row( size_t s_width );
|
||||||
};
|
};
|
||||||
|
|
||||||
class Framebuffer {
|
class DrawState {
|
||||||
public:
|
private:
|
||||||
int width, height;
|
int width, height;
|
||||||
|
|
||||||
|
void new_grapheme( void );
|
||||||
|
void snap_cursor_to_border( void );
|
||||||
|
|
||||||
int cursor_col, cursor_row;
|
int cursor_col, cursor_row;
|
||||||
int combining_char_col, combining_char_row;
|
int combining_char_col, combining_char_row;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool next_print_will_wrap;
|
||||||
|
|
||||||
|
/* bold, etc. */
|
||||||
|
|
||||||
|
void move_row( int N, bool relative = false );
|
||||||
|
void move_col( int N, bool relative = false, bool implicit = false );
|
||||||
|
|
||||||
|
int get_cursor_col( void ) { return cursor_col; }
|
||||||
|
int get_cursor_row( void ) { return cursor_row; }
|
||||||
|
int get_combining_char_col( void ) { return combining_char_col; }
|
||||||
|
int get_combining_char_row( void ) { return combining_char_row; }
|
||||||
|
int get_width( void ) { return width; }
|
||||||
|
int get_height( void ) { return height; }
|
||||||
|
|
||||||
|
DrawState( int s_width, int s_height );
|
||||||
|
};
|
||||||
|
|
||||||
|
class Framebuffer {
|
||||||
|
private:
|
||||||
std::deque<Row> rows;
|
std::deque<Row> rows;
|
||||||
|
|
||||||
void scroll( int N );
|
void scroll( int N );
|
||||||
void autoscroll( void );
|
|
||||||
void newgrapheme( void );
|
|
||||||
|
|
||||||
|
public:
|
||||||
Framebuffer( int s_width, int s_height );
|
Framebuffer( int s_width, int s_height );
|
||||||
|
DrawState ds;
|
||||||
|
|
||||||
|
void move_rows_autoscroll( int rows );
|
||||||
|
|
||||||
|
Cell *get_cell( void );
|
||||||
|
Cell *get_cell( int row, int col );
|
||||||
|
Cell *get_combining_cell( void );
|
||||||
|
|
||||||
|
void claim_overlap( int row, int col );
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user