From 465fd9510aeaabacf16ac3145f32653c1e461e2d Mon Sep 17 00:00:00 2001 From: Markus Gans Date: Wed, 10 Mar 2021 00:26:22 +0100 Subject: [PATCH] Implementation of an own padding print method for sending control codes to the terminal --- ChangeLog | 4 + examples/calculator.cpp | 6 +- examples/termcap.cpp | 12 +- examples/treeview.cpp | 8 +- src/fbuttongroup.cpp | 4 +- src/fdialog.cpp | 6 +- src/fevent.cpp | 6 +- src/ffiledialog.cpp | 12 +- src/fkeyboard.cpp | 10 +- src/flineedit.cpp | 4 +- src/flistview.cpp | 8 +- src/flogger.cpp | 4 +- src/fmenuitem.cpp | 4 +- src/fmouse.cpp | 35 +- src/foptiattr.cpp | 10 +- src/foptimove.cpp | 7 +- src/fsize.cpp | 2 +- src/fstring.cpp | 32 +- src/fterm.cpp | 11 +- src/fterm_functions.cpp | 14 +- src/ftermcap.cpp | 161 +++++++++- src/ftermlinux.cpp | 4 +- src/ftermxterminal.cpp | 20 +- src/ftextview.cpp | 2 +- src/fvterm.cpp | 15 +- src/include/final/fc.h | 40 +-- src/include/final/fcombobox.h | 2 +- src/include/final/fdata.h | 4 +- src/include/final/flistbox.h | 8 +- src/include/final/flistview.h | 6 +- src/include/final/fmenuitem.h | 4 +- src/include/final/fobject.h | 6 +- src/include/final/foptimove.h | 40 +-- src/include/final/fsystemimpl.h | 1 + src/include/final/ftermcap.h | 41 ++- src/include/final/ftermxterminal.h | 4 +- src/include/final/ftextview.h | 4 +- src/include/final/fvterm.h | 18 +- test/Makefile.am | 3 + test/ftermcap-test.cpp | 493 +++++++++++++++++++++++++++++ 40 files changed, 876 insertions(+), 199 deletions(-) create mode 100644 test/ftermcap-test.cpp diff --git a/ChangeLog b/ChangeLog index 05a93c5e..c8ca9cc2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2021-02-09 Markus Gans + * Implementation of an own padding print method for sending + control codes to the terminal + 2021-02-28 Markus Gans * Removing the termcap library from the header files so that FINAL CUT programs are not affected by the preprocessor diff --git a/examples/calculator.cpp b/examples/calculator.cpp index e04064e1..1722da9f 100644 --- a/examples/calculator.cpp +++ b/examples/calculator.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2016-2020 Markus Gans * +* Copyright 2016-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -1183,13 +1183,13 @@ void Calc::mapKeyFunctions() //---------------------------------------------------------------------- inline bool operator < (const Calc::ButtonName& c, const int n) noexcept { - return bool( int(c) < n ); + return int(c) < n; } //---------------------------------------------------------------------- inline bool operator <= (const Calc::ButtonName& c, const int n) noexcept { - return bool( int(c) <= n ); + return int(c) <= n; } //---------------------------------------------------------------------- diff --git a/examples/termcap.cpp b/examples/termcap.cpp index d9fc91a9..1cff2ea3 100644 --- a/examples/termcap.cpp +++ b/examples/termcap.cpp @@ -51,15 +51,16 @@ struct Data const Termcap cap; }; - static std::array strings; + static std::array strings; }; //---------------------------------------------------------------------- // struct data - string data array //---------------------------------------------------------------------- -std::array Data::strings = +std::array Data::strings = {{ { "t_bell", Termcap::t_bell }, + { "t_flash_screen", Termcap::t_flash_screen }, { "t_erase_chars", Termcap::t_erase_chars }, { "t_clear_screen", Termcap::t_clear_screen }, { "t_clr_eos", Termcap::t_clr_eos }, @@ -70,6 +71,7 @@ std::array Data::strings = { "t_carriage_return", Termcap::t_carriage_return }, { "t_tab", Termcap::t_tab }, { "t_back_tab", Termcap::t_back_tab }, + { "t_pad_char", Termcap::t_pad_char }, { "t_insert_padding", Termcap::t_insert_padding }, { "t_insert_character", Termcap::t_insert_character }, { "t_parm_ich", Termcap::t_parm_ich }, @@ -266,6 +268,10 @@ void booleans() , finalcut::FTermcap::osc_support ); tcapBoolean ( "no_utf8_acs_chars" , finalcut::FTermcap::no_utf8_acs_chars ); + tcapBoolean ( "no_padding_char" + , finalcut::FTermcap::no_padding_char ); + tcapBoolean ( "xon_xoff_flow_control" + , finalcut::FTermcap::xon_xoff_flow_control ); } //---------------------------------------------------------------------- @@ -276,6 +282,8 @@ void numeric() , finalcut::FTermcap::max_color); tcapNumeric ("tabstop" , finalcut::FTermcap::tabstop); + tcapNumeric ("padding_baudrate" + , finalcut::FTermcap::padding_baudrate); tcapNumeric ("attr_without_color" , finalcut::FTermcap::attr_without_color); } diff --git a/examples/treeview.cpp b/examples/treeview.cpp index 730f1327..7532adb9 100644 --- a/examples/treeview.cpp +++ b/examples/treeview.cpp @@ -59,7 +59,7 @@ inline bool isLessThanInteger ( const finalcut::FString& lhs { const sInt64 l_number = stringToNumber(lhs); const sInt64 r_number = stringToNumber(rhs); - return bool( l_number < r_number ); // lhs < rhs + return l_number < r_number; // lhs < rhs } //---------------------------------------------------------------------- @@ -69,7 +69,7 @@ inline bool isLessThanDouble ( const finalcut::FString& lhs std::setlocale(LC_NUMERIC, "C"); const double l_number = lhs.toDouble(); const double r_number = rhs.toDouble(); - return bool( l_number < r_number ); // lhs < rhs + return l_number < r_number; // lhs < rhs } //---------------------------------------------------------------------- @@ -78,7 +78,7 @@ inline bool isGreaterThanInteger ( const finalcut::FString& lhs { const sInt64 l_number = stringToNumber(lhs); const sInt64 r_number = stringToNumber(rhs); - return bool( l_number > r_number ); // lhs > rhs + return l_number > r_number; // lhs > rhs } //---------------------------------------------------------------------- @@ -88,7 +88,7 @@ inline bool isGreaterThanDouble ( const finalcut::FString& lhs std::setlocale(LC_NUMERIC, "C"); const double l_number = lhs.toDouble(); const double r_number = rhs.toDouble(); - return bool( l_number > r_number ); // lhs > rhs + return l_number > r_number; // lhs > rhs } //---------------------------------------------------------------------- diff --git a/src/fbuttongroup.cpp b/src/fbuttongroup.cpp index 7fdcc447..2404bbe8 100644 --- a/src/fbuttongroup.cpp +++ b/src/fbuttongroup.cpp @@ -4,7 +4,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2014-2020 Markus Gans * +* Copyright 2014-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -386,7 +386,7 @@ bool FButtonGroup::isRadioButton (const FToggleButton* button) const if ( ! button ) return false; - return bool( button->getClassName() == "FRadioButton" ); + return button->getClassName() == "FRadioButton"; } //---------------------------------------------------------------------- diff --git a/src/fdialog.cpp b/src/fdialog.cpp index a90f9e59..a453022f 100644 --- a/src/fdialog.cpp +++ b/src/fdialog.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2012-2020 Markus Gans * +* Copyright 2012-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -112,7 +112,7 @@ bool FDialog::setModal (bool enable) //---------------------------------------------------------------------- bool FDialog::setScrollable (bool enable) { - return (setFlags().scrollable = enable); + return ( setFlags().scrollable = enable ); } @@ -134,7 +134,7 @@ bool FDialog::setBorder (bool enable) setRightPadding(0); } - return (setFlags().no_border = ! enable); + return ( setFlags().no_border = ! enable ); } //---------------------------------------------------------------------- diff --git a/src/fevent.cpp b/src/fevent.cpp index 68570430..89512ccf 100644 --- a/src/fevent.cpp +++ b/src/fevent.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2014-2020 Markus Gans * +* Copyright 2014-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -184,13 +184,13 @@ FFocusEvent::FFocusEvent (Event ev_type) // constructor //---------------------------------------------------------------------- bool FFocusEvent::gotFocus() const { - return ( getType() == Event::FocusIn ); + return getType() == Event::FocusIn; } //---------------------------------------------------------------------- bool FFocusEvent::lostFocus() const { - return ( getType() == Event::FocusOut ); + return getType() == Event::FocusOut; } //---------------------------------------------------------------------- diff --git a/src/ffiledialog.cpp b/src/ffiledialog.cpp index d00c379f..67e78537 100644 --- a/src/ffiledialog.cpp +++ b/src/ffiledialog.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2014-2020 Markus Gans * +* Copyright 2014-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -41,7 +41,7 @@ bool sortByName ( const FFileDialog::FDirEntry& lhs , const FFileDialog::FDirEntry& rhs ) { // lhs < rhs - return bool( strcasecmp(lhs.name.c_str(), rhs.name.c_str()) < 0 ); + return strcasecmp(lhs.name.c_str(), rhs.name.c_str()) < 0; } //---------------------------------------------------------------------- @@ -131,9 +131,9 @@ FString FFileDialog::getSelectedFile() const const auto n = uLong(filebrowser.currentItem() - 1); if ( dir_entries[n].directory ) - return FString{""}; + return {""}; else - return FString{dir_entries[n].name}; + return {dir_entries[n].name}; } //---------------------------------------------------------------------- @@ -695,9 +695,9 @@ FString FFileDialog::getHomeDir() const uid_t euid = fsystem->geteuid(); if ( fsystem->getpwuid_r(euid, &pwd, buf.data(), buf.size(), &pwd_ptr) ) - return FString{""}; + return {""}; else - return FString{pwd.pw_dir}; + return {pwd.pw_dir}; } //---------------------------------------------------------------------- diff --git a/src/fkeyboard.cpp b/src/fkeyboard.cpp index 5c30c094..33ecfdfe 100644 --- a/src/fkeyboard.cpp +++ b/src/fkeyboard.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2018-2020 Markus Gans * +* Copyright 2018-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -91,17 +91,17 @@ FString FKeyboard::getKeyName (const FKey keynum) const fc::fkeyname.cend(), [&keynum] (const fc::FKeyName& kn) { - return (kn.num != FKey::None && kn.num == keynum); + return ( kn.num != FKey::None && kn.num == keynum ); } ); if ( found_key != fc::fkeyname.end() ) - return FString{found_key->string}; + return {found_key->string}; if ( keynum > 32 && keynum < 127 ) - return FString{char(keynum)}; + return {char(keynum)}; - return FString{""}; + return {""}; } //---------------------------------------------------------------------- diff --git a/src/flineedit.cpp b/src/flineedit.cpp index e7270875..a6497683 100644 --- a/src/flineedit.cpp +++ b/src/flineedit.cpp @@ -763,13 +763,13 @@ inline std::size_t FLineEdit::getCursorColumnPos() const //---------------------------------------------------------------------- inline FString FLineEdit::getPasswordText() const { - return FString{text.getLength(), UniChar::Bullet}; // • + return {text.getLength(), UniChar::Bullet}; // • } //---------------------------------------------------------------------- inline bool FLineEdit::isPasswordField() const { - return bool( input_type == InputType::Password ); + return input_type == InputType::Password; } //---------------------------------------------------------------------- diff --git a/src/flistview.cpp b/src/flistview.cpp index b2a23538..9ccc0fc5 100644 --- a/src/flistview.cpp +++ b/src/flistview.cpp @@ -122,7 +122,7 @@ bool sortAscendingByName (const FObject* lhs, const FObject* rhs) const auto& r_string = r_item->getText(column); // lhs < rhs - return bool( strcasecmp(l_string.c_str(), r_string.c_str()) < 0 ); + return strcasecmp(l_string.c_str(), r_string.c_str()) < 0; } //---------------------------------------------------------------------- @@ -135,7 +135,7 @@ bool sortDescendingByName (const FObject* lhs, const FObject* rhs) const auto& r_string = r_item->getText(column); // lhs > rhs - return bool( strcasecmp(l_string.c_str(), r_string.c_str()) > 0 ); + return strcasecmp(l_string.c_str(), r_string.c_str()) > 0; } //---------------------------------------------------------------------- @@ -148,7 +148,7 @@ bool sortAscendingByNumber (const FObject* lhs, const FObject* rhs) const auto& r_number = firstNumberFromString(r_item->getText(column)); // lhs < rhs - return bool( l_number < r_number ); + return l_number < r_number; } //---------------------------------------------------------------------- @@ -161,7 +161,7 @@ bool sortDescendingByNumber (const FObject* lhs, const FObject* rhs) const auto& r_number = firstNumberFromString(r_item->getText(column)); // lhs > rhs - return bool( l_number > r_number ); + return l_number > r_number; } diff --git a/src/flogger.cpp b/src/flogger.cpp index b71a9c31..dc2c4fbf 100644 --- a/src/flogger.cpp +++ b/src/flogger.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2020 Markus Gans * +* Copyright 2020-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -63,7 +63,7 @@ std::string FLogger::getTimeString() const struct tm time{}; localtime_r (&t, &time); std::strftime (str.data(), str.size(), "%a, %d %b %Y %T %z", &time); - return std::string(str.data()); + return {str.data()}; } //---------------------------------------------------------------------- diff --git a/src/fmenuitem.cpp b/src/fmenuitem.cpp index 4405fff5..261abbca 100644 --- a/src/fmenuitem.cpp +++ b/src/fmenuitem.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2015-2020 Markus Gans * +* Copyright 2015-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -478,7 +478,7 @@ bool FMenuItem::isMenu (const FWidget* w) const const bool m1 = w->isInstanceOf("FMenu"); const bool m2 = w->isInstanceOf("FDialogListMenu"); - return bool( m1 || m2 ); + return m1 || m2; } diff --git a/src/fmouse.cpp b/src/fmouse.cpp index 1ae8421c..ae9233de 100644 --- a/src/fmouse.cpp +++ b/src/fmouse.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2018-2020 Markus Gans * +* Copyright 2018-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -62,81 +62,82 @@ const FPoint& FMouseData::getPos() const { return mouse; } + //---------------------------------------------------------------------- bool FMouseData::isLeftButtonPressed() const { - return bool(getButtonState().left_button == State::Pressed); + return getButtonState().left_button == State::Pressed; } //---------------------------------------------------------------------- bool FMouseData::isLeftButtonReleased() const { - return bool(getButtonState().left_button == State::Released); + return getButtonState().left_button == State::Released; } //---------------------------------------------------------------------- bool FMouseData::isLeftButtonDoubleClick() const { - return bool(getButtonState().left_button == State::DoubleClick); + return getButtonState().left_button == State::DoubleClick; } //---------------------------------------------------------------------- bool FMouseData::isRightButtonPressed() const { - return bool(getButtonState().right_button == State::Pressed); + return getButtonState().right_button == State::Pressed; } //---------------------------------------------------------------------- bool FMouseData::isRightButtonReleased() const { - return bool(getButtonState().right_button == State::Released); + return getButtonState().right_button == State::Released; } //---------------------------------------------------------------------- bool FMouseData::isMiddleButtonPressed() const { - return bool(getButtonState().middle_button == State::Pressed); + return getButtonState().middle_button == State::Pressed; } //---------------------------------------------------------------------- bool FMouseData::isMiddleButtonReleased() const { - return bool(getButtonState().middle_button == State::Released); + return getButtonState().middle_button == State::Released; } //---------------------------------------------------------------------- bool FMouseData::isShiftKeyPressed() const { - return bool(getButtonState().shift_button); + return getButtonState().shift_button; } //---------------------------------------------------------------------- bool FMouseData::isControlKeyPressed() const { - return bool(getButtonState().control_button); + return getButtonState().control_button; } //---------------------------------------------------------------------- bool FMouseData::isMetaKeyPressed() const { - return bool(getButtonState().meta_button); + return getButtonState().meta_button; } //---------------------------------------------------------------------- bool FMouseData::isWheelUp() const { - return bool(getButtonState().wheel_up); + return getButtonState().wheel_up; } //---------------------------------------------------------------------- bool FMouseData::isWheelDown() const { - return bool(getButtonState().wheel_down); + return getButtonState().wheel_down; } //---------------------------------------------------------------------- bool FMouseData::isMoved() const { - return bool(getButtonState().mouse_moved); + return getButtonState().mouse_moved; } //---------------------------------------------------------------------- @@ -551,7 +552,7 @@ FString FMouseX11::getClassName() const //---------------------------------------------------------------------- bool FMouseX11::hasData() { - return bool(x11_mouse[0]); + return ( x11_mouse[0] ); } //---------------------------------------------------------------------- @@ -729,7 +730,7 @@ FString FMouseSGR::getClassName() const //---------------------------------------------------------------------- bool FMouseSGR::hasData() { - return bool(sgr_mouse[0]); + return ( sgr_mouse[0] ); } //---------------------------------------------------------------------- @@ -959,7 +960,7 @@ FString FMouseUrxvt::getClassName() const //---------------------------------------------------------------------- bool FMouseUrxvt::hasData() { - return bool(urxvt_mouse[0]); + return ( urxvt_mouse[0] ); } //---------------------------------------------------------------------- diff --git a/src/foptiattr.cpp b/src/foptiattr.cpp index 071418bd..6231b47f 100644 --- a/src/foptiattr.cpp +++ b/src/foptiattr.cpp @@ -1129,13 +1129,13 @@ bool FOptiAttr::hasNoAttribute (const FChar& attr) inline bool FOptiAttr::hasColorChanged ( const FChar& term , const FChar& next ) const { - bool frev ( ( on.attr.bit.reverse + bool frev { ( on.attr.bit.reverse || on.attr.bit.standout || off.attr.bit.reverse - || off.attr.bit.standout ) && fake_reverse ); - return bool ( frev - || term.fg_color != next.fg_color - || term.bg_color != next.bg_color ); + || off.attr.bit.standout ) && fake_reverse }; + return frev + || term.fg_color != next.fg_color + || term.bg_color != next.bg_color; } //---------------------------------------------------------------------- diff --git a/src/foptimove.cpp b/src/foptimove.cpp index 59ce75a3..63fd37e1 100644 --- a/src/foptimove.cpp +++ b/src/foptimove.cpp @@ -895,10 +895,9 @@ inline void FOptiMove::leftMove ( char hmove[], int& htime inline bool FOptiMove::isWideMove ( int xold, int yold , int xnew, int ynew ) const { - return bool ( xnew > MOVE_LIMIT - && xnew < int(screen_width) - 1 - MOVE_LIMIT - && std::abs(xnew - xold) + std::abs(ynew - yold) - > MOVE_LIMIT ); + return xnew > MOVE_LIMIT + && xnew < int(screen_width) - 1 - MOVE_LIMIT + && std::abs(xnew - xold) + std::abs(ynew - yold) > MOVE_LIMIT; } //---------------------------------------------------------------------- diff --git a/src/fsize.cpp b/src/fsize.cpp index 18f88330..5a4129e3 100644 --- a/src/fsize.cpp +++ b/src/fsize.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2014-2020 Markus Gans * +* Copyright 2014-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * diff --git a/src/fstring.cpp b/src/fstring.cpp index 0d1da758..e814c0e3 100644 --- a/src/fstring.cpp +++ b/src/fstring.cpp @@ -333,7 +333,7 @@ const FString& FString::operator >> (float& num) const //---------------------------------------------------------------------- FString::operator bool () const { - return bool(string); + return string; } //---------------------------------------------------------------------- @@ -404,7 +404,7 @@ char* FString::c_str() //---------------------------------------------------------------------- std::string FString::toString() const { - return std::string(c_str(), length); + return {c_str(), length}; } //---------------------------------------------------------------------- @@ -442,7 +442,7 @@ sInt16 FString::toShort() const if ( num < SHRT_MIN ) throw std::underflow_error ("underflow"); - return sInt16(num); + return static_cast(num); } //---------------------------------------------------------------------- @@ -453,7 +453,7 @@ uInt16 FString::toUShort() const if ( num > USHRT_MAX ) throw std::overflow_error ("overflow"); - return uInt16(num); + return static_cast(num); } //---------------------------------------------------------------------- @@ -467,7 +467,7 @@ int FString::toInt() const if ( num < INT_MIN ) throw std::underflow_error ("underflow"); - return int(num); + return static_cast(num); } //---------------------------------------------------------------------- @@ -478,7 +478,7 @@ uInt FString::toUInt() const if ( num > UINT_MAX ) throw std::overflow_error ("overflow"); - return uInt(num); + return static_cast(num); } //---------------------------------------------------------------------- @@ -532,7 +532,7 @@ long FString::toLong() const if ( neg ) num = (~num) + 1; - return num; + return static_cast(num); } //---------------------------------------------------------------------- @@ -576,7 +576,7 @@ uLong FString::toULong() const if ( *p != L'\0' && ! std::iswdigit(std::wint_t(*p)) ) throw std::invalid_argument ("no valid number"); - return num; + return static_cast(num); } //---------------------------------------------------------------------- @@ -590,7 +590,7 @@ float FString::toFloat() const if ( std::fabs(num) < double(FLT_EPSILON) ) // num == 0.0f throw std::underflow_error ("underflow"); - return float(num); + return static_cast(num); } //---------------------------------------------------------------------- @@ -722,7 +722,7 @@ FString FString::mid (std::size_t pos, std::size_t len) const len = length - pos + 1; if ( pos > length || pos + len - 1 > length || len == 0 ) - return FString{L""}; + return {L""}; wchar_t* p = s.string; wchar_t* first = p + pos - 1; @@ -907,7 +907,7 @@ bool FString::operator < (const FString& s) const if ( ! (string || s.string) ) return false; - return ( std::wcscmp(string, s.string) < 0 ); + return std::wcscmp(string, s.string) < 0; } //---------------------------------------------------------------------- @@ -922,7 +922,7 @@ bool FString::operator <= (const FString& s) const if ( ! string && s.string ) return true; - return ( std::wcscmp(string, s.string) <= 0 ); + return std::wcscmp(string, s.string) <= 0; } //---------------------------------------------------------------------- @@ -934,7 +934,7 @@ bool FString::operator == (const FString& s) const if ( bool(string) != bool(s.string) || length != s.length ) return false; - return ( std::wcscmp(string, s.string) == 0 ); + return std::wcscmp(string, s.string) == 0; } //---------------------------------------------------------------------- @@ -955,7 +955,7 @@ bool FString::operator >= (const FString& s) const if ( ! (string || s.string) ) return true; - return ( std::wcscmp(string, s.string) >= 0 ); + return std::wcscmp(string, s.string) >= 0; } //---------------------------------------------------------------------- @@ -970,7 +970,7 @@ bool FString::operator > (const FString& s) const if ( ! string && s.string ) return false; - return ( std::wcscmp(string, s.string) > 0 ); + return std::wcscmp(string, s.string) > 0; } //---------------------------------------------------------------------- @@ -1189,7 +1189,7 @@ bool FString::includes (const FString& s) const if ( ! (string && s.string) ) return false; - return ( std::wcsstr(string, s.string) != nullptr ); + return std::wcsstr(string, s.string) != nullptr; } diff --git a/src/fterm.cpp b/src/fterm.cpp index 2469a428..99ae5616 100644 --- a/src/fterm.cpp +++ b/src/fterm.cpp @@ -20,10 +20,10 @@ * . * ***********************************************************************/ -#include #include -#include +#include #include +#include #include #include "final/fapplication.h" @@ -974,10 +974,7 @@ void FTerm::resetBeep() void FTerm::beep() { if ( TCAP(t_bell) ) - { putstring (TCAP(t_bell)); - std::fflush(stdout); - } } //---------------------------------------------------------------------- @@ -1054,7 +1051,7 @@ std::string FTerm::getEncodingString() bool FTerm::charEncodable (wchar_t c) { const wchar_t ch = charEncode(c); - return bool(ch > 0 && ch != c); + return ch > 0 && ch != c; } //---------------------------------------------------------------------- @@ -1558,7 +1555,7 @@ bool FTerm::init_font() FApplication::exit(EXIT_FAILURE); } - return ( ! FApplication::isQuit() ); + return ! FApplication::isQuit(); } //---------------------------------------------------------------------- diff --git a/src/fterm_functions.cpp b/src/fterm_functions.cpp index bbbac89f..5d375134 100644 --- a/src/fterm_functions.cpp +++ b/src/fterm_functions.cpp @@ -276,7 +276,7 @@ bool hasFullWidthSupports() has_fullwidth_support = FullWidthSupport::Yes; } - return ( has_fullwidth_support == FullWidthSupport::Yes) ? true : false; + return ( has_fullwidth_support == FullWidthSupport::Yes ) ? true : false; } //---------------------------------------------------------------------- @@ -385,7 +385,7 @@ FString getColumnSubString ( const FString& str std::size_t num{0}; if ( col_len == 0 || s.isEmpty() ) - return FString{L""}; + return {L""}; if ( col_pos == 0 ) col_pos = 1; @@ -431,7 +431,7 @@ FString getColumnSubString ( const FString& str } if ( col_first < col_pos ) // String length < col_pos - return FString{L""}; + return {L""}; return s.mid(first, num); } @@ -590,7 +590,7 @@ int getCharLength (const FString& string, std::size_t pos) } while ( n < len && char_width == 0 && ! isWhitespace(string[n]) ); - return int(n - pos); + return static_cast(n - pos); } //---------------------------------------------------------------------- @@ -684,7 +684,7 @@ FPoint readCursorPos() // Report Cursor Position (DECXCPR) if ( write(stdout_no, DECXCPR, std::strlen(DECXCPR)) < 1 ) - return FPoint{x, y}; + return {x, y}; std::fflush(stdout); FD_ZERO(&ifds); @@ -696,7 +696,7 @@ FPoint readCursorPos() // Read the answer if ( select (stdin_no + 1, &ifds, nullptr, nullptr, &tv) != 1 ) - return FPoint{x, y}; + return {x, y}; do { @@ -716,7 +716,7 @@ FPoint readCursorPos() std::sscanf(temp.data(), parse, &y, &x ); } - return FPoint{x, y}; + return {x, y}; } } // namespace finalcut diff --git a/src/ftermcap.cpp b/src/ftermcap.cpp index da4c6227..65e7c6f6 100644 --- a/src/ftermcap.cpp +++ b/src/ftermcap.cpp @@ -42,6 +42,7 @@ #include #include +#include #include #include "final/emptyfstring.h" @@ -68,9 +69,14 @@ bool FTermcap::has_ansi_escape_sequences{false}; bool FTermcap::ansi_default_color {false}; bool FTermcap::osc_support {false}; bool FTermcap::no_utf8_acs_chars {false}; +bool FTermcap::no_padding_char {false}; +bool FTermcap::xon_xoff_flow_control {false}; int FTermcap::max_color {1}; int FTermcap::tabstop {8}; +int FTermcap::padding_baudrate {0}; int FTermcap::attr_without_color {0}; +int FTermcap::baudrate {9600}; +char FTermcap::PC {'\0'}; char FTermcap::string_buf[2048] {}; //---------------------------------------------------------------------- @@ -90,13 +96,14 @@ char FTermcap::string_buf[2048] {}; //---------------------------------------------------------------------- bool FTermcap::getFlag (const std::string& cap) { - return ::tgetflag(C_STR(cap.data())); + return ::tgetflag(C_STR(cap.data())) == 1; } //---------------------------------------------------------------------- int FTermcap::getNumber (const std::string& cap) { - return ::tgetnum(C_STR(cap.data())); + auto num = ::tgetnum(C_STR(cap.data())); + return ( num > 0) ? num : 0; } //---------------------------------------------------------------------- @@ -112,6 +119,110 @@ std::string FTermcap::encodeMotionParameter (const std::string& cap, int col, in return ( str ) ? str : std::string(); } +//---------------------------------------------------------------------- +FTermcap::Status FTermcap::paddingPrint ( const std::string& string + , int affcnt + , const defaultPutChar& outc ) +{ + if ( string.empty() ) + return Status::Error; + + bool has_delay = (TCAP(t_bell) && string == std::string(TCAP(t_bell))) + || (TCAP(t_flash_screen) && string == std::string(TCAP(t_flash_screen))) + || ( ! xon_xoff_flow_control && padding_baudrate + && (baudrate >= padding_baudrate) ); + auto iter = string.begin(); + + while ( iter != string.end() ) + { + if ( *iter != '$' ) + outc(int(*iter)); + else + { + ++iter; + + if ( *iter != '<' ) + { + outc(int('$')); + + if ( iter != string.end() ) + outc(int(*iter)); + } + else + { + ++iter; + const auto first_digit = iter; + + if ( (! std::isdigit(int(*iter)) && *iter != '.') ) + { + outc(int('$')); + outc(int('<')); + continue; + } + + int number = 0; + + while ( std::isdigit(int(*iter)) && number < 1000 ) + { + number = number * 10 + (*iter - '0'); + ++iter; + } + + number *= 10; + + if ( *iter == '.' ) + { + ++iter; + + if ( std::isdigit(int(*iter)) ) + { + number += (*iter - '0'); // Position after decimal point + ++iter; + } + + while ( std::isdigit(int(*iter)) ) + ++iter; + } + + while ( *iter == '*' || *iter == '/' ) + { + if ( *iter == '*' ) + { + // Padding is proportional to the number of affected lines (suffix '*') + number *= affcnt; + ++iter; + } + else + { + // Padding is mandatory (suffix '/') + has_delay = true; + ++iter; + } + } + + if ( *iter != '>' ) + { + outc(int('$')); + outc(int('<')); + iter = first_digit; + continue; + } + else if ( has_delay && number > 0 ) + { + delay_output(number / 10, outc); + } + } // end of else (*iter == '<') + } // end of else (*iter == '$') + + if ( iter == string.end() ) + break; + + ++iter; + } + + return Status::OK; +} + //---------------------------------------------------------------------- void FTermcap::init() { @@ -130,6 +241,7 @@ void FTermcap::termcap() int status = uninitialized; const auto& term_detection = FTerm::getFTermDetection(); const bool color256 = term_detection->canDisplay256Colors(); + baudrate = int(FTerm::getFTermData()->getBaudrate()); // Open termcap file const auto& termtype = fterm_data->getTermType(); @@ -154,7 +266,6 @@ void FTermcap::termcap() status = tgetent(term_buffer, termtype.data()); #endif - if ( status == success ) initialized = true; @@ -240,6 +351,12 @@ void FTermcap::termcapBoleans() // U8 is nonzero for terminals with no VT100 line-drawing in UTF-8 mode no_utf8_acs_chars = bool(getNumber("U8") != 0); + + // No padding character available + no_padding_char = getFlag("NP"); + + // Terminal uses software flow control (XON/XOFF) with (Ctrl-Q/Ctrl-S) + xon_xoff_flow_control = getFlag("xo"); } //---------------------------------------------------------------------- @@ -263,6 +380,9 @@ void FTermcap::termcapNumerics() // Get initial spacing for hardware tab stop tabstop = getNumber("it"); + // Get the smallest baud rate where padding is required + padding_baudrate = getNumber("pb"); + // Get video attributes that cannot be used with colors attr_without_color = getNumber("NC"); } @@ -279,8 +399,13 @@ void FTermcap::termcapStrings() const auto& ho = TCAP(t_cursor_home); - if ( std::strncmp(ho, "\033[H", 3) == 0 ) + if ( ho && std::strncmp(ho, "\033[H", 3) == 0 ) has_ansi_escape_sequences = true; + + const auto& pc = TCAP(t_pad_char); + + if ( pc ) + PC = pc[0]; } //---------------------------------------------------------------------- @@ -311,14 +436,26 @@ std::string FTermcap::encodeParams ( const std::string& cap } //---------------------------------------------------------------------- -int FTermcap::_tputs (const char* str, int affcnt, fn_putc putc) +void FTermcap::delay_output (int ms, const defaultPutChar& outc) { -#if defined(__sun) && defined(__SVR4) - return ::tputs ( C_STR(str) - , affcnt, reinterpret_cast(putc) ); -#else - return ::tputs (str, affcnt, putc); -#endif + + if ( no_padding_char ) + { + std::this_thread::sleep_for(std::chrono::milliseconds(ms)); + } + else + { + static constexpr int baudbyte = 9; // = 7 bit + 1 parity + 1 stop + + for ( int pad_char_count = (ms * baudrate) / (baudbyte * 1000); + pad_char_count > 0; + pad_char_count-- ) + { + outc(int(PC)); + } + + std::fflush(stdout); + } } @@ -331,6 +468,7 @@ FTermcap::TCapMapType FTermcap::strings = // | | // variable name -> description //------------------------------------------------------------------------------ { nullptr, "bl" }, // bell -> audible signal (bell) (P) + { nullptr, "vb" }, // flash_screen -> visible bell (may not move cursor) { nullptr, "ec" }, // erase_chars -> erase #1 characters (P) { nullptr, "cl" }, // clear_screen -> clear screen and home cursor (P*) { nullptr, "cd" }, // clr_eos -> clear to end of screen (P*) @@ -341,6 +479,7 @@ FTermcap::TCapMapType FTermcap::strings = { nullptr, "cr" }, // carriage_return -> carriage return (P*) { nullptr, "ta" }, // tab -> tab to next 8-space hardware tab stop { nullptr, "bt" }, // back_tab -> back tab (P) + { nullptr, "pc" }, // pad_char -> padding char (instead of null) { nullptr, "ip" }, // insert_padding -> insert padding after inserted character { nullptr, "ic" }, // insert_character -> insert character (P) { nullptr, "IC" }, // parm_ich -> insert #1 characters (P*) diff --git a/src/ftermlinux.cpp b/src/ftermlinux.cpp index 452713e6..25f96bf1 100644 --- a/src/ftermlinux.cpp +++ b/src/ftermlinux.cpp @@ -482,7 +482,7 @@ int FTermLinux::getFramebuffer_bpp() const && fsystem->ioctl(fd, FBIOGET_FSCREENINFO, &fb_fix) == 0 ) { fsystem->close(fd); - return int(fb_var.bits_per_pixel); + return static_cast(fb_var.bits_per_pixel); } else { @@ -1159,7 +1159,7 @@ sInt16 FTermLinux::getFontPos (wchar_t ucs) const for (std::size_t n{0}; n < screen_unicode_map.entry_ct; n++) { if ( screen_unicode_map.entries[n].unicode == ucs ) - return sInt16(screen_unicode_map.entries[n].fontpos); + return static_cast(screen_unicode_map.entries[n].fontpos); } return NOT_FOUND; diff --git a/src/ftermxterminal.cpp b/src/ftermxterminal.cpp index 526b7220..30389043 100644 --- a/src/ftermxterminal.cpp +++ b/src/ftermxterminal.cpp @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2018-2020 Markus Gans * +* Copyright 2018-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -741,7 +741,7 @@ FString FTermXTerminal::captureXTermFont() const && ! term_detection->isScreenTerm() && ! FTermcap::osc_support ) { - return FString{}; + return {}; } fd_set ifds{}; @@ -760,7 +760,7 @@ FString FTermXTerminal::captureXTermFont() const // Read the terminal answer if ( select(stdin_no + 1, &ifds, nullptr, nullptr, &tv) < 1 ) - return FString{}; + return {}; std::array temp{}; std::size_t pos{0}; @@ -788,10 +788,10 @@ FString FTermXTerminal::captureXTermFont() const if ( n >= 5 && str[n - 1] == BEL[0] && str[n] == '\0' ) str[n - 1] = '\0'; - return FString{str}; + return {str}; } - return FString{}; + return {}; } //---------------------------------------------------------------------- @@ -800,7 +800,7 @@ FString FTermXTerminal::captureXTermTitle() const const auto& term_detection = FTerm::getFTermDetection(); if ( term_detection->isKdeTerminal() ) - return FString{}; + return {}; fd_set ifds{}; struct timeval tv{}; @@ -816,7 +816,7 @@ FString FTermXTerminal::captureXTermTitle() const // read the terminal answer if ( select (stdin_no + 1, &ifds, nullptr, nullptr, &tv) < 1 ) - return FString{}; + return {}; std::array temp{}; std::size_t pos{0}; @@ -843,14 +843,14 @@ FString FTermXTerminal::captureXTermTitle() const if ( n >= 2 && str[n - 2] == ESC[0] && str[n - 1] == '\\' ) { if ( n < 4 ) - return FString{}; + return {}; str[n - 2] = '\0'; - return FString{str}; + return {str}; } } - return FString{}; + return {}; } //---------------------------------------------------------------------- diff --git a/src/ftextview.cpp b/src/ftextview.cpp index 5e730a54..e8961389 100644 --- a/src/ftextview.cpp +++ b/src/ftextview.cpp @@ -57,7 +57,7 @@ FTextView::~FTextView() noexcept = default; // destructor FString FTextView::getText() const { if ( data.empty() ) - return FString{""}; + return {""}; std::size_t len{0}; diff --git a/src/fvterm.cpp b/src/fvterm.cpp index b224c2be..7f35e105 100644 --- a/src/fvterm.cpp +++ b/src/fvterm.cpp @@ -581,7 +581,7 @@ void FVTerm::flush() const { const auto& first = output_buffer->front(); const auto& type = std::get<0>(first); - const auto& wstring = std::get<1>(first); + const auto& str = std::get<1>(first); if ( type == OutputType::String ) { @@ -590,11 +590,11 @@ void FVTerm::flush() const if ( ! FTermPutchar ) return; - for (auto&& ch : wstring) + for (auto&& ch : str.wstring) FTermPutchar(int(ch)); } else if ( type == OutputType::Control ) - FTerm::putstring (std::string(wstring.begin(), wstring.end())); + FTerm::putstring (str.string); output_buffer->pop(); } @@ -2625,7 +2625,7 @@ FVTerm::PrintState FVTerm::repeatCharacter (uInt& x, uInt xmax, uInt y) const //---------------------------------------------------------------------- inline bool FVTerm::isFullWidthChar (const FChar& ch) const { - return bool(ch.attr.bit.char_width == 2); + return ch.attr.bit.char_width == 2; } //---------------------------------------------------------------------- @@ -3105,8 +3105,7 @@ inline bool FVTerm::isOutputBufferLimitReached() const //---------------------------------------------------------------------- inline void FVTerm::appendOutputBuffer (const FTermControl& ctrl) const { - const auto& wstring = std::wstring{ctrl.string.begin(), ctrl.string.end()}; - output_buffer->emplace(std::make_tuple(OutputType::Control, wstring)); + output_buffer->emplace(std::make_tuple(OutputType::Control, TermString(ctrl.string))); if ( isOutputBufferLimitReached() ) flush(); @@ -3129,7 +3128,7 @@ void FVTerm::appendOutputBuffer (const FTermString& str) const auto& string_buf = std::get<1>(output_buffer->back()); std::transform ( str.string.begin() , str.string.end() - , std::back_inserter(string_buf) + , std::back_inserter(string_buf.wstring) , [] (wchar_t ch) { return ch; @@ -3137,7 +3136,7 @@ void FVTerm::appendOutputBuffer (const FTermString& str) const ); } else - output_buffer->emplace(std::make_tuple(OutputType::String, str.string)); + output_buffer->emplace(std::make_tuple(OutputType::String, TermString(str.string))); if ( isOutputBufferLimitReached() ) flush(); diff --git a/src/include/final/fc.h b/src/include/final/fc.h index 3a220efe..0d033246 100644 --- a/src/include/final/fc.h +++ b/src/include/final/fc.h @@ -257,51 +257,51 @@ enum class UniChar : wchar_t constexpr bool operator < (const UniChar& c1, const wchar_t c2) noexcept { - return bool( wchar_t(c1) < c2 ); + return wchar_t(c1) < c2; } constexpr bool operator > (const UniChar& c1, const wchar_t c2) noexcept { - return bool( wchar_t(c1) > c2 ); + return wchar_t(c1) > c2; } constexpr bool operator < (const wchar_t c1, const UniChar& c2) noexcept { - return bool( c1 < wchar_t(c2) ); + return c1 < wchar_t(c2); } constexpr bool operator > (const wchar_t c1, const UniChar& c2) noexcept { - return bool( c1 > wchar_t(c2) ); + return c1 > wchar_t(c2); } constexpr bool operator <= (const UniChar& c1, const wchar_t c2) noexcept { - return bool( wchar_t(c1) <= c2 ); + return wchar_t(c1) <= c2; } constexpr bool operator >= (const UniChar& c1, const wchar_t c2) noexcept { - return bool( wchar_t(c1) >= c2 ); + return wchar_t(c1) >= c2; } constexpr bool operator <= (const wchar_t c1, const UniChar& c2) noexcept { - return bool( c1 <= wchar_t(c2) ); + return c1 <= wchar_t(c2); } constexpr bool operator >= (const wchar_t c1, const UniChar& c2) noexcept { - return bool( c1 >= wchar_t(c2) ); + return c1 >= wchar_t(c2); } constexpr bool operator == (const wchar_t c1, const UniChar& c2) noexcept { - return bool( c1 == wchar_t(c2) ); + return c1 == wchar_t(c2); } constexpr bool operator == (const UniChar& c1, const wchar_t c2) noexcept { - return bool( wchar_t(c1) == c2 ); + return wchar_t(c1) == c2; } @@ -819,22 +819,22 @@ constexpr FKey operator << (const FKey& k, const uInt32 n) noexcept constexpr bool operator < (const FKey& k1, const uInt32 k2) noexcept { - return bool( uInt32(k1) < k2 ); + return uInt32(k1) < k2; } constexpr bool operator > (const FKey& k1, const uInt32 k2) noexcept { - return bool( uInt32(k1) > k2 ); + return uInt32(k1) > k2; } constexpr bool operator <= (const FKey& k1, const uInt32 k2) noexcept { - return bool( uInt32(k1) <= k2 ); + return uInt32(k1) <= k2; } constexpr bool operator >= (const FKey& k1, const uInt32 k2) noexcept { - return bool( uInt32(k1) >= k2 ); + return uInt32(k1) >= k2; } constexpr FKey operator | (const FKey& k1, const FKey& k2) noexcept @@ -1156,27 +1156,27 @@ constexpr FColor operator << (const FColor& c, const uInt16 n) noexcept constexpr bool operator < (const FColor& c, const uInt16 n) noexcept { - return bool( uInt16(c) < n ); + return uInt16(c) < n; } constexpr bool operator > (const FColor& c, const uInt16 n) noexcept { - return bool( uInt16(c) > n ); + return uInt16(c) > n; } constexpr bool operator == (const FColor& c, const uInt16 n) noexcept { - return bool( uInt16(c) == n ); + return uInt16(c) == n; } constexpr bool operator <= (const FColor& c, const uInt16 n) noexcept { - return bool( uInt16(c) <= n ); + return uInt16(c) <= n; } constexpr bool operator >= (const FColor& c, const uInt16 n) noexcept { - return bool( uInt16(c) >= n ); + return uInt16(c) >= n; } constexpr FColor operator + (const FColor& c, const uInt16 n) noexcept @@ -1433,6 +1433,7 @@ enum class BracketType enum class Termcap { t_bell, + t_flash_screen, t_erase_chars, t_clear_screen, t_clr_eos, @@ -1443,6 +1444,7 @@ enum class Termcap t_carriage_return, t_tab, t_back_tab, + t_pad_char, t_insert_padding, t_insert_character, t_parm_ich, diff --git a/src/include/final/fcombobox.h b/src/include/final/fcombobox.h index a52528ec..0f0d00e3 100644 --- a/src/include/final/fcombobox.h +++ b/src/include/final/fcombobox.h @@ -122,7 +122,7 @@ inline FString FDropDownListBox::getClassName() const //---------------------------------------------------------------------- inline bool FDropDownListBox::isEmpty() const -{ return bool( list.getCount() == 0 ); } +{ return list.getCount() == 0; } //---------------------------------------------------------------------- diff --git a/src/include/final/fdata.h b/src/include/final/fdata.h index 03c40574..800c4276 100644 --- a/src/include/final/fdata.h +++ b/src/include/final/fdata.h @@ -3,7 +3,7 @@ * * * This file is part of the FINAL CUT widget toolkit * * * -* Copyright 2020 Markus Gans * +* Copyright 2020-2021 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -247,7 +247,7 @@ class FData : public FDataAccess { const auto& v = reinterpret_cast(const_cast(&value)); const auto& r = reinterpret_cast(const_cast(&value_ref.get())); - return bool( v == r ); + return v == r; } bool isInitializedReference() const diff --git a/src/include/final/flistbox.h b/src/include/final/flistbox.h index be1becde..e8151aa9 100644 --- a/src/include/final/flistbox.h +++ b/src/include/final/flistbox.h @@ -522,11 +522,11 @@ inline bool FListBox::isMultiSelection() const //---------------------------------------------------------------------- inline bool FListBox::hasBrackets(std::size_t index) const -{ return bool(index2iterator(index - 1)->brackets != BracketType::None); } +{ return index2iterator(index - 1)->brackets != BracketType::None; } //---------------------------------------------------------------------- inline bool FListBox::hasBrackets(FListBoxItems::iterator iter) const -{ return bool(iter->brackets != BracketType::None); } +{ return iter->brackets != BracketType::None; } //---------------------------------------------------------------------- inline void FListBox::reserve (std::size_t new_cap) @@ -605,11 +605,11 @@ void FListBox::insert ( const ItemT& item //---------------------------------------------------------------------- inline bool FListBox::isHorizontallyScrollable() const -{ return bool( max_line_width + 1 >= getClientWidth() ); } +{ return max_line_width + 1 >= getClientWidth(); } //---------------------------------------------------------------------- inline bool FListBox::isVerticallyScrollable() const -{ return bool( getCount() > getClientHeight() ); } +{ return getCount() > getClientHeight(); } //---------------------------------------------------------------------- inline FListBox::FListBoxItems::iterator \ diff --git a/src/include/final/flistview.h b/src/include/final/flistview.h index 95cfb290..67b3d974 100644 --- a/src/include/final/flistview.h +++ b/src/include/final/flistview.h @@ -170,7 +170,7 @@ inline FString FListViewItem::getClassName() const //---------------------------------------------------------------------- inline uInt FListViewItem::getColumnCount() const -{ return uInt(column_list.size()); } +{ return static_cast(column_list.size()); } //---------------------------------------------------------------------- template @@ -718,11 +718,11 @@ inline const FListView::FListViewItems& FListView::getData() const //---------------------------------------------------------------------- inline bool FListView::isHorizontallyScrollable() const -{ return bool( max_line_width > getClientWidth() ); } +{ return max_line_width > getClientWidth(); } //---------------------------------------------------------------------- inline bool FListView::isVerticallyScrollable() const -{ return bool( getCount() > getClientHeight() ); } +{ return getCount() > getClientHeight(); } //---------------------------------------------------------------------- inline void FListView::scrollTo (const FPoint& pos) diff --git a/src/include/final/fmenuitem.h b/src/include/final/fmenuitem.h index 8dc29025..6c246022 100644 --- a/src/include/final/fmenuitem.h +++ b/src/include/final/fmenuitem.h @@ -286,11 +286,11 @@ inline bool FMenuItem::isRadioButton() const //---------------------------------------------------------------------- inline bool FMenuItem::hasHotkey() const -{ return bool(hotkey != FKey::None); } +{ return hotkey != FKey::None; } //---------------------------------------------------------------------- inline bool FMenuItem::hasMenu() const -{ return bool(menu != nullptr); } +{ return menu != nullptr; } //---------------------------------------------------------------------- inline FWidget* FMenuItem::getSuperMenu() const diff --git a/src/include/final/fobject.h b/src/include/final/fobject.h index 34af10dd..663b8528 100644 --- a/src/include/final/fobject.h +++ b/src/include/final/fobject.h @@ -248,11 +248,11 @@ inline bool FObject::hasParent() const //---------------------------------------------------------------------- inline bool FObject::hasChildren() const -{ return bool( ! children_list.empty() ); } +{ return ! children_list.empty(); } //---------------------------------------------------------------------- inline bool FObject::isDirectChild (const FObject* obj) const -{ return bool( obj->getParent() == this ); } +{ return obj->getParent() == this; } //---------------------------------------------------------------------- inline bool FObject::isWidget() const @@ -260,7 +260,7 @@ inline bool FObject::isWidget() const //---------------------------------------------------------------------- inline bool FObject::isInstanceOf (const FString& classname) const -{ return bool( classname == getClassName() ); } +{ return classname == getClassName(); } //---------------------------------------------------------------------- inline bool FObject::isTimerInUpdating() const diff --git a/src/include/final/foptimove.h b/src/include/final/foptimove.h index 4c9239b6..9fc5d288 100644 --- a/src/include/final/foptimove.h +++ b/src/include/final/foptimove.h @@ -227,83 +227,83 @@ inline FString FOptiMove::getClassName() const //---------------------------------------------------------------------- inline uInt FOptiMove::getCursorHomeLength() const -{ return uInt(F_cursor_home.length); } +{ return static_cast(F_cursor_home.length); } //---------------------------------------------------------------------- inline uInt FOptiMove::getCarriageReturnLength() const -{ return uInt(F_carriage_return.length); } +{ return static_cast(F_carriage_return.length); } //---------------------------------------------------------------------- inline uInt FOptiMove::getCursorToLLLength() const -{ return uInt(F_cursor_to_ll.length); } +{ return static_cast(F_cursor_to_ll.length); } //---------------------------------------------------------------------- inline uInt FOptiMove::getTabLength() const -{ return uInt(F_tab.length); } +{ return static_cast(F_tab.length); } //---------------------------------------------------------------------- inline uInt FOptiMove::getBackTabLength() const -{ return uInt(F_back_tab.length); } +{ return static_cast(F_back_tab.length); } //---------------------------------------------------------------------- inline uInt FOptiMove::getCursorUpLength() const -{ return uInt(F_cursor_up.length); } +{ return static_cast(F_cursor_up.length); } //---------------------------------------------------------------------- inline uInt FOptiMove::getCursorDownLength() const -{ return uInt(F_cursor_down.length); } +{ return static_cast(F_cursor_down.length); } //---------------------------------------------------------------------- inline uInt FOptiMove::getCursorLeftLength() const -{ return uInt(F_cursor_left.length); } +{ return static_cast(F_cursor_left.length); } //---------------------------------------------------------------------- inline uInt FOptiMove::getCursorRightLength() const -{ return uInt(F_cursor_right.length); } +{ return static_cast(F_cursor_right.length); } //---------------------------------------------------------------------- inline uInt FOptiMove::getCursorAddressLength() const -{ return uInt(F_cursor_address.length); } +{ return static_cast(F_cursor_address.length); } //---------------------------------------------------------------------- inline uInt FOptiMove::getColumnAddressLength() const -{ return uInt(F_column_address.length); } +{ return static_cast(F_column_address.length); } //---------------------------------------------------------------------- inline uInt FOptiMove::getRowAddressLength() const -{ return uInt(F_row_address.length); } +{ return static_cast(F_row_address.length); } //---------------------------------------------------------------------- inline uInt FOptiMove::getParmUpCursorLength() const -{ return uInt(F_parm_up_cursor.length); } +{ return static_cast(F_parm_up_cursor.length); } //---------------------------------------------------------------------- inline uInt FOptiMove::getParmDownCursorLength() const -{ return uInt(F_parm_down_cursor.length); } +{ return static_cast(F_parm_down_cursor.length); } //---------------------------------------------------------------------- inline uInt FOptiMove::getParmLeftCursorLength() const -{ return uInt(F_parm_left_cursor.length); } +{ return static_cast(F_parm_left_cursor.length); } //---------------------------------------------------------------------- inline uInt FOptiMove::getParmRightCursorLength() const -{ return uInt(F_parm_right_cursor.length); } +{ return static_cast(F_parm_right_cursor.length); } //---------------------------------------------------------------------- inline uInt FOptiMove::getEraseCharsLength() const -{ return uInt(F_erase_chars.length); } +{ return static_cast(F_erase_chars.length); } //---------------------------------------------------------------------- inline uInt FOptiMove::getRepeatCharLength() const -{ return uInt(F_repeat_char.length); } +{ return static_cast(F_repeat_char.length); } //---------------------------------------------------------------------- inline uInt FOptiMove::getClrBolLength() const -{ return uInt(F_clr_bol.length); } +{ return static_cast(F_clr_bol.length); } //---------------------------------------------------------------------- inline uInt FOptiMove::getClrEolLength() const -{ return uInt(F_clr_eol.length); } +{ return static_cast(F_clr_eol.length); } //---------------------------------------------------------------------- inline void FOptiMove::set_auto_left_margin (bool bcap) diff --git a/src/include/final/fsystemimpl.h b/src/include/final/fsystemimpl.h index 9e33aec5..44454fe1 100644 --- a/src/include/final/fsystemimpl.h +++ b/src/include/final/fsystemimpl.h @@ -67,6 +67,7 @@ #include "final/fc.h" #include "final/fsystem.h" + namespace finalcut { diff --git a/src/include/final/ftermcap.h b/src/include/final/ftermcap.h index 652e725a..9293ec96 100644 --- a/src/include/final/ftermcap.h +++ b/src/include/final/ftermcap.h @@ -53,6 +53,13 @@ namespace finalcut class FTermcap final { public: + // Enumeration + enum class Status + { + Error = -1, + OK = 0 + }; + struct TCapMap { const char* string; @@ -60,8 +67,8 @@ class FTermcap final }; // Using-declaration - using fn_putc = int (*)(int); - using TCapMapType = std::array; + using TCapMapType = std::array; + using defaultPutChar = std::function; // Constructors FTermcap() = default; @@ -77,13 +84,18 @@ class FTermcap final static std::string encodeMotionParameter (const std::string&, int, int); template static std::string encodeParameter (const std::string&, Args&&...); - static int paddingPrint (const std::string&, int, fn_putc); + static Status paddingPrint ( const std::string& + , int + , const defaultPutChar&); // Inquiry static bool isInitialized(); + // Mutator + static void setBaudrate (int); + // Methods - static void init(); + static void init(); // Data members static bool background_color_erase; @@ -95,8 +107,11 @@ class FTermcap final static bool ansi_default_color; static bool osc_support; static bool no_utf8_acs_chars; + static bool no_padding_char; + static bool xon_xoff_flow_control; static int max_color; static int tabstop; + static int padding_baudrate; static int attr_without_color; static TCapMapType strings; @@ -114,11 +129,13 @@ class FTermcap final static void termcapKeys(); static std::string encodeParams ( const std::string& , const std::vector& ); - static int _tputs (const char*, int, fn_putc); + static void delay_output (int, const defaultPutChar&); // Data member - static char string_buf[BUF_SIZE]; static bool initialized; + static int baudrate; + static char PC; + static char string_buf[BUF_SIZE]; }; // FTermcap inline functions @@ -133,18 +150,18 @@ std::string FTermcap::encodeParameter (const std::string& cap, Args&&... args) return encodeParams(cap, {static_cast(args)...}); } -//---------------------------------------------------------------------- -inline int FTermcap::paddingPrint (const std::string& str, int affcnt, fn_putc putc) -{ - return _tputs (C_STR(str.data()), affcnt, putc); -} - //---------------------------------------------------------------------- inline bool FTermcap::isInitialized() { return initialized; } +//---------------------------------------------------------------------- +inline void FTermcap::setBaudrate (int baud) +{ + baudrate = baud; +} + } // namespace finalcut diff --git a/src/include/final/ftermxterminal.h b/src/include/final/ftermxterminal.h index 6abae428..d17cfa95 100644 --- a/src/include/final/ftermxterminal.h +++ b/src/include/final/ftermxterminal.h @@ -205,11 +205,11 @@ inline FString FTermXTerminal::getHighlightBackground() const //---------------------------------------------------------------------- inline bool FTermXTerminal::hasFont() const -{ return bool(xterm_font.getLength() > 2); } +{ return xterm_font.getLength() > 2; } //---------------------------------------------------------------------- inline bool FTermXTerminal::hasTitle() const -{ return bool(xterm_title.getLength() > 0); } +{ return xterm_title.getLength() > 0; } //---------------------------------------------------------------------- inline void FTermXTerminal::unsetMouseSupport() diff --git a/src/include/final/ftextview.h b/src/include/final/ftextview.h index 88aa3b59..ad31c613 100644 --- a/src/include/final/ftextview.h +++ b/src/include/final/ftextview.h @@ -260,11 +260,11 @@ inline void FTextView::deleteLine (int pos) //---------------------------------------------------------------------- inline bool FTextView::isHorizontallyScrollable() const -{ return bool( max_line_width > getTextWidth() ); } +{ return max_line_width > getTextWidth(); } //---------------------------------------------------------------------- inline bool FTextView::isVerticallyScrollable() const -{ return bool( getRows() > getTextHeight() ); } +{ return getRows() > getTextHeight(); } } // namespace finalcut diff --git a/src/include/final/fvterm.h b/src/include/final/fvterm.h index 1480e691..2a887403 100644 --- a/src/include/final/fvterm.h +++ b/src/include/final/fvterm.h @@ -324,8 +324,22 @@ class FVTerm Control }; + struct TermString + { + TermString (const std::wstring& wstr) + : wstring{wstr} + { } + + TermString (const std::string& str) + : string{str} + { } + + std::wstring wstring{}; + std::string string{}; + }; + // Using-declaration - using OutputData = std::tuple; + using OutputData = std::tuple; using OutputBuffer = std::queue; // Constants @@ -863,7 +877,7 @@ inline void FVTerm::setActiveArea (FTermArea* area) const //---------------------------------------------------------------------- inline bool FVTerm::isActive (const FTermArea* area) const -{ return bool( area == active_area ); } +{ return area == active_area; } //---------------------------------------------------------------------- inline bool FVTerm::hasPrintArea() const diff --git a/test/Makefile.am b/test/Makefile.am index 53dd0b99..865cbf1c 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -13,6 +13,7 @@ noinst_PROGRAMS = \ fmouse_test \ fkeyboard_test \ fterm_functions_test \ + ftermcap_test \ ftermdata_test \ ftermbuffer_test \ ftermdetection_test \ @@ -37,6 +38,7 @@ fdata_test_SOURCES = fdata-test.cpp fmouse_test_SOURCES = fmouse-test.cpp fkeyboard_test_SOURCES = fkeyboard-test.cpp fterm_functions_test_SOURCES = fterm_functions-test.cpp +ftermcap_test_SOURCES = ftermcap-test.cpp ftermdata_test_SOURCES = ftermdata-test.cpp ftermbuffer_test_SOURCES = ftermbuffer-test.cpp ftermdetection_test_SOURCES = ftermdetection-test.cpp @@ -61,6 +63,7 @@ TESTS = fobject_test \ fmouse_test \ fkeyboard_test \ fterm_functions_test \ + ftermcap_test \ ftermdata_test \ ftermbuffer_test \ ftermdetection_test \ diff --git a/test/ftermcap-test.cpp b/test/ftermcap-test.cpp new file mode 100644 index 00000000..eeedf375 --- /dev/null +++ b/test/ftermcap-test.cpp @@ -0,0 +1,493 @@ +/*********************************************************************** +* ftermcap-test.cpp - FTermcap unit tests * +* * +* This file is part of the FINAL CUT widget toolkit * +* * +* Copyright 2021 Markus Gans * +* * +* FINAL CUT is free software; you can redistribute it and/or modify * +* it under the terms of the GNU Lesser General Public License as * +* published by the Free Software Foundation; either version 3 of * +* the License, or (at your option) any later version. * +* * +* FINAL CUT is distributed in the hope that it will be useful, but * +* WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU Lesser General Public License for more details. * +* * +* You should have received a copy of the GNU Lesser General Public * +* License along with this program. If not, see * +* . * +***********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +// FTermcap string macro +#ifdef TCAP + #undef TCAP +#endif +#define TCAP(...) finalcut::FTermcap::strings[int(finalcut::Termcap::__VA_ARGS__)].string + +using std::chrono::duration_cast; +using std::chrono::milliseconds; +using std::chrono::high_resolution_clock; + + +#define CPPUNIT_ASSERT_CSTRING(expected, actual) \ + check_c_string (expected, actual, CPPUNIT_SOURCELINE()) + +//---------------------------------------------------------------------- +void check_c_string ( const char* s1 + , const char* s2 + , CppUnit::SourceLine sourceLine ) +{ + if ( s1 == 0 && s2 == 0 ) // Strings are equal + return; + + if ( s1 && s2 && std::strcmp (s1, s2) == 0 ) // Strings are equal + return; + + ::CppUnit::Asserter::fail ("Strings are not equal", sourceLine); +} + + +//---------------------------------------------------------------------- +// class FTermcapTest +//---------------------------------------------------------------------- + +class FTermcapTest : public CPPUNIT_NS::TestFixture +{ + public: + FTermcapTest() + { } + + protected: + void classNameTest(); + void initTest(); + void getFlagTest(); + void getNumberTest(); + void getStringTest(); + void encodeMotionParameterTest(); + void encodeParameterTest(); + void paddingPrintTest(); + + private: + static int putchar_test(int); + static void clear(); + + // Adds code needed to register the test suite + CPPUNIT_TEST_SUITE (FTermcapTest); + + // Add a methods to the test suite + CPPUNIT_TEST (classNameTest); + CPPUNIT_TEST (initTest); + CPPUNIT_TEST (getFlagTest); + CPPUNIT_TEST (getNumberTest); + CPPUNIT_TEST (getStringTest); + CPPUNIT_TEST (encodeMotionParameterTest); + CPPUNIT_TEST (encodeParameterTest); + //CPPUNIT_TEST (paddingPrintTest); + + // End of test suite definition + CPPUNIT_TEST_SUITE_END(); + + // Data member + static std::string output; +}; + +// static class attribute +std::string FTermcapTest::output{}; + + +//---------------------------------------------------------------------- +void FTermcapTest::classNameTest() +{ + finalcut::FTermcap tcap; + const finalcut::FString& classname = tcap.getClassName(); + CPPUNIT_ASSERT ( classname == "FTermcap" ); +} + +//---------------------------------------------------------------------- +void FTermcapTest::initTest() +{ + // Without a terminal type + const auto& fterm_data = finalcut::FTerm::getFTermData(); + CPPUNIT_ASSERT ( fterm_data->getTermType().empty() ); + finalcut::FTermcap tcap; + CPPUNIT_ASSERT ( ! tcap.isInitialized() ); + tcap.init(); + CPPUNIT_ASSERT ( tcap.isInitialized() ); + CPPUNIT_ASSERT ( ! fterm_data->getTermType().empty() ); + CPPUNIT_ASSERT ( fterm_data->getTermType() == "xterm" ); + + // With terminal type ansi + fterm_data->setTermType("ansi"); + tcap.init(); + CPPUNIT_ASSERT ( fterm_data->getTermType() == "ansi" ); + + // With a non-existent terminal type + fterm_data->setTermType("bang!"); + tcap.init(); + CPPUNIT_ASSERT ( fterm_data->getTermType() == "xterm" ); + setenv ("TERM", "xterm-256color", 1); // 256 color terminal + const auto& term_detection = finalcut::FTerm::getFTermDetection(); + CPPUNIT_ASSERT ( ! term_detection->canDisplay256Colors() ); + term_detection->detect(); + CPPUNIT_ASSERT ( term_detection->canDisplay256Colors() ); + fterm_data->setTermType("bang!"); + tcap.init(); + CPPUNIT_ASSERT ( fterm_data->getTermType() == "xterm-256color" ); + fterm_data->setTermType("dumb"); + tcap.init(); + CPPUNIT_ASSERT ( fterm_data->getTermType() == "dumb" ); +} + +//---------------------------------------------------------------------- +void FTermcapTest::getFlagTest() +{ + const auto& fterm_data = finalcut::FTerm::getFTermData(); + fterm_data->setTermType("ansi"); + finalcut::FTermcap tcap; + tcap.init(); + CPPUNIT_ASSERT ( tcap.isInitialized() ); + CPPUNIT_ASSERT ( fterm_data->getTermType() == "ansi" ); + + CPPUNIT_ASSERT ( tcap.getFlag("am") ); // Automatic right margin + CPPUNIT_ASSERT ( ! tcap.getFlag("cc") ); // Can change color palette + CPPUNIT_ASSERT ( ! tcap.getFlag("xo") ); // Xon/Xoff flow control +} + +//---------------------------------------------------------------------- +void FTermcapTest::getNumberTest() +{ + const auto& fterm_data = finalcut::FTerm::getFTermData(); + fterm_data->setTermType("xterm"); + finalcut::FTermcap tcap; + tcap.init(); + CPPUNIT_ASSERT ( tcap.isInitialized() ); + CPPUNIT_ASSERT ( fterm_data->getTermType() == "xterm" ); + + CPPUNIT_ASSERT ( tcap.getNumber("Co") == 8 ); // Colors + CPPUNIT_ASSERT ( tcap.getNumber("it") == 8 ); // Tab stop + CPPUNIT_ASSERT ( tcap.getNumber("NC") == 0 ); // Attr. without color + CPPUNIT_ASSERT ( tcap.getNumber("co") == 80 ); // Columns + CPPUNIT_ASSERT ( tcap.getNumber("li") == 24 ); // Lines +} + +//---------------------------------------------------------------------- +void FTermcapTest::getStringTest() +{ + const auto& fterm_data = finalcut::FTerm::getFTermData(); + fterm_data->setTermType("ansi"); + finalcut::FTermcap tcap; + tcap.init(); + CPPUNIT_ASSERT ( tcap.isInitialized() ); + CPPUNIT_ASSERT ( fterm_data->getTermType() == "ansi" ); + + CPPUNIT_ASSERT_CSTRING ( tcap.getString("me"), CSI "0m" ); // Exit attribute mode + CPPUNIT_ASSERT_CSTRING ( tcap.getString("mr"), CSI "7m" ); // Enter reverse mode + CPPUNIT_ASSERT_CSTRING ( tcap.getString("us"), CSI "4m" ); // Enter underline mode + CPPUNIT_ASSERT_CSTRING ( tcap.getString("cd"), CSI "J" ); // Clear to end of screen + CPPUNIT_ASSERT_CSTRING ( tcap.getString("ce"), CSI "K" ); // Clear to end of line + CPPUNIT_ASSERT_CSTRING ( tcap.getString("cl"), CSI "H" CSI "J" ); // Clear screen +} + +//---------------------------------------------------------------------- +void FTermcapTest::encodeMotionParameterTest() +{ + const auto& fterm_data = finalcut::FTerm::getFTermData(); + fterm_data->setTermType("ansi"); + finalcut::FTermcap tcap; + tcap.init(); + CPPUNIT_ASSERT ( tcap.isInitialized() ); + CPPUNIT_ASSERT ( fterm_data->getTermType() == "ansi" ); + const auto& cursor_address = tcap.getString("cm"); + CPPUNIT_ASSERT ( tcap.encodeMotionParameter(cursor_address, 10, 15) == CSI "16;11H" ); + CPPUNIT_ASSERT ( tcap.encodeMotionParameter(cursor_address, 25, 1) == CSI "2;26H" ); + CPPUNIT_ASSERT ( tcap.encodeMotionParameter(cursor_address, 0, 0) == CSI "1;1H" ); + CPPUNIT_ASSERT ( tcap.encodeMotionParameter(cursor_address, 79, 23) == CSI "24;80H" ); +} + +//---------------------------------------------------------------------- +void FTermcapTest::encodeParameterTest() +{ + const auto& fterm_data = finalcut::FTerm::getFTermData(); + fterm_data->setTermType("ansi"); + finalcut::FTermcap tcap; + tcap.init(); + CPPUNIT_ASSERT ( tcap.isInitialized() ); + CPPUNIT_ASSERT ( fterm_data->getTermType() == "ansi" ); + const auto& parm_insert_line = tcap.getString("AL"); + CPPUNIT_ASSERT ( tcap.encodeParameter(parm_insert_line, 7) == CSI "7L" ); + const auto& parm_left_cursor = tcap.getString("LE"); + CPPUNIT_ASSERT ( tcap.encodeParameter(parm_left_cursor, 3) == CSI "3D" ); + const auto& parm_right_cursor = tcap.getString("RI"); + CPPUNIT_ASSERT ( tcap.encodeParameter(parm_right_cursor, 4) == CSI "4C" ); + const auto& parm_down_cursor = tcap.getString("DO"); + CPPUNIT_ASSERT ( tcap.encodeParameter(parm_down_cursor, 12) == CSI "12B" ); + const auto& parm_up_cursor = tcap.getString("UP"); + CPPUNIT_ASSERT ( tcap.encodeParameter(parm_up_cursor, 5) == CSI "5A" ); + const auto& parm_delete_line = tcap.getString("DL"); + CPPUNIT_ASSERT ( tcap.encodeParameter(parm_delete_line, 9) == CSI "9M" ); +} + +//---------------------------------------------------------------------- +void FTermcapTest::paddingPrintTest() +{ + finalcut::FTermcap tcap; + setenv ("TERM", "xterm", 1); // xterm has no padding character + unsetenv("TERMCAP"); + auto& fterm_data = finalcut::FTerm::getFTermData(); + fterm_data->setTermType("xterm"); + CPPUNIT_ASSERT ( ! tcap.xon_xoff_flow_control ); + tcap.init(); + CPPUNIT_ASSERT ( tcap.isInitialized() ); + CPPUNIT_ASSERT ( tcap.no_padding_char ); + + // '$' without '<' + CPPUNIT_ASSERT ( output.empty() ); + tcap.paddingPrint ("12$34567", 1, FTermcapTest::putchar_test); + CPPUNIT_ASSERT ( ! output.empty() ); + CPPUNIT_ASSERT ( output == "12$34567" ); + + // No closing '>' + output.clear(); + tcap.paddingPrint ("12$3$<4567", 1, FTermcapTest::putchar_test); + CPPUNIT_ASSERT ( ! output.empty() ); + CPPUNIT_ASSERT ( output == "12$3$<4567" ); + + // With 2 ms print delay + output.clear(); + auto start = high_resolution_clock::now(); + tcap.paddingPrint ("1234$<2/>567", 1, FTermcapTest::putchar_test); + auto end = high_resolution_clock::now(); + auto duration_ms = int(duration_cast(end - start).count()); + CPPUNIT_ASSERT ( duration_ms >= 2 ); + CPPUNIT_ASSERT ( ! output.empty() ); + CPPUNIT_ASSERT ( output == "1234567" ); + + // With 20 ms print delay + output.clear(); + start = high_resolution_clock::now(); + tcap.paddingPrint ("12$3$<45$<20/>67", 1, FTermcapTest::putchar_test); + end = high_resolution_clock::now(); + duration_ms = int(duration_cast(end - start).count()); + CPPUNIT_ASSERT ( duration_ms >= 20 ); + CPPUNIT_ASSERT ( ! output.empty() ); + CPPUNIT_ASSERT ( output == "12$3$<4567" ); + + // With a high a delay (9.999 seconds) + output.clear(); + start = high_resolution_clock::now(); + tcap.paddingPrint ("1234$<9999/>567", 1, FTermcapTest::putchar_test); + end = high_resolution_clock::now(); + duration_ms = int(duration_cast(end - start).count()); + CPPUNIT_ASSERT ( duration_ms >= 9999 ); + CPPUNIT_ASSERT ( ! output.empty() ); + CPPUNIT_ASSERT ( output == "1234567" ); + + // With too high a delay (delay > 9999 ms = 9.999 sec) + output.clear(); + start = high_resolution_clock::now(); + tcap.paddingPrint ("1234$<10000>567", 1, FTermcapTest::putchar_test); + end = high_resolution_clock::now(); + duration_ms = int(duration_cast(end - start).count()); + CPPUNIT_ASSERT ( duration_ms < 20 ); + CPPUNIT_ASSERT ( ! output.empty() ); + CPPUNIT_ASSERT ( output == "1234$<10000>567" ); + + // Beep has delayed output and flush + output.clear(); + tcap.paddingPrint (TCAP(t_bell), 1, FTermcapTest::putchar_test); + CPPUNIT_ASSERT ( ! output.empty() ); + CPPUNIT_ASSERT ( output == std::string(TCAP(t_bell)) ); + + // Flash screen has delayed output and flush + output.clear(); + start = high_resolution_clock::now(); + tcap.paddingPrint ("\033[?5h$<100/>\033[?5l", 1, FTermcapTest::putchar_test); + end = high_resolution_clock::now(); + duration_ms = int(duration_cast(end - start).count()); + CPPUNIT_ASSERT ( duration_ms >= 100 ); + CPPUNIT_ASSERT ( ! output.empty() ); + CPPUNIT_ASSERT ( output == std::string("\033[?5h\033[?5l") ); + + // With 5 ms prints 21 padding chars ('\0') + setenv ("TERM", "ansi", 1); // ansi terminals used for delay padding character + fterm_data->setTermType("ansi"); + tcap.init(); + CPPUNIT_ASSERT ( ! tcap.no_padding_char ); + CPPUNIT_ASSERT ( ! tcap.xon_xoff_flow_control ); + output.clear(); + tcap.setBaudrate (38400); + tcap.paddingPrint ("1234$<5*/>567", 1, FTermcapTest::putchar_test); + const auto& str1_with_0 = "1234" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "567"; + std::string target_output(std::begin(str1_with_0), std::end(str1_with_0) - 1); + CPPUNIT_ASSERT ( ! output.empty() ); + CPPUNIT_ASSERT ( output.length() == 28 ); + CPPUNIT_ASSERT ( output == target_output ); + + // Wait 2 ms with padding characters and with 1 affected line + output.clear(); + tcap.setBaudrate (9600); + tcap.padding_baudrate = 0; // no padding baudrate + tcap.paddingPrint ("abc$<2*>def", 1, FTermcapTest::putchar_test); + CPPUNIT_ASSERT ( output.length() == 6 ); + CPPUNIT_ASSERT ( output == "abcdef" ); + output.clear(); + tcap.paddingPrint ("abc$<2*/>def", 1, FTermcapTest::putchar_test); // with "*/" + const auto& str2_with_0 = "abc" "\0\0" "def"; + target_output = std::string(std::begin(str2_with_0), std::end(str2_with_0) - 1); + CPPUNIT_ASSERT ( output.length() == 8 ); + CPPUNIT_ASSERT ( output == target_output ); + output.clear(); + tcap.paddingPrint ("abc$<2/*>def", 1, FTermcapTest::putchar_test); // with "/*" + CPPUNIT_ASSERT ( output.length() == 8 ); + CPPUNIT_ASSERT ( output == target_output ); + output.clear(); + tcap.paddingPrint ("abc$<2/x*>def", 1, FTermcapTest::putchar_test); // defekt + CPPUNIT_ASSERT ( output.length() == 13 ); + CPPUNIT_ASSERT ( output == "abc$<2/x*>def" ); + output.clear(); + tcap.paddingPrint ("abc$<2/*x>def", 1, FTermcapTest::putchar_test); // defekt + CPPUNIT_ASSERT ( output.length() == 13 ); + CPPUNIT_ASSERT ( output == "abc$<2/*x>def" ); + output.clear(); + tcap.padding_baudrate = 19200; // baudrate < padding baudrate + tcap.paddingPrint ("abc$<2*>def", 1, FTermcapTest::putchar_test); + CPPUNIT_ASSERT ( output.length() == 6 ); + CPPUNIT_ASSERT ( output == "abcdef" ); + output.clear(); + tcap.paddingPrint ("abc$<2*/>def", 1, FTermcapTest::putchar_test); // with "*/" + CPPUNIT_ASSERT ( output.length() == 8 ); + CPPUNIT_ASSERT ( output == target_output ); + output.clear(); + tcap.padding_baudrate = 9600; // baudrate >= padding baudrate + tcap.paddingPrint ("abc$<2*>def", 1, FTermcapTest::putchar_test); + CPPUNIT_ASSERT ( output.length() == 8 ); + CPPUNIT_ASSERT ( output == target_output ); + + // Wait 2 ms with padding characters and with 2 affected line + output.clear(); + tcap.padding_baudrate = 0; // no padding baudrate + tcap.paddingPrint ("abc$<2*>>def", 2, FTermcapTest::putchar_test); // double >> + CPPUNIT_ASSERT ( output.length() == 7 ); + CPPUNIT_ASSERT ( output == "abc>def" ); + output.clear(); + tcap.paddingPrint ("abc$<2*/>def", 2, FTermcapTest::putchar_test); // with "*/" + const auto& str3_with_0 = "abc" "\0\0\0\0" "def"; + target_output = std::string(std::begin(str3_with_0), std::end(str3_with_0) - 1); + CPPUNIT_ASSERT ( output.length() == 10 ); + CPPUNIT_ASSERT ( output == target_output ); + output.clear(); + tcap.paddingPrint ("abc$<2/*>def", 2, FTermcapTest::putchar_test); // with "/*" + CPPUNIT_ASSERT ( output.length() == 10 ); + CPPUNIT_ASSERT ( output == target_output ); + output.clear(); + tcap.padding_baudrate = 19200; // baudrate < padding baudrate + tcap.paddingPrint ("abc$<2*>def", 2, FTermcapTest::putchar_test); + CPPUNIT_ASSERT ( output.length() == 6 ); + CPPUNIT_ASSERT ( output == "abcdef" ); + output.clear(); + tcap.paddingPrint ("abc$<2*/>def", 2, FTermcapTest::putchar_test); // with "*/" + CPPUNIT_ASSERT ( output.length() == 10 ); + CPPUNIT_ASSERT ( output == target_output ); + output.clear(); + tcap.paddingPrint ("abc$<2/*>def", 2, FTermcapTest::putchar_test); // with "/*" + CPPUNIT_ASSERT ( output.length() == 10 ); + CPPUNIT_ASSERT ( output == target_output ); + output.clear(); + tcap.padding_baudrate = 9600; // baudrate >= padding baudrate + tcap.paddingPrint ("abc$<2*>def", 2, FTermcapTest::putchar_test); + CPPUNIT_ASSERT ( output.length() == 10 ); + CPPUNIT_ASSERT ( output == target_output ); + + // Wait 2 ms with padding characters and with 3 affected line + output.clear(); + tcap.padding_baudrate = 0; // no padding baudrate + tcap.paddingPrint ("abc$<2*>def", 3, FTermcapTest::putchar_test); + CPPUNIT_ASSERT ( output == "abcdef" ); + output.clear(); + tcap.paddingPrint ("abc$<2*/>def", 3, FTermcapTest::putchar_test); // with "*/" + const auto& str4_with_0 = "abc" "\0\0\0\0\0\0" "def"; + target_output = std::string(std::begin(str4_with_0), std::end(str4_with_0) - 1); + CPPUNIT_ASSERT ( output.length() == 12 ); + CPPUNIT_ASSERT ( output == target_output ); + output.clear(); + tcap.paddingPrint ("abc$<2/*>def", 3, FTermcapTest::putchar_test); // with "/*" + CPPUNIT_ASSERT ( output.length() == 12 ); + CPPUNIT_ASSERT ( output == target_output ); + output.clear(); + tcap.padding_baudrate = 19200; // baudrate < padding baudrate + tcap.paddingPrint ("abc$<2*>def", 3, FTermcapTest::putchar_test); + CPPUNIT_ASSERT ( output.length() == 6 ); + CPPUNIT_ASSERT ( output == "abcdef" ); + output.clear(); + tcap.paddingPrint ("abc$<2*/>def", 3, FTermcapTest::putchar_test); // with "*/" + CPPUNIT_ASSERT ( output.length() == 12 ); + CPPUNIT_ASSERT ( output == target_output ); + output.clear(); + tcap.paddingPrint ("abc$<2/*>def", 3, FTermcapTest::putchar_test); // with "/*" + CPPUNIT_ASSERT ( output.length() == 12 ); + CPPUNIT_ASSERT ( output == target_output ); + output.clear(); + tcap.padding_baudrate = 9600; // baudrate >= padding baudrate + tcap.paddingPrint ("abc$<2*>def", 3, FTermcapTest::putchar_test); + CPPUNIT_ASSERT ( output.length() == 12 ); + CPPUNIT_ASSERT ( output == target_output ); + + // With decimal point + output.clear(); + tcap.setBaudrate(19200); + tcap.padding_baudrate = 19200; // baudrate == padding baudrate + tcap.paddingPrint ("abc$<2.>def", 1, FTermcapTest::putchar_test); // 2. + const auto& str5_with_0 = "abc" "\0\0\0\0" "def"; + target_output = std::string(std::begin(str5_with_0), std::end(str5_with_0) - 1); + CPPUNIT_ASSERT ( output.length() == 10 ); + CPPUNIT_ASSERT ( output == target_output ); + output.clear(); + tcap.paddingPrint ("abc$<2.0>def", 1, FTermcapTest::putchar_test); // 2.0 + CPPUNIT_ASSERT ( output.length() == 10 ); + CPPUNIT_ASSERT ( output == target_output ); + output.clear(); + tcap.paddingPrint ("abc$<2.7>def", 1, FTermcapTest::putchar_test); // 2.7 + CPPUNIT_ASSERT ( output.length() == 10 ); + CPPUNIT_ASSERT ( output == target_output ); + output.clear(); + tcap.paddingPrint ("abc$<2.77>def", 1, FTermcapTest::putchar_test); // 2.77 + CPPUNIT_ASSERT ( output.length() == 10 ); + CPPUNIT_ASSERT ( output == target_output ); +} + +//---------------------------------------------------------------------- +int FTermcapTest::putchar_test (int ch) +{ + //std::cout << std::hex << "0x" << ch << "," << std::flush; + output.push_back(char(ch)); + return ch; +} + +//---------------------------------------------------------------------- +void FTermcapTest::clear() +{ + output.clear(); +} + +//---------------------------------------------------------------------- + +// Put the test suite in the registry +CPPUNIT_TEST_SUITE_REGISTRATION (FTermcapTest); + +// The general unit test main part +#include