Added smarter display routine

This commit is contained in:
Keith Winstein
2011-02-05 02:55:30 -05:00
parent 225ddbe2bf
commit a54cc9d0c4
6 changed files with 179 additions and 6 deletions
+2 -2
View File
@@ -1,5 +1,5 @@
source = parse.cpp parserstate.cpp parser.cpp templates.cpp terminal.cpp termemu.cpp parseraction.cpp terminalfunctions.cpp swrite.cpp terminalframebuffer.cpp terminaldispatcher.cpp terminaluserinput.cpp source = parse.cpp parserstate.cpp parser.cpp templates.cpp terminal.cpp termemu.cpp parseraction.cpp terminalfunctions.cpp swrite.cpp terminalframebuffer.cpp terminaldispatcher.cpp terminaluserinput.cpp terminaldisplay.cpp
objects = parserstate.o parser.o templates.o terminal.o parseraction.o terminalfunctions.o swrite.o terminalframebuffer.o terminaldispatcher.o terminaluserinput.o objects = parserstate.o parser.o templates.o terminal.o parseraction.o terminalfunctions.o swrite.o terminalframebuffer.o terminaldispatcher.o terminaluserinput.o terminaldisplay.o
repos = templates.rpo repos = templates.rpo
executables = parse termemu executables = parse termemu
+3 -2
View File
@@ -166,6 +166,7 @@ void emulate_terminal( int fd, int debug_fd )
/* open parser and terminal */ /* open parser and terminal */
Parser::UTF8Parser parser; Parser::UTF8Parser parser;
Terminal::Emulator terminal( window_size.ws_col, window_size.ws_row ); Terminal::Emulator terminal( window_size.ws_col, window_size.ws_row );
struct pollfd pollfds[ 3 ]; struct pollfd pollfds[ 3 ];
pollfds[ 0 ].fd = STDIN_FILENO; pollfds[ 0 ].fd = STDIN_FILENO;
@@ -194,6 +195,8 @@ void emulate_terminal( int fd, int debug_fd )
if ( termemu( fd, fd, false, debug_fd, &parser, &terminal ) < 0 ) { if ( termemu( fd, fd, false, debug_fd, &parser, &terminal ) < 0 ) {
break; break;
} }
std::string update = terminal.new_frame();
swrite( STDOUT_FILENO, update.c_str() );
} else if ( pollfds[ 2 ].revents & POLLIN ) { } else if ( pollfds[ 2 ].revents & POLLIN ) {
/* resize */ /* resize */
struct signalfd_siginfo info; struct signalfd_siginfo info;
@@ -269,8 +272,6 @@ int termemu( int host_fd, int src_fd, bool user, int debug_fd,
} }
} }
terminal->debug_printout( STDOUT_FILENO );
/* write writeback */ /* write writeback */
std::string terminal_to_host = terminal->read_octets_to_host(); std::string terminal_to_host = terminal->read_octets_to_host();
return swrite( host_fd, terminal_to_host.c_str(), terminal_to_host.length() ); return swrite( host_fd, terminal_to_host.c_str(), terminal_to_host.length() );
+1 -1
View File
@@ -10,7 +10,7 @@
using namespace Terminal; using namespace Terminal;
Emulator::Emulator( size_t s_width, size_t s_height ) Emulator::Emulator( size_t s_width, size_t s_height )
: fb( s_width, s_height ), dispatch(), user() : fb( s_width, s_height ), dispatch(), user(), display( s_width, s_height )
{} {}
std::string Emulator::read_octets_to_host( void ) std::string Emulator::read_octets_to_host( void )
+18
View File
@@ -12,6 +12,21 @@
#include "terminaluserinput.hpp" #include "terminaluserinput.hpp"
namespace Terminal { namespace Terminal {
class Display {
private:
bool initialized;
Framebuffer last_frame;
std::vector<int> current_renditions;
public:
Display( int width, int height )
: initialized( false ), last_frame( width, height ),
current_renditions()
{}
std::string new_frame( Framebuffer &f );
};
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 * );
@@ -30,6 +45,7 @@ namespace Terminal {
Framebuffer fb; Framebuffer fb;
Dispatcher dispatch; Dispatcher dispatch;
UserInput user; UserInput user;
Display display;
/* action methods */ /* action methods */
void print( Parser::Print *act ); void print( Parser::Print *act );
@@ -48,6 +64,8 @@ namespace Terminal {
std::string open( void ); /* put user cursor keys in application mode */ std::string open( void ); /* put user cursor keys in application mode */
std::string close( void ); /* restore user cursor keys */ std::string close( void ); /* restore user cursor keys */
std::string new_frame( void ) { return display.new_frame( fb ); }
}; };
} }
+150
View File
@@ -0,0 +1,150 @@
#include "terminal.hpp"
using namespace Terminal;
std::string Display::new_frame( Framebuffer &f )
{
f.back_color_erase();
std::string screen;
bool cursor_was_moved = false;
/* has window title changed? */
if ( (!initialized)
|| (f.get_window_title() != last_frame.get_window_title()) ) {
/* set window title */
screen.append( "\033]0;[rtm] " );
std::vector<wchar_t> window_title = f.get_window_title();
for ( std::vector<wchar_t>::iterator i = window_title.begin();
i != window_title.end();
i++ ) {
char utf8[ 8 ];
snprintf( utf8, 8, "%lc", *i );
screen.append( utf8 );
}
screen.append( "\033\\" );
}
/* has reverse video state changed? */
if ( (!initialized)
|| (f.ds.reverse_video != last_frame.ds.reverse_video) ) {
/* set reverse video */
char rev[ 8 ];
snprintf( rev, 8, "\033[?5%c", (f.ds.reverse_video ? 'h' : 'l') );
screen.append( rev );
}
/* has size changed? */
if ( (!initialized)
|| (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" );
initialized = false;
cursor_was_moved = true;
current_renditions.clear();
current_renditions.push_back( 0 );
}
/* iterate for every cell */
for ( int y = 0; y < f.ds.get_height(); y++ ) {
for ( int x = 0; x < f.ds.get_width(); /* let charwidth handle advance */ ) {
std::string cell_string;
Cell *cell = f.get_cell( y, x );
bool different = false;
char curmove[ 32 ];
snprintf( curmove, 32, "\033[%d;%dH", y + 1, x + 1 );
cell_string.append( curmove );
/* have renditions changed? */
if ( (!initialized)
|| (cell->renditions != last_frame.get_cell( y, x )->renditions) ) {
different = true;
}
std::vector<int> cell_print_renditions;
cell_print_renditions = cell->renditions;
cell_print_renditions.insert( cell_print_renditions.begin(), 0 );
if ( cell_print_renditions != current_renditions ) {
/* print renditions */
cell_string.append( "\033[0" );
char rendition[ 32 ];
for ( std::vector<int>::iterator i = cell->renditions.begin();
i != cell->renditions.end();
i++ ) {
snprintf( rendition, 32, ";%d", *i );
cell_string.append( rendition );
}
cell_string.append( "m" );
}
/* clear cell */
cell_string.append( "\033[X" );
/* did fallback status change? */
if ( (!initialized)
|| (cell->fallback != last_frame.get_cell( y, x )->fallback) ) {
different = true;
}
/* cells that begin with combining character get combiner attached to no-break space */
if ( cell->fallback ) {
char utf8[ 8 ];
snprintf( utf8, 8, "%lc", 0xA0 );
cell_string.append( utf8 );
}
/* have cell contents changed? */
if ( (!initialized)
|| (cell->contents != last_frame.get_cell( y, x )->contents) ) {
different = true;
}
/* always restrike the cell contents if anything changed */
for ( std::vector<wchar_t>::iterator i = cell->contents.begin();
i != cell->contents.end();
i++ ) {
char utf8[ 8 ];
snprintf( utf8, 8, "%lc", *i );
cell_string.append( utf8 );
}
/* if anything changed, redo cell */
if ( different ) {
screen.append( cell_string );
cursor_was_moved = true;
current_renditions = cell_print_renditions;
}
x += cell->width;
}
}
/* has cursor location changed? */
if ( (!initialized)
|| (f.ds.get_cursor_row() != last_frame.ds.get_cursor_row())
|| (f.ds.get_cursor_col() != last_frame.ds.get_cursor_col())
|| cursor_was_moved ) {
char curmove[ 32 ];
snprintf( curmove, 32, "\033[%d;%dH", f.ds.get_cursor_row() + 1,
f.ds.get_cursor_col() + 1 );
screen.append( curmove );
}
/* 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;
}
+5 -1
View File
@@ -395,7 +395,7 @@ void DrawState::resize( int s_width, int s_height )
int DrawState::get_background_rendition( void ) int DrawState::get_background_rendition( void )
{ {
int color = 0; int color = -1;
for ( std::vector<int>::iterator i = renditions.begin(); for ( std::vector<int>::iterator i = renditions.begin();
i != renditions.end(); i != renditions.end();
i++ ) { i++ ) {
@@ -412,6 +412,10 @@ void Framebuffer::back_color_erase( void )
{ {
int bg_color = ds.get_background_rendition(); int bg_color = ds.get_background_rendition();
if ( bg_color < 0 ) {
return;
}
for ( int row = 0; row < ds.get_height(); row++ ) { for ( int row = 0; row < ds.get_height(); row++ ) {
for ( int col = 0; col < ds.get_width(); col++ ) { for ( int col = 0; col < ds.get_width(); col++ ) {
Cell *cell = get_cell( row, col ); Cell *cell = get_cell( row, col );