Reduce the character output by using character erase and character repeat

This commit is contained in:
Markus Gans 2016-12-15 23:11:34 +01:00
parent e4284615db
commit fedb5f64f3
11 changed files with 236 additions and 93 deletions

View File

@ -1,3 +1,7 @@
2016-12-15 Markus Gans <guru.mail@muenster.de>
* Reduce the character output by using character erase
and character repeat
2016-12-11 Markus Gans <guru.mail@muenster.de> 2016-12-11 Markus Gans <guru.mail@muenster.de>
* Accelerates text line drawing by clear with CSI sequences * Accelerates text line drawing by clear with CSI sequences
to begin or to end of the current line. to begin or to end of the current line.

View File

@ -79,24 +79,28 @@ printf(...)
║ │ resizeVTerm()║ ║ │ resizeVTerm()║
╚═══▼═══════════════════════════════════════════════════════╝ ╚═══▼═══════════════════════════════════════════════════════╝
│ putVTerm() ┌───────────────┐ │ putVTerm()
└───────────────────►│ output_buffer │ └──────────────────► updateTerminalLine(y)
updateTerminal() └───────┬───────┘ updateTerminal() │
│ flush_out() ┌───────────────┐
│ + │ output_buffer │
│ Fputchar(char) └───────────────┘
│ flush_out()
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ │ +
▌ ▐ │ Fputchar(char)
▌ screen ▐
▌ ───────────── ▐
▌ real terminal ▐ ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
▌ ▐ ▌ ▐
▀▀▀▀▀▀▀███▀▀▀▀▀▀▀ ▌ screen ▐
███ ▌ ───────────── ▐
▀▀▀▀▀▀▀▀▀ ▌ real terminal ▐
▌ ▐
▀▀▀▀▀▀▀███▀▀▀▀▀▀▀
███
▀▀▀▀▀▀▀▀▀
</pre> </pre>

View File

@ -30,22 +30,26 @@ printf(...)
║ │ resizeVTerm()║ ║ │ resizeVTerm()║
╚═══▼═══════════════════════════════════════════════════════╝ ╚═══▼═══════════════════════════════════════════════════════╝
│ putVTerm() ┌───────────────┐ │ putVTerm()
└───────────────────►│ output_buffer │ └──────────────────► updateTerminalLine(y)
updateTerminal() └───────┬───────┘ updateTerminal() │
│ flush_out() ┌───────────────┐
│ + │ output_buffer │
│ Fputchar(char) └───────────────┘
│ flush_out()
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ │ +
▌ ▐ │ Fputchar(char)
▌ screen ▐
▌ ───────────── ▐
▌ real terminal ▐ ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
▌ ▐ ▌ ▐
▀▀▀▀▀▀▀███▀▀▀▀▀▀▀ ▌ screen ▐
███ ▌ ───────────── ▐
▀▀▀▀▀▀▀▀▀ ▌ real terminal ▐
▌ ▐
▀▀▀▀▀▀▀███▀▀▀▀▀▀▀
███
▀▀▀▀▀▀▀▀▀

View File

@ -971,6 +971,7 @@ class fc
enum termcaps enum termcaps
{ {
t_bell, t_bell,
t_erase_chars,
t_clear_screen, t_clear_screen,
t_clr_eos, t_clr_eos,
t_clr_eol, t_clr_eol,
@ -983,6 +984,7 @@ class fc
t_insert_padding, t_insert_padding,
t_insert_character, t_insert_character,
t_parm_ich, t_parm_ich,
t_repeat_char,
t_initialize_color, t_initialize_color,
t_initialize_pair, t_initialize_pair,
t_set_a_foreground, t_set_a_foreground,

View File

@ -27,6 +27,8 @@ FOptiMove::FOptiMove (int baud)
, F_parm_down_cursor() , F_parm_down_cursor()
, F_parm_left_cursor() , F_parm_left_cursor()
, F_parm_right_cursor() , F_parm_right_cursor()
, F_erase_chars()
, F_repeat_char()
, F_clr_bol() , F_clr_bol()
, F_clr_eol() , F_clr_eol()
, automatic_left_margin(false) , automatic_left_margin(false)
@ -320,6 +322,38 @@ int FOptiMove::set_parm_right_cursor (char*& cap)
return F_parm_right_cursor.length; return F_parm_right_cursor.length;
} }
//----------------------------------------------------------------------
int FOptiMove::set_erase_chars (char*& cap)
{
if ( cap )
{
char* temp = tparm(cap, 23);
F_erase_chars.cap = cap;
F_erase_chars.duration = capDuration (temp, 1);
F_erase_chars.length = capDurationToLength (F_erase_chars.duration);
}
else
F_erase_chars.duration = LONG_DURATION;
return F_erase_chars.length;
}
//----------------------------------------------------------------------
int FOptiMove::set_repeat_char (char*& cap)
{
if ( cap )
{
char* temp = tparm(cap, ' ', 23);
F_repeat_char.cap = cap;
F_repeat_char.duration = capDuration (temp, 1);
F_repeat_char.length = capDurationToLength (F_repeat_char.duration);
}
else
F_repeat_char.duration = LONG_DURATION;
return F_repeat_char.length;
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
int FOptiMove::set_clr_bol (char*& cap) int FOptiMove::set_clr_bol (char*& cap)
{ {

View File

@ -60,6 +60,8 @@ class FOptiMove
int set_parm_down_cursor (char*&); int set_parm_down_cursor (char*&);
int set_parm_left_cursor (char*&); int set_parm_left_cursor (char*&);
int set_parm_right_cursor (char*&); int set_parm_right_cursor (char*&);
int set_erase_chars (char*&);
int set_repeat_char (char*&);
int set_clr_bol (char*&); int set_clr_bol (char*&);
int set_clr_eol (char*&); int set_clr_eol (char*&);
void set_auto_left_margin (bool&); void set_auto_left_margin (bool&);
@ -112,6 +114,8 @@ class FOptiMove
capability F_parm_down_cursor; capability F_parm_down_cursor;
capability F_parm_left_cursor; capability F_parm_left_cursor;
capability F_parm_right_cursor; capability F_parm_right_cursor;
capability F_erase_chars;
capability F_repeat_char;
capability F_clr_bol; capability F_clr_bol;
capability F_clr_eol; capability F_clr_eol;

View File

@ -12,6 +12,7 @@ static FTermcap::tcap_map term_caps[] =
// | | // variable name -> description // | | // variable name -> description
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
{ 0, "bl" }, // bell -> audible signal (bell) (P) { 0, "bl" }, // bell -> audible signal (bell) (P)
{ 0, "ec" }, // erase_chars -> erase #1 characters (P)
{ 0, "cl" }, // clear_screen -> clear screen and home cursor (P*) { 0, "cl" }, // clear_screen -> clear screen and home cursor (P*)
{ 0, "cd" }, // clr_eos -> clear to end of screen (P*) { 0, "cd" }, // clr_eos -> clear to end of screen (P*)
{ 0, "ce" }, // clr_eol -> clear to end of line (P) { 0, "ce" }, // clr_eol -> clear to end of line (P)
@ -24,6 +25,7 @@ static FTermcap::tcap_map term_caps[] =
{ 0, "ip" }, // insert_padding -> insert padding after inserted character { 0, "ip" }, // insert_padding -> insert padding after inserted character
{ 0, "ic" }, // insert_character -> insert character (P) { 0, "ic" }, // insert_character -> insert character (P)
{ 0, "IC" }, // parm_ich -> insert #1 characters (P*) { 0, "IC" }, // parm_ich -> insert #1 characters (P*)
{ 0, "rp" }, // repeat_char -> repeat char #1 #2 times (P*)
{ 0, "Ic" }, // initialize_color -> initialize color #1 to (#2,#3,#4) { 0, "Ic" }, // initialize_color -> initialize color #1 to (#2,#3,#4)
{ 0, "Ip" }, // initialize_pair -> Initialize color pair #1 to { 0, "Ip" }, // initialize_pair -> Initialize color pair #1 to
// fg=(#2,#3,#4), bg=(#5,#6,#7) // fg=(#2,#3,#4), bg=(#5,#6,#7)

View File

@ -24,8 +24,11 @@ int FTerm::stdin_no;
int FTerm::stdout_no; int FTerm::stdout_no;
int FTerm::fd_tty; int FTerm::fd_tty;
int FTerm::stdin_status_flags; int FTerm::stdin_status_flags;
int FTerm::erase_ch_length;
int FTerm::repeat_char_length;
int FTerm::clr_bol_length; int FTerm::clr_bol_length;
int FTerm::clr_eol_length; int FTerm::clr_eol_length;
int FTerm::cursor_addres_lengths;
uInt FTerm::baudrate; uInt FTerm::baudrate;
bool FTerm::resize_term; bool FTerm::resize_term;
bool FTerm::mouse_support; bool FTerm::mouse_support;
@ -2905,7 +2908,7 @@ void FTerm::init_termcaps()
opti_move->set_cursor_down (tcap[fc::t_cursor_down].string); opti_move->set_cursor_down (tcap[fc::t_cursor_down].string);
opti_move->set_cursor_left (tcap[fc::t_cursor_left].string); opti_move->set_cursor_left (tcap[fc::t_cursor_left].string);
opti_move->set_cursor_right (tcap[fc::t_cursor_right].string); opti_move->set_cursor_right (tcap[fc::t_cursor_right].string);
opti_move->set_cursor_address (tcap[fc::t_cursor_address].string); cursor_addres_lengths = opti_move->set_cursor_address (tcap[fc::t_cursor_address].string);
opti_move->set_column_address (tcap[fc::t_column_address].string); opti_move->set_column_address (tcap[fc::t_column_address].string);
opti_move->set_row_address (tcap[fc::t_row_address].string); opti_move->set_row_address (tcap[fc::t_row_address].string);
opti_move->set_parm_up_cursor (tcap[fc::t_parm_up_cursor].string); opti_move->set_parm_up_cursor (tcap[fc::t_parm_up_cursor].string);
@ -2914,6 +2917,8 @@ void FTerm::init_termcaps()
opti_move->set_parm_right_cursor (tcap[fc::t_parm_right_cursor].string); opti_move->set_parm_right_cursor (tcap[fc::t_parm_right_cursor].string);
opti_move->set_auto_left_margin (FTermcap::automatic_left_margin); opti_move->set_auto_left_margin (FTermcap::automatic_left_margin);
opti_move->set_eat_newline_glitch (FTermcap::eat_nl_glitch); opti_move->set_eat_newline_glitch (FTermcap::eat_nl_glitch);
erase_ch_length = opti_move->set_erase_chars (tcap[fc::t_erase_chars].string);
repeat_char_length = opti_move->set_repeat_char (tcap[fc::t_repeat_char].string);
clr_bol_length = opti_move->set_clr_bol (tcap[fc::t_clr_bol].string); clr_bol_length = opti_move->set_clr_bol (tcap[fc::t_clr_bol].string);
clr_eol_length = opti_move->set_clr_eol (tcap[fc::t_clr_eol].string); clr_eol_length = opti_move->set_clr_eol (tcap[fc::t_clr_eol].string);
@ -3106,12 +3111,9 @@ void FTerm::init()
if ( isatty(stdout_no) ) if ( isatty(stdout_no) )
opti_move->setBaudRate(int(baudrate)); opti_move->setBaudRate(int(baudrate));
// detect the type of the terminal // get the set type of the terminal
identifyTermType(); identifyTermType();
// initialize 256 colors terminals
new_termtype = init_256colorTerminal();
if ( std::strncmp(termtype, "cygwin", 6) == 0 ) if ( std::strncmp(termtype, "cygwin", 6) == 0 )
cygwin_terminal = true; cygwin_terminal = true;
else else
@ -3143,6 +3145,8 @@ void FTerm::init()
t.c_cc[VMIN] = 0; // Minimum number of characters t.c_cc[VMIN] = 0; // Minimum number of characters
tcsetattr (stdin_no, TCSANOW, &t); tcsetattr (stdin_no, TCSANOW, &t);
// initialize 256 colors terminals
new_termtype = init_256colorTerminal();
// Identify the terminal via the answerback-message // Identify the terminal via the answerback-message
new_termtype = parseAnswerbackMsg (new_termtype); new_termtype = parseAnswerbackMsg (new_termtype);

View File

@ -254,8 +254,11 @@ class FTerm
// Data Members // Data Members
static int stdin_no; static int stdin_no;
static int stdout_no; static int stdout_no;
static int erase_ch_length;
static int repeat_char_length;
static int clr_bol_length; static int clr_bol_length;
static int clr_eol_length; static int clr_eol_length;
static int cursor_addres_lengths;
static bool NewFont; static bool NewFont;
static bool VGAFont; static bool VGAFont;
static bool no_shadow_character; static bool no_shadow_character;

View File

@ -127,7 +127,7 @@ void FVTerm::clearTerm (int fillchar)
for (int i=0; i < vdesktop->height; i++) for (int i=0; i < vdesktop->height; i++)
{ {
vdesktop->changes[i].xmin = 0; vdesktop->changes[i].xmin = 0;
vdesktop->changes[i].xmax = vdesktop->width - 1; vdesktop->changes[i].xmax = uInt(vdesktop->width) - 1;
vdesktop->changes[i].trans_count = 0; vdesktop->changes[i].trans_count = 0;
} }
@ -289,6 +289,7 @@ void FVTerm::updateTerminal()
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FVTerm::updateTerminalLine (uInt y) void FVTerm::updateTerminalLine (uInt y)
{ {
// Updates pending changes from line y to the terminal
term_area* vt = vterm; term_area* vt = vterm;
uInt& xmin = vt->changes[y].xmin; uInt& xmin = vt->changes[y].xmin;
uInt& xmax = vt->changes[y].xmax; uInt& xmax = vt->changes[y].xmax;
@ -302,18 +303,20 @@ void FVTerm::updateTerminalLine (uInt y)
bool draw_tailing_ws = false; bool draw_tailing_ws = false;
char*& ce = tcap[fc::t_clr_eol].string; char*& ce = tcap[fc::t_clr_eol].string;
char*& cb = tcap[fc::t_clr_bol].string; char*& cb = tcap[fc::t_clr_bol].string;
char*& ec = tcap[fc::t_erase_chars].string;
char*& rp = tcap[fc::t_repeat_char].string;
bool ut = FTermcap::background_color_erase; bool ut = FTermcap::background_color_erase;
char_data* first_char = &vt->text[y * uInt(vt->width)]; char_data* first_char = &vt->text[y * uInt(vt->width)];
char_data* last_char = &vt->text[(y+1) * uInt(vt->width) - 1]; char_data* last_char = &vt->text[(y+1) * uInt(vt->width) - 1];
char_data* min_char = &vt->text[y * uInt(vt->width) + xmin]; char_data* min_char = &vt->text[y * uInt(vt->width) + xmin];
// Is the line from xmin to the end of the line blank? // Is the line from xmin to the end of the line blank?
if ( min_char->code == ' ' ) if ( ce && min_char->code == ' ' )
{ {
uInt beginning_whitespace = 1; uInt beginning_whitespace = 1;
bool normal = isNormal(min_char); bool normal = isNormal(min_char);
for (register uInt x=xmin+1; x < uInt(vt->width); x++) for (uInt x=xmin+1; x < uInt(vt->width); x++)
{ {
if ( *min_char == vt->text[y * uInt(vt->width) + x] ) if ( *min_char == vt->text[y * uInt(vt->width) + x] )
beginning_whitespace++; beginning_whitespace++;
@ -322,54 +325,57 @@ void FVTerm::updateTerminalLine (uInt y)
} }
if ( beginning_whitespace == uInt(vt->width) - xmin if ( beginning_whitespace == uInt(vt->width) - xmin
&& ce && (ut || normal) && (ut || normal)
&& clr_eol_length < int(beginning_whitespace) ) && clr_eol_length < int(beginning_whitespace) )
is_eol_clean = true; is_eol_clean = true;
} }
// leading whitespace if ( ! is_eol_clean )
if ( ! is_eol_clean && first_char->code == ' ' )
{ {
uInt leading_whitespace = 1; // leading whitespace
bool normal = isNormal(first_char); if ( cb && first_char->code == ' ' )
for (register uInt x=1; x < uInt(vt->width); x++)
{ {
if ( *first_char == vt->text[y * uInt(vt->width) + x] ) uInt leading_whitespace = 1;
leading_whitespace++; bool normal = isNormal(first_char);
else
break; for (uInt x=1; x < uInt(vt->width); x++)
{
if ( *first_char == vt->text[y * uInt(vt->width) + x] )
leading_whitespace++;
else
break;
}
if ( leading_whitespace > xmin
&& (ut || normal)
&& clr_bol_length < int(leading_whitespace) )
{
draw_leading_ws = true;
xmin = leading_whitespace - 1;
}
} }
if ( leading_whitespace > xmin // tailing whitespace
&& cb && (ut || normal) if ( ce && last_char->code == ' ' )
&& clr_bol_length < int(leading_whitespace) )
{ {
draw_leading_ws = true; uInt tailing_whitespace = 1;
xmin = leading_whitespace - 1; bool normal = isNormal(last_char);
}
}
// tailing whitespace for (uInt x=uInt(vt->width)-1; x > 0 ; x--)
if ( ! is_eol_clean && last_char->code == ' ' ) {
{ if ( *last_char == vt->text[y * uInt(vt->width) + x] )
uInt tailing_whitespace = 1; tailing_whitespace++;
bool normal = isNormal(last_char); else
break;
}
for (register uInt x=uInt(vt->width)-1; x > 0 ; x--) if ( tailing_whitespace > uInt(vt->width) - xmax
{ && (ut || normal)
if ( *last_char == vt->text[y * uInt(vt->width) + x] ) && clr_bol_length < int(tailing_whitespace) )
tailing_whitespace++; {
else draw_tailing_ws = true;
break; xmax = uInt(vt->width) - tailing_whitespace;
} }
if ( tailing_whitespace > uInt(vt->width) - xmax
&& ce && (ut || normal)
&& clr_bol_length < int(tailing_whitespace) )
{
draw_tailing_ws = true;
xmax = uInt(vt->width) - tailing_whitespace;
} }
} }
@ -388,18 +394,78 @@ void FVTerm::updateTerminalLine (uInt y)
appendOutputBuffer (cb); appendOutputBuffer (cb);
} }
for (register uInt x=xmin; x <= xmax; x++) for (uInt x=xmin; x <= xmax; x++)
{ {
char_data* print_char; char_data* print_char;
print_char = &vt->text[y * uInt(vt->width) + x]; print_char = &vt->text[y * uInt(vt->width) + x];
if ( term_pos->getX() == term_width // Erase a number of characters to draw simple whitespaces
&& term_pos->getY() == term_height ) if ( ec && print_char->code == ' ' )
appendLowerRight (print_char); {
uInt whitespace = 1;
bool normal = isNormal(print_char);
for (uInt i=x+1; i <= xmax; i++)
{
if ( *print_char == vt->text[y * uInt(vt->width) + i] )
whitespace++;
else
break;
}
if ( whitespace > uInt(erase_ch_length) + uInt(cursor_addres_lengths)
&& (ut || normal) )
{
appendAttributes (print_char);
appendOutputBuffer (tparm(ec, whitespace));
if ( x + whitespace - 1 < xmax || draw_tailing_ws )
setTermXY (int(x + whitespace), int(y));
else
break;
x = x + whitespace - 1;
}
else
{
x--;
for (uInt i=0; i < whitespace; i++, x++)
appendCharacter (print_char);
}
}
else if ( rp ) // Repeat one character n-fold
{
uInt repetitions = 1;
for (uInt i=x+1; i <= xmax; i++)
{
if ( *print_char == vt->text[y * uInt(vt->width) + i] )
repetitions++;
else
break;
}
if ( repetitions > uInt(repeat_char_length)
&& print_char->code < 128 )
{
newFontChanges (print_char);
charsetChanges (print_char);
appendAttributes (print_char);
appendOutputBuffer (tparm(rp, print_char->code, repetitions));
term_pos->x_ref() += short(repetitions);
x = x + repetitions - 1;
}
else
{
x--;
for (uInt i=0; i < repetitions; i++, x++)
appendCharacter (print_char);
}
}
else else
appendCharacter (print_char); appendCharacter (print_char);
term_pos->x_ref()++;
} }
if ( draw_tailing_ws ) if ( draw_tailing_ws )
@ -944,6 +1010,21 @@ inline void FVTerm::charsetChanges (char_data*& next_char)
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline void FVTerm::appendCharacter (char_data*& next_char) inline void FVTerm::appendCharacter (char_data*& next_char)
{
int term_width = vterm->width - 1;
int term_height = vterm->height - 1;
if ( term_pos->getX() == term_width
&& term_pos->getY() == term_height )
appendLowerRight (next_char);
else
appendChar (next_char);
term_pos->x_ref()++;
}
//----------------------------------------------------------------------
inline void FVTerm::appendChar (char_data*& next_char)
{ {
newFontChanges (next_char); newFontChanges (next_char);
charsetChanges (next_char); charsetChanges (next_char);
@ -973,12 +1054,12 @@ int FVTerm::appendLowerRight (char_data*& screen_char)
if ( ! FTermcap::automatic_right_margin ) if ( ! FTermcap::automatic_right_margin )
{ {
appendCharacter (screen_char); appendChar (screen_char);
} }
else if ( SA && RA ) else if ( SA && RA )
{ {
appendOutputBuffer (RA); appendOutputBuffer (RA);
appendCharacter (screen_char); appendChar (screen_char);
appendOutputBuffer (SA); appendOutputBuffer (SA);
} }
else else
@ -993,7 +1074,7 @@ int FVTerm::appendLowerRight (char_data*& screen_char)
x = getColumnNumber() - 2; x = getColumnNumber() - 2;
y = getLineNumber() - 1; y = getLineNumber() - 1;
setTermXY (x, y); setTermXY (x, y);
appendCharacter (screen_char); appendChar (screen_char);
term_pos->x_ref()++; term_pos->x_ref()++;
setTermXY (x, y); setTermXY (x, y);
@ -1002,12 +1083,12 @@ int FVTerm::appendLowerRight (char_data*& screen_char)
if ( IC ) if ( IC )
{ {
appendOutputBuffer (tparm(IC, 1)); appendOutputBuffer (tparm(IC, 1));
appendCharacter (screen_char); appendChar (screen_char);
} }
else if ( im && ei ) else if ( im && ei )
{ {
appendOutputBuffer (im); appendOutputBuffer (im);
appendCharacter (screen_char); appendChar (screen_char);
if ( ip ) if ( ip )
appendOutputBuffer (ip); appendOutputBuffer (ip);
@ -1017,7 +1098,7 @@ int FVTerm::appendLowerRight (char_data*& screen_char)
else if ( ic ) else if ( ic )
{ {
appendOutputBuffer (ic); appendOutputBuffer (ic);
appendCharacter (screen_char); appendChar (screen_char);
if ( ip ) if ( ip )
appendOutputBuffer (ip); appendOutputBuffer (ip);

View File

@ -220,6 +220,7 @@ class FVTerm : public FObject, public FTerm
static void newFontChanges (char_data*&); static void newFontChanges (char_data*&);
static void charsetChanges (char_data*&); static void charsetChanges (char_data*&);
static void appendCharacter (char_data*&); static void appendCharacter (char_data*&);
static void appendChar (char_data*&);
static void appendAttributes (char_data*&); static void appendAttributes (char_data*&);
static int appendLowerRight (char_data*&); static int appendLowerRight (char_data*&);
static void appendOutputBuffer (std::string&); static void appendOutputBuffer (std::string&);