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:
John Hood
2014-06-14 19:16:13 -04:00
parent 8fdcdc88cd
commit 32afa96111
10 changed files with 195 additions and 164 deletions
+7 -7
View File
@@ -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
+3 -3
View File
@@ -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() {}
+1 -2
View File
@@ -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;
+2 -3
View File
@@ -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 );
} }
+31 -27
View File
@@ -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 );
}
+5 -9
View File
@@ -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 );
}; };
+1 -1
View File
@@ -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;
+65 -38
View File
@@ -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];
} }
} }
+78 -72
View File
@@ -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 );
+1 -1
View File
@@ -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 ); }