Modularize display code and add representation of wrapped line flag
This commit is contained in:
@@ -40,6 +40,7 @@ void Emulator::print( Parser::Print *act )
|
|||||||
case 1: /* normal character */
|
case 1: /* normal character */
|
||||||
case 2: /* wide character */
|
case 2: /* wide character */
|
||||||
if ( fb.ds.auto_wrap_mode && fb.ds.next_print_will_wrap ) {
|
if ( fb.ds.auto_wrap_mode && fb.ds.next_print_will_wrap ) {
|
||||||
|
fb.get_row( -1 )->wrap = true;
|
||||||
fb.ds.move_col( 0 );
|
fb.ds.move_col( 0 );
|
||||||
fb.move_rows_autoscroll( 1 );
|
fb.move_rows_autoscroll( 1 );
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-17
@@ -10,25 +10,9 @@
|
|||||||
#include "terminalframebuffer.hpp"
|
#include "terminalframebuffer.hpp"
|
||||||
#include "terminaldispatcher.hpp"
|
#include "terminaldispatcher.hpp"
|
||||||
#include "terminaluserinput.hpp"
|
#include "terminaluserinput.hpp"
|
||||||
|
#include "terminaldisplay.hpp"
|
||||||
|
|
||||||
namespace Terminal {
|
namespace Terminal {
|
||||||
class Display {
|
|
||||||
private:
|
|
||||||
bool initialized;
|
|
||||||
Framebuffer last_frame;
|
|
||||||
std::string current_rendition_string;
|
|
||||||
int cursor_x, cursor_y;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Display( int width, int height )
|
|
||||||
: initialized( false ), last_frame( width, height ),
|
|
||||||
current_rendition_string(), cursor_x( -1 ), cursor_y( -1 )
|
|
||||||
{}
|
|
||||||
|
|
||||||
std::string new_frame( Framebuffer &f );
|
|
||||||
void invalidate( void ) { initialized = false; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class Emulator {
|
class Emulator {
|
||||||
friend void Parser::Print::act_on_terminal( Emulator * );
|
friend void Parser::Print::act_on_terminal( Emulator * );
|
||||||
friend void Parser::Execute::act_on_terminal( Emulator * );
|
friend void Parser::Execute::act_on_terminal( Emulator * );
|
||||||
|
|||||||
+63
-60
@@ -1,4 +1,4 @@
|
|||||||
#include "terminal.hpp"
|
#include "terminaldisplay.hpp"
|
||||||
|
|
||||||
using namespace Terminal;
|
using namespace Terminal;
|
||||||
|
|
||||||
@@ -6,33 +6,34 @@ using namespace Terminal;
|
|||||||
|
|
||||||
std::string Display::new_frame( Framebuffer &f )
|
std::string Display::new_frame( Framebuffer &f )
|
||||||
{
|
{
|
||||||
|
/* fill in background color on any cells that have been reset
|
||||||
|
or created since last time */
|
||||||
f.back_color_erase();
|
f.back_color_erase();
|
||||||
|
|
||||||
std::string screen;
|
str.clear();
|
||||||
|
char tmp[ 64 ];
|
||||||
|
|
||||||
/* has window title changed? */
|
/* has window title changed? */
|
||||||
if ( (!initialized)
|
if ( (!initialized)
|
||||||
|| (f.get_window_title() != last_frame.get_window_title()) ) {
|
|| (f.get_window_title() != last_frame.get_window_title()) ) {
|
||||||
/* set window title */
|
/* set window title */
|
||||||
screen.append( "\033]0;[rtm] " );
|
str.append( "\033]0;[rtm] " );
|
||||||
std::vector<wchar_t> window_title = f.get_window_title();
|
std::vector<wchar_t> window_title = f.get_window_title();
|
||||||
for ( std::vector<wchar_t>::iterator i = window_title.begin();
|
for ( std::vector<wchar_t>::iterator i = window_title.begin();
|
||||||
i != window_title.end();
|
i != window_title.end();
|
||||||
i++ ) {
|
i++ ) {
|
||||||
char utf8[ 8 ];
|
snprintf( tmp, 64, "%lc", *i );
|
||||||
snprintf( utf8, 8, "%lc", *i );
|
str.append( tmp );
|
||||||
screen.append( utf8 );
|
|
||||||
}
|
}
|
||||||
screen.append( "\033\\" );
|
str.append( "\033\\" );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* has reverse video state changed? */
|
/* has reverse video state changed? */
|
||||||
if ( (!initialized)
|
if ( (!initialized)
|
||||||
|| (f.ds.reverse_video != last_frame.ds.reverse_video) ) {
|
|| (f.ds.reverse_video != last_frame.ds.reverse_video) ) {
|
||||||
/* set reverse video */
|
/* set reverse video */
|
||||||
char rev[ 8 ];
|
snprintf( tmp, 64, "\033[?5%c", (f.ds.reverse_video ? 'h' : 'l') );
|
||||||
snprintf( rev, 8, "\033[?5%c", (f.ds.reverse_video ? 'h' : 'l') );
|
str.append( tmp );
|
||||||
screen.append( rev );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* has size changed? */
|
/* has size changed? */
|
||||||
@@ -40,37 +41,71 @@ std::string Display::new_frame( Framebuffer &f )
|
|||||||
|| (f.ds.get_width() != last_frame.ds.get_width())
|
|| (f.ds.get_width() != last_frame.ds.get_width())
|
||||||
|| (f.ds.get_height() != last_frame.ds.get_height()) ) {
|
|| (f.ds.get_height() != last_frame.ds.get_height()) ) {
|
||||||
/* clear screen */
|
/* clear screen */
|
||||||
screen.append( "\033[0m\033[H\033[2J" );
|
str.append( "\033[0m\033[H\033[2J" );
|
||||||
initialized = false;
|
initialized = false;
|
||||||
cursor_x = cursor_y = 0;
|
cursor_x = cursor_y = 0;
|
||||||
current_rendition_string = "\033[0m";
|
current_rendition_string = "\033[0m";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* iterate for every cell */
|
/* iterate for every cell */
|
||||||
for ( int y = 0; y < f.ds.get_height(); y++ ) {
|
for ( y = 0; y < f.ds.get_height(); y++ ) {
|
||||||
for ( int x = 0; x < f.ds.get_width(); /* let charwidth handle advance */ ) {
|
for ( x = 0; x < f.ds.get_width(); /* let charwidth handle advance */ ) {
|
||||||
|
put_cell( f );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* has cursor location changed? */
|
||||||
|
if ( (!initialized)
|
||||||
|
|| (f.ds.get_cursor_row() != cursor_y)
|
||||||
|
|| (f.ds.get_cursor_col() != cursor_x) ) {
|
||||||
|
snprintf( tmp, 64, "\033[%d;%dH", f.ds.get_cursor_row() + 1,
|
||||||
|
f.ds.get_cursor_col() + 1 );
|
||||||
|
str.append( tmp );
|
||||||
|
cursor_x = f.ds.get_cursor_col();
|
||||||
|
cursor_y = f.ds.get_cursor_row();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* has cursor visibility changed? */
|
||||||
|
if ( (!initialized)
|
||||||
|
|| (f.ds.cursor_visible != last_frame.ds.cursor_visible) ) {
|
||||||
|
if ( f.ds.cursor_visible ) {
|
||||||
|
str.append( "\033[?25h" );
|
||||||
|
} else {
|
||||||
|
str.append( "\033[?25l" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
last_frame = f;
|
||||||
|
initialized = true;
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Display::put_cell( Framebuffer &f )
|
||||||
|
{
|
||||||
|
char tmp[ 64 ];
|
||||||
|
|
||||||
Cell *cell = f.get_cell( y, x );
|
Cell *cell = f.get_cell( y, x );
|
||||||
|
Cell *last_cell = last_frame.get_cell( y, x );
|
||||||
|
|
||||||
if ( initialized
|
if ( initialized
|
||||||
&& ( *cell == *(last_frame.get_cell( y, x )) ) ) {
|
&& ( *cell == *last_cell ) ) {
|
||||||
x += cell->width;
|
x += cell->width;
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( (x != cursor_x) || (y != cursor_y) ) {
|
if ( (x != cursor_x) || (y != cursor_y) ) {
|
||||||
char curmove[ 32 ];
|
snprintf( tmp, 64, "\033[%d;%dH", y + 1, x + 1 );
|
||||||
snprintf( curmove, 32, "\033[%d;%dH", y + 1, x + 1 );
|
str.append( tmp );
|
||||||
screen.append( curmove );
|
|
||||||
}
|
|
||||||
|
|
||||||
cursor_x = x;
|
cursor_x = x;
|
||||||
cursor_y = y;
|
cursor_y = y;
|
||||||
|
}
|
||||||
|
|
||||||
std::string rendition_str = cell->renditions.sgr();
|
std::string rendition_str = cell->renditions.sgr();
|
||||||
|
|
||||||
if ( current_rendition_string != rendition_str ) {
|
if ( current_rendition_string != rendition_str ) {
|
||||||
/* print renditions */
|
/* print renditions */
|
||||||
screen.append( rendition_str );
|
str.append( rendition_str );
|
||||||
current_rendition_string = rendition_str;
|
current_rendition_string = rendition_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,58 +121,26 @@ std::string Display::new_frame( Framebuffer &f )
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
char clearer[ 32 ];
|
snprintf( tmp, 64, "\033[%dX", clear_count );
|
||||||
snprintf( clearer, 32, "\033[%dX", clear_count );
|
str.append( tmp );
|
||||||
screen.append( clearer );
|
|
||||||
|
|
||||||
x += clear_count;
|
x += clear_count;
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cells that begin with combining character get combiner attached to no-break space */
|
/* cells that begin with combining character get combiner attached to no-break space */
|
||||||
if ( cell->fallback ) {
|
if ( cell->fallback ) {
|
||||||
char utf8[ 8 ];
|
snprintf( tmp, 64, "%lc", 0xA0 );
|
||||||
snprintf( utf8, 8, "%lc", 0xA0 );
|
str.append( tmp );
|
||||||
screen.append( utf8 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( std::vector<wchar_t>::iterator i = cell->contents.begin();
|
for ( std::vector<wchar_t>::iterator i = cell->contents.begin();
|
||||||
i != cell->contents.end();
|
i != cell->contents.end();
|
||||||
i++ ) {
|
i++ ) {
|
||||||
char utf8[ 8 ];
|
snprintf( tmp, 64, "%lc", *i );
|
||||||
snprintf( utf8, 8, "%lc", *i );
|
str.append( tmp );
|
||||||
screen.append( utf8 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
x += cell->width;
|
x += cell->width;
|
||||||
cursor_x += cell->width;
|
cursor_x += cell->width;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* has cursor location changed? */
|
|
||||||
if ( (!initialized)
|
|
||||||
|| (f.ds.get_cursor_row() != cursor_y)
|
|
||||||
|| (f.ds.get_cursor_col() != cursor_x) ) {
|
|
||||||
char curmove[ 32 ];
|
|
||||||
snprintf( curmove, 32, "\033[%d;%dH", f.ds.get_cursor_row() + 1,
|
|
||||||
f.ds.get_cursor_col() + 1 );
|
|
||||||
screen.append( curmove );
|
|
||||||
cursor_x = f.ds.get_cursor_col();
|
|
||||||
cursor_y = f.ds.get_cursor_row();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* has cursor visibility changed? */
|
|
||||||
if ( (!initialized)
|
|
||||||
|| (f.ds.cursor_visible != last_frame.ds.cursor_visible) ) {
|
|
||||||
if ( f.ds.cursor_visible ) {
|
|
||||||
screen.append( "\033[?25h" );
|
|
||||||
} else {
|
|
||||||
screen.append( "\033[?25l" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
last_frame = f;
|
|
||||||
initialized = true;
|
|
||||||
|
|
||||||
return screen;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
#ifndef TERMINALDISPLAY_HPP
|
||||||
|
#define TERMINALDISPLAY_HPP
|
||||||
|
|
||||||
|
#include "terminalframebuffer.hpp"
|
||||||
|
|
||||||
|
namespace Terminal {
|
||||||
|
class Display {
|
||||||
|
private:
|
||||||
|
bool initialized;
|
||||||
|
Framebuffer last_frame;
|
||||||
|
std::string current_rendition_string;
|
||||||
|
int cursor_x, cursor_y;
|
||||||
|
int x, y;
|
||||||
|
std::string str;
|
||||||
|
|
||||||
|
void put_cell( Framebuffer &f );
|
||||||
|
|
||||||
|
public:
|
||||||
|
Display( int width, int height )
|
||||||
|
: initialized( false ), last_frame( width, height ),
|
||||||
|
current_rendition_string(), cursor_x( -1 ), cursor_y( -1 ),
|
||||||
|
x( 0 ), y( 0 ), str( "" )
|
||||||
|
{}
|
||||||
|
|
||||||
|
std::string new_frame( Framebuffer &f );
|
||||||
|
void invalidate( void ) { initialized = false; }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -411,3 +411,12 @@ std::string Renditions::sgr( void )
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Row::reset( void )
|
||||||
|
{
|
||||||
|
for ( std::vector<Cell>::iterator i = cells.begin();
|
||||||
|
i != cells.end();
|
||||||
|
i++ ) {
|
||||||
|
i->reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+11
-1
@@ -60,13 +60,16 @@ namespace Terminal {
|
|||||||
class Row {
|
class Row {
|
||||||
public:
|
public:
|
||||||
std::vector<Cell> cells;
|
std::vector<Cell> cells;
|
||||||
|
bool wrap;
|
||||||
|
|
||||||
Row( size_t s_width )
|
Row( size_t s_width )
|
||||||
: cells( s_width )
|
: cells( s_width ), wrap( false )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void insert_cell( int col );
|
void insert_cell( int col );
|
||||||
void delete_cell( int col );
|
void delete_cell( int col );
|
||||||
|
|
||||||
|
void reset( void );
|
||||||
};
|
};
|
||||||
|
|
||||||
class SavedCursor {
|
class SavedCursor {
|
||||||
@@ -161,6 +164,13 @@ namespace Terminal {
|
|||||||
|
|
||||||
void move_rows_autoscroll( int rows );
|
void move_rows_autoscroll( int rows );
|
||||||
|
|
||||||
|
Row *get_row( int row )
|
||||||
|
{
|
||||||
|
if ( row == -1 ) row = ds.get_cursor_row();
|
||||||
|
|
||||||
|
return &rows[ row ];
|
||||||
|
}
|
||||||
|
|
||||||
inline Cell *get_cell( void )
|
inline Cell *get_cell( void )
|
||||||
{
|
{
|
||||||
return &rows[ ds.get_cursor_row() ].cells[ ds.get_cursor_col() ];
|
return &rows[ ds.get_cursor_row() ].cells[ ds.get_cursor_col() ];
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ void CSI_EL( Framebuffer *fb, Dispatcher *dispatch )
|
|||||||
clearline( fb, -1, 0, fb->ds.get_cursor_col() );
|
clearline( fb, -1, 0, fb->ds.get_cursor_col() );
|
||||||
break;
|
break;
|
||||||
case 2: /* all of line */
|
case 2: /* all of line */
|
||||||
clearline( fb, -1, 0, fb->ds.get_width() - 1 );
|
fb->get_row( -1 )->reset();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40,18 +40,18 @@ void CSI_ED( Framebuffer *fb, Dispatcher *dispatch ) {
|
|||||||
case 0: /* active position to end of screen, inclusive */
|
case 0: /* active position to end of screen, inclusive */
|
||||||
clearline( fb, -1, fb->ds.get_cursor_col(), fb->ds.get_width() - 1 );
|
clearline( fb, -1, fb->ds.get_cursor_col(), fb->ds.get_width() - 1 );
|
||||||
for ( int y = fb->ds.get_cursor_row() + 1; y < fb->ds.get_height(); y++ ) {
|
for ( int y = fb->ds.get_cursor_row() + 1; y < fb->ds.get_height(); y++ ) {
|
||||||
clearline( fb, y, 0, fb->ds.get_width() - 1 );
|
fb->get_row( y )->reset();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1: /* start of screen to active position, inclusive */
|
case 1: /* start of screen to active position, inclusive */
|
||||||
for ( int y = 0; y < fb->ds.get_cursor_row(); y++ ) {
|
for ( int y = 0; y < fb->ds.get_cursor_row(); y++ ) {
|
||||||
clearline( fb, y, 0, fb->ds.get_width() - 1 );
|
fb->get_row( y )->reset();
|
||||||
}
|
}
|
||||||
clearline( fb, -1, 0, fb->ds.get_cursor_col() );
|
clearline( fb, -1, 0, fb->ds.get_cursor_col() );
|
||||||
break;
|
break;
|
||||||
case 2: /* entire screen */
|
case 2: /* entire screen */
|
||||||
for ( int y = 0; y < fb->ds.get_height(); y++ ) {
|
for ( int y = 0; y < fb->ds.get_height(); y++ ) {
|
||||||
clearline( fb, y, 0, fb->ds.get_width() - 1 );
|
fb->get_row( y )->reset();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -215,7 +215,7 @@ static bool *get_DEC_mode( int param, Framebuffer *fb ) {
|
|||||||
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++ ) {
|
for ( int y = 0; y < fb->ds.get_height(); y++ ) {
|
||||||
clearline( fb, y, 0, fb->ds.get_width() - 1 );
|
fb->get_row( y )->reset();
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
case 5: /* reverse video */
|
case 5: /* reverse video */
|
||||||
|
|||||||
Reference in New Issue
Block a user