Isolated algorithmic improvements.
* Fix inefficient STL use around Parser::UTF8Parser. * Reduce typeid() usage, change some of it to a virtual method * Do multiple-line scrolls as a single move
This commit is contained in:
+6
-14
@@ -41,21 +41,19 @@
|
||||
const Parser::StateFamily Parser::family;
|
||||
|
||||
static void append_or_delete( Parser::Action *act,
|
||||
std::list<Parser::Action *> &vec )
|
||||
Parser::Actions &vec )
|
||||
{
|
||||
assert( act );
|
||||
|
||||
if ( typeid( *act ) != typeid( Parser::Ignore ) ) {
|
||||
if ( !act->ignore() ) {
|
||||
vec.push_back( act );
|
||||
} else {
|
||||
delete act;
|
||||
}
|
||||
}
|
||||
|
||||
std::list<Parser::Action *> Parser::Parser::input( wchar_t ch )
|
||||
void Parser::Parser::input( wchar_t ch, Actions &ret )
|
||||
{
|
||||
std::list<Action *> ret;
|
||||
|
||||
Transition tx = state->input( ch );
|
||||
|
||||
if ( tx.next_state != NULL ) {
|
||||
@@ -69,8 +67,6 @@ std::list<Parser::Action *> Parser::Parser::input( wchar_t ch )
|
||||
append_or_delete( tx.next_state->enter(), ret );
|
||||
state = tx.next_state;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Parser::UTF8Parser::UTF8Parser()
|
||||
@@ -80,7 +76,7 @@ Parser::UTF8Parser::UTF8Parser()
|
||||
buf[0] = '\0';
|
||||
}
|
||||
|
||||
std::list<Parser::Action *> Parser::UTF8Parser::input( char c )
|
||||
void Parser::UTF8Parser::input( char c, Actions &ret )
|
||||
{
|
||||
assert( buf_len < BUF_SIZE );
|
||||
|
||||
@@ -94,7 +90,6 @@ std::list<Parser::Action *> Parser::UTF8Parser::input( char c )
|
||||
|
||||
size_t total_bytes_parsed = 0;
|
||||
size_t orig_buf_len = buf_len;
|
||||
std::list<Action *> ret;
|
||||
|
||||
/* this routine is somewhat complicated in order to comply with
|
||||
Unicode 6.0, section 3.9, "Best Practices for using U+FFFD" */
|
||||
@@ -138,7 +133,7 @@ std::list<Parser::Action *> Parser::UTF8Parser::input( char c )
|
||||
/* Cast to unsigned for checks, because some
|
||||
platforms (e.g. ARM) use uint32_t as wchar_t,
|
||||
causing compiler warning on "pwc > 0" check. */
|
||||
uint64_t pwcheck = pwc;
|
||||
const uint32_t pwcheck = pwc;
|
||||
|
||||
if ( pwcheck > 0x10FFFF ) { /* outside Unicode range */
|
||||
pwc = (wchar_t) 0xFFFD;
|
||||
@@ -153,13 +148,10 @@ std::list<Parser::Action *> Parser::UTF8Parser::input( char c )
|
||||
pwc = (wchar_t) 0xFFFD;
|
||||
}
|
||||
|
||||
std::list<Action *> vec = parser.input( pwc );
|
||||
ret.insert( ret.end(), vec.begin(), vec.end() );
|
||||
parser.input( pwc, ret );
|
||||
|
||||
total_bytes_parsed += bytes_parsed;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Parser::Parser::Parser( const Parser &other )
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
http://www.vt100.net/emu/dec_ansi_parser */
|
||||
|
||||
#include <wchar.h>
|
||||
#include <list>
|
||||
#include <string.h>
|
||||
|
||||
#include "parsertransition.h"
|
||||
@@ -59,7 +58,7 @@ namespace Parser {
|
||||
Parser & operator=( const Parser & );
|
||||
~Parser() {}
|
||||
|
||||
std::list<Action *> input( wchar_t ch );
|
||||
void input( wchar_t ch, Actions &actions );
|
||||
|
||||
bool operator==( const Parser &x ) const
|
||||
{
|
||||
@@ -81,7 +80,7 @@ namespace Parser {
|
||||
public:
|
||||
UTF8Parser();
|
||||
|
||||
std::list<Action *> input( char c );
|
||||
void input( char c, Actions &actions );
|
||||
|
||||
bool operator==( const UTF8Parser &x ) const
|
||||
{
|
||||
|
||||
@@ -43,9 +43,9 @@ std::string Action::str( void )
|
||||
char thechar[ 10 ] = { 0 };
|
||||
if ( char_present ) {
|
||||
if ( iswprint( ch ) )
|
||||
snprintf( thechar, 10, "(%lc)", (wint_t)ch );
|
||||
snprintf( thechar, 10, "(%lc)", static_cast<wint_t>(ch) );
|
||||
else
|
||||
snprintf( thechar, 10, "(0x%x)", (unsigned int)ch );
|
||||
snprintf( thechar, 10, "(0x%x)", static_cast<unsigned int>(ch) );
|
||||
}
|
||||
|
||||
return name() + std::string( thechar );
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define PARSERACTION_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Terminal {
|
||||
class Emulator;
|
||||
@@ -43,8 +44,8 @@ namespace Parser {
|
||||
class Action
|
||||
{
|
||||
public:
|
||||
bool char_present;
|
||||
wchar_t ch;
|
||||
bool char_present;
|
||||
mutable bool handled;
|
||||
|
||||
std::string str( void );
|
||||
@@ -53,14 +54,20 @@ namespace Parser {
|
||||
|
||||
virtual void act_on_terminal( Terminal::Emulator * ) const {};
|
||||
|
||||
Action() : char_present( false ), ch( -1 ), handled( false ) {};
|
||||
virtual bool ignore() const { return false; }
|
||||
|
||||
Action() : ch( -1 ), char_present( false ), handled( false ) {};
|
||||
virtual ~Action() {};
|
||||
|
||||
virtual bool operator==( const Action &other ) const;
|
||||
};
|
||||
|
||||
typedef std::vector<Action *> Actions;
|
||||
|
||||
class Ignore : public Action {
|
||||
public: std::string name( void ) { return std::string( "Ignore" ); }
|
||||
public:
|
||||
std::string name( void ) { return std::string( "Ignore" ); }
|
||||
bool ignore() const { return true; }
|
||||
};
|
||||
class Print : public Action {
|
||||
public:
|
||||
|
||||
@@ -78,18 +78,12 @@ Framebuffer::Framebuffer( int s_width, int s_height )
|
||||
void Framebuffer::scroll( int N )
|
||||
{
|
||||
if ( N >= 0 ) {
|
||||
for ( int i = 0; i < N; i++ ) {
|
||||
delete_line( ds.get_scrolling_region_top_row() );
|
||||
ds.move_row( -1, true );
|
||||
}
|
||||
delete_line( ds.get_scrolling_region_top_row(), N );
|
||||
ds.move_row( -N, true );
|
||||
} else {
|
||||
N = -N;
|
||||
|
||||
for ( int i = 0; i < N; i++ ) {
|
||||
rows.insert( rows.begin() + ds.get_scrolling_region_top_row(), newrow() );
|
||||
rows.erase( rows.begin() + ds.get_scrolling_region_bottom_row() + 1 );
|
||||
ds.move_row( 1, true );
|
||||
}
|
||||
insert_line( ds.get_scrolling_region_top_row(), N );
|
||||
ds.move_row( N, true );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,32 +252,62 @@ void DrawState::restore_cursor( void )
|
||||
new_grapheme();
|
||||
}
|
||||
|
||||
void Framebuffer::insert_line( int before_row )
|
||||
void Framebuffer::insert_line( int before_row, int count )
|
||||
{
|
||||
if ( (before_row < ds.get_scrolling_region_top_row())
|
||||
|| (before_row > ds.get_scrolling_region_bottom_row() + 1) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
rows.insert( rows.begin() + before_row, newrow() );
|
||||
rows.erase( rows.begin() + ds.get_scrolling_region_bottom_row() + 1 );
|
||||
int max_scroll = ds.get_scrolling_region_bottom_row() + 1 - before_row;
|
||||
if ( count > max_scroll ) {
|
||||
count = max_scroll;
|
||||
}
|
||||
|
||||
if ( count == 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// delete old rows
|
||||
rows_type::iterator start = rows.begin() + ds.get_scrolling_region_bottom_row() + 1 - count;
|
||||
rows.erase( start, start + count );
|
||||
// insert a block of dummy rows
|
||||
start = rows.begin() + before_row;
|
||||
rows.insert( start, count, Row( 0, 0 ) );
|
||||
// then replace with real new rows
|
||||
start = rows.begin() + before_row;
|
||||
for (rows_type::iterator i = start; i < start + count; i++) {
|
||||
*i = newrow();
|
||||
}
|
||||
}
|
||||
|
||||
void Framebuffer::delete_line( int row )
|
||||
void Framebuffer::delete_line( int row, int count )
|
||||
{
|
||||
if ( (row < ds.get_scrolling_region_top_row())
|
||||
|| (row > ds.get_scrolling_region_bottom_row()) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
int insertbefore = ds.get_scrolling_region_bottom_row() + 1;
|
||||
if ( insertbefore == ds.get_height() ) {
|
||||
rows.push_back( newrow() );
|
||||
} else {
|
||||
rows.insert( rows.begin() + insertbefore, newrow() );
|
||||
int max_scroll = ds.get_scrolling_region_bottom_row() + 1 - row;
|
||||
if ( count > max_scroll ) {
|
||||
count = max_scroll;
|
||||
}
|
||||
|
||||
rows.erase( rows.begin() + row );
|
||||
if ( count == 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// delete old rows
|
||||
rows_type::iterator start = rows.begin() + row;
|
||||
rows.erase( start, start + count );
|
||||
// insert a block of dummy rows
|
||||
start = rows.begin() + ds.get_scrolling_region_bottom_row() + 1 - count;
|
||||
rows.insert( start, count, Row( 0, 0 ) );
|
||||
// then replace with real new rows
|
||||
start = rows.begin() + ds.get_scrolling_region_bottom_row() + 1 - count;
|
||||
for (rows_type::iterator i = start; i < start + count; i++) {
|
||||
*i = newrow();
|
||||
}
|
||||
}
|
||||
|
||||
void Row::insert_cell( int col, int background_color )
|
||||
|
||||
@@ -326,8 +326,8 @@ namespace Terminal {
|
||||
|
||||
void apply_renditions_to_current_cell( void );
|
||||
|
||||
void insert_line( int before_row );
|
||||
void delete_line( int row );
|
||||
void insert_line( int before_row, int count );
|
||||
void delete_line( int row, int count );
|
||||
|
||||
void insert_cell( int row, int col );
|
||||
void delete_cell( int row, int col );
|
||||
|
||||
@@ -441,9 +441,7 @@ static void CSI_IL( Framebuffer *fb, Dispatcher *dispatch )
|
||||
{
|
||||
int lines = dispatch->getparam( 0, 1 );
|
||||
|
||||
for ( int i = 0; i < lines; i++ ) {
|
||||
fb->insert_line( fb->ds.get_cursor_row() );
|
||||
}
|
||||
fb->insert_line( fb->ds.get_cursor_row(), lines );
|
||||
|
||||
/* vt220 manual and Ecma-48 say to move to first column */
|
||||
/* but xterm and gnome-terminal don't */
|
||||
@@ -457,9 +455,7 @@ static void CSI_DL( Framebuffer *fb, Dispatcher *dispatch )
|
||||
{
|
||||
int lines = dispatch->getparam( 0, 1 );
|
||||
|
||||
for ( int i = 0; i < lines; i++ ) {
|
||||
fb->delete_line( fb->ds.get_cursor_row() );
|
||||
}
|
||||
fb->delete_line( fb->ds.get_cursor_row(), lines );
|
||||
|
||||
/* same story -- xterm and gnome-terminal don't
|
||||
move to first column */
|
||||
|
||||
Reference in New Issue
Block a user