From 628bec0b29d6d4124930531795a0c6425868677d Mon Sep 17 00:00:00 2001 From: Markus Gans Date: Wed, 28 Dec 2016 16:29:49 +0100 Subject: [PATCH] Reduce public methods in FVTerm --- ChangeLog | 3 + src/fdialog.cpp | 2 +- src/fmenu.cpp | 2 +- src/ftooltip.cpp | 2 +- src/fvterm.cpp | 1196 ++++++++++++++++++++++---------------------- src/fvterm.h | 32 +- test/opti-move.cpp | 2 +- 7 files changed, 625 insertions(+), 614 deletions(-) diff --git a/ChangeLog b/ChangeLog index c78d362f..b89f18a4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2016-12-28 Markus Gans + * Reduce public methods in FVTerm + 2016-12-27 Markus Gans * Avoid non-working tab-cursor-movements on Linux terminals with activated PC or VT100 encoding diff --git a/src/fdialog.cpp b/src/fdialog.cpp index 4df21dce..f0a7ca33 100644 --- a/src/fdialog.cpp +++ b/src/fdialog.cpp @@ -1007,7 +1007,7 @@ void FDialog::draw() if ( isMonochron() ) setReverse(true); - clearArea (vwin); + clearArea(); drawBorder(); drawTitleBar(); setCursorPos(2, getHeight() - 1); diff --git a/src/fmenu.cpp b/src/fmenu.cpp index 5f75e924..f6fb1224 100644 --- a/src/fmenu.cpp +++ b/src/fmenu.cpp @@ -1222,7 +1222,7 @@ void FMenu::draw() if ( isMonochron() ) setReverse(true); - clearArea (vwin); + clearArea(); drawBorder(); drawItems(); drawShadow(); diff --git a/src/ftooltip.cpp b/src/ftooltip.cpp index 48eb9072..28c6a21c 100644 --- a/src/ftooltip.cpp +++ b/src/ftooltip.cpp @@ -84,7 +84,7 @@ void FToolTip::draw() if ( getMaxColor() < 16 ) setBold(); - clearArea (vwin); + clearArea(); drawBorder(); for (int i=0; i < int(text_num_lines); i++) diff --git a/src/fvterm.cpp b/src/fvterm.cpp index 4e7c1e3c..ac9b548d 100644 --- a/src/fvterm.cpp +++ b/src/fvterm.cpp @@ -106,52 +106,6 @@ void FVTerm::setTermXY (register int x, register int y) term_pos->setPoint(x,y); } -//---------------------------------------------------------------------- -bool FVTerm::clearTerm (int fillchar) -{ - // Clear the real terminal and put cursor at home - char*& cl = tcap[fc::t_clear_screen].string; - char*& cd = tcap[fc::t_clr_eos].string; - char*& cb = tcap[fc::t_clr_eol].string; - bool ut = FTermcap::background_color_erase; - char_data* next = &next_attribute; - bool normal = isNormal(next); - appendAttributes(next); - - if ( ! ( (cl || cd || cb) && (normal || ut) ) - || fillchar != ' ' ) - { - return false; - } - - if ( cl ) - { - appendOutputBuffer (cl); - term_pos->setPoint(0,0); - } - else if ( cd ) - { - setTermXY (0, 0); - appendOutputBuffer (cd); - term_pos->setPoint(-1,-1); - } - else if ( cb ) - { - term_pos->setPoint(-1,-1); - - for (int i=0; i < getLineNumber(); i++) - { - setTermXY (0, i); - appendOutputBuffer (cb); - } - - setTermXY (0,0); - } - - flush_out(); - return true; -} - //---------------------------------------------------------------------- bool FVTerm::hideCursor (bool on) { @@ -200,6 +154,12 @@ void FVTerm::setPrintCursor (register int x, register int y) } } +//---------------------------------------------------------------------- +void FVTerm::clearArea (int fillchar) +{ + clearArea (vwin, fillchar); +} + //---------------------------------------------------------------------- void FVTerm::createVTerm (const FRect& r) { @@ -280,347 +240,6 @@ void FVTerm::updateTerminal() updateTerminalCursor(); } -//---------------------------------------------------------------------- -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; - int term_width = vt->width - 1; - int term_height = vt->height - 1; - - if ( xmin <= xmax ) - { - bool is_eol_clean = false; - bool draw_leading_ws = false; - 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 ( ce && min_char->code == ' ' ) - { - uInt beginning_whitespace = 1; - bool normal = isNormal(min_char); - - for (uInt x=xmin+1; x < uInt(vt->width); x++) - { - char_data* ch = &vt->text[y * uInt(vt->width) + x]; - - if ( *min_char == *ch ) - beginning_whitespace++; - else - break; - } - - if ( beginning_whitespace == uInt(vt->width) - xmin - && (ut || normal) - && clr_eol_length < int(beginning_whitespace) ) - is_eol_clean = true; - } - - if ( ! is_eol_clean ) - { - // leading whitespace - if ( cb && first_char->code == ' ' ) - { - uInt leading_whitespace = 1; - bool normal = isNormal(first_char); - - for (uInt x=1; x < uInt(vt->width); x++) - { - char_data* ch = &vt->text[y * uInt(vt->width) + x]; - - if ( *first_char == *ch ) - leading_whitespace++; - else - break; - } - - if ( leading_whitespace > xmin - && (ut || normal) - && clr_bol_length < int(leading_whitespace) ) - { - draw_leading_ws = true; - xmin = leading_whitespace - 1; - } - } - - // tailing whitespace - if ( ce && last_char->code == ' ' ) - { - uInt tailing_whitespace = 1; - bool normal = isNormal(last_char); - - for (uInt x=uInt(vt->width)-1; x > 0 ; x--) - { - char_data* ch = &vt->text[y * uInt(vt->width) + x]; - - if ( *last_char == *ch ) - tailing_whitespace++; - else - break; - } - - if ( tailing_whitespace > uInt(vt->width) - xmax - && (ut || normal) - && clr_bol_length < int(tailing_whitespace) ) - { - draw_tailing_ws = true; - xmax = uInt(vt->width) - tailing_whitespace; - } - } - } - - 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); - } - - for (uInt x=xmin; x <= xmax; x++) - { - char_data* print_char; - print_char = &vt->text[y * uInt(vt->width) + x]; - print_char->printed = true; - - // skip character with no changes - if ( print_char->no_changes ) - { - uInt count = 1; - - for (uInt i=x+1; i <= xmax; i++) - { - char_data* ch = &vt->text[y * uInt(vt->width) + i]; - - if ( ch->no_changes ) - count++; - else - break; - } - - if ( count > uInt(cursor_addres_lengths) ) - { - setTermXY (int(x + count), int(y)); - x = x + count - 1; - continue; - } - } - - // 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++) - { - char_data* ch = &vt->text[y * uInt(vt->width) + i]; - - if ( *print_char == *ch ) - whitespace++; - else - break; - } - - if ( whitespace == 1 ) - { - appendCharacter (print_char); - markAsPrinted (x, y); - } - else - { - uInt start_pos = x; - - 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); - } - - markAsPrinted (start_pos, x, y); - } - } - else if ( rp ) // Repeat one character n-fold - { - uInt repetitions = 1; - - for (uInt i=x+1; i <= xmax; i++) - { - char_data* ch = &vt->text[y * uInt(vt->width) + i]; - - if ( *print_char == *ch ) - repetitions++; - else - break; - } - - if ( repetitions == 1 ) - { - appendCharacter (print_char); - markAsPrinted (x, y); - } - else - { - uInt start_pos = x; - - 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); - } - - markAsPrinted (start_pos, x, y); - } - } - else // General character output - { - appendCharacter (print_char); - markAsPrinted (x, y); - } - } - - 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 ) - term_pos->x_ref()--; - else - { - if ( FTermcap::eat_nl_glitch ) - { - term_pos->setPoint(-1,-1); - } - else if ( FTermcap::automatic_right_margin ) - { - term_pos->setX(0); - term_pos->y_ref()++; - } - else - term_pos->x_ref()--; - } - } -} - -//---------------------------------------------------------------------- -bool FVTerm::updateTerminalCursor() -{ - // Updates the input cursor visibility and the position - if ( vterm && vterm->input_cursor_visible ) - { - int x = vterm->input_cursor_x; - int y = vterm->input_cursor_y; - - if ( isInsideTerminal(x, y) ) - { - setTermXY (x,y); - showCursor(); - return true; - } - } - else - hideCursor(); - - return false; -} - -//---------------------------------------------------------------------- -void FVTerm::processTerminalUpdate() -{ - // Retains terminal updates if there are unprocessed inputs - static const int max_skip = 8; - - if ( terminal_update_pending ) - { - if ( ! unprocessedInput() ) - { - updateTerminal(); - terminal_update_pending = false; - skipped_terminal_update = 0; - } - else if ( skipped_terminal_update > max_skip ) - { - force_terminal_update = true; - updateTerminal(); - force_terminal_update = false; - terminal_update_pending = false; - skipped_terminal_update = 0; - } - else - skipped_terminal_update++; - } -} - -//---------------------------------------------------------------------- -bool FVTerm::isInsideTerminal (int x, int y) -{ - // Check whether the coordinates are within the virtual terminal - FRect term_geometry (0, 0, getColumnNumber(), getLineNumber()); - - if ( term_geometry.contains(x,y) ) - return true; - else - return false; -} - //---------------------------------------------------------------------- int FVTerm::printf (const wchar_t* format, ...) { @@ -998,214 +617,6 @@ int FVTerm::print (term_area* area, register int c) return 1; } -//---------------------------------------------------------------------- -inline void FVTerm::newFontChanges (char_data*& next_char) -{ - // NewFont special cases - if ( NewFont ) - { - switch ( next_char->code ) - { - case fc::LowerHalfBlock: - next_char->code = fc::UpperHalfBlock; - // fall through - case fc::NF_rev_left_arrow2: - case fc::NF_rev_right_arrow2: - case fc::NF_rev_border_corner_upper_right: - case fc::NF_rev_border_line_right: - case fc::NF_rev_border_line_vertical_left: - case fc::NF_rev_border_corner_lower_right: - case fc::NF_rev_up_arrow2: - case fc::NF_rev_down_arrow2: - case fc::NF_rev_up_arrow1: - case fc::NF_rev_down_arrow1: - case fc::NF_rev_left_arrow1: - case fc::NF_rev_right_arrow1: - case fc::NF_rev_menu_button1: - case fc::NF_rev_menu_button2: - case fc::NF_rev_up_pointing_triangle1: - case fc::NF_rev_down_pointing_triangle1: - case fc::NF_rev_up_pointing_triangle2: - case fc::NF_rev_down_pointing_triangle2: - case fc::NF_rev_menu_button3: - case fc::NF_rev_border_line_right_and_left: - // swap foreground and background color - std::swap (next_char->fg_color, next_char->bg_color); - break; - - default: - break; - } - } -} - -//---------------------------------------------------------------------- -inline void FVTerm::charsetChanges (char_data*& next_char) -{ - if ( Encoding == fc::UTF8 ) - return; - - uInt code = uInt(next_char->code); - uInt ch = charEncode(code); - - if ( ch != code ) - { - if ( ch == 0 ) - { - next_char->code = int(charEncode(code, fc::ASCII)); - return; - } - - next_char->code = int(ch); - - if ( Encoding == fc::VT100 ) - next_char->alt_charset = true; - else if ( Encoding == fc::PC ) - { - next_char->pc_charset = true; - - if ( isXTerminal() && hasUTF8() && ch < 0x20 ) // Character 0x00..0x1f - next_char->code = int(charEncode(code, fc::ASCII)); - } - } -} - -//---------------------------------------------------------------------- -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); - - appendAttributes (next_char); - appendOutputBuffer (next_char->code); -} - -//---------------------------------------------------------------------- -inline void FVTerm::appendAttributes (char_data*& next_attr) -{ - char* attr_str; - char_data* term_attr = &term_attribute; - - // generate attribute string for the next character - attr_str = changeAttribute (term_attr, next_attr); - - if ( attr_str ) - appendOutputBuffer (attr_str); -} - -//---------------------------------------------------------------------- -int FVTerm::appendLowerRight (char_data*& screen_char) -{ - char* SA = tcap[fc::t_enter_am_mode].string; - char* RA = tcap[fc::t_exit_am_mode].string; - - if ( ! FTermcap::automatic_right_margin ) - { - appendChar (screen_char); - } - else if ( SA && RA ) - { - appendOutputBuffer (RA); - appendChar (screen_char); - appendOutputBuffer (SA); - } - else - { - int x, y; - char* IC = tcap[fc::t_parm_ich].string; - char* im = tcap[fc::t_enter_insert_mode].string; - char* ei = tcap[fc::t_exit_insert_mode].string; - char* ip = tcap[fc::t_insert_padding].string; - char* ic = tcap[fc::t_insert_character].string; - - x = getColumnNumber() - 2; - y = getLineNumber() - 1; - setTermXY (x, y); - appendChar (screen_char); - term_pos->x_ref()++; - - setTermXY (x, y); - screen_char--; - - if ( IC ) - { - appendOutputBuffer (tparm(IC, 1)); - appendChar (screen_char); - } - else if ( im && ei ) - { - appendOutputBuffer (im); - appendChar (screen_char); - - if ( ip ) - appendOutputBuffer (ip); - - appendOutputBuffer (ei); - } - else if ( ic ) - { - appendOutputBuffer (ic); - appendChar (screen_char); - - if ( ip ) - appendOutputBuffer (ip); - } - } - - return screen_char->code; -} - -//---------------------------------------------------------------------- -inline void FVTerm::appendOutputBuffer (std::string& s) -{ - const char* c_string = s.c_str(); - tputs (c_string, 1, appendOutputBuffer); -} - -//---------------------------------------------------------------------- -inline void FVTerm::appendOutputBuffer (const char* s) -{ - tputs (s, 1, appendOutputBuffer); -} - -//---------------------------------------------------------------------- -int FVTerm::appendOutputBuffer (int ch) -{ - output_buffer->push(ch); - - if ( output_buffer->size() >= TERMINAL_OUTPUT_BUFFER_SIZE ) - flush_out(); - - return ch; -} - -//---------------------------------------------------------------------- -void FVTerm::flush_out() -{ - while ( ! output_buffer->empty() ) - { - Fputchar (output_buffer->front()); - output_buffer->pop(); - } - - std::fflush(stdout); -} - // protected methods of FVTerm //---------------------------------------------------------------------- @@ -2445,6 +1856,33 @@ FVTerm::char_data FVTerm::getOverlappedCharacter ( int x return getCharacter (overlapped_character, x, y, obj); } +//---------------------------------------------------------------------- +void FVTerm::processTerminalUpdate() +{ + // Retains terminal updates if there are unprocessed inputs + static const int max_skip = 8; + + if ( terminal_update_pending ) + { + if ( ! unprocessedInput() ) + { + updateTerminal(); + terminal_update_pending = false; + skipped_terminal_update = 0; + } + else if ( skipped_terminal_update > max_skip ) + { + force_terminal_update = true; + updateTerminal(); + force_terminal_update = false; + terminal_update_pending = false; + skipped_terminal_update = 0; + } + else + skipped_terminal_update++; + } +} + //---------------------------------------------------------------------- void FVTerm::startTerminalUpdate() { @@ -2459,6 +1897,18 @@ void FVTerm::finishTerminalUpdate() terminal_update_complete = true; } +//---------------------------------------------------------------------- +void FVTerm::flush_out() +{ + while ( ! output_buffer->empty() ) + { + Fputchar (output_buffer->front()); + output_buffer->pop(); + } + + std::fflush(stdout); +} + // private methods of FVTerm //---------------------------------------------------------------------- @@ -2568,6 +2018,366 @@ void FVTerm::finish() delete term_pos; } +//---------------------------------------------------------------------- +bool FVTerm::clearTerm (int fillchar) +{ + // Clear the real terminal and put cursor at home + char*& cl = tcap[fc::t_clear_screen].string; + char*& cd = tcap[fc::t_clr_eos].string; + char*& cb = tcap[fc::t_clr_eol].string; + bool ut = FTermcap::background_color_erase; + char_data* next = &next_attribute; + bool normal = isNormal(next); + appendAttributes(next); + + if ( ! ( (cl || cd || cb) && (normal || ut) ) + || fillchar != ' ' ) + { + return false; + } + + if ( cl ) + { + appendOutputBuffer (cl); + term_pos->setPoint(0,0); + } + else if ( cd ) + { + setTermXY (0, 0); + appendOutputBuffer (cd); + term_pos->setPoint(-1,-1); + } + else if ( cb ) + { + term_pos->setPoint(-1,-1); + + for (int i=0; i < getLineNumber(); i++) + { + setTermXY (0, i); + appendOutputBuffer (cb); + } + + setTermXY (0,0); + } + + flush_out(); + return true; +} + +//---------------------------------------------------------------------- +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; + int term_width = vt->width - 1; + int term_height = vt->height - 1; + + if ( xmin <= xmax ) + { + bool is_eol_clean = false; + bool draw_leading_ws = false; + 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 ( ce && min_char->code == ' ' ) + { + uInt beginning_whitespace = 1; + bool normal = isNormal(min_char); + + for (uInt x=xmin+1; x < uInt(vt->width); x++) + { + char_data* ch = &vt->text[y * uInt(vt->width) + x]; + + if ( *min_char == *ch ) + beginning_whitespace++; + else + break; + } + + if ( beginning_whitespace == uInt(vt->width) - xmin + && (ut || normal) + && clr_eol_length < int(beginning_whitespace) ) + is_eol_clean = true; + } + + if ( ! is_eol_clean ) + { + // leading whitespace + if ( cb && first_char->code == ' ' ) + { + uInt leading_whitespace = 1; + bool normal = isNormal(first_char); + + for (uInt x=1; x < uInt(vt->width); x++) + { + char_data* ch = &vt->text[y * uInt(vt->width) + x]; + + if ( *first_char == *ch ) + leading_whitespace++; + else + break; + } + + if ( leading_whitespace > xmin + && (ut || normal) + && clr_bol_length < int(leading_whitespace) ) + { + draw_leading_ws = true; + xmin = leading_whitespace - 1; + } + } + + // tailing whitespace + if ( ce && last_char->code == ' ' ) + { + uInt tailing_whitespace = 1; + bool normal = isNormal(last_char); + + for (uInt x=uInt(vt->width)-1; x > 0 ; x--) + { + char_data* ch = &vt->text[y * uInt(vt->width) + x]; + + if ( *last_char == *ch ) + tailing_whitespace++; + else + break; + } + + if ( tailing_whitespace > uInt(vt->width) - xmax + && (ut || normal) + && clr_bol_length < int(tailing_whitespace) ) + { + draw_tailing_ws = true; + xmax = uInt(vt->width) - tailing_whitespace; + } + } + } + + 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); + } + + for (uInt x=xmin; x <= xmax; x++) + { + char_data* print_char; + print_char = &vt->text[y * uInt(vt->width) + x]; + print_char->printed = true; + + // skip character with no changes + if ( print_char->no_changes ) + { + uInt count = 1; + + for (uInt i=x+1; i <= xmax; i++) + { + char_data* ch = &vt->text[y * uInt(vt->width) + i]; + + if ( ch->no_changes ) + count++; + else + break; + } + + if ( count > uInt(cursor_addres_lengths) ) + { + setTermXY (int(x + count), int(y)); + x = x + count - 1; + continue; + } + } + + // 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++) + { + char_data* ch = &vt->text[y * uInt(vt->width) + i]; + + if ( *print_char == *ch ) + whitespace++; + else + break; + } + + if ( whitespace == 1 ) + { + appendCharacter (print_char); + markAsPrinted (x, y); + } + else + { + uInt start_pos = x; + + 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); + } + + markAsPrinted (start_pos, x, y); + } + } + else if ( rp ) // Repeat one character n-fold + { + uInt repetitions = 1; + + for (uInt i=x+1; i <= xmax; i++) + { + char_data* ch = &vt->text[y * uInt(vt->width) + i]; + + if ( *print_char == *ch ) + repetitions++; + else + break; + } + + if ( repetitions == 1 ) + { + appendCharacter (print_char); + markAsPrinted (x, y); + } + else + { + uInt start_pos = x; + + 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); + } + + markAsPrinted (start_pos, x, y); + } + } + else // General character output + { + appendCharacter (print_char); + markAsPrinted (x, y); + } + } + + 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 ) + term_pos->x_ref()--; + else + { + if ( FTermcap::eat_nl_glitch ) + { + term_pos->setPoint(-1,-1); + } + else if ( FTermcap::automatic_right_margin ) + { + term_pos->setX(0); + term_pos->y_ref()++; + } + else + term_pos->x_ref()--; + } + } +} + +//---------------------------------------------------------------------- +bool FVTerm::updateTerminalCursor() +{ + // Updates the input cursor visibility and the position + if ( vterm && vterm->input_cursor_visible ) + { + int x = vterm->input_cursor_x; + int y = vterm->input_cursor_y; + + if ( isInsideTerminal(x, y) ) + { + setTermXY (x,y); + showCursor(); + return true; + } + } + else + hideCursor(); + + return false; +} + +//---------------------------------------------------------------------- +bool FVTerm::isInsideTerminal (int x, int y) +{ + // Check whether the coordinates are within the virtual terminal + FRect term_geometry (0, 0, getColumnNumber(), getLineNumber()); + + if ( term_geometry.contains(x,y) ) + return true; + else + return false; +} + //---------------------------------------------------------------------- inline void FVTerm::markAsPrinted (uInt pos, uInt line) { @@ -2584,3 +2394,199 @@ inline void FVTerm::markAsPrinted (uInt from, uInt to, uInt line) for (uInt x=from; x <= to; x++) vterm->text[line * uInt(vterm->width) + x].printed = true; } + +//---------------------------------------------------------------------- +inline void FVTerm::newFontChanges (char_data*& next_char) +{ + // NewFont special cases + if ( NewFont ) + { + switch ( next_char->code ) + { + case fc::LowerHalfBlock: + next_char->code = fc::UpperHalfBlock; + // fall through + case fc::NF_rev_left_arrow2: + case fc::NF_rev_right_arrow2: + case fc::NF_rev_border_corner_upper_right: + case fc::NF_rev_border_line_right: + case fc::NF_rev_border_line_vertical_left: + case fc::NF_rev_border_corner_lower_right: + case fc::NF_rev_up_arrow2: + case fc::NF_rev_down_arrow2: + case fc::NF_rev_up_arrow1: + case fc::NF_rev_down_arrow1: + case fc::NF_rev_left_arrow1: + case fc::NF_rev_right_arrow1: + case fc::NF_rev_menu_button1: + case fc::NF_rev_menu_button2: + case fc::NF_rev_up_pointing_triangle1: + case fc::NF_rev_down_pointing_triangle1: + case fc::NF_rev_up_pointing_triangle2: + case fc::NF_rev_down_pointing_triangle2: + case fc::NF_rev_menu_button3: + case fc::NF_rev_border_line_right_and_left: + // swap foreground and background color + std::swap (next_char->fg_color, next_char->bg_color); + break; + + default: + break; + } + } +} + +//---------------------------------------------------------------------- +inline void FVTerm::charsetChanges (char_data*& next_char) +{ + if ( Encoding == fc::UTF8 ) + return; + + uInt code = uInt(next_char->code); + uInt ch = charEncode(code); + + if ( ch != code ) + { + if ( ch == 0 ) + { + next_char->code = int(charEncode(code, fc::ASCII)); + return; + } + + next_char->code = int(ch); + + if ( Encoding == fc::VT100 ) + next_char->alt_charset = true; + else if ( Encoding == fc::PC ) + { + next_char->pc_charset = true; + + if ( isXTerminal() && hasUTF8() && ch < 0x20 ) // Character 0x00..0x1f + next_char->code = int(charEncode(code, fc::ASCII)); + } + } +} + +//---------------------------------------------------------------------- +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); + + appendAttributes (next_char); + appendOutputBuffer (next_char->code); +} + +//---------------------------------------------------------------------- +inline void FVTerm::appendAttributes (char_data*& next_attr) +{ + char* attr_str; + char_data* term_attr = &term_attribute; + + // generate attribute string for the next character + attr_str = changeAttribute (term_attr, next_attr); + + if ( attr_str ) + appendOutputBuffer (attr_str); +} + +//---------------------------------------------------------------------- +int FVTerm::appendLowerRight (char_data*& screen_char) +{ + char* SA = tcap[fc::t_enter_am_mode].string; + char* RA = tcap[fc::t_exit_am_mode].string; + + if ( ! FTermcap::automatic_right_margin ) + { + appendChar (screen_char); + } + else if ( SA && RA ) + { + appendOutputBuffer (RA); + appendChar (screen_char); + appendOutputBuffer (SA); + } + else + { + int x, y; + char* IC = tcap[fc::t_parm_ich].string; + char* im = tcap[fc::t_enter_insert_mode].string; + char* ei = tcap[fc::t_exit_insert_mode].string; + char* ip = tcap[fc::t_insert_padding].string; + char* ic = tcap[fc::t_insert_character].string; + + x = getColumnNumber() - 2; + y = getLineNumber() - 1; + setTermXY (x, y); + appendChar (screen_char); + term_pos->x_ref()++; + + setTermXY (x, y); + screen_char--; + + if ( IC ) + { + appendOutputBuffer (tparm(IC, 1)); + appendChar (screen_char); + } + else if ( im && ei ) + { + appendOutputBuffer (im); + appendChar (screen_char); + + if ( ip ) + appendOutputBuffer (ip); + + appendOutputBuffer (ei); + } + else if ( ic ) + { + appendOutputBuffer (ic); + appendChar (screen_char); + + if ( ip ) + appendOutputBuffer (ip); + } + } + + return screen_char->code; +} + +//---------------------------------------------------------------------- +inline void FVTerm::appendOutputBuffer (std::string& s) +{ + const char* c_string = s.c_str(); + tputs (c_string, 1, appendOutputBuffer); +} + +//---------------------------------------------------------------------- +inline void FVTerm::appendOutputBuffer (const char* s) +{ + tputs (s, 1, appendOutputBuffer); +} + +//---------------------------------------------------------------------- +int FVTerm::appendOutputBuffer (int ch) +{ + output_buffer->push(ch); + + if ( output_buffer->size() >= TERMINAL_OUTPUT_BUFFER_SIZE ) + flush_out(); + + return ch; +} diff --git a/src/fvterm.h b/src/fvterm.h index 8068e4c1..f91f00fb 100644 --- a/src/fvterm.h +++ b/src/fvterm.h @@ -98,7 +98,6 @@ class FVTerm : public FObject, public FTerm // Mutators static void setTermXY (register int, register int); - static bool clearTerm (int = ' '); static bool hideCursor (bool); static bool hideCursor(); static bool showCursor(); @@ -190,6 +189,8 @@ class FVTerm : public FObject, public FTerm static bool isTransShadow(); static bool isInheritBackground(); + // Methods + void clearArea (int = ' '); void createVTerm (const FRect&); void createVTerm (int, int); static void resizeVTerm (const FRect&); @@ -197,10 +198,6 @@ class FVTerm : public FObject, public FTerm static void putVTerm(); static void updateTerminal (bool); static void updateTerminal(); - static void updateTerminalLine (uInt); - static bool updateTerminalCursor(); - static void processTerminalUpdate(); - static bool isInsideTerminal (int, int); int printf (const wchar_t*, ...); int printf (const char*, ...) @@ -223,16 +220,6 @@ class FVTerm : public FObject, public FTerm int print (int); int print (term_area*, int); FVTerm& print(); - 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&); - static void appendOutputBuffer (const char*); - static int appendOutputBuffer (int); - static void flush_out(); protected: // Enumeration @@ -302,8 +289,10 @@ class FVTerm : public FObject, public FTerm static char_data getCoveredCharacter (int, int, FVTerm*); static char_data getOverlappedCharacter (const FPoint&, FVTerm*); static char_data getOverlappedCharacter (int, int, FVTerm*); + static void processTerminalUpdate(); static void startTerminalUpdate(); static void finishTerminalUpdate(); + static void flush_out(); // Data Members static term_area* vterm; // virtual terminal @@ -335,8 +324,21 @@ class FVTerm : public FObject, public FTerm // Methods void init(); void finish(); + static bool clearTerm (int = ' '); + static void updateTerminalLine (uInt); + static bool updateTerminalCursor(); + static bool isInsideTerminal (int, int); static void markAsPrinted (uInt, uInt); static void markAsPrinted (uInt, uInt, uInt); + 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&); + static void appendOutputBuffer (const char*); + static int appendOutputBuffer (int); // Data Members static std::queue* output_buffer; diff --git a/test/opti-move.cpp b/test/opti-move.cpp index 1d0c7168..85fd69cc 100644 --- a/test/opti-move.cpp +++ b/test/opti-move.cpp @@ -138,7 +138,7 @@ int main (int argc, char* argv[]) terminal->setTermXY(0,0); terminal->setNormal(); - terminal->clearTerm(); + terminal->clearArea(); std::cout << "Terminal: " << terminal->getTermType() << "\r\n"; std::cout << " Columns: 0.." << xmax << "\r\n";