From 9073a3bb89b2835a0616642ec94b3d58d07e8c26 Mon Sep 17 00:00:00 2001 From: Markus Gans Date: Sat, 2 Dec 2023 20:24:42 +0100 Subject: [PATCH] Reduce the complexity of some internal methods --- examples/mouse.cpp | 2 +- final/fwidget.cpp | 2 +- final/output/tty/foptiattr.cpp | 201 ++++++++++++++------------- final/output/tty/foptiattr.h | 6 + final/output/tty/foptimove.cpp | 78 +++++++---- final/output/tty/foptimove.h | 4 + final/output/tty/fterm.cpp | 140 ++++++++++++++----- final/output/tty/fterm.h | 7 + final/output/tty/fterm_functions.cpp | 3 +- final/output/tty/ftermdetection.cpp | 43 ++++-- final/output/tty/ftermdetection.h | 6 + final/output/tty/sgr_optimizer.cpp | 41 +++--- final/output/tty/sgr_optimizer.h | 1 + final/vterm/fvterm.cpp | 23 ++- final/vterm/fvterm.h | 28 ++-- final/vterm/fvtermbuffer.cpp | 47 +++---- final/vterm/fvtermbuffer.h | 12 +- final/widget/fwindow.cpp | 12 +- test/fmouse-test.cpp | 2 +- test/foptiattr-test.cpp | 6 + test/fvterm-test.cpp | 22 +-- 21 files changed, 414 insertions(+), 272 deletions(-) diff --git a/examples/mouse.cpp b/examples/mouse.cpp index 8d650f38..aca6890f 100644 --- a/examples/mouse.cpp +++ b/examples/mouse.cpp @@ -387,7 +387,7 @@ void MouseDraw::setGeometry ( const FPoint& p, const FSize& s, bool adjust) const FSize no_shadow{0, 0}; const int old_w = canvas->size.width; const int old_h = canvas->size.height; - resizeArea (scroll_geometry, no_shadow, canvas.get()); + resizeArea ({scroll_geometry, no_shadow}, canvas.get()); if ( old_w != canvas->size.width || old_h != canvas->size.height ) { diff --git a/final/fwidget.cpp b/final/fwidget.cpp index e907a3a5..9d6c3021 100644 --- a/final/fwidget.cpp +++ b/final/fwidget.cpp @@ -858,7 +858,7 @@ void FWidget::resize() return; resizeVTerm (term_geometry.getSize()); - resizeArea (term_geometry, getShadow(), getVirtualDesktop()); + resizeArea ({term_geometry, getShadow()}, getVirtualDesktop()); startDrawing(); // Avoid flickering - no update during adjustment adjustSizeGlobal(); finishDrawing(); diff --git a/final/output/tty/foptiattr.cpp b/final/output/tty/foptiattr.cpp index d3176961..3af77861 100644 --- a/final/output/tty/foptiattr.cpp +++ b/final/output/tty/foptiattr.cpp @@ -492,41 +492,17 @@ auto FOptiAttr::isNormal (const FChar& ch) -> bool void FOptiAttr::initialize() { F_color.monochron = F_color.max_color < 8; - - if ( caused_reset_attributes(F_bold.off.cap) ) - F_bold.off.caused_reset = true; - - if ( caused_reset_attributes(F_dim.off.cap) ) - F_dim.off.caused_reset = true; - - if ( caused_reset_attributes(F_italics.off.cap) ) - F_italics.off.caused_reset = true; - - if ( caused_reset_attributes(F_blink.off.cap) ) - F_blink.off.caused_reset = true; - - if ( caused_reset_attributes ( F_underline.off.cap - , all_tests & ~same_like_ue) ) - F_underline.off.caused_reset = true; - - if ( caused_reset_attributes(F_reverse.off.cap) ) - F_reverse.off.caused_reset = true; - - if ( caused_reset_attributes(F_secure.off.cap) ) - F_secure.off.caused_reset = true; - - if ( caused_reset_attributes(F_protected.off.cap) ) - F_protected.off.caused_reset = true; - - if ( caused_reset_attributes(F_crossed_out.off.cap) ) - F_crossed_out.off.caused_reset = true; - - if ( caused_reset_attributes(F_dbl_underline.off.cap) ) - F_dbl_underline.off.caused_reset = true; - - if ( caused_reset_attributes ( F_standout.off.cap - , all_tests & ~same_like_se) ) - F_standout.off.caused_reset = true; + init_reset_attribute (F_bold.off); + init_reset_attribute (F_dim.off); + init_reset_attribute (F_italics.off); + init_reset_attribute (F_blink.off); + init_reset_attribute (F_underline.off, all_tests & ~same_like_ue); + init_reset_attribute (F_reverse.off); + init_reset_attribute (F_secure.off); + init_reset_attribute (F_protected.off); + init_reset_attribute (F_crossed_out.off); + init_reset_attribute (F_dbl_underline.off); + init_reset_attribute (F_standout.off, all_tests & ~same_like_se); if ( hasCharsetEquivalence() ) alt_equal_pc_charset = true; @@ -1176,66 +1152,56 @@ void FOptiAttr::change_color (FChar& term, FChar& next) return; } - if ( next.fg_color != FColor::Default ) - next.fg_color %= uInt16(F_color.max_color); - - if ( next.bg_color != FColor::Default ) - next.bg_color %= uInt16(F_color.max_color); - + normalizeColor (next.fg_color); + normalizeColor (next.bg_color); FColor fg = next.fg_color; FColor bg = next.bg_color; - - if ( fg == FColor::Default || bg == FColor::Default ) - change_to_default_color (term, next, fg, bg); + handleDefaultColors (term, next, fg, bg); if ( fake_reverse && fg == FColor::Default && bg == FColor::Default ) return; - if ( fake_reverse - && (next.attr.bit.reverse || next.attr.bit.standout) ) + if ( fake_reverse && (next.attr.bit.reverse || next.attr.bit.standout) ) { std::swap (fg, bg); - - if ( fg == FColor::Default || bg == FColor::Default ) - setTermDefaultColor(term); + handleDefaultColors (term, next, fg, bg); } change_current_color (term, fg, bg); - term.fg_color = next.fg_color; term.bg_color = next.bg_color; } +//---------------------------------------------------------------------- +inline void FOptiAttr::normalizeColor (FColor& color) noexcept +{ + if ( color != FColor::Default ) + color %= uInt16(F_color.max_color); +} + +//---------------------------------------------------------------------- +inline void FOptiAttr::handleDefaultColors ( FChar& term, FChar& next + , FColor& fg, FColor& bg ) +{ + if ( fg == FColor::Default || bg == FColor::Default ) + change_to_default_color(term, next, fg, bg); +} + //---------------------------------------------------------------------- inline void FOptiAttr::change_to_default_color ( FChar& term, FChar& next , FColor& fg, FColor& bg ) { if ( F_color.ansi_default_color ) { - if ( fg == FColor::Default && term.fg_color != FColor::Default - && bg == FColor::Default && term.bg_color != FColor::Default ) - { - setTermDefaultColor(term); - } - else if ( fg == FColor::Default && term.fg_color != FColor::Default ) - { - std::string sgr_39{CSI "39m"}; - append_sequence (sgr_39); - term.fg_color = FColor::Default; - } - else if ( bg == FColor::Default && term.bg_color != FColor::Default ) - { - const char* sgr_49; - const auto& op = F_color.orig_pair.cap; - - if ( op && std::memcmp (op, CSI "39;49;25m", 11) == 0 ) - sgr_49 = CSI "49;25m"; - else - sgr_49 = CSI "49m"; + auto set_default_fg = fg == FColor::Default && term.fg_color != FColor::Default; + auto set_default_bg = bg == FColor::Default && term.bg_color != FColor::Default; - append_sequence (sgr_49); - term.bg_color = FColor::Default; - } + if ( set_default_fg && set_default_bg ) + setTermDefaultColor(term); + else if ( set_default_fg ) + setDefaultForeground(term); + else if ( set_default_bg ) + setDefaultBackground(term); } else if ( ! setTermDefaultColor(term) ) { @@ -1245,6 +1211,29 @@ inline void FOptiAttr::change_to_default_color ( FChar& term, FChar& next } } +//---------------------------------------------------------------------- +inline void FOptiAttr::setDefaultForeground (FChar& term) +{ + std::string sgr_39{CSI "39m"}; + append_sequence (sgr_39); + term.fg_color = FColor::Default; +} + +//---------------------------------------------------------------------- +inline void FOptiAttr::setDefaultBackground (FChar& term) +{ + const char* sgr_49; + const auto& op = F_color.orig_pair.cap; + + if ( op && std::memcmp (op, CSI "39;49;25m", 11) == 0 ) + sgr_49 = CSI "49;25m"; + else + sgr_49 = CSI "49m"; + + append_sequence (sgr_49); + term.bg_color = FColor::Default; +} + //---------------------------------------------------------------------- inline void FOptiAttr::change_current_color ( const FChar& term , const FColor fg, const FColor bg ) @@ -1254,39 +1243,38 @@ inline void FOptiAttr::change_current_color ( const FChar& term const auto& Sf = F_color.foreground.cap; const auto& Sb = F_color.background.cap; const auto& sp = F_color.color_pair.cap; - const auto& b0_reverse_mask = internal::var::b0_reverse_mask; - const bool frev ( ( (changes.off.attr.byte[0] & b0_reverse_mask) - || (term.attr.byte[0] & b0_reverse_mask) ) && fake_reverse ); + const bool frev = fake_reverse_color_change(term); + constexpr auto ANSI = 0; + constexpr auto VGA = 1; - auto append_color_sequence = [this] (const auto& cap, const uInt16 value) + auto apply_color_change = [this, &term, &fg, &bg, &frev] ( const char* fg_cap + , const char* bg_cap + , int cm ) { - const auto& color_str = FTermcap::encodeParameter(cap, value); - append_sequence(color_str); - }; + if ( ! fg_cap || ! bg_cap ) + return false; - if ( AF && AB ) - { - if ( has_foreground_changes(term, fg, frev) ) - append_color_sequence(AF, uInt16(vga2ansi(fg))); + const auto fg_value = ( cm == VGA ) ? uInt16(vga2ansi(fg)) : uInt16(fg); + const auto bg_value = ( cm == VGA ) ? uInt16(vga2ansi(bg)) : uInt16(bg); - if ( has_background_changes(term, bg, frev) ) - append_color_sequence(AB, uInt16(vga2ansi(bg))); - } - else if ( Sf && Sb ) - { if ( has_foreground_changes(term, fg, frev) ) - append_color_sequence(Sf, uInt16(fg)); + append_sequence(FTermcap::encodeParameter(fg_cap, fg_value)); if ( has_background_changes(term, bg, frev) ) - append_color_sequence(Sb, uInt16(bg)); - } - else if ( sp ) - { - const auto ansi_fg = uInt16(vga2ansi(fg)); - const auto ansi_bg = uInt16(vga2ansi(bg)); - const auto& color_str = FTermcap::encodeParameter(sp, ansi_fg, ansi_bg); - append_sequence (color_str); - } + append_sequence(FTermcap::encodeParameter(bg_cap, bg_value)); + + return true; + }; + + const auto& apply_AF_AB = apply_color_change(AF, AB, VGA); + const auto& apply_Sf_Sb = apply_color_change(Sf, Sb, ANSI); + + if ( apply_AF_AB || apply_Sf_Sb || ! sp ) + return; + + const auto fg_value = uInt16(vga2ansi(fg)); + const auto bg_value = uInt16(vga2ansi(bg)); + append_sequence (FTermcap::encodeParameter(sp, fg_value, bg_value)); } //---------------------------------------------------------------------- @@ -1325,6 +1313,21 @@ auto FOptiAttr::caused_reset_attributes (const char cap[], uChar test) const -> || ( (test & same_like_me) && me && std::strcmp (cap, me) == 0 ); } +//---------------------------------------------------------------------- +void FOptiAttr::init_reset_attribute (Capability& off, uChar test) +{ + if ( caused_reset_attributes(off.cap, test) ) + off.caused_reset = true; +} + +//---------------------------------------------------------------------- +inline auto FOptiAttr::fake_reverse_color_change (const FChar& term) const -> bool +{ + const auto& b0_reverse_mask = internal::var::b0_reverse_mask; + return ( (changes.off.attr.byte[0] & b0_reverse_mask) + || (term.attr.byte[0] & b0_reverse_mask) ) && fake_reverse; +} + //---------------------------------------------------------------------- inline auto FOptiAttr::hasCharsetEquivalence() const -> bool { diff --git a/final/output/tty/foptiattr.h b/final/output/tty/foptiattr.h index ff671194..b6ec6ac0 100644 --- a/final/output/tty/foptiattr.h +++ b/final/output/tty/foptiattr.h @@ -262,11 +262,17 @@ class FOptiAttr final void changeAttributeSGR (FChar&, FChar&); void changeAttributeSeparately (FChar&, FChar&); void change_color (FChar&, FChar&); + void normalizeColor (FColor&) noexcept; + void handleDefaultColors (FChar&, FChar&, FColor&, FColor&); void change_to_default_color (FChar&, FChar&, FColor&, FColor&); + void setDefaultForeground (FChar&); + void setDefaultBackground (FChar&); void change_current_color (const FChar&, const FColor, const FColor); void resetAttribute (FChar&) const; void reset (FChar&) const; auto caused_reset_attributes (const char[], uChar = all_tests) const -> bool; + void init_reset_attribute (Capability&, uChar = all_tests); + auto fake_reverse_color_change (const FChar& term) const -> bool; auto hasCharsetEquivalence() const -> bool; static auto getNoColorVideoHandlerTable() -> const NoColorVideoHandlerTable&; static auto getAttributeOnHandlers() -> const AttributeHandlers&; diff --git a/final/output/tty/foptimove.cpp b/final/output/tty/foptimove.cpp index ef2620f1..55b47141 100644 --- a/final/output/tty/foptimove.cpp +++ b/final/output/tty/foptimove.cpp @@ -1037,44 +1037,19 @@ void FOptiMove::moveByMethod ( int method break; case 2: - if ( cursor.carriage_return.cap ) - { - move_buf = cursor.carriage_return.cap; - relativeMove (temp_result, 0, yold, xnew, ynew); - move_buf.append(temp_result); - } + moveWithCarriageReturn (yold, xnew, ynew); break; case 3: - move_buf = cursor.home.cap; - { - relativeMove (temp_result, 0, 0, xnew, ynew); - move_buf.append(temp_result); - } + moveWithHome (xnew, ynew); break; case 4: - move_buf = cursor.to_ll.cap; - { - int down = int(screen.height) - 1; - relativeMove (temp_result, 0, down, xnew, ynew); - move_buf.append(temp_result); - } + moveWithToLL (xnew, ynew); break; case 5: - if ( xold >= 0 ) - move_buf = cursor.carriage_return.cap; - else - move_buf.clear(); - - move_buf.append(cursor.left.cap); - { - int x = int(screen.width) - 1; - int y = yold - 1; - relativeMove (temp_result, x, y, xnew, ynew); - move_buf.append(temp_result); - } + moveWithCRAndWrapToLeft (xold, yold, xnew, ynew); break; default: @@ -1082,6 +1057,51 @@ void FOptiMove::moveByMethod ( int method } } +//---------------------------------------------------------------------- +inline void FOptiMove::moveWithCarriageReturn (int yold, int xnew, int ynew) +{ + if ( ! cursor.carriage_return.cap ) + return; + + move_buf = cursor.carriage_return.cap; + relativeMove (temp_result, 0, yold, xnew, ynew); + move_buf.append(temp_result); +} + +//---------------------------------------------------------------------- +inline void FOptiMove::moveWithHome (int xnew, int ynew) +{ + move_buf = cursor.home.cap; + relativeMove (temp_result, 0, 0, xnew, ynew); + move_buf.append(temp_result); +} + +//---------------------------------------------------------------------- +inline void FOptiMove::moveWithToLL (int xnew, int ynew) +{ + move_buf = cursor.to_ll.cap; + int down = int(screen.height) - 1; + relativeMove (temp_result, 0, down, xnew, ynew); + move_buf.append(temp_result); +} + +//---------------------------------------------------------------------- +inline void FOptiMove::moveWithCRAndWrapToLeft ( int xold, int yold + , int xnew, int ynew ) +{ + if ( xold >= 0 ) + move_buf = cursor.carriage_return.cap; + else + move_buf.clear(); + + move_buf.append(cursor.left.cap); + int x = int(screen.width) - 1; + int y = yold - 1; + relativeMove (temp_result, x, y, xnew, ynew); + move_buf.append(temp_result); +} + + // FOptiMove non-member function //---------------------------------------------------------------------- void printDurations (const FOptiMove& om) diff --git a/final/output/tty/foptimove.h b/final/output/tty/foptimove.h index a25081d8..38528155 100644 --- a/final/output/tty/foptimove.h +++ b/final/output/tty/foptimove.h @@ -239,6 +239,10 @@ class FOptiMove final auto isMethod4Faster (int&, int, int) -> bool; auto isMethod5Faster (int&, int, int, int) -> bool; void moveByMethod (int, int, int, int, int); + void moveWithCarriageReturn (int, int, int); + void moveWithHome (int, int); + void moveWithToLL (int, int); + void moveWithCRAndWrapToLeft (int, int, int, int); // Data members Cursor cursor; diff --git a/final/output/tty/fterm.cpp b/final/output/tty/fterm.cpp index 507c300d..6eb4e095 100644 --- a/final/output/tty/fterm.cpp +++ b/final/output/tty/fterm.cpp @@ -1081,28 +1081,51 @@ void FTerm::init_cygwin_charmap() if ( ! data.isTermType(FTermType::cygwin) ) return; + updatePCEncodingForCygwin(); + updateCharMappingForCygwin(); +} + +//---------------------------------------------------------------------- +void FTerm::updatePCEncodingForCygwin() +{ // PC encoding changes + for (auto&& entry : FCharMap::getCharEncodeMap()) { - if ( entry.unicode == UniChar::BlackUpPointingTriangle ) // ▲ - entry.pc = 0x18; - - if ( entry.unicode == UniChar::BlackDownPointingTriangle ) // ▼ - entry.pc = 0x19; - - if ( entry.unicode == UniChar::InverseBullet // ◘ - || entry.unicode == UniChar::InverseWhiteCircle // ◙ - || entry.unicode == UniChar::UpDownArrow // ↕ - || entry.unicode == UniChar::LeftRightArrow // ↔ - || entry.unicode == UniChar::DoubleExclamationMark // ‼ - || entry.unicode == UniChar::BlackRectangle // ▬ - || entry.unicode == UniChar::RightwardsArrow // → - || entry.unicode == UniChar::Section // § - || entry.unicode == UniChar::SquareRoot ) // SquareRoot √ - entry.pc = entry.ascii; + switch ( UniChar(entry.unicode) ) + { + case UniChar::BlackUpPointingTriangle: // ▲ + entry.pc = 0x18; + break; + + case UniChar::BlackDownPointingTriangle: // ▼ + entry.pc = 0x19; + break; + + case UniChar::InverseBullet: // ◘ + case UniChar::InverseWhiteCircle: // ◙ + case UniChar::UpDownArrow: // ↕ + case UniChar::LeftRightArrow: // ↔ + case UniChar::DoubleExclamationMark: // ‼ + case UniChar::BlackRectangle: // ▬ + case UniChar::RightwardsArrow: // → + case UniChar::Section: // § + case UniChar::SquareRoot: // SquareRoot √ + entry.pc = entry.ascii; + break; + + default: + return; + } } +} +//---------------------------------------------------------------------- +void FTerm::updateCharMappingForCygwin() +{ // General encoding changes + + static auto& data = FTermData::getInstance(); auto& sub_map = data.getCharSubstitutionMap(); sub_map.setCharMapping({L'•', L'*'}); sub_map.setCharMapping({L'●', L'*'}); @@ -1262,13 +1285,26 @@ auto FTerm::init_font() -> bool //---------------------------------------------------------------------- void FTerm::init_locale() { - // Init current locale + // Initialize current locale - static const auto& data = FTermData::getInstance(); - const auto& termtype = data.getTermType(); const char* locale_name = std::setlocale (LC_ALL, ""); std::setlocale (LC_NUMERIC, ""); + // Initialize special terminal locales + locale_name = init_xterm_locale (locale_name); + locale_name = init_tera_term_locale (locale_name); + locale_name = init_kterm_locale (locale_name); + locale_name = init_sun_locale (locale_name); + locale_name = init_locale_if_not_found (locale_name); + + // Fallback to C + if ( ! locale_name ) + std::setlocale (LC_ALL, "C"); +} + +//---------------------------------------------------------------------- +auto FTerm::init_xterm_locale (const char* locale_name) -> const char* +{ // Get XTERM_LOCALE const char* locale_xterm = std::getenv("XTERM_LOCALE"); @@ -1276,46 +1312,80 @@ void FTerm::init_locale() if ( locale_xterm ) locale_name = std::setlocale (LC_ALL, locale_xterm); - // TeraTerm can not show UTF-8 character + return locale_name; +} + +//---------------------------------------------------------------------- +auto FTerm::init_tera_term_locale (const char* locale_name) -> const char* +{ + // TeraTerm can not display UTF-8 characters + + static const auto& data = FTermData::getInstance(); + if ( data.isTermType(FTermType::tera_term) && ! std::strcmp(nl_langinfo(CODESET), "UTF-8") ) locale_name = std::setlocale (LC_ALL, "C"); - // Kterm + return locale_name; +} + +//---------------------------------------------------------------------- +auto FTerm::init_kterm_locale (const char* locale_name) -> const char* +{ + // Kterm can not display UTF-8 characters + + static const auto& data = FTermData::getInstance(); + if ( data.isTermType(FTermType::kterm) && ! std::strcmp(nl_langinfo(CODESET), "UTF-8") ) locale_name = std::setlocale (LC_ALL, "C"); - // Sun (color) workstation console can't show UTF-8 character + return locale_name; +} + +//---------------------------------------------------------------------- +auto FTerm::init_sun_locale (const char* locale_name) -> const char* +{ + // The Sun (color) workstation console can not display UTF-8 characters + + static const auto& data = FTermData::getInstance(); + const auto& termtype = data.getTermType(); + if ( termtype.substr(0, 3) == "sun" && ! std::strcmp(nl_langinfo(CODESET), "UTF-8") ) locale_name = std::setlocale (LC_ALL, "C"); + return locale_name; +} + +//---------------------------------------------------------------------- +auto FTerm::init_locale_if_not_found (const char* locale_name) -> const char* +{ // Try to found a meaningful content for locale_name + if ( locale_name ) - locale_name = std::setlocale (LC_CTYPE, nullptr); - else { - locale_name = std::getenv("LC_ALL"); + locale_name = std::setlocale (LC_CTYPE, nullptr); + return locale_name; + } - if ( ! locale_name ) - { - locale_name = std::getenv("LC_CTYPE"); + locale_name = std::getenv("LC_ALL"); - if ( ! locale_name ) - locale_name = std::getenv("LANG"); - } - } + if ( locale_name ) + return locale_name; + + locale_name = std::getenv("LC_CTYPE"); - // Fallback to C if ( ! locale_name ) - std::setlocale (LC_ALL, "C"); + locale_name = std::getenv("LANG"); + + return locale_name; } //---------------------------------------------------------------------- void FTerm::init_encoding() { - // detect encoding + // Detect encoding bool force_vt100{false}; // VT100 line drawing (G1 character set) init_encoding_set(); diff --git a/final/output/tty/fterm.h b/final/output/tty/fterm.h index 5812c8d5..3bd5ab7c 100644 --- a/final/output/tty/fterm.h +++ b/final/output/tty/fterm.h @@ -248,6 +248,8 @@ class FTerm final static void init_alt_charset(); static void init_pc_charset(); static void init_cygwin_charmap(); + static void updatePCEncodingForCygwin(); + static void updateCharMappingForCygwin(); static void init_teraterm_charmap(); static void init_fixed_max_color(); static void init_termcap(); @@ -256,6 +258,11 @@ class FTerm final static void init_optiAttr(); static auto init_font() -> bool; static void init_locale(); + static auto init_xterm_locale (const char*) -> const char*; + static auto init_tera_term_locale (const char*) -> const char*; + static auto init_kterm_locale (const char*) -> const char*; + static auto init_sun_locale (const char*) -> const char*; + static auto init_locale_if_not_found (const char*) -> const char*; static void init_encoding(); static void init_encoding_set(); static void init_term_encoding(); diff --git a/final/output/tty/fterm_functions.cpp b/final/output/tty/fterm_functions.cpp index e9d94ba8..853c0b8e 100644 --- a/final/output/tty/fterm_functions.cpp +++ b/final/output/tty/fterm_functions.cpp @@ -634,7 +634,8 @@ auto getColumnWidth (const wchar_t wchar) -> std::size_t static auto& char_width_cache = getCharWidthCacheInstance(); static const auto& fterm_data = FTermData::getInstance(); - if ( fterm_data.getTerminalEncoding() != Encoding::UTF8 && wchar != L'\0' ) + if ( ( fterm_data.getTerminalEncoding() != Encoding::UTF8 && wchar != L'\0' ) + || (wchar >= L' ' && wchar <= L'~') ) return 1U; const auto iter = char_width_cache.find(wchar); diff --git a/final/output/tty/ftermdetection.cpp b/final/output/tty/ftermdetection.cpp index 3f7b75ca..27d8e23c 100644 --- a/final/output/tty/ftermdetection.cpp +++ b/final/output/tty/ftermdetection.cpp @@ -236,7 +236,7 @@ auto FTermDetection::getTermBasename() const -> const char* void FTermDetection::termtypeAnalysis() { static auto& fterm_data = FTermData::getInstance(); - const std::vector> termTypeMap = + const TermTypeMap term_type_map = { // Cygwin console { L"cygwin" , FTermType::cygwin }, @@ -271,23 +271,44 @@ void FTermDetection::termtypeAnalysis() { L"alacritty" , FTermType::xterm } }; + auto iter = findMatchingTerm(term_type_map); + + if ( iter == term_type_map.end() ) // not found + return; + + fterm_data.setTermType (iter->second); + + if ( isTerminalWithoutDetection() ) + terminal_detection = false; + + handleScreenAndTmux(); +} + +//---------------------------------------------------------------------- +auto FTermDetection::findMatchingTerm (const TermTypeMap& map) -> TermTypeMap::const_iterator +{ auto search_predicate = [this] (const auto& pair) { return startsWithTermType(pair.first); }; - auto iter = std::find_if ( termTypeMap.begin() - , termTypeMap.end() - , search_predicate ); - if ( iter == termTypeMap.end() ) // not found - return; + return std::find_if (map.begin(), map.end(), search_predicate); +} - fterm_data.setTermType (iter->second); +//---------------------------------------------------------------------- +inline auto FTermDetection::isTerminalWithoutDetection() -> bool +{ + static auto& fterm_data = FTermData::getInstance(); - if ( fterm_data.isTermType(FTermType::ansi) - || fterm_data.isTermType(FTermType::sun_con) - || fterm_data.isTermType(FTermType::kterm) ) - terminal_detection = false; + return fterm_data.isTermType(FTermType::ansi) + || fterm_data.isTermType(FTermType::sun_con) + || fterm_data.isTermType(FTermType::kterm); +} + +//---------------------------------------------------------------------- +inline void FTermDetection::handleScreenAndTmux() +{ + static auto& fterm_data = FTermData::getInstance(); if ( fterm_data.isTermType(FTermType::screen) ) { diff --git a/final/output/tty/ftermdetection.h b/final/output/tty/ftermdetection.h index 9db0f735..17727f8e 100644 --- a/final/output/tty/ftermdetection.h +++ b/final/output/tty/ftermdetection.h @@ -101,6 +101,9 @@ class FTermDetection final int terminal_id_hardware{-1}; }; + // Using-declaration + using TermTypeMap = std::vector>; + // Methods void getSystemTermType(); auto getTTYtype() -> bool; @@ -111,6 +114,9 @@ class FTermDetection final template bool startsWithTermType (StringT&&) const; void termtypeAnalysis(); + auto findMatchingTerm (const TermTypeMap&) -> TermTypeMap::const_iterator; + auto isTerminalWithoutDetection() -> bool; + void handleScreenAndTmux(); void detectTerminal(); auto init_256colorTerminal() -> FString; auto get256colorEnvString() -> bool; diff --git a/final/output/tty/sgr_optimizer.cpp b/final/output/tty/sgr_optimizer.cpp index 46fc957a..91e1b77e 100644 --- a/final/output/tty/sgr_optimizer.cpp +++ b/final/output/tty/sgr_optimizer.cpp @@ -59,47 +59,44 @@ void SGRoptimizer::findParameter() { // Find ANSI X3.64 terminal SGR (Select Graphic Rendition) strings + std::size_t start{NOT_SET}; csi_parameter.clear(); + const std::size_t seq_length = seq.length(); - if ( seq.length() < 6 ) + if ( seq_length < 6 ) return; - std::size_t start{NOT_SET}; - bool esc{false}; - bool csi{false}; - // Find SGR parameter - for (std::size_t index{0}; index < seq.length(); ++index) + for (std::size_t index{0}; index < seq_length; ++index) { char ch = seq[index]; - if ( csi ) - { - if ( start == NOT_SET ) - start = index; - - if ( std::isdigit(ch) || ch == ';' ) - continue; + if ( isSGRStart(index) ) // Esc [ + start = index; - if ( ch == 'm') - csi_parameter.push_back({start, index}); + if ( std::isdigit(ch) || ch == ';' ) + continue; - esc = csi = false; + if ( start != NOT_SET && ch == 'm' ) + { + csi_parameter.push_back({start, index}); start = NOT_SET; } // Other content if ( ! csi_parameter.empty() && index > csi_parameter.back().end + 2 ) break; - - if ( esc && ch == '[' ) // Esc [ - csi = true; - - if ( ch == ESC[0] ) // Esc - esc = true; } } +//---------------------------------------------------------------------- +inline auto SGRoptimizer::isSGRStart (std::size_t index) -> bool +{ + return index > 1 + && seq[index - 2] == ESC[0] + && seq[index - 1] == '['; +} + //---------------------------------------------------------------------- void SGRoptimizer::combineParameter() { diff --git a/final/output/tty/sgr_optimizer.h b/final/output/tty/sgr_optimizer.h index 9fa8e3a4..bc4698b6 100644 --- a/final/output/tty/sgr_optimizer.h +++ b/final/output/tty/sgr_optimizer.h @@ -70,6 +70,7 @@ class SGRoptimizer final // Methods void findParameter(); + auto isSGRStart (std::size_t) -> bool; void combineParameter(); void handleSGRterminating ( const std::vector::const_iterator, std::size_t& , std::size_t, std::size_t ); diff --git a/final/vterm/fvterm.cpp b/final/vterm/fvterm.cpp index 82760f25..d26647b9 100644 --- a/final/vterm/fvterm.cpp +++ b/final/vterm/fvterm.cpp @@ -513,14 +513,14 @@ auto FVTerm::getPrintArea() -> FTermArea* } //---------------------------------------------------------------------- -auto FVTerm::createArea (const FRect& box, const FSize& shadow) -> std::unique_ptr +auto FVTerm::createArea (const FShadowBox& shadowbox) -> std::unique_ptr { // initialize virtual window auto area = std::make_unique(); area->setOwner(this); area->encoding = foutput->getEncoding(); - resizeArea (box, shadow, area.get()); + resizeArea (shadowbox, area.get()); return area; } @@ -530,22 +530,21 @@ auto FVTerm::createArea (const FRect& box) -> std::unique_ptr // initialize virtual window const auto no_shadow = FSize(0, 0); - return createArea (box, no_shadow); + return createArea ({box, no_shadow}); } //---------------------------------------------------------------------- -void FVTerm::resizeArea ( const FRect& box - , const FSize& shadow +void FVTerm::resizeArea ( const FShadowBox& shadowbox , FTermArea* area ) const { // Resize the virtual window to a new size - const auto position_x = box.getX(); - const auto position_y = box.getY(); - const auto width = int(box.getWidth()); - const auto height = int(box.getHeight()); - const auto rsw = int(shadow.getWidth()); - const auto bsh = int(shadow.getHeight()); + const auto position_x = shadowbox.box.getX(); + const auto position_y = shadowbox.box.getY(); + const auto width = int(shadowbox.box.getWidth()); + const auto height = int(shadowbox.box.getHeight()); + const auto rsw = int(shadowbox.shadow.getWidth()); + const auto bsh = int(shadowbox.shadow.getHeight()); assert ( position_y >= 0 && width > 0 && height > 0 && rsw >= 0 && bsh >= 0 ); @@ -602,7 +601,7 @@ void FVTerm::resizeArea (const FRect& box, FTermArea* area) const // Resize the virtual window to a new size const auto no_shadow = FSize(0, 0); - resizeArea (box, no_shadow, area); + resizeArea ({box, no_shadow}, area); } //---------------------------------------------------------------------- diff --git a/final/vterm/fvterm.h b/final/vterm/fvterm.h index da95cb01..8dcdec02 100644 --- a/final/vterm/fvterm.h +++ b/final/vterm/fvterm.h @@ -114,14 +114,7 @@ class FVTerm : public FVTermAttribute using FPreprocVector = std::vector>; using FVTermList = std::vector; - // Enumerations - enum class CoveredState - { - None, - Half, - Full - }; - + // Enumeration enum class TerminalUpdate { Stop, // No terminal refresh @@ -225,6 +218,12 @@ class FVTerm : public FVTermAttribute void flush() const; protected: + struct FShadowBox + { + FRect box{}; + FSize shadow{}; + }; + // Accessor virtual auto getPrintArea() -> FTermArea*; auto getChildPrintArea() const -> FTermArea*; @@ -245,9 +244,9 @@ class FVTerm : public FVTermAttribute auto isCursorHideable() const -> bool; // Methods - auto createArea (const FRect&, const FSize&) -> std::unique_ptr; + auto createArea (const FShadowBox&) -> std::unique_ptr; auto createArea (const FRect&) -> std::unique_ptr; - void resizeArea (const FRect&, const FSize&, FTermArea*) const; + void resizeArea (const FShadowBox&, FTermArea*) const; void resizeArea (const FRect&, FTermArea*) const; void restoreVTerm (const FRect&) const noexcept; auto updateVTermCursor (const FTermArea*) const noexcept -> bool; @@ -273,11 +272,12 @@ class FVTerm : public FVTermAttribute // Constants static constexpr int DEFAULT_MINIMIZED_HEIGHT = 1; - // Enumerations - enum class CharacterType + // Enumeration + enum class CoveredState { - Overlapped, - Covered + None, + Half, + Full }; // Methods diff --git a/final/vterm/fvtermbuffer.cpp b/final/vterm/fvtermbuffer.cpp index 5ec97a27..b887ec8e 100644 --- a/final/vterm/fvtermbuffer.cpp +++ b/final/vterm/fvtermbuffer.cpp @@ -75,10 +75,7 @@ auto FVTermBuffer::print (const FString& string) -> int { checkCapacity(data, data.size() + string.getLength()); getNextCharacterAttribute(); - const auto last = string.cend(); - auto cbegin = string.cbegin(); - auto iter = cbegin; - int char_width{0}; + UnicodeBoundary ucb{string.cbegin(), string.cend(), string.cbegin(), 0}; for (auto&& ch : string) { @@ -87,26 +84,26 @@ auto FVTermBuffer::print (const FString& string) -> int if ( width == 0 && ! ctrl_char ) // zero-width character { - if ( iter == cbegin ) - ++cbegin; + if ( ucb.iter == ucb.cbegin ) + ++ucb.cbegin; - ++iter; + ++ucb.iter; } - else if ( iter != cbegin ) - add(cbegin, iter, char_width); + else if ( ucb.iter != ucb.cbegin ) + add(ucb); - if ( iter == cbegin && (width > 0 || is7bit(ch)) ) // 1st char - ++iter; + if ( ucb.iter == ucb.cbegin && (width > 0 || is7bit(ch)) ) // 1st char + ++ucb.iter; if ( width > 0 ) - char_width += width; + ucb.char_width += width; if ( ctrl_char ) - add(cbegin, iter, char_width); + add(ucb); } - if ( iter == last ) - add(cbegin, iter, char_width); + if ( ucb.iter == ucb.cend ) + add(ucb); return int(string.getLength()); } @@ -151,16 +148,14 @@ inline void FVTermBuffer::getNextCharacterAttribute() } //---------------------------------------------------------------------- -void FVTermBuffer::add ( FString::const_iterator& cbegin - , const FString::const_iterator& cend - , int& char_width ) +void FVTermBuffer::add (UnicodeBoundary& ucb) { static const auto& fterm_data = FTermData::getInstance(); - if ( cbegin == cend ) + if ( ucb.cbegin == ucb.iter ) return; - if ( char_width == 2 + if ( ucb.char_width == 2 && fterm_data.getTerminalEncoding() != Encoding::UTF8 ) { nc.ch[0] = L'.'; @@ -169,18 +164,18 @@ void FVTermBuffer::add ( FString::const_iterator& cbegin } else { - const auto end = std::min(cend, cbegin + UNICODE_MAX); - std::copy(cbegin, end, nc.ch.begin()); - nc.attr.bit.char_width = uInt8(char_width) & 0x03; - const auto idx = std::size_t(end - cbegin); + const auto end = std::min(ucb.iter, ucb.cbegin + UNICODE_MAX); + std::copy(ucb.cbegin, end, nc.ch.begin()); + nc.attr.bit.char_width = uInt8(ucb.char_width) & 0x03; + const auto idx = std::size_t(end - ucb.cbegin); if ( idx < UNICODE_MAX ) nc.ch[idx] = L'\0'; } data.emplace_back(nc); - cbegin = cend; - char_width = 0; // reset char width + ucb.cbegin = ucb.iter; + ucb.char_width = 0; // reset char width } diff --git a/final/vterm/fvtermbuffer.h b/final/vterm/fvtermbuffer.h index bd3ed589..eb8f8167 100644 --- a/final/vterm/fvtermbuffer.h +++ b/final/vterm/fvtermbuffer.h @@ -123,10 +123,16 @@ class FVTermBuffer auto print () -> FVTermBuffer&; private: + struct UnicodeBoundary + { + FString::const_iterator cbegin{}; + FString::const_iterator cend{}; + FString::const_iterator iter{}; + int char_width{0}; + }; + void getNextCharacterAttribute(); - void add ( FString::const_iterator& - , const FString::const_iterator& - , int& ); + void add (UnicodeBoundary&); // Data member FCharVector data{}; diff --git a/final/widget/fwindow.cpp b/final/widget/fwindow.cpp index 987be34c..3f43313d 100644 --- a/final/widget/fwindow.cpp +++ b/final/widget/fwindow.cpp @@ -375,7 +375,7 @@ void FWindow::setWidth (std::size_t w, bool adjust) { FRect geometry {getTermGeometry()}; geometry.move(-1, -1); - resizeArea (geometry, getShadow(), getVWin()); + resizeArea ({geometry, getShadow()}, getVWin()); } } @@ -389,7 +389,7 @@ void FWindow::setHeight (std::size_t h, bool adjust) { FRect geometry {getTermGeometry()}; geometry.move(-1, -1); - resizeArea (geometry, getShadow(), getVWin()); + resizeArea ({geometry, getShadow()}, getVWin()); } } @@ -403,7 +403,7 @@ void FWindow::setSize (const FSize& size, bool adjust) { FRect geometry {getTermGeometry()}; geometry.move(-1, -1); - resizeArea (geometry, getShadow(), getVWin()); + resizeArea ({geometry, getShadow()}, getVWin()); } } @@ -429,7 +429,7 @@ void FWindow::setGeometry ( const FPoint& p, const FSize& size, bool adjust) { FRect geometry {getTermGeometry()}; geometry.move(-1, -1); - resizeArea (geometry, getShadow(), getVWin()); + resizeArea ({geometry, getShadow()}, getVWin()); } else { @@ -734,7 +734,7 @@ void FWindow::setShadowSize (const FSize& size) { auto geometry = getTermGeometry(); geometry.move(-1, -1); - resizeArea (geometry, getShadow(), getVWin()); + resizeArea ({geometry, getShadow()}, getVWin()); } } @@ -823,7 +823,7 @@ inline void FWindow::createVWin() noexcept FRect geometry {getTermGeometry()}; geometry.move(-1, -1); - setVWin(createArea(geometry, getShadow())); + setVWin(createArea({geometry, getShadow()})); } //---------------------------------------------------------------------- diff --git a/test/fmouse-test.cpp b/test/fmouse-test.cpp index 643fcbc7..2435b689 100644 --- a/test/fmouse-test.cpp +++ b/test/fmouse-test.cpp @@ -1373,7 +1373,7 @@ void FMouseTest::mouseControlTest() mouse_control.setEventCommand (mouse_cmd); mouse_control.setEnableXTermMouseCommand (enable_xterm_mouse_cmd); mouse_control.setDisableXTermMouseCommand (disable_xterm_mouse_cmd); - + mouse_control.setStdinNo(fileno(stdin)); mouse_control.setMaxWidth(100); mouse_control.setMaxHeight(40); diff --git a/test/foptiattr-test.cpp b/test/foptiattr-test.cpp index 8f1d9475..ba2477dd 100644 --- a/test/foptiattr-test.cpp +++ b/test/foptiattr-test.cpp @@ -192,6 +192,9 @@ void FOptiAttrTest::sgrOptimizerTest() to.attr.bit.dim = true; to.attr.bit.italic = true; CPPUNIT_ASSERT ( from != to ); +//std::cerr << "--->" +// << printSequence(oa.changeAttribute(from, to)) +// << "<---\n"; CPPUNIT_ASSERT_STRING ( oa.changeAttribute(from, to) , CSI "0;10;2;1;3;34;47m" ); CPPUNIT_ASSERT ( from == to ); @@ -228,6 +231,9 @@ void FOptiAttrTest::sgrOptimizerTest() buffer = CSI "m" CSI "34m"; CPPUNIT_ASSERT ( buffer.length() == 8 ); sgr_optimizer.optimize(); +//std::cerr << "--->" +// << printSequence(buffer) +// << "<---\n"; CPPUNIT_ASSERT ( buffer.length() == 7 ); CPPUNIT_ASSERT_STRING ( buffer, CSI "0;34m" ); diff --git a/test/fvterm-test.cpp b/test/fvterm-test.cpp index 6fa16329..78c4fc5e 100644 --- a/test/fvterm-test.cpp +++ b/test/fvterm-test.cpp @@ -475,9 +475,9 @@ class FVTerm_protected : public finalcut::FVTerm auto p_isCursorHideable() const -> bool; // Methods - auto p_createArea (const finalcut::FRect&, const finalcut::FSize&) -> std::unique_ptr; + auto p_createArea (const finalcut::FVTerm::FShadowBox&) -> std::unique_ptr; auto p_createArea (const finalcut::FRect&) -> std::unique_ptr; - void p_resizeArea (const finalcut::FRect&, const finalcut::FSize&, FTermArea*) const; + void p_resizeArea (const finalcut::FVTerm::FShadowBox&, FTermArea*) const; void p_resizeArea (const finalcut::FRect&, FTermArea*) const; void p_restoreVTerm (const finalcut::FRect&) const; auto p_updateVTermCursor (const FTermArea*) const -> bool; @@ -634,9 +634,9 @@ inline auto FVTerm_protected::p_isCursorHideable() const -> bool } //---------------------------------------------------------------------- -inline auto FVTerm_protected::p_createArea (const finalcut::FRect& box, const finalcut::FSize& shadow) -> std::unique_ptr +inline auto FVTerm_protected::p_createArea (const finalcut::FVTerm::FShadowBox& shadowbox) -> std::unique_ptr { - return finalcut::FVTerm::createArea (box, shadow); + return finalcut::FVTerm::createArea ({shadowbox.box, shadowbox.shadow}); } //---------------------------------------------------------------------- @@ -646,9 +646,9 @@ inline auto FVTerm_protected::p_createArea (const finalcut::FRect& box) -> std:: } //---------------------------------------------------------------------- -inline void FVTerm_protected::p_resizeArea (const finalcut::FRect& box, const finalcut::FSize& shadow, FTermArea* area) const +inline void FVTerm_protected::p_resizeArea (const finalcut::FVTerm::FShadowBox& shadowbox, FTermArea* area) const { - finalcut::FVTerm::resizeArea (box, shadow, area); + finalcut::FVTerm::resizeArea ({shadowbox.box, shadowbox.shadow}, area); } //---------------------------------------------------------------------- @@ -906,7 +906,7 @@ void FVTermTest::FVTermBasesTest() // Create and check a virtual window for the p_fvterm object finalcut::FRect geometry {finalcut::FPoint{5, 5}, finalcut::FSize{20, 20}}; finalcut::FSize Shadow(2, 1); - auto vwin_ptr = p_fvterm.p_createArea (geometry, Shadow); + auto vwin_ptr = p_fvterm.p_createArea ({geometry, Shadow}); vwin = vwin_ptr.get(); p_fvterm.setVWin(std::move(vwin_ptr)); @@ -1201,7 +1201,7 @@ void FVTermTest::FVTermBasesTest() // Create a vwin comparison area finalcut::FVTerm::FTermArea* test_vwin_area{}; - auto test_vwin_area_ptr = p_fvterm.p_createArea (geometry, Shadow); + auto test_vwin_area_ptr = p_fvterm.p_createArea ({geometry, Shadow}); test_vwin_area = test_vwin_area_ptr.get(); // .-------------------------- 20 line repetitions @@ -1464,7 +1464,7 @@ void FVTermTest::FVTermPrintTest() finalcut::FRect geometry {finalcut::FPoint{0, 0}, finalcut::FSize{15, 10}}; finalcut::FSize Shadow(1, 1); - auto vwin_ptr = p_fvterm.p_createArea (geometry, Shadow); + auto vwin_ptr = p_fvterm.p_createArea ({geometry, Shadow}); vwin = vwin_ptr.get(); p_fvterm.setVWin(std::move(vwin_ptr)); const finalcut::FVTerm::FTermArea* const_vwin = p_fvterm.getVWin(); @@ -1489,7 +1489,7 @@ void FVTermTest::FVTermPrintTest() auto move_geometry = finalcut::FRect ( finalcut::FPoint{12, 37} , finalcut::FSize{15, 10} ); - p_fvterm.p_resizeArea (move_geometry, Shadow, vwin); + p_fvterm.p_resizeArea ({move_geometry, Shadow}, vwin); CPPUNIT_ASSERT ( vwin->position.x == 12 ); CPPUNIT_ASSERT ( vwin->position.y == 37 ); @@ -1507,7 +1507,7 @@ void FVTermTest::FVTermPrintTest() // Create a vwin comparison area finalcut::FVTerm::FTermArea* test_vwin_area{}; - auto test_vwin_area_ptr = p_fvterm.p_createArea (geometry, Shadow); + auto test_vwin_area_ptr = p_fvterm.p_createArea ({geometry, Shadow}); test_vwin_area = test_vwin_area_ptr.get(); CPPUNIT_ASSERT ( p_fvterm.getPrintArea() == vwin );