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>
* Accelerates text line drawing by clear with CSI sequences
to begin or to end of the current line.

View File

@ -79,9 +79,13 @@ printf(...)
║ │ resizeVTerm()║
╚═══▼═══════════════════════════════════════════════════════╝
│ putVTerm() ┌───────────────┐
└───────────────────►│ output_buffer │
updateTerminal() └───────┬───────┘
│ putVTerm()
└──────────────────► updateTerminalLine(y)
updateTerminal() │
┌───────────────┐
│ output_buffer │
└───────────────┘
│ flush_out()
│ +

View File

@ -30,9 +30,13 @@ printf(...)
║ │ resizeVTerm()║
╚═══▼═══════════════════════════════════════════════════════╝
│ putVTerm() ┌───────────────┐
└───────────────────►│ output_buffer │
updateTerminal() └───────┬───────┘
│ putVTerm()
└──────────────────► updateTerminalLine(y)
updateTerminal() │
┌───────────────┐
│ output_buffer │
└───────────────┘
│ flush_out()
│ +

View File

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

View File

@ -27,6 +27,8 @@ FOptiMove::FOptiMove (int baud)
, F_parm_down_cursor()
, F_parm_left_cursor()
, F_parm_right_cursor()
, F_erase_chars()
, F_repeat_char()
, F_clr_bol()
, F_clr_eol()
, automatic_left_margin(false)
@ -320,6 +322,38 @@ int FOptiMove::set_parm_right_cursor (char*& cap)
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)
{

View File

@ -60,6 +60,8 @@ class FOptiMove
int set_parm_down_cursor (char*&);
int set_parm_left_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_eol (char*&);
void set_auto_left_margin (bool&);
@ -112,6 +114,8 @@ class FOptiMove
capability F_parm_down_cursor;
capability F_parm_left_cursor;
capability F_parm_right_cursor;
capability F_erase_chars;
capability F_repeat_char;
capability F_clr_bol;
capability F_clr_eol;

View File

@ -12,6 +12,7 @@ static FTermcap::tcap_map term_caps[] =
// | | // variable name -> description
//-----------------------------------------------------------------------------
{ 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, "cd" }, // clr_eos -> clear to end of screen (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, "ic" }, // insert_character -> insert character (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, "Ip" }, // initialize_pair -> Initialize color pair #1 to
// fg=(#2,#3,#4), bg=(#5,#6,#7)

View File

@ -24,8 +24,11 @@ int FTerm::stdin_no;
int FTerm::stdout_no;
int FTerm::fd_tty;
int FTerm::stdin_status_flags;
int FTerm::erase_ch_length;
int FTerm::repeat_char_length;
int FTerm::clr_bol_length;
int FTerm::clr_eol_length;
int FTerm::cursor_addres_lengths;
uInt FTerm::baudrate;
bool FTerm::resize_term;
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_left (tcap[fc::t_cursor_left].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_row_address (tcap[fc::t_row_address].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_auto_left_margin (FTermcap::automatic_left_margin);
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_eol_length = opti_move->set_clr_eol (tcap[fc::t_clr_eol].string);
@ -3106,12 +3111,9 @@ void FTerm::init()
if ( isatty(stdout_no) )
opti_move->setBaudRate(int(baudrate));
// detect the type of the terminal
// get the set type of the terminal
identifyTermType();
// initialize 256 colors terminals
new_termtype = init_256colorTerminal();
if ( std::strncmp(termtype, "cygwin", 6) == 0 )
cygwin_terminal = true;
else
@ -3143,6 +3145,8 @@ void FTerm::init()
t.c_cc[VMIN] = 0; // Minimum number of characters
tcsetattr (stdin_no, TCSANOW, &t);
// initialize 256 colors terminals
new_termtype = init_256colorTerminal();
// Identify the terminal via the answerback-message
new_termtype = parseAnswerbackMsg (new_termtype);

View File

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

View File

@ -127,7 +127,7 @@ void FVTerm::clearTerm (int fillchar)
for (int i=0; i < vdesktop->height; i++)
{
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;
}
@ -289,6 +289,7 @@ void FVTerm::updateTerminal()
//----------------------------------------------------------------------
void FVTerm::updateTerminalLine (uInt y)
{
// Updates pending changes from line y to the terminal
term_area* vt = vterm;
uInt& xmin = vt->changes[y].xmin;
uInt& xmax = vt->changes[y].xmax;
@ -302,18 +303,20 @@ void FVTerm::updateTerminalLine (uInt y)
bool draw_tailing_ws = false;
char*& ce = tcap[fc::t_clr_eol].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;
char_data* first_char = &vt->text[y * uInt(vt->width)];
char_data* last_char = &vt->text[(y+1) * uInt(vt->width) - 1];
char_data* min_char = &vt->text[y * uInt(vt->width) + xmin];
// 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;
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] )
beginning_whitespace++;
@ -322,18 +325,20 @@ void FVTerm::updateTerminalLine (uInt y)
}
if ( beginning_whitespace == uInt(vt->width) - xmin
&& ce && (ut || normal)
&& (ut || normal)
&& clr_eol_length < int(beginning_whitespace) )
is_eol_clean = true;
}
if ( ! is_eol_clean )
{
// leading whitespace
if ( ! is_eol_clean && first_char->code == ' ' )
if ( cb && first_char->code == ' ' )
{
uInt leading_whitespace = 1;
bool normal = isNormal(first_char);
for (register uInt x=1; x < uInt(vt->width); x++)
for (uInt x=1; x < uInt(vt->width); x++)
{
if ( *first_char == vt->text[y * uInt(vt->width) + x] )
leading_whitespace++;
@ -342,7 +347,7 @@ void FVTerm::updateTerminalLine (uInt y)
}
if ( leading_whitespace > xmin
&& cb && (ut || normal)
&& (ut || normal)
&& clr_bol_length < int(leading_whitespace) )
{
draw_leading_ws = true;
@ -351,12 +356,12 @@ void FVTerm::updateTerminalLine (uInt y)
}
// tailing whitespace
if ( ! is_eol_clean && last_char->code == ' ' )
if ( ce && last_char->code == ' ' )
{
uInt tailing_whitespace = 1;
bool normal = isNormal(last_char);
for (register uInt x=uInt(vt->width)-1; x > 0 ; x--)
for (uInt x=uInt(vt->width)-1; x > 0 ; x--)
{
if ( *last_char == vt->text[y * uInt(vt->width) + x] )
tailing_whitespace++;
@ -365,13 +370,14 @@ void FVTerm::updateTerminalLine (uInt y)
}
if ( tailing_whitespace > uInt(vt->width) - xmax
&& ce && (ut || normal)
&& (ut || normal)
&& clr_bol_length < int(tailing_whitespace) )
{
draw_tailing_ws = true;
xmax = uInt(vt->width) - tailing_whitespace;
}
}
}
setTermXY (int(xmin), int(y));
@ -388,18 +394,78 @@ void FVTerm::updateTerminalLine (uInt y)
appendOutputBuffer (cb);
}
for (register uInt x=xmin; x <= xmax; x++)
for (uInt x=xmin; x <= xmax; x++)
{
char_data* print_char;
print_char = &vt->text[y * uInt(vt->width) + x];
if ( term_pos->getX() == term_width
&& term_pos->getY() == term_height )
appendLowerRight (print_char);
// Erase a number of characters to draw simple whitespaces
if ( ec && print_char->code == ' ' )
{
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
appendCharacter (print_char);
term_pos->x_ref()++;
}
if ( draw_tailing_ws )
@ -944,6 +1010,21 @@ inline void FVTerm::charsetChanges (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);
charsetChanges (next_char);
@ -973,12 +1054,12 @@ int FVTerm::appendLowerRight (char_data*& screen_char)
if ( ! FTermcap::automatic_right_margin )
{
appendCharacter (screen_char);
appendChar (screen_char);
}
else if ( SA && RA )
{
appendOutputBuffer (RA);
appendCharacter (screen_char);
appendChar (screen_char);
appendOutputBuffer (SA);
}
else
@ -993,7 +1074,7 @@ int FVTerm::appendLowerRight (char_data*& screen_char)
x = getColumnNumber() - 2;
y = getLineNumber() - 1;
setTermXY (x, y);
appendCharacter (screen_char);
appendChar (screen_char);
term_pos->x_ref()++;
setTermXY (x, y);
@ -1002,12 +1083,12 @@ int FVTerm::appendLowerRight (char_data*& screen_char)
if ( IC )
{
appendOutputBuffer (tparm(IC, 1));
appendCharacter (screen_char);
appendChar (screen_char);
}
else if ( im && ei )
{
appendOutputBuffer (im);
appendCharacter (screen_char);
appendChar (screen_char);
if ( ip )
appendOutputBuffer (ip);
@ -1017,7 +1098,7 @@ int FVTerm::appendLowerRight (char_data*& screen_char)
else if ( ic )
{
appendOutputBuffer (ic);
appendCharacter (screen_char);
appendChar (screen_char);
if ( ip )
appendOutputBuffer (ip);

View File

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