Reduce the character output by using character erase and character repeat
This commit is contained in:
parent
e4284615db
commit
fedb5f64f3
|
@ -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.
|
||||
|
|
10
README.md
10
README.md
|
@ -79,9 +79,13 @@ printf(...)
|
|||
║ │ resizeVTerm()║
|
||||
╚═══▼═══════════════════════════════════════════════════════╝
|
||||
│
|
||||
│ putVTerm() ┌───────────────┐
|
||||
└───────────────────►│ output_buffer │
|
||||
updateTerminal() └───────┬───────┘
|
||||
│ putVTerm()
|
||||
└──────────────────► updateTerminalLine(y)
|
||||
updateTerminal() │
|
||||
▼
|
||||
┌───────────────┐
|
||||
│ output_buffer │
|
||||
└───────────────┘
|
||||
│
|
||||
│ flush_out()
|
||||
│ +
|
||||
|
|
|
@ -30,9 +30,13 @@ printf(...)
|
|||
║ │ resizeVTerm()║
|
||||
╚═══▼═══════════════════════════════════════════════════════╝
|
||||
│
|
||||
│ putVTerm() ┌───────────────┐
|
||||
└───────────────────►│ output_buffer │
|
||||
updateTerminal() └───────┬───────┘
|
||||
│ putVTerm()
|
||||
└──────────────────► updateTerminalLine(y)
|
||||
updateTerminal() │
|
||||
▼
|
||||
┌───────────────┐
|
||||
│ output_buffer │
|
||||
└───────────────┘
|
||||
│
|
||||
│ flush_out()
|
||||
│ +
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
125
src/fvterm.cpp
125
src/fvterm.cpp
|
@ -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);
|
||||
|
|
|
@ -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&);
|
||||
|
|
Loading…
Reference in New Issue