Change Framebuffer's containers/methods to improve performance.
* Reduce the size of Terminal::Cell. * Change colors and attributes in Terminal::Rendition to bitfields/bitmask. * Change Cells to use UTF-8 strings instead of vector<wchar_t>. Store Rows in a vector instead of a deque. * Add various Framebuffer::append() methods for more efficient passing of single and repeated characters. * Change title/icon strings from deques to a vector typedef-- this is more for tidiness than any real performance.
This commit is contained in:
@@ -61,15 +61,15 @@ void ConditionalOverlayCell::apply( Framebuffer &fb, uint64_t confirmed_epoch, i
|
|||||||
|
|
||||||
if ( unknown ) {
|
if ( unknown ) {
|
||||||
if ( flag && ( col != fb.ds.get_width() - 1 ) ) {
|
if ( flag && ( col != fb.ds.get_width() - 1 ) ) {
|
||||||
fb.get_mutable_cell( row, col )->renditions.underlined = true;
|
fb.get_mutable_cell( row, col )->renditions.set_attribute(Renditions::underlined, true);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !(*(fb.get_cell( row, col )) == replacement) ) {
|
if ( *fb.get_cell( row, col ) != replacement ) {
|
||||||
*(fb.get_mutable_cell( row, col )) = replacement;
|
*(fb.get_mutable_cell( row, col )) = replacement;
|
||||||
if ( flag ) {
|
if ( flag ) {
|
||||||
fb.get_mutable_cell( row, col )->renditions.underlined = true;
|
fb.get_mutable_cell( row, col )->renditions.set_attribute( Renditions::underlined, true );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -275,7 +275,7 @@ void NotificationEngine::apply( Framebuffer &fb ) const
|
|||||||
case 2: /* wide character */
|
case 2: /* wide character */
|
||||||
this_cell = fb.get_mutable_cell( 0, overlay_col );
|
this_cell = fb.get_mutable_cell( 0, overlay_col );
|
||||||
fb.reset_cell( this_cell );
|
fb.reset_cell( this_cell );
|
||||||
this_cell->renditions.bold = true;
|
this_cell->renditions.set_attribute(Renditions::bold, true);
|
||||||
this_cell->renditions.foreground_color = 37;
|
this_cell->renditions.foreground_color = 37;
|
||||||
this_cell->renditions.background_color = 44;
|
this_cell->renditions.background_color = 44;
|
||||||
|
|
||||||
@@ -296,7 +296,7 @@ void NotificationEngine::apply( Framebuffer &fb ) const
|
|||||||
overlay_col++;
|
overlay_col++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( combining_cell->contents.size() < 16 ) {
|
if ( combining_cell->contents.size() < 32 ) {
|
||||||
combining_cell->contents.push_back( ch );
|
combining_cell->contents.push_back( ch );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -345,9 +345,9 @@ void OverlayManager::apply( Framebuffer &fb )
|
|||||||
title.apply( fb );
|
title.apply( fb );
|
||||||
}
|
}
|
||||||
|
|
||||||
void TitleEngine::set_prefix( const wstring s )
|
void TitleEngine::set_prefix( const wstring &s )
|
||||||
{
|
{
|
||||||
prefix = deque<wchar_t>( s.begin(), s.end() );
|
prefix = Terminal::Framebuffer::title_type( s.begin(), s.end() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConditionalOverlayRow::apply( Framebuffer &fb, uint64_t confirmed_epoch, bool flag ) const
|
void ConditionalOverlayRow::apply( Framebuffer &fb, uint64_t confirmed_epoch, bool flag ) const
|
||||||
|
|||||||
@@ -310,12 +310,12 @@ namespace Overlay {
|
|||||||
|
|
||||||
class TitleEngine {
|
class TitleEngine {
|
||||||
private:
|
private:
|
||||||
deque<wchar_t> prefix;
|
Terminal::Framebuffer::title_type prefix;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void apply( Framebuffer &fb ) const { fb.prefix_window_title( prefix ); }
|
void apply( Framebuffer &fb ) const { fb.prefix_window_title( prefix ); }
|
||||||
void set_prefix( const wstring s );
|
|
||||||
TitleEngine() : prefix() {}
|
TitleEngine() : prefix() {}
|
||||||
|
void set_prefix( const wstring &s );
|
||||||
};
|
};
|
||||||
|
|
||||||
/* the overlay manager */
|
/* the overlay manager */
|
||||||
@@ -331,7 +331,7 @@ namespace Overlay {
|
|||||||
NotificationEngine & get_notification_engine( void ) { return notifications; }
|
NotificationEngine & get_notification_engine( void ) { return notifications; }
|
||||||
PredictionEngine & get_prediction_engine( void ) { return predictions; }
|
PredictionEngine & get_prediction_engine( void ) { return predictions; }
|
||||||
|
|
||||||
void set_title_prefix( const wstring s ) { title.set_prefix( s ); }
|
void set_title_prefix( const wstring &s ) { title.set_prefix( s ); }
|
||||||
|
|
||||||
OverlayManager() : notifications(), predictions(), title() {}
|
OverlayManager() : notifications(), predictions(), title() {}
|
||||||
|
|
||||||
|
|||||||
@@ -85,8 +85,7 @@ void Parser::UTF8Parser::input( char c, Actions &ret )
|
|||||||
/* This function will only work in a UTF-8 locale. */
|
/* This function will only work in a UTF-8 locale. */
|
||||||
|
|
||||||
wchar_t pwc;
|
wchar_t pwc;
|
||||||
mbstate_t ps;
|
mbstate_t ps = mbstate_t();
|
||||||
memset( &ps, 0, sizeof( ps ) );
|
|
||||||
|
|
||||||
size_t total_bytes_parsed = 0;
|
size_t total_bytes_parsed = 0;
|
||||||
size_t orig_buf_len = buf_len;
|
size_t orig_buf_len = buf_len;
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ void Emulator::print( const Parser::Print *act )
|
|||||||
this_cell = fb.get_mutable_cell();
|
this_cell = fb.get_mutable_cell();
|
||||||
|
|
||||||
fb.reset_cell( this_cell );
|
fb.reset_cell( this_cell );
|
||||||
this_cell->contents.push_back( act->ch );
|
this_cell->append( act->ch );
|
||||||
this_cell->width = chwidth;
|
this_cell->width = chwidth;
|
||||||
fb.apply_renditions_to_current_cell();
|
fb.apply_renditions_to_current_cell();
|
||||||
|
|
||||||
@@ -127,8 +127,7 @@ void Emulator::print( const Parser::Print *act )
|
|||||||
combining_cell->fallback = true;
|
combining_cell->fallback = true;
|
||||||
fb.ds.move_col( 1, true, true );
|
fb.ds.move_col( 1, true, true );
|
||||||
}
|
}
|
||||||
|
if ( combining_cell->contents.size() < 32 ) {
|
||||||
if ( combining_cell->contents.size() < 16 ) {
|
|
||||||
/* seems like a reasonable limit on combining characters */
|
/* seems like a reasonable limit on combining characters */
|
||||||
combining_cell->contents.push_back( act->ch );
|
combining_cell->contents.push_back( act->ch );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "terminaldisplay.h"
|
#include "terminaldisplay.h"
|
||||||
|
#include "terminalframebuffer.h"
|
||||||
|
|
||||||
using namespace Terminal;
|
using namespace Terminal;
|
||||||
|
|
||||||
@@ -65,7 +66,7 @@ std::string Display::new_frame( bool initialized, const Framebuffer &last, const
|
|||||||
|
|
||||||
/* has bell been rung? */
|
/* has bell been rung? */
|
||||||
if ( f.get_bell_count() != frame.last_frame.get_bell_count() ) {
|
if ( f.get_bell_count() != frame.last_frame.get_bell_count() ) {
|
||||||
frame.append( "\x07" );
|
frame.append( '\007' );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* has icon name or window title changed? */
|
/* has icon name or window title changed? */
|
||||||
@@ -73,40 +74,38 @@ std::string Display::new_frame( bool initialized, const Framebuffer &last, const
|
|||||||
( (!initialized)
|
( (!initialized)
|
||||||
|| (f.get_icon_name() != frame.last_frame.get_icon_name())
|
|| (f.get_icon_name() != frame.last_frame.get_icon_name())
|
||||||
|| (f.get_window_title() != frame.last_frame.get_window_title()) ) ) {
|
|| (f.get_window_title() != frame.last_frame.get_window_title()) ) ) {
|
||||||
|
typedef Terminal::Framebuffer::title_type title_type;
|
||||||
/* set icon name and window title */
|
/* set icon name and window title */
|
||||||
if ( f.get_icon_name() == f.get_window_title() ) {
|
if ( f.get_icon_name() == f.get_window_title() ) {
|
||||||
/* write combined Icon Name and Window Title */
|
/* write combined Icon Name and Window Title */
|
||||||
frame.append( "\033]0;" );
|
frame.append( "\033]0;" );
|
||||||
const std::deque<wchar_t> &window_title( f.get_window_title() );
|
const title_type &window_title( f.get_window_title() );
|
||||||
for ( std::deque<wchar_t>::const_iterator i = window_title.begin();
|
for ( title_type::const_iterator i = window_title.begin();
|
||||||
i != window_title.end();
|
i != window_title.end();
|
||||||
i++ ) {
|
i++ ) {
|
||||||
snprintf( tmp, 64, "%lc", (wint_t)*i );
|
frame.append( *i );
|
||||||
frame.append( tmp );
|
|
||||||
}
|
}
|
||||||
frame.append( "\007" );
|
frame.append( '\007' );
|
||||||
/* ST is more correct, but BEL more widely supported */
|
/* ST is more correct, but BEL more widely supported */
|
||||||
} else {
|
} else {
|
||||||
/* write Icon Name */
|
/* write Icon Name */
|
||||||
frame.append( "\033]1;" );
|
frame.append( "\033]1;" );
|
||||||
const std::deque<wchar_t> &icon_name( f.get_icon_name() );
|
const title_type &icon_name( f.get_icon_name() );
|
||||||
for ( std::deque<wchar_t>::const_iterator i = icon_name.begin();
|
for ( title_type::const_iterator i = icon_name.begin();
|
||||||
i != icon_name.end();
|
i != icon_name.end();
|
||||||
i++ ) {
|
i++ ) {
|
||||||
snprintf( tmp, 64, "%lc", (wint_t)*i );
|
frame.append( *i );
|
||||||
frame.append( tmp );
|
|
||||||
}
|
}
|
||||||
frame.append( "\007" );
|
frame.append( '\007' );
|
||||||
|
|
||||||
frame.append( "\033]2;" );
|
frame.append( "\033]2;" );
|
||||||
const std::deque<wchar_t> &window_title( f.get_window_title() );
|
const title_type &window_title( f.get_window_title() );
|
||||||
for ( std::deque<wchar_t>::const_iterator i = window_title.begin();
|
for ( title_type::const_iterator i = window_title.begin();
|
||||||
i != window_title.end();
|
i != window_title.end();
|
||||||
i++ ) {
|
i++ ) {
|
||||||
snprintf( tmp, 64, "%lc", (wint_t)*i );
|
frame.append( *i );
|
||||||
frame.append( tmp );
|
|
||||||
}
|
}
|
||||||
frame.append( "\007" );
|
frame.append( '\007' );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -192,7 +191,7 @@ std::string Display::new_frame( bool initialized, const Framebuffer &last, const
|
|||||||
|
|
||||||
/* scroll */
|
/* scroll */
|
||||||
for ( int i = 0; i < lines_scrolled; i++ ) {
|
for ( int i = 0; i < lines_scrolled; i++ ) {
|
||||||
frame.append( "\n" );
|
frame.append( '\n' );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* do the move in memory */
|
/* do the move in memory */
|
||||||
@@ -285,7 +284,7 @@ std::string Display::new_frame( bool initialized, const Framebuffer &last, const
|
|||||||
/* have renditions changed? */
|
/* have renditions changed? */
|
||||||
if ( (!initialized)
|
if ( (!initialized)
|
||||||
|| !(f.ds.get_renditions() == frame.current_rendition) ) {
|
|| !(f.ds.get_renditions() == frame.current_rendition) ) {
|
||||||
frame.appendstring( f.ds.get_renditions().sgr() );
|
frame.append( f.ds.get_renditions().sgr() );
|
||||||
frame.current_rendition = f.ds.get_renditions();
|
frame.current_rendition = f.ds.get_renditions();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -359,7 +358,7 @@ void Display::put_cell( bool initialized, FrameState &frame, const Framebuffer &
|
|||||||
|
|
||||||
if ( !(frame.current_rendition == cell->renditions) ) {
|
if ( !(frame.current_rendition == cell->renditions) ) {
|
||||||
/* print renditions */
|
/* print renditions */
|
||||||
frame.appendstring( cell->renditions.sgr() );
|
frame.append( cell->renditions.sgr() );
|
||||||
frame.current_rendition = cell->renditions;
|
frame.current_rendition = cell->renditions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,7 +380,7 @@ void Display::put_cell( bool initialized, FrameState &frame, const Framebuffer &
|
|||||||
bool can_use_erase = has_bce || (cell->renditions == initial_rendition());
|
bool can_use_erase = has_bce || (cell->renditions == initial_rendition());
|
||||||
|
|
||||||
if ( frame.force_next_put ) {
|
if ( frame.force_next_put ) {
|
||||||
frame.append( " " );
|
frame.append( ' ' );
|
||||||
frame.cursor_x++;
|
frame.cursor_x++;
|
||||||
frame.x++;
|
frame.x++;
|
||||||
frame.force_next_put = false;
|
frame.force_next_put = false;
|
||||||
@@ -404,7 +403,7 @@ void Display::put_cell( bool initialized, FrameState &frame, const Framebuffer &
|
|||||||
frame.x += clear_count;
|
frame.x += clear_count;
|
||||||
} else { /* no ECH, so just print a space */
|
} else { /* no ECH, so just print a space */
|
||||||
/* unlike erases, this will use background color irrespective of BCE */
|
/* unlike erases, this will use background color irrespective of BCE */
|
||||||
frame.append( " " );
|
frame.append( ' ' );
|
||||||
frame.cursor_x++;
|
frame.cursor_x++;
|
||||||
frame.x++;
|
frame.x++;
|
||||||
}
|
}
|
||||||
@@ -418,12 +417,7 @@ void Display::put_cell( bool initialized, FrameState &frame, const Framebuffer &
|
|||||||
frame.append( "\xC2\xA0" );
|
frame.append( "\xC2\xA0" );
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( std::vector<wchar_t>::const_iterator i = cell->contents.begin();
|
frame.append( cell->contents );
|
||||||
i != cell->contents.end();
|
|
||||||
i++ ) {
|
|
||||||
snprintf( tmp, 64, "%lc", (wint_t)*i );
|
|
||||||
frame.append( tmp );
|
|
||||||
}
|
|
||||||
|
|
||||||
frame.x += cell->width;
|
frame.x += cell->width;
|
||||||
frame.cursor_x += cell->width;
|
frame.cursor_x += cell->width;
|
||||||
@@ -446,3 +440,13 @@ void FrameState::append_silent_move( int y, int x )
|
|||||||
cursor_x = x;
|
cursor_x = x;
|
||||||
cursor_y = y;
|
cursor_y = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FrameState::FrameState( const Framebuffer &s_last )
|
||||||
|
: x(0), y(0),
|
||||||
|
force_next_put( false ),
|
||||||
|
str(), cursor_x(0), cursor_y(0), current_rendition( 0 ),
|
||||||
|
last_frame( s_last )
|
||||||
|
{
|
||||||
|
/* just a guess-- doesn't matter for correctness */
|
||||||
|
str.reserve( last_frame.ds.get_width() * last_frame.ds.get_height() * 4 );
|
||||||
|
}
|
||||||
|
|||||||
@@ -48,17 +48,13 @@ namespace Terminal {
|
|||||||
|
|
||||||
Framebuffer last_frame;
|
Framebuffer last_frame;
|
||||||
|
|
||||||
FrameState( const Framebuffer &s_last )
|
FrameState( const Framebuffer &s_last );
|
||||||
: x(0), y(0),
|
|
||||||
force_next_put( false ),
|
|
||||||
str(), cursor_x(0), cursor_y(0), current_rendition( 0 ),
|
|
||||||
last_frame( s_last )
|
|
||||||
{
|
|
||||||
str.reserve( 1024 );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
void append( const char c ) { str.append( 1, c ); }
|
||||||
|
void append( const wchar_t wc ) { Cell::append_to_str( str, wc ); }
|
||||||
void append( const char * s ) { str.append( s ); }
|
void append( const char * s ) { str.append( s ); }
|
||||||
void appendstring( const std::string &s ) { str.append( s ); }
|
void append( const Cell::content_type &contents ) { str.append( contents.begin(), contents.end() ); }
|
||||||
|
void append_string( const std::string &append ) { str.append(append); }
|
||||||
|
|
||||||
void append_silent_move( int y, int x );
|
void append_silent_move( int y, int x );
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ const char *Display::ti_str( const char *capname )
|
|||||||
}
|
}
|
||||||
|
|
||||||
Display::Display( bool use_environment )
|
Display::Display( bool use_environment )
|
||||||
: has_ech( true ), has_bce( true ), has_title( true ), posterize_colors( false ), smcup( NULL ), rmcup( NULL )
|
: has_ech( true ), has_bce( true ), has_title( true ), posterize_colors( 0 ), smcup( NULL ), rmcup( NULL )
|
||||||
{
|
{
|
||||||
if ( use_environment ) {
|
if ( use_environment ) {
|
||||||
int errret = -2;
|
int errret = -2;
|
||||||
|
|||||||
@@ -32,17 +32,37 @@
|
|||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "terminalframebuffer.h"
|
#include "terminalframebuffer.h"
|
||||||
|
|
||||||
using namespace Terminal;
|
using namespace Terminal;
|
||||||
|
|
||||||
void Cell::reset( int background_color )
|
Cell::Cell( color_type background_color )
|
||||||
|
: contents(),
|
||||||
|
renditions( background_color ),
|
||||||
|
width( 1 ),
|
||||||
|
fallback( false ),
|
||||||
|
wrap( false )
|
||||||
|
{}
|
||||||
|
#if 0
|
||||||
|
Cell::Cell() /* default constructor required by C++11 STL */
|
||||||
|
: contents(),
|
||||||
|
renditions( 0 ),
|
||||||
|
width( 1 ),
|
||||||
|
fallback( false ),
|
||||||
|
wrap( false )
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void Cell::reset( color_type background_color )
|
||||||
{
|
{
|
||||||
contents.clear();
|
contents.clear();
|
||||||
fallback = false;
|
|
||||||
width = 1;
|
|
||||||
renditions = Renditions( background_color );
|
renditions = Renditions( background_color );
|
||||||
|
width = 1;
|
||||||
|
fallback = false;
|
||||||
wrap = false;
|
wrap = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,13 +330,25 @@ void Framebuffer::delete_line( int row, int count )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Row::insert_cell( int col, int background_color )
|
Row::Row( size_t s_width, color_type background_color )
|
||||||
|
: cells( s_width, Cell( background_color ) )
|
||||||
|
{}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
Row::Row() /* default constructor required by C++11 STL */
|
||||||
|
: cells( 1, Cell() )
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void Row::insert_cell( int col, color_type background_color )
|
||||||
{
|
{
|
||||||
cells.insert( cells.begin() + col, Cell( background_color ) );
|
cells.insert( cells.begin() + col, Cell( background_color ) );
|
||||||
cells.pop_back();
|
cells.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Row::delete_cell( int col, int background_color )
|
void Row::delete_cell( int col, color_type background_color )
|
||||||
{
|
{
|
||||||
cells.push_back( Cell( background_color ) );
|
cells.push_back( Cell( background_color ) );
|
||||||
cells.erase( cells.begin() + col );
|
cells.erase( cells.begin() + col );
|
||||||
@@ -336,7 +368,7 @@ void Framebuffer::reset( void )
|
|||||||
{
|
{
|
||||||
int width = ds.get_width(), height = ds.get_height();
|
int width = ds.get_width(), height = ds.get_height();
|
||||||
ds = DrawState( width, height );
|
ds = DrawState( width, height );
|
||||||
rows = std::deque<Row>( height, newrow() );
|
rows = rows_type( height, newrow() );
|
||||||
window_title.clear();
|
window_title.clear();
|
||||||
/* do not reset bell_count */
|
/* do not reset bell_count */
|
||||||
}
|
}
|
||||||
@@ -412,17 +444,16 @@ void DrawState::resize( int s_width, int s_height )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Renditions::Renditions( int s_background )
|
Renditions::Renditions( color_type s_background )
|
||||||
: bold( false ), italic( false ), underlined( false ), blink( false ),
|
: foreground_color( 0 ), background_color( s_background ),
|
||||||
inverse( false ), invisible( false ), foreground_color( 0 ),
|
attributes( 0 )
|
||||||
background_color( s_background )
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/* This routine cannot be used to set a color beyond the 16-color set. */
|
/* This routine cannot be used to set a color beyond the 16-color set. */
|
||||||
void Renditions::set_rendition( int num )
|
void Renditions::set_rendition( color_type num )
|
||||||
{
|
{
|
||||||
if ( num == 0 ) {
|
if ( num == 0 ) {
|
||||||
bold = italic = underlined = blink = inverse = invisible = false;
|
clear_attributes();
|
||||||
foreground_color = background_color = 0;
|
foreground_color = background_color = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -449,13 +480,14 @@ void Renditions::set_rendition( int num )
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool value = num < 9;
|
||||||
switch ( num ) {
|
switch ( num ) {
|
||||||
case 1: case 22: bold = (num == 1); break;
|
case 1: case 22: set_attribute(bold, value); break;
|
||||||
case 3: case 23: italic = (num == 3); break;
|
case 3: case 23: set_attribute(italic, value); break;
|
||||||
case 4: case 24: underlined = (num == 4); break;
|
case 4: case 24: set_attribute(underlined, value); break;
|
||||||
case 5: case 25: blink = (num == 5); break;
|
case 5: case 25: set_attribute(blink, value); break;
|
||||||
case 7: case 27: inverse = (num == 7); break;
|
case 7: case 27: set_attribute(inverse, value); break;
|
||||||
case 8: case 28: invisible = (num == 8); break;
|
case 8: case 28: set_attribute(invisible, value); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -478,12 +510,12 @@ std::string Renditions::sgr( void ) const
|
|||||||
std::string ret;
|
std::string ret;
|
||||||
|
|
||||||
ret.append( "\033[0" );
|
ret.append( "\033[0" );
|
||||||
if ( bold ) ret.append( ";1" );
|
if ( get_attribute( bold ) ) ret.append( ";1" );
|
||||||
if ( italic ) ret.append( ";3" );
|
if ( get_attribute( italic ) ) ret.append( ";3" );
|
||||||
if ( underlined ) ret.append( ";4" );
|
if ( get_attribute( underlined ) ) ret.append( ";4" );
|
||||||
if ( blink ) ret.append( ";5" );
|
if ( get_attribute( blink ) ) ret.append( ";5" );
|
||||||
if ( inverse ) ret.append( ";7" );
|
if ( get_attribute( inverse ) ) ret.append( ";7" );
|
||||||
if ( invisible ) ret.append( ";8" );
|
if ( get_attribute( invisible ) ) ret.append( ";8" );
|
||||||
|
|
||||||
if ( foreground_color
|
if ( foreground_color
|
||||||
&& (foreground_color <= 37) ) {
|
&& (foreground_color <= 37) ) {
|
||||||
@@ -570,7 +602,7 @@ void Renditions::posterize( void )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Row::reset( int background_color )
|
void Row::reset( color_type background_color )
|
||||||
{
|
{
|
||||||
for ( cells_type::iterator i = cells.begin();
|
for ( cells_type::iterator i = cells.begin();
|
||||||
i != cells.end();
|
i != cells.end();
|
||||||
@@ -579,22 +611,13 @@ void Row::reset( int background_color )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Framebuffer::prefix_window_title( const std::deque<wchar_t> &s )
|
void Framebuffer::prefix_window_title( const title_type &s )
|
||||||
{
|
{
|
||||||
if ( icon_name == window_title ) {
|
if ( icon_name == window_title ) {
|
||||||
/* preserve equivalence */
|
/* preserve equivalence */
|
||||||
for ( std::deque<wchar_t>::const_reverse_iterator i = s.rbegin();
|
icon_name.insert(icon_name.begin(), s.begin(), s.end() );
|
||||||
i != s.rend();
|
|
||||||
i++ ) {
|
|
||||||
icon_name.push_front( *i );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( std::deque<wchar_t>::const_reverse_iterator i = s.rbegin();
|
|
||||||
i != s.rend();
|
|
||||||
i++ ) {
|
|
||||||
window_title.push_front( *i );
|
|
||||||
}
|
}
|
||||||
|
window_title.insert(window_title.begin(), s.begin(), s.end() );
|
||||||
}
|
}
|
||||||
|
|
||||||
wint_t Cell::debug_contents( void ) const
|
wint_t Cell::debug_contents( void ) const
|
||||||
@@ -602,7 +625,11 @@ wint_t Cell::debug_contents( void ) const
|
|||||||
if ( contents.empty() ) {
|
if ( contents.empty() ) {
|
||||||
return '_';
|
return '_';
|
||||||
} else {
|
} else {
|
||||||
return contents.front();
|
/* very, very cheesy */
|
||||||
|
wchar_t ch[2];
|
||||||
|
const std::string chars( contents.begin(), contents.end() );
|
||||||
|
mbstowcs(ch, chars.c_str(), 1);
|
||||||
|
return ch[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,65 +33,68 @@
|
|||||||
#ifndef TERMINALFB_HPP
|
#ifndef TERMINALFB_HPP
|
||||||
#define TERMINALFB_HPP
|
#define TERMINALFB_HPP
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
/* Terminal framebuffer */
|
/* Terminal framebuffer */
|
||||||
|
|
||||||
namespace Terminal {
|
namespace Terminal {
|
||||||
|
typedef uint16_t color_type;
|
||||||
|
|
||||||
class Renditions {
|
class Renditions {
|
||||||
public:
|
public:
|
||||||
bool bold, italic, underlined, blink, inverse, invisible;
|
typedef enum { bold, faint, italic, underlined, blink, inverse, invisible, SIZE } attribute_type;
|
||||||
int foreground_color;
|
|
||||||
int background_color;
|
|
||||||
|
|
||||||
Renditions( int s_background );
|
// all together, a 32 bit word now...
|
||||||
|
unsigned int foreground_color : 12;
|
||||||
|
unsigned int background_color : 12;
|
||||||
|
private:
|
||||||
|
unsigned int attributes : 8;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Renditions( color_type s_background );
|
||||||
void set_foreground_color( int num );
|
void set_foreground_color( int num );
|
||||||
void set_background_color( int num );
|
void set_background_color( int num );
|
||||||
void set_rendition( int num );
|
void set_rendition( color_type num );
|
||||||
std::string sgr( void ) const;
|
std::string sgr( void ) const;
|
||||||
|
|
||||||
void posterize( void );
|
void posterize( void );
|
||||||
|
|
||||||
bool operator==( const Renditions &x ) const
|
bool operator==( const Renditions &x ) const
|
||||||
{
|
{
|
||||||
return (bold == x.bold) && (italic == x.italic) && (underlined == x.underlined)
|
return ( attributes == x.attributes )
|
||||||
&& (blink == x.blink) && (inverse == x.inverse)
|
&& ( foreground_color == x.foreground_color )
|
||||||
&& (invisible == x.invisible) && (foreground_color == x.foreground_color)
|
|
||||||
&& ( background_color == x.background_color );
|
&& ( background_color == x.background_color );
|
||||||
}
|
}
|
||||||
|
void set_attribute( attribute_type attr, bool val )
|
||||||
|
{
|
||||||
|
attributes = val ?
|
||||||
|
( attributes | (1 << attr) ) :
|
||||||
|
( attributes & ~(1 << attr) );
|
||||||
|
}
|
||||||
|
bool get_attribute( attribute_type attr ) const { return attributes & ( 1 << attr ); }
|
||||||
|
void clear_attributes() { attributes = 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class Cell {
|
class Cell {
|
||||||
public:
|
public:
|
||||||
std::vector<wchar_t> contents;
|
typedef std::string content_type; /* can be std::string, std::vector<uint8_t>, or __gnu_cxx::__vstring */
|
||||||
char fallback; /* first character is combining character */
|
content_type contents;
|
||||||
int width;
|
|
||||||
Renditions renditions;
|
Renditions renditions;
|
||||||
|
uint8_t width;
|
||||||
|
bool fallback; /* first character is combining character */
|
||||||
bool wrap; /* if last cell, wrap to next line */
|
bool wrap; /* if last cell, wrap to next line */
|
||||||
|
|
||||||
Cell( int background_color )
|
Cell( color_type background_color );
|
||||||
: contents(),
|
Cell(); /* default constructor required by C++11 STL */
|
||||||
fallback( false ),
|
|
||||||
width( 1 ),
|
|
||||||
renditions( background_color ),
|
|
||||||
wrap( false )
|
|
||||||
{}
|
|
||||||
|
|
||||||
Cell() /* default constructor required by C++11 STL */
|
void reset( color_type background_color );
|
||||||
: contents(),
|
|
||||||
fallback( false ),
|
|
||||||
width( 1 ),
|
|
||||||
renditions( 0 ),
|
|
||||||
wrap( false )
|
|
||||||
{
|
|
||||||
assert( false );
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset( int background_color );
|
|
||||||
|
|
||||||
bool operator==( const Cell &x ) const
|
bool operator==( const Cell &x ) const
|
||||||
{
|
{
|
||||||
@@ -102,13 +105,15 @@ namespace Terminal {
|
|||||||
&& (wrap == x.wrap) );
|
&& (wrap == x.wrap) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator!=( const Cell &x ) const { return !operator==( x ); }
|
||||||
|
|
||||||
wint_t debug_contents( void ) const;
|
wint_t debug_contents( void ) const;
|
||||||
|
|
||||||
bool is_blank( void ) const
|
bool is_blank( void ) const
|
||||||
{
|
{
|
||||||
return ( contents.empty()
|
return ( contents.empty()
|
||||||
|| ( (contents.size() == 1) && ( (contents.front() == 0x20)
|
|| contents == " "
|
||||||
|| (contents.front() == 0xA0) ) ) );
|
|| contents == "\xC2\xA0" );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool contents_match ( const Cell &other ) const
|
bool contents_match ( const Cell &other ) const
|
||||||
@@ -118,6 +123,26 @@ namespace Terminal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool compare( const Cell &other ) const;
|
bool compare( const Cell &other ) const;
|
||||||
|
|
||||||
|
static void append_to_str( std::string &dest, const wchar_t c )
|
||||||
|
{
|
||||||
|
static mbstate_t ps = mbstate_t();
|
||||||
|
char tmp[MB_LEN_MAX];
|
||||||
|
size_t ignore = wcrtomb(NULL, 0, &ps);
|
||||||
|
(void)ignore;
|
||||||
|
size_t len = wcrtomb(tmp, c, &ps);
|
||||||
|
dest.append( tmp, len );
|
||||||
|
}
|
||||||
|
|
||||||
|
void append( const wchar_t c )
|
||||||
|
{
|
||||||
|
static mbstate_t ps = mbstate_t();
|
||||||
|
char tmp[MB_LEN_MAX];
|
||||||
|
size_t ignore = wcrtomb(NULL, 0, &ps);
|
||||||
|
(void)ignore;
|
||||||
|
size_t len = wcrtomb(tmp, c, &ps);
|
||||||
|
contents.insert( contents.end(), tmp, tmp+len );
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Row {
|
class Row {
|
||||||
@@ -125,20 +150,13 @@ namespace Terminal {
|
|||||||
typedef std::vector<Cell> cells_type;
|
typedef std::vector<Cell> cells_type;
|
||||||
cells_type cells;
|
cells_type cells;
|
||||||
|
|
||||||
Row( size_t s_width, int background_color )
|
Row( size_t s_width, color_type background_color );
|
||||||
: cells( s_width, Cell( background_color ) )
|
Row(); /* default constructor required by C++11 STL */
|
||||||
{}
|
|
||||||
|
|
||||||
Row() /* default constructor required by C++11 STL */
|
void insert_cell( int col, color_type background_color );
|
||||||
: cells( 1, Cell() )
|
void delete_cell( int col, color_type background_color );
|
||||||
{
|
|
||||||
assert( false );
|
|
||||||
}
|
|
||||||
|
|
||||||
void insert_cell( int col, int background_color );
|
void reset( color_type background_color );
|
||||||
void delete_cell( int col, int background_color );
|
|
||||||
|
|
||||||
void reset( int background_color );
|
|
||||||
|
|
||||||
bool operator==( const Row &x ) const
|
bool operator==( const Row &x ) const
|
||||||
{
|
{
|
||||||
@@ -240,7 +258,7 @@ namespace Terminal {
|
|||||||
|
|
||||||
void set_foreground_color( int x ) { renditions.set_foreground_color( x ); }
|
void set_foreground_color( int x ) { renditions.set_foreground_color( x ); }
|
||||||
void set_background_color( int x ) { renditions.set_background_color( x ); }
|
void set_background_color( int x ) { renditions.set_background_color( x ); }
|
||||||
void add_rendition( int x ) { renditions.set_rendition( x ); }
|
void add_rendition( color_type x ) { renditions.set_rendition( x ); }
|
||||||
Renditions get_renditions( void ) const { return renditions; }
|
Renditions get_renditions( void ) const { return renditions; }
|
||||||
int get_background_rendition( void ) const { return renditions.background_color; }
|
int get_background_rendition( void ) const { return renditions.background_color; }
|
||||||
|
|
||||||
@@ -265,11 +283,14 @@ namespace Terminal {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class Framebuffer {
|
class Framebuffer {
|
||||||
|
public:
|
||||||
|
typedef std::vector<wchar_t> title_type;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::deque<Row> rows_type;
|
typedef std::vector<Row> rows_type;
|
||||||
rows_type rows;
|
rows_type rows;
|
||||||
std::deque<wchar_t> icon_name;
|
title_type icon_name;
|
||||||
std::deque<wchar_t> window_title;
|
title_type window_title;
|
||||||
unsigned int bell_count;
|
unsigned int bell_count;
|
||||||
bool title_initialized; /* true if the window title has been set via an OSC */
|
bool title_initialized; /* true if the window title has been set via an OSC */
|
||||||
|
|
||||||
@@ -289,12 +310,7 @@ namespace Terminal {
|
|||||||
return &rows[ row ];
|
return &rows[ row ];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const Cell *get_cell( void ) const
|
inline const Cell *get_cell( int row = -1, int col = -1 ) const
|
||||||
{
|
|
||||||
return &rows[ ds.get_cursor_row() ].cells[ ds.get_cursor_col() ];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const Cell *get_cell( int row, int col ) const
|
|
||||||
{
|
{
|
||||||
if ( row == -1 ) row = ds.get_cursor_row();
|
if ( row == -1 ) row = ds.get_cursor_row();
|
||||||
if ( col == -1 ) col = ds.get_cursor_col();
|
if ( col == -1 ) col = ds.get_cursor_col();
|
||||||
@@ -304,22 +320,12 @@ namespace Terminal {
|
|||||||
|
|
||||||
Row *get_mutable_row( int row )
|
Row *get_mutable_row( int row )
|
||||||
{
|
{
|
||||||
if ( row == -1 ) row = ds.get_cursor_row();
|
return const_cast<Row *>(get_row( row ));
|
||||||
|
|
||||||
return &rows[ row ];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Cell *get_mutable_cell( void )
|
inline Cell *get_mutable_cell( int row = -1, int col = -1 )
|
||||||
{
|
{
|
||||||
return &rows[ ds.get_cursor_row() ].cells[ ds.get_cursor_col() ];
|
return const_cast<Cell *>(get_cell( row, col ));
|
||||||
}
|
|
||||||
|
|
||||||
inline Cell *get_mutable_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 *get_combining_cell( void );
|
Cell *get_combining_cell( void );
|
||||||
@@ -337,12 +343,12 @@ namespace Terminal {
|
|||||||
|
|
||||||
void set_title_initialized( void ) { title_initialized = true; }
|
void set_title_initialized( void ) { title_initialized = true; }
|
||||||
bool is_title_initialized( void ) const { return title_initialized; }
|
bool is_title_initialized( void ) const { return title_initialized; }
|
||||||
void set_icon_name( const std::deque<wchar_t> &s ) { icon_name = s; }
|
void set_icon_name( const title_type &s ) { icon_name = s; }
|
||||||
void set_window_title( const std::deque<wchar_t> &s ) { window_title = s; }
|
void set_window_title( const title_type &s ) { window_title = s; }
|
||||||
const std::deque<wchar_t> & get_icon_name( void ) const { return icon_name; }
|
const title_type & get_icon_name( void ) const { return icon_name; }
|
||||||
const std::deque<wchar_t> & get_window_title( void ) const { return window_title; }
|
const title_type & get_window_title( void ) const { return window_title; }
|
||||||
|
|
||||||
void prefix_window_title( const std::deque<wchar_t> &s );
|
void prefix_window_title( const title_type &s );
|
||||||
|
|
||||||
void resize( int s_width, int s_height );
|
void resize( int s_width, int s_height );
|
||||||
|
|
||||||
|
|||||||
@@ -559,7 +559,7 @@ void Dispatcher::OSC_dispatch( const Parser::OSC_End *act, Framebuffer *fb )
|
|||||||
bool set_title = (cmd_num == 0 || cmd_num == 2);
|
bool set_title = (cmd_num == 0 || cmd_num == 2);
|
||||||
if ( set_icon || set_title ) {
|
if ( set_icon || set_title ) {
|
||||||
fb->set_title_initialized();
|
fb->set_title_initialized();
|
||||||
std::deque<wchar_t> newtitle( OSC_string.begin() + offset, OSC_string.end() );
|
Terminal::Framebuffer::title_type newtitle( OSC_string.begin() + offset, OSC_string.end() );
|
||||||
if ( set_icon ) { fb->set_icon_name( newtitle ); }
|
if ( set_icon ) { fb->set_icon_name( newtitle ); }
|
||||||
if ( set_title ) { fb->set_window_title( newtitle ); }
|
if ( set_title ) { fb->set_window_title( newtitle ); }
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user