Refactoring FVTerm::updateTerminalLine
This commit is contained in:
parent
6be608ba57
commit
abf89f1538
|
@ -1,3 +1,6 @@
|
||||||
|
2017-11-30 Markus Gans <guru.mail@muenster.de>
|
||||||
|
* Refactoring FVTerm::updateTerminalLine
|
||||||
|
|
||||||
2017-11-26 Markus Gans <guru.mail@muenster.de>
|
2017-11-26 Markus Gans <guru.mail@muenster.de>
|
||||||
* Better code readability by splitting FOptiMove::moveCursor
|
* Better code readability by splitting FOptiMove::moveCursor
|
||||||
into sub-functions
|
into sub-functions
|
||||||
|
|
|
@ -343,9 +343,16 @@ class FVTerm : public FTerm
|
||||||
term_area* vwin; // virtual window
|
term_area* vwin; // virtual window
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Typedef
|
// Typedef and Enumeration
|
||||||
typedef FTermcap::tcap_map termcap_map;
|
typedef FTermcap::tcap_map termcap_map;
|
||||||
|
|
||||||
|
enum exit_state
|
||||||
|
{
|
||||||
|
not_used,
|
||||||
|
used,
|
||||||
|
line_completely_printed
|
||||||
|
};
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
static const uInt TERMINAL_OUTPUT_BUFFER_SIZE = 32768;
|
static const uInt TERMINAL_OUTPUT_BUFFER_SIZE = 32768;
|
||||||
// Buffer size for character output on the terminal
|
// Buffer size for character output on the terminal
|
||||||
|
@ -363,6 +370,14 @@ class FVTerm : public FTerm
|
||||||
void init();
|
void init();
|
||||||
void finish();
|
void finish();
|
||||||
static bool clearTerm (int = ' ');
|
static bool clearTerm (int = ' ');
|
||||||
|
static bool canClearToEOL (uInt, uInt);
|
||||||
|
static bool canClearLeadingWS (uInt&, uInt);
|
||||||
|
static bool canClearTailingWS (uInt&, uInt);
|
||||||
|
static bool skipUnchangedCharacters (uInt&, uInt, uInt);
|
||||||
|
static void printRange (uInt, uInt, uInt, bool);
|
||||||
|
static exit_state eraseCharacters (uInt&, uInt, uInt, bool);
|
||||||
|
static exit_state repeatCharacter (uInt&, uInt, uInt);
|
||||||
|
static void cursorWrap();
|
||||||
static void updateTerminalLine (uInt);
|
static void updateTerminalLine (uInt);
|
||||||
static bool updateTerminalCursor();
|
static bool updateTerminalCursor();
|
||||||
static bool isInsideTerminal (int, int);
|
static bool isInsideTerminal (int, int);
|
||||||
|
|
254
src/fvterm.cpp
254
src/fvterm.cpp
|
@ -2244,28 +2244,16 @@ bool FVTerm::clearTerm (int fillchar)
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
void FVTerm::updateTerminalLine (uInt y)
|
bool FVTerm::canClearToEOL (uInt xmin, uInt y)
|
||||||
{
|
{
|
||||||
// Updates pending changes from line y to the terminal
|
// Is the line from xmin to the end of the line blank?
|
||||||
term_area* vt = vterm;
|
// => clear to end of line
|
||||||
uInt& xmin = vt->changes[y].xmin;
|
|
||||||
uInt& xmax = vt->changes[y].xmax;
|
|
||||||
int term_width = vt->width - 1;
|
|
||||||
int term_height = vt->height - 1;
|
|
||||||
|
|
||||||
if ( xmin <= xmax )
|
term_area*& vt = vterm;
|
||||||
{
|
bool& ut = FTermcap::background_color_erase;
|
||||||
bool is_eol_clean = false;
|
|
||||||
bool draw_leading_ws = false;
|
|
||||||
bool draw_tailing_ws = false;
|
|
||||||
char*& ce = TCAP(fc::t_clr_eol);
|
char*& ce = TCAP(fc::t_clr_eol);
|
||||||
char*& cb = TCAP(fc::t_clr_bol);
|
|
||||||
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];
|
char_data* min_char = &vt->text[y * uInt(vt->width) + xmin];
|
||||||
|
|
||||||
// Is the line from xmin to the end of the line blank?
|
|
||||||
if ( ce && min_char->code == ' ' )
|
if ( ce && min_char->code == ' ' )
|
||||||
{
|
{
|
||||||
uInt beginning_whitespace = 1;
|
uInt beginning_whitespace = 1;
|
||||||
|
@ -2284,12 +2272,23 @@ void FVTerm::updateTerminalLine (uInt y)
|
||||||
if ( beginning_whitespace == uInt(vt->width) - xmin
|
if ( beginning_whitespace == uInt(vt->width) - xmin
|
||||||
&& (ut || normal)
|
&& (ut || normal)
|
||||||
&& clr_eol_length < int(beginning_whitespace) )
|
&& clr_eol_length < int(beginning_whitespace) )
|
||||||
is_eol_clean = true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! is_eol_clean )
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
bool FVTerm::canClearLeadingWS (uInt& xmin, uInt y)
|
||||||
{
|
{
|
||||||
// leading whitespace
|
// Line has leading whitespace
|
||||||
|
// => clear from xmin to beginning of line
|
||||||
|
|
||||||
|
term_area*& vt = vterm;
|
||||||
|
bool& ut = FTermcap::background_color_erase;
|
||||||
|
char*& cb = TCAP(fc::t_clr_bol);
|
||||||
|
char_data* first_char = &vt->text[y * uInt(vt->width)];
|
||||||
|
|
||||||
if ( cb && first_char->code == ' ' )
|
if ( cb && first_char->code == ' ' )
|
||||||
{
|
{
|
||||||
uInt leading_whitespace = 1;
|
uInt leading_whitespace = 1;
|
||||||
|
@ -2309,12 +2308,25 @@ void FVTerm::updateTerminalLine (uInt y)
|
||||||
&& (ut || normal)
|
&& (ut || normal)
|
||||||
&& clr_bol_length < int(leading_whitespace) )
|
&& clr_bol_length < int(leading_whitespace) )
|
||||||
{
|
{
|
||||||
draw_leading_ws = true;
|
|
||||||
xmin = leading_whitespace - 1;
|
xmin = leading_whitespace - 1;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// tailing whitespace
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
bool FVTerm::canClearTailingWS (uInt& xmax, uInt y)
|
||||||
|
{
|
||||||
|
// Line has tailing whitespace
|
||||||
|
// => clear from xmax to end of line
|
||||||
|
|
||||||
|
term_area*& vt = vterm;
|
||||||
|
bool& ut = FTermcap::background_color_erase;
|
||||||
|
char*& ce = TCAP(fc::t_clr_eol);
|
||||||
|
char_data* last_char = &vt->text[(y + 1) * uInt(vt->width) - 1];
|
||||||
|
|
||||||
if ( ce && last_char->code == ' ' )
|
if ( ce && last_char->code == ' ' )
|
||||||
{
|
{
|
||||||
uInt tailing_whitespace = 1;
|
uInt tailing_whitespace = 1;
|
||||||
|
@ -2334,38 +2346,23 @@ void FVTerm::updateTerminalLine (uInt y)
|
||||||
&& (ut || normal)
|
&& (ut || normal)
|
||||||
&& clr_bol_length < int(tailing_whitespace) )
|
&& clr_bol_length < int(tailing_whitespace) )
|
||||||
{
|
{
|
||||||
draw_tailing_ws = true;
|
|
||||||
xmax = uInt(vt->width) - tailing_whitespace;
|
xmax = uInt(vt->width) - tailing_whitespace;
|
||||||
}
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setTermXY (int(xmin), int(y));
|
return false;
|
||||||
|
|
||||||
if ( is_eol_clean )
|
|
||||||
{
|
|
||||||
appendAttributes (min_char);
|
|
||||||
appendOutputBuffer (ce);
|
|
||||||
markAsPrinted (xmin, uInt(vt->width - 1), y);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ( draw_leading_ws )
|
|
||||||
{
|
|
||||||
appendAttributes (first_char);
|
|
||||||
appendOutputBuffer (cb);
|
|
||||||
markAsPrinted (0, xmin, y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uInt x = xmin; x <= xmax; x++)
|
//----------------------------------------------------------------------
|
||||||
|
bool FVTerm::skipUnchangedCharacters(uInt& x, uInt xmax, uInt y)
|
||||||
{
|
{
|
||||||
char_data* print_char;
|
// Skip characters without changes if it is faster than redrawing
|
||||||
char*& ec = TCAP(fc::t_erase_chars);
|
|
||||||
char*& rp = TCAP(fc::t_repeat_char);
|
term_area*& vt = vterm;
|
||||||
print_char = &vt->text[y * uInt(vt->width) + x];
|
char_data* print_char = &vt->text[y * uInt(vt->width) + x];
|
||||||
print_char->attr.bit.printed = true;
|
print_char->attr.bit.printed = true;
|
||||||
|
|
||||||
// skip character with no changes
|
|
||||||
if ( print_char->attr.bit.no_changes )
|
if ( print_char->attr.bit.no_changes )
|
||||||
{
|
{
|
||||||
uInt count = 1;
|
uInt count = 1;
|
||||||
|
@ -2384,13 +2381,65 @@ void FVTerm::updateTerminalLine (uInt y)
|
||||||
{
|
{
|
||||||
setTermXY (int(x + count), int(y));
|
setTermXY (int(x + count), int(y));
|
||||||
x = x + count - 1;
|
x = x + count - 1;
|
||||||
continue;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Erase a number of characters to draw simple whitespaces
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
void FVTerm::printRange ( uInt xmin, uInt xmax, uInt y
|
||||||
|
, bool draw_tailing_ws )
|
||||||
|
{
|
||||||
|
for (uInt x = xmin; x <= xmax; x++)
|
||||||
|
{
|
||||||
|
char_data* print_char;
|
||||||
|
term_area*& vt = vterm;
|
||||||
|
char*& ec = TCAP(fc::t_erase_chars);
|
||||||
|
char*& rp = TCAP(fc::t_repeat_char);
|
||||||
|
print_char = &vt->text[y * uInt(vt->width) + x];
|
||||||
|
print_char->attr.bit.printed = true;
|
||||||
|
|
||||||
|
// skip character with no changes
|
||||||
|
if ( skipUnchangedCharacters(x, xmax, y) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Erase character
|
||||||
if ( ec && print_char->code == ' ' )
|
if ( ec && print_char->code == ' ' )
|
||||||
{
|
{
|
||||||
|
exit_state erase_state = \
|
||||||
|
eraseCharacters(x, xmax, y, draw_tailing_ws);
|
||||||
|
|
||||||
|
if ( erase_state == line_completely_printed )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if ( rp ) // Repeat one character n-fold
|
||||||
|
{
|
||||||
|
repeatCharacter(x, xmax, y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// General character output
|
||||||
|
appendCharacter (print_char);
|
||||||
|
markAsPrinted (x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
FVTerm::exit_state FVTerm::eraseCharacters ( uInt& x, uInt xmax, uInt y
|
||||||
|
, bool draw_tailing_ws )
|
||||||
|
{
|
||||||
|
// Erase a number of characters to draw simple whitespaces
|
||||||
|
|
||||||
|
term_area*& vt = vterm;
|
||||||
|
bool& ut = FTermcap::background_color_erase;
|
||||||
|
char*& ec = TCAP(fc::t_erase_chars);
|
||||||
|
char_data* print_char = &vt->text[y * uInt(vt->width) + x];
|
||||||
|
|
||||||
|
if ( ! ec || print_char->code != ' ' )
|
||||||
|
return not_used;
|
||||||
|
|
||||||
uInt whitespace = 1;
|
uInt whitespace = 1;
|
||||||
bool normal = isNormal(print_char);
|
bool normal = isNormal(print_char);
|
||||||
|
|
||||||
|
@ -2422,7 +2471,7 @@ void FVTerm::updateTerminalLine (uInt y)
|
||||||
if ( x + whitespace - 1 < xmax || draw_tailing_ws )
|
if ( x + whitespace - 1 < xmax || draw_tailing_ws )
|
||||||
setTermXY (int(x + whitespace), int(y));
|
setTermXY (int(x + whitespace), int(y));
|
||||||
else
|
else
|
||||||
break;
|
return line_completely_printed;
|
||||||
|
|
||||||
x = x + whitespace - 1;
|
x = x + whitespace - 1;
|
||||||
}
|
}
|
||||||
|
@ -2436,9 +2485,22 @@ void FVTerm::updateTerminalLine (uInt y)
|
||||||
|
|
||||||
markAsPrinted (start_pos, x, y);
|
markAsPrinted (start_pos, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return used;
|
||||||
}
|
}
|
||||||
else if ( rp ) // Repeat one character n-fold
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
FVTerm::exit_state FVTerm::repeatCharacter (uInt& x, uInt xmax, uInt y)
|
||||||
{
|
{
|
||||||
|
// Repeat one character n-fold
|
||||||
|
|
||||||
|
term_area*& vt = vterm;
|
||||||
|
char*& rp = TCAP(fc::t_repeat_char);
|
||||||
|
char_data* print_char = &vt->text[y * uInt(vt->width) + x];
|
||||||
|
|
||||||
|
if ( ! rp )
|
||||||
|
return not_used;
|
||||||
|
|
||||||
uInt repetitions = 1;
|
uInt repetitions = 1;
|
||||||
|
|
||||||
for (uInt i = x + 1; i <= xmax; i++)
|
for (uInt i = x + 1; i <= xmax; i++)
|
||||||
|
@ -2480,28 +2542,18 @@ void FVTerm::updateTerminalLine (uInt y)
|
||||||
|
|
||||||
markAsPrinted (start_pos, x, y);
|
markAsPrinted (start_pos, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return used;
|
||||||
}
|
}
|
||||||
else // General character output
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
void FVTerm::cursorWrap()
|
||||||
{
|
{
|
||||||
appendCharacter (print_char);
|
// Wrap the cursor
|
||||||
markAsPrinted (x, y);
|
term_area*& vt = vterm;
|
||||||
}
|
int term_width = vt->width - 1;
|
||||||
}
|
int term_height = vt->height - 1;
|
||||||
|
|
||||||
if ( draw_tailing_ws )
|
|
||||||
{
|
|
||||||
appendAttributes (last_char);
|
|
||||||
appendOutputBuffer (ce);
|
|
||||||
markAsPrinted (xmax + 1, uInt(vt->width - 1), y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset line changes
|
|
||||||
xmin = uInt(vt->width);
|
|
||||||
xmax = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// cursor wrap
|
|
||||||
if ( term_pos->getX() > term_width )
|
if ( term_pos->getX() > term_width )
|
||||||
{
|
{
|
||||||
if ( term_pos->getY() == term_height )
|
if ( term_pos->getY() == term_height )
|
||||||
|
@ -2523,6 +2575,72 @@ void FVTerm::updateTerminalLine (uInt y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
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;
|
||||||
|
|
||||||
|
if ( xmin <= xmax )
|
||||||
|
{
|
||||||
|
bool draw_leading_ws = false;
|
||||||
|
bool draw_tailing_ws = false;
|
||||||
|
char*& ce = TCAP(fc::t_clr_eol);
|
||||||
|
char*& cb = TCAP(fc::t_clr_bol);
|
||||||
|
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];
|
||||||
|
|
||||||
|
// Clear rest of line
|
||||||
|
bool is_eol_clean = canClearToEOL (xmin, y);
|
||||||
|
|
||||||
|
if ( ! is_eol_clean )
|
||||||
|
{
|
||||||
|
// leading whitespace
|
||||||
|
draw_leading_ws = canClearLeadingWS (xmin, y);
|
||||||
|
|
||||||
|
// tailing whitespace
|
||||||
|
draw_tailing_ws = canClearTailingWS (xmax, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
setTermXY (int(xmin), int(y));
|
||||||
|
|
||||||
|
if ( is_eol_clean )
|
||||||
|
{
|
||||||
|
appendAttributes (min_char);
|
||||||
|
appendOutputBuffer (ce);
|
||||||
|
markAsPrinted (xmin, uInt(vt->width - 1), y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( draw_leading_ws )
|
||||||
|
{
|
||||||
|
appendAttributes (first_char);
|
||||||
|
appendOutputBuffer (cb);
|
||||||
|
markAsPrinted (0, xmin, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
printRange (xmin, xmax, y, draw_tailing_ws);
|
||||||
|
|
||||||
|
if ( draw_tailing_ws )
|
||||||
|
{
|
||||||
|
appendAttributes (last_char);
|
||||||
|
appendOutputBuffer (ce);
|
||||||
|
markAsPrinted (xmax + 1, uInt(vt->width - 1), y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset line changes
|
||||||
|
xmin = uInt(vt->width);
|
||||||
|
xmax = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cursorWrap();
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
bool FVTerm::updateTerminalCursor()
|
bool FVTerm::updateTerminalCursor()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue