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>
|
||||
* Better code readability by splitting FOptiMove::moveCursor
|
||||
into sub-functions
|
||||
|
|
|
@ -343,9 +343,16 @@ class FVTerm : public FTerm
|
|||
term_area* vwin; // virtual window
|
||||
|
||||
private:
|
||||
// Typedef
|
||||
// Typedef and Enumeration
|
||||
typedef FTermcap::tcap_map termcap_map;
|
||||
|
||||
enum exit_state
|
||||
{
|
||||
not_used,
|
||||
used,
|
||||
line_completely_printed
|
||||
};
|
||||
|
||||
// Constants
|
||||
static const uInt TERMINAL_OUTPUT_BUFFER_SIZE = 32768;
|
||||
// Buffer size for character output on the terminal
|
||||
|
@ -363,6 +370,14 @@ class FVTerm : public FTerm
|
|||
void init();
|
||||
void finish();
|
||||
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 bool updateTerminalCursor();
|
||||
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
|
||||
term_area* vt = vterm;
|
||||
uInt& xmin = vt->changes[y].xmin;
|
||||
uInt& xmax = vt->changes[y].xmax;
|
||||
int term_width = vt->width - 1;
|
||||
int term_height = vt->height - 1;
|
||||
// Is the line from xmin to the end of the line blank?
|
||||
// => clear to end of line
|
||||
|
||||
if ( xmin <= xmax )
|
||||
{
|
||||
bool is_eol_clean = false;
|
||||
bool draw_leading_ws = false;
|
||||
bool draw_tailing_ws = false;
|
||||
term_area*& vt = vterm;
|
||||
bool& ut = FTermcap::background_color_erase;
|
||||
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];
|
||||
|
||||
// Is the line from xmin to the end of the line blank?
|
||||
if ( ce && min_char->code == ' ' )
|
||||
{
|
||||
uInt beginning_whitespace = 1;
|
||||
|
@ -2284,12 +2272,23 @@ void FVTerm::updateTerminalLine (uInt y)
|
|||
if ( beginning_whitespace == uInt(vt->width) - xmin
|
||||
&& (ut || normal)
|
||||
&& 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 == ' ' )
|
||||
{
|
||||
uInt leading_whitespace = 1;
|
||||
|
@ -2309,12 +2308,25 @@ void FVTerm::updateTerminalLine (uInt y)
|
|||
&& (ut || normal)
|
||||
&& clr_bol_length < int(leading_whitespace) )
|
||||
{
|
||||
draw_leading_ws = true;
|
||||
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 == ' ' )
|
||||
{
|
||||
uInt tailing_whitespace = 1;
|
||||
|
@ -2334,38 +2346,23 @@ void FVTerm::updateTerminalLine (uInt y)
|
|||
&& (ut || normal)
|
||||
&& clr_bol_length < int(tailing_whitespace) )
|
||||
{
|
||||
draw_tailing_ws = true;
|
||||
xmax = uInt(vt->width) - tailing_whitespace;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uInt x = xmin; x <= xmax; x++)
|
||||
//----------------------------------------------------------------------
|
||||
bool FVTerm::skipUnchangedCharacters(uInt& x, uInt xmax, uInt y)
|
||||
{
|
||||
char_data* print_char;
|
||||
char*& ec = TCAP(fc::t_erase_chars);
|
||||
char*& rp = TCAP(fc::t_repeat_char);
|
||||
print_char = &vt->text[y * uInt(vt->width) + x];
|
||||
// Skip characters without changes if it is faster than redrawing
|
||||
|
||||
term_area*& vt = vterm;
|
||||
char_data* print_char = &vt->text[y * uInt(vt->width) + x];
|
||||
print_char->attr.bit.printed = true;
|
||||
|
||||
// skip character with no changes
|
||||
if ( print_char->attr.bit.no_changes )
|
||||
{
|
||||
uInt count = 1;
|
||||
|
@ -2384,13 +2381,65 @@ void FVTerm::updateTerminalLine (uInt y)
|
|||
{
|
||||
setTermXY (int(x + count), int(y));
|
||||
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 == ' ' )
|
||||
{
|
||||
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;
|
||||
bool normal = isNormal(print_char);
|
||||
|
||||
|
@ -2422,7 +2471,7 @@ void FVTerm::updateTerminalLine (uInt y)
|
|||
if ( x + whitespace - 1 < xmax || draw_tailing_ws )
|
||||
setTermXY (int(x + whitespace), int(y));
|
||||
else
|
||||
break;
|
||||
return line_completely_printed;
|
||||
|
||||
x = x + whitespace - 1;
|
||||
}
|
||||
|
@ -2436,9 +2485,22 @@ void FVTerm::updateTerminalLine (uInt 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;
|
||||
|
||||
for (uInt i = x + 1; i <= xmax; i++)
|
||||
|
@ -2480,28 +2542,18 @@ void FVTerm::updateTerminalLine (uInt y)
|
|||
|
||||
markAsPrinted (start_pos, x, y);
|
||||
}
|
||||
|
||||
return used;
|
||||
}
|
||||
else // General character output
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void FVTerm::cursorWrap()
|
||||
{
|
||||
appendCharacter (print_char);
|
||||
markAsPrinted (x, y);
|
||||
}
|
||||
}
|
||||
// Wrap the cursor
|
||||
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->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()
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue