diff --git a/.travis.yml b/.travis.yml index dfeb55a3..fcabedb0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ language: cpp dist: xenial -sudo: required compiler: - gcc @@ -41,7 +40,7 @@ env: bL/epiiMBKJ37X1UcRU4WZYq+peLME8EefcPcXOSWNLwJtR7mtON8uMBrLL9CWmRMFD5Hy lQYALW2DhCnDBROKB3gxB/VkBGFNE0IPGeDtBGbLqDtKWPQoL125I= -matrix: +jobs: include: # # Coverity Scan diff --git a/ChangeLog b/ChangeLog index a65440a9..4b6ab317 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2020-10-11 Markus Gans + * Solaris build fix + * Added saving and restoring xterm titles to the stack + for vte terminals + * Menu key - activates the menu bar + * Shift-Menu - opens the dialog menu + 2020-10-08 Markus Gans * Better keyboard support for urxvt terminals * Screen reports (like Secondary DA) are now read directly diff --git a/doc/first-steps.md b/doc/first-steps.md index 172a4e64..7cafbacb 100644 --- a/doc/first-steps.md +++ b/doc/first-steps.md @@ -137,7 +137,7 @@ int main (int argc, char* argv[]) After entering the source code in *dialog.cpp* you can compile the above program with gcc: -```cpp +```bash g++ dialog.cpp -o dialog -O2 -lfinal ``` @@ -284,7 +284,7 @@ int main (int argc, char* argv[]) After entering the source code in *memory.cpp* you can compile the above program with gcc: -```cpp +```bash g++ memory.cpp -o memory -O2 -lfinal ``` @@ -424,7 +424,7 @@ int main (int argc, char* argv[]) After entering the source code in *timer.cpp* you can compile the above program with gcc: -```cpp +```bash g++ timer.cpp -o timer -O2 -lfinal -std=c++11 ``` @@ -537,7 +537,7 @@ int main (int argc, char* argv[]) After entering the source code in *user-event.cpp* you can compile the above program with gcc: -```cpp +```bash g++ user-event.cpp -o user-event -O2 -lfinal -std=c++11 ``` @@ -808,7 +808,7 @@ int main (int argc, char* argv[]) After entering the source code in *callback-function.cpp* you can compile the above program with gcc: -```cpp +```bash g++ callback-function.cpp -o callback-function -O2 -lfinal ```   @@ -871,7 +871,7 @@ int main (int argc, char* argv[]) After entering the source code in *callback-lambda.cpp* you can compile the above program with gcc: -```cpp +```bash g++ callback-lambda.cpp -o callback-lambda -O2 -lfinal -std=c++11 ```   @@ -930,7 +930,7 @@ int main (int argc, char* argv[]) After entering the source code in *callback-method.cpp* you can compile the above program with gcc: -```cpp +```bash g++ callback-method.cpp -o callback-method -O2 -lfinal -std=c++11 ```   @@ -1051,7 +1051,7 @@ int main (int argc, char* argv[]) After entering the source code in *emit-signal.cpp* you can compile the above program with gcc: -```cpp +```bash g++ emit-signal.cpp -o emit-signal -O2 -lfinal -std=c++11 ``` @@ -1322,7 +1322,7 @@ int main (int argc, char* argv[]) After entering the source code in *size-adjustment.cpp* you can compile the above program with gcc: -```cpp +```bash g++ size-adjustment.cpp -o size-adjustment -O2 -lfinal -std=c++11 ``` @@ -1450,6 +1450,6 @@ int main (int argc, char* argv[]) After entering the source code in *scrollview.cpp* you can compile the above program with gcc: -```cpp +```bash g++ scrollview.cpp -o scrollview -O2 -lfinal -std=c++11 ``` diff --git a/doc/user-theme.md b/doc/user-theme.md index 611a2c23..18156010 100644 --- a/doc/user-theme.md +++ b/doc/user-theme.md @@ -437,7 +437,7 @@ int main (int argc, char* argv[]) After entering the source code in *theme.cpp* you can compile the above program with gcc: -```cpp +```bash g++ theme.cpp -o theme -O2 -lfinal -std=c++11 ``` diff --git a/examples/menu.cpp b/examples/menu.cpp index 66099bf8..a60dd65e 100644 --- a/examples/menu.cpp +++ b/examples/menu.cpp @@ -151,8 +151,10 @@ Menu::Menu (finalcut::FWidget* parent) // Info label Info << " Activate menu bar\n" << "+ Activate menu bar\n" + << " Activate menu bar\n" + << "+ Open dialog menu\n" << "+ Exit"; - Info.setGeometry(FPoint{2, 1}, FSize{36, 3}); + Info.setGeometry(FPoint{2, 1}, FSize{36, 5}); } //---------------------------------------------------------------------- @@ -327,7 +329,7 @@ int main (int argc, char* argv[]) // Create main dialog object Menu main_dlg {&app}; main_dlg.setText ("Menu example"); - main_dlg.setSize ({40, 6}); + main_dlg.setSize ({40, 8}); main_dlg.setShadow(); // Set dialog main_dlg as main widget diff --git a/examples/ui.cpp b/examples/ui.cpp index 1b16c5f1..6e429bac 100644 --- a/examples/ui.cpp +++ b/examples/ui.cpp @@ -780,10 +780,9 @@ void MyDialog::initWidgetsCallbacks() //---------------------------------------------------------------------- void MyDialog::adjustSize() { - finalcut::FDialog::adjustSize(); - const auto h = getDesktopHeight() - 4; setHeight (h, false); + finalcut::FDialog::adjustSize(); // with new client area size auto x = int((getDesktopWidth() - getWidth()) / 2); if ( x < 1 ) @@ -792,7 +791,7 @@ void MyDialog::adjustSize() setPos (FPoint{x, 2}, false); if ( initialized ) - myList.setHeight (getHeight() - 3, true); + myList.setHeight (h - 3, true); } //---------------------------------------------------------------------- diff --git a/src/fapplication.cpp b/src/fapplication.cpp index 87fa16e1..7c43f8c7 100644 --- a/src/fapplication.cpp +++ b/src/fapplication.cpp @@ -66,9 +66,35 @@ FMouseControl* FApplication::mouse {nullptr}; // mouse control int FApplication::loop_level {0}; // event loop level int FApplication::quit_code {EXIT_SUCCESS}; bool FApplication::quit_now {false}; -uInt64 FApplication::next_event_wait {5000}; // preset to 5 ms /200 Hz +uInt64 FApplication::next_event_wait {5000}; // preset to 5 ms (200 Hz) struct timeval FApplication::time_last_event{}; + +constexpr FApplication::CmdOption FApplication::long_options[] = +{ + {"encoding", required_argument, nullptr, 'e' }, + {"log-file", required_argument, nullptr, 'l' }, + {"no-mouse", no_argument, nullptr, 'm' }, + {"no-optimized-cursor", no_argument, nullptr, 'o' }, + {"no-terminal-detection", no_argument, nullptr, 'd' }, + {"no-terminal-data-request", no_argument, nullptr, 'r' }, + {"no-color-change", no_argument, nullptr, 'c' }, + {"no-sgr-optimizer", no_argument, nullptr, 's' }, + {"vgafont", no_argument, nullptr, 'v' }, + {"newfont", no_argument, nullptr, 'n' }, + {"dark-theme", no_argument, nullptr, 't' }, + +#if defined(__FreeBSD__) || defined(__DragonFly__) + {"no-esc-for-alt-meta", no_argument, nullptr, 'E' }, + {"no-cursorstyle-change", no_argument, nullptr, 'C' }, +#elif defined(__NetBSD__) || defined(__OpenBSD__) + {"no-esc-for-alt-meta", no_argument, nullptr, 'E' }, +#endif + + {nullptr, 0, nullptr, 0 } +}; + + //---------------------------------------------------------------------- // class FApplication //---------------------------------------------------------------------- @@ -382,7 +408,9 @@ void FApplication::closeConfirmationDialog (FWidget* w, FCloseEvent* ev) void FApplication::processExternalUserEvent() { // This method can be overloaded and replaced by own code - std::this_thread::sleep_for(std::chrono::milliseconds(5)); + + if ( FKeyboard::getReadBlockingTime() < 10000 ) + std::this_thread::sleep_for(std::chrono::milliseconds(5)); } @@ -463,81 +491,72 @@ void FApplication::cmd_options (const int& argc, char* argv[]) while ( true ) { - static struct option long_options[] = - { - {"encoding", required_argument, nullptr, 0 }, - {"log-file", required_argument, nullptr, 0 }, - {"no-mouse", no_argument, nullptr, 0 }, - {"no-optimized-cursor", no_argument, nullptr, 0 }, - {"no-terminal-detection", no_argument, nullptr, 0 }, - {"no-terminal-data-request", no_argument, nullptr, 0 }, - {"no-color-change", no_argument, nullptr, 0 }, - {"no-sgr-optimizer", no_argument, nullptr, 0 }, - {"vgafont", no_argument, nullptr, 0 }, - {"newfont", no_argument, nullptr, 0 }, - {"dark-theme", no_argument, nullptr, 0 }, - - #if defined(__FreeBSD__) || defined(__DragonFly__) - {"no-esc-for-alt-meta", no_argument, nullptr, 0 }, - {"no-cursorstyle-change", no_argument, nullptr, 0 }, - #elif defined(__NetBSD__) || defined(__OpenBSD__) - {"no-esc-for-alt-meta", no_argument, nullptr, 0 }, - #endif - - {nullptr, 0, nullptr, 0 } - }; - opterr = 0; int idx{0}; - const int c = getopt_long (argc, argv, "", long_options, &idx); + auto p = reinterpret_cast(long_options); + const int opt = getopt_long (argc, argv, "", p, &idx); - if ( c == -1 ) + if ( opt == -1 ) break; - if ( c == 0 ) + switch ( opt ) { - if ( std::strcmp(long_options[idx].name, "encoding") == 0 ) + case 'e': // --encoding setTerminalEncoding(FString(optarg)); + break; - if ( std::strcmp(long_options[idx].name, "log-file") == 0 ) + case 'l': // --log-file setLogFile(FString(optarg)); + break; - if ( std::strcmp(long_options[idx].name, "no-mouse") == 0 ) + case 'm': // --no-mouse getStartOptions().mouse_support = false; + break; - if ( std::strcmp(long_options[idx].name, "no-optimized-cursor") == 0 ) + case 'o': // --no-optimized-cursor getStartOptions().cursor_optimisation = false; + break; - if ( std::strcmp(long_options[idx].name, "no-terminal-detection") == 0 ) + case 'd': // --no-terminal-detection getStartOptions().terminal_detection = false; + break; - if ( std::strcmp(long_options[idx].name, "no-terminal-data-request") == 0 ) + case 'r': // --no-terminal-data-request getStartOptions().terminal_data_request = false; + break; - if ( std::strcmp(long_options[idx].name, "no-color-change") == 0 ) + case 'c': // --no-color-change getStartOptions().color_change = false; + break; - if ( std::strcmp(long_options[idx].name, "no-sgr-optimizer") == 0 ) + case 's': // --no-sgr-optimizer getStartOptions().sgr_optimizer = false; + break; - if ( std::strcmp(long_options[idx].name, "vgafont") == 0 ) + case 'v': // --vgafont getStartOptions().vgafont = true; + break; - if ( std::strcmp(long_options[idx].name, "newfont") == 0 ) + case 'n': // --newfont getStartOptions().newfont = true; + break; - if ( std::strcmp(long_options[idx].name, "dark-theme") == 0 ) + case 't': // --dark-theme getStartOptions().dark_theme = true; + break; #if defined(__FreeBSD__) || defined(__DragonFly__) - if ( std::strcmp(long_options[idx].name, "no-esc-for-alt-meta") == 0 ) + case 'E': // --no-esc-for-alt-meta getStartOptions().meta_sends_escape = false; + break; - if ( std::strcmp(long_options[idx].name, "no-cursorstyle-change") == 0 ) + case 'C': // --no-cursorstyle-change getStartOptions().change_cursorstyle = false; + break; #elif defined(__NetBSD__) || defined(__OpenBSD__) - if ( std::strcmp(long_options[idx].name, "no-esc-for-alt-meta") == 0 ) + case 'E': // --no-esc-for-alt-meta getStartOptions().meta_sends_escape = false; + break; #endif } } diff --git a/src/fdialog.cpp b/src/fdialog.cpp index d726452c..b4c6be82 100644 --- a/src/fdialog.cpp +++ b/src/fdialog.cpp @@ -459,8 +459,9 @@ void FDialog::onKeyPress (FKeyEvent* ev) cancelMouseResize(); - if ( ev->key() == fc::Fckey_caret // Ctrl+^ (Ctrl+6) - || ev->key() == fc::Fkey_f22 ) // Shift+F10 + if ( ev->key() == fc::Fckey_caret // Ctrl+^ (Ctrl+6) + || ev->key() == fc::Fkey_f22 // Shift+F10 + || ev->key() == fc::Fkey_smenu ) // Shift+Menu { ev->accept(); // open the titlebar menu diff --git a/src/flog.cpp b/src/flog.cpp index 9a244551..c06e1d2c 100644 --- a/src/flog.cpp +++ b/src/flog.cpp @@ -47,6 +47,7 @@ FLog& FLog::operator << (LogLevel l) { using std::placeholders::_1; sync(); + std::lock_guard lock_guard(mut); switch ( l ) { @@ -77,6 +78,7 @@ int FLog::sync() { if ( ! str().empty() ) { + std::lock_guard lock_guard(mut); current_log (str()); str(""); } diff --git a/src/flogger.cpp b/src/flogger.cpp index d75341b3..6f1bf2a7 100644 --- a/src/flogger.cpp +++ b/src/flogger.cpp @@ -72,8 +72,10 @@ std::string FLogger::getTimeString() const } //---------------------------------------------------------------------- -std::string FLogger::getEOL() const +std::string FLogger::getEOL() { + std::lock_guard lock_guard(getMutex()); + if ( getEnding() == FLog::LF ) return "\n"; else if ( getEnding() == FLog::CR ) @@ -89,6 +91,8 @@ void FLogger::printLogLine (const std::string& msg) { const std::string& log_level = [this] () { + std::lock_guard lock_guard(getMutex()); + switch ( getLevel() ) { case Info: diff --git a/src/fmenubar.cpp b/src/fmenubar.cpp index cb57dc8a..e03f7dd2 100644 --- a/src/fmenubar.cpp +++ b/src/fmenubar.cpp @@ -256,6 +256,7 @@ void FMenuBar::init() addAccelerator (fc::Fkey_f10); addAccelerator (fc::Fckey_space); + addAccelerator (fc::Fkey_menu); resetColors(); unsetFocusable(); } diff --git a/src/fterm_functions.cpp b/src/fterm_functions.cpp index e1e42515..0d9dba11 100644 --- a/src/fterm_functions.cpp +++ b/src/fterm_functions.cpp @@ -553,15 +553,13 @@ FPoint readCursorPos() FD_SET(stdin_no, &ifds); tv.tv_sec = 0; tv.tv_usec = 100000; // 100 ms + std::array temp{}; + std::size_t pos{0}; // Read the answer if ( select (stdin_no + 1, &ifds, nullptr, nullptr, &tv) != 1 ) return FPoint{x, y}; - constexpr auto parse = "\033[%4d;%4dR"; - std::array temp{}; - std::size_t pos{0}; - do { std::size_t bytes_free = temp.size() - pos - 1; @@ -572,10 +570,13 @@ FPoint readCursorPos() pos += std::size_t(bytes); } - while ( pos < temp.size() && std::strchr(temp.data(), 'R') == nullptr ); + while ( pos < temp.size() && ! std::strchr(temp.data(), 'R') ); if ( pos > 4 ) + { + constexpr auto parse = "\033[%4d;%4dR"; std::sscanf(temp.data(), parse, &x, &y); + } return FPoint{x, y}; } diff --git a/src/ftermcap.cpp b/src/ftermcap.cpp index 372173ca..ae2f712e 100644 --- a/src/ftermcap.cpp +++ b/src/ftermcap.cpp @@ -91,7 +91,7 @@ void FTermcap::termcap() // Open termcap file #if defined(__sun) && defined(__SVR4) - char* termtype = fterm_data->getTermType(); + char* termtype = const_cast(fterm_data->getTermType()); #else const char* termtype = fterm_data->getTermType(); #endif diff --git a/src/ftermcapquirks.cpp b/src/ftermcapquirks.cpp index 07faf1bd..ca93d2a8 100644 --- a/src/ftermcapquirks.cpp +++ b/src/ftermcapquirks.cpp @@ -20,6 +20,7 @@ * . * ***********************************************************************/ +#include #include #include "final/fc.h" @@ -267,6 +268,25 @@ void FTermcapQuirks::vte() // set exit underline for gnome terminal TCAP(fc::t_exit_underline_mode) = \ CSI "24m"; + + if ( term_detection->getGnomeTerminalID() >= 5300 ) // vte >= 0.53.0 + { + if ( ! std::strstr(TCAP(fc::t_enter_ca_mode), "\033[22;0;0t") ) + { + // Save the cursor position, enter alternate screen buffer + // and save xterm icon and window title on stack + TCAP(fc::t_enter_ca_mode) = \ + CSI "?1049h" CSI "22;0;0t"; + } + + if ( ! std::strstr(TCAP(fc::t_exit_ca_mode), "\033[23;0;0t") ) + { + // Use normal screen buffer, restore the cursor position + // and restore xterm icon and window title from stack + TCAP(fc::t_exit_ca_mode) = \ + CSI "?1049l" CSI "23;0;0t"; + } + } } //---------------------------------------------------------------------- diff --git a/src/ftermdetection.cpp b/src/ftermdetection.cpp index 8eed2bd6..d4d545de 100644 --- a/src/ftermdetection.cpp +++ b/src/ftermdetection.cpp @@ -843,7 +843,7 @@ FString FTermDetection::getSecDA() pos += std::size_t(bytes); } - while ( pos < temp.size() && std::strchr(temp.data(), 'c') == nullptr ); + while ( pos < temp.size() && ! std::strchr(temp.data(), 'c') ); if ( pos > 3 && std::sscanf(temp.data(), parse, &a, &b, &c) == 3 ) sec_da_str.sprintf("\033[>%d;%d;%dc", a, b, c); diff --git a/src/ftermlinux.cpp b/src/ftermlinux.cpp index fd8fade7..1d574d71 100644 --- a/src/ftermlinux.cpp +++ b/src/ftermlinux.cpp @@ -316,9 +316,11 @@ bool FTermLinux::loadNewFont() // Set the graphical font int ret; +#if defined(ISA_SYSCTL_SUPPORT) if ( has9BitCharacters() ) ret = setScreenFont(fc::__9x16graph, 256, 8, 16); // set 9×16 else +#endif ret = setScreenFont(fc::__8x16graph, 256, 8, 16); // set 8×16 if ( ret != 0 ) diff --git a/src/ftermxterminal.cpp b/src/ftermxterminal.cpp index a73717dd..d9651dd6 100644 --- a/src/ftermxterminal.cpp +++ b/src/ftermxterminal.cpp @@ -805,7 +805,7 @@ FString FTermXTerminal::captureXTermFont() const pos += std::size_t(bytes); } - while ( pos < temp.size() && std::strchr(temp.data(), '\a') == nullptr ); + while ( pos < temp.size() && ! std::strchr(temp.data(), '\a') ); if ( pos > 5 && temp[0] == ESC[0] && temp[1] == ']' && temp[2] == '5' && temp[3] == '0' && temp[4] == ';' ) diff --git a/src/include/final/fapplication.h b/src/include/final/fapplication.h index 4a0b0d07..17bf7daa 100644 --- a/src/include/final/fapplication.h +++ b/src/include/final/fapplication.h @@ -218,6 +218,20 @@ class FApplication : public FWidget static FMouseControl* mouse; static FKeyboard* keyboard; static FWidget* keyboard_widget; + +#if defined(__sun) && defined(__SVR4) + struct CmdOption + { + const char* name; // <- name is without 'const' in Solaris + int has_arg; + int* flag; + int val; + }; +#else + using CmdOption = struct option; +#endif + + static const CmdOption long_options[]; }; diff --git a/src/include/final/flog.h b/src/include/final/flog.h index 92f0e6f9..67e6f927 100644 --- a/src/include/final/flog.h +++ b/src/include/final/flog.h @@ -42,6 +42,7 @@ #include #include +#include #include #include #include @@ -97,15 +98,17 @@ class FLog : public std::stringbuf protected: int sync() override; - const LogLevel& getLevel() const; + const LogLevel& getLevel(); LogLevel& setLevel(); - const LineEnding& getEnding() const; + const LineEnding& getEnding(); LineEnding& setEnding(); + std::mutex& getMutex(); private: // Data member LogLevel level{Info}; LineEnding end_of_line{CRLF}; + std::mutex mut; FLogPrint current_log{std::bind(&FLog::info, this, std::placeholders::_1)}; std::ostream stream{this}; @@ -118,6 +121,7 @@ class FLog : public std::stringbuf template inline FLog& FLog::operator << (const T& s) { + std::lock_guard lock_guard(mut); stream << s; return *this; } @@ -125,6 +129,7 @@ inline FLog& FLog::operator << (const T& s) //---------------------------------------------------------------------- inline FLog& FLog::operator << (IOManip pf) { + std::lock_guard lock_guard(mut); pf(stream); return *this; } @@ -134,21 +139,33 @@ inline FString FLog::getClassName() const { return "FLog"; } //---------------------------------------------------------------------- -inline const FLog::LogLevel& FLog::getLevel() const -{ return level; } +inline const FLog::LogLevel& FLog::getLevel() +{ + return level; +} //---------------------------------------------------------------------- inline FLog::LogLevel& FLog::setLevel() -{ return level; } +{ + return level; +} //---------------------------------------------------------------------- -inline const FLog::LineEnding& FLog::getEnding() const -{ return end_of_line; } +inline const FLog::LineEnding& FLog::getEnding() +{ + std::lock_guard lock_guard(mut); + return end_of_line; +} //---------------------------------------------------------------------- inline FLog::LineEnding& FLog::setEnding() -{ return end_of_line; } +{ + return end_of_line; +} +//---------------------------------------------------------------------- +inline std::mutex& FLog::getMutex() +{ return mut; } } // namespace finalcut diff --git a/src/include/final/flogger.h b/src/include/final/flogger.h index 5f0d64ea..d5caff76 100644 --- a/src/include/final/flogger.h +++ b/src/include/final/flogger.h @@ -87,7 +87,7 @@ class FLogger : public FLog // Methods void newlineReplace (std::string&, const std::string&) const; std::string getTimeString() const; - std::string getEOL() const; + std::string getEOL(); void printLogLine (const std::string&); // Data member @@ -103,6 +103,7 @@ inline FString FLogger::getClassName() const //---------------------------------------------------------------------- inline void FLogger::info (const std::string& msg) { + std::lock_guard lock_guard(getMutex()); setLevel() = Info; printLogLine (msg); } @@ -110,6 +111,7 @@ inline void FLogger::info (const std::string& msg) //---------------------------------------------------------------------- inline void FLogger::warn (const std::string& msg) { + std::lock_guard lock_guard(getMutex()); setLevel() = Warn; printLogLine (msg); } @@ -117,6 +119,7 @@ inline void FLogger::warn (const std::string& msg) //---------------------------------------------------------------------- inline void FLogger::error (const std::string& msg) { + std::lock_guard lock_guard(getMutex()); setLevel() = Error; printLogLine (msg); } @@ -124,29 +127,45 @@ inline void FLogger::error (const std::string& msg) //---------------------------------------------------------------------- inline void FLogger::debug (const std::string& msg) { + std::lock_guard lock_guard(getMutex()); setLevel() = Debug; printLogLine (msg); } //---------------------------------------------------------------------- inline void FLogger::flush() -{ output.flush(); } +{ + std::lock_guard lock_guard(getMutex()); + output.flush(); +} //---------------------------------------------------------------------- inline void FLogger::setOutputStream (const std::ostream& os) -{ output.rdbuf(os.rdbuf()); } +{ + std::lock_guard lock_guard(getMutex()); + output.rdbuf(os.rdbuf()); +} //---------------------------------------------------------------------- inline void FLogger::setLineEnding (LineEnding eol) -{ setEnding() = eol; } +{ + std::lock_guard lock_guard(getMutex()); + setEnding() = eol; +} //---------------------------------------------------------------------- inline void FLogger::enableTimestamp() -{ timestamp = true; } +{ + std::lock_guard lock_guard(getMutex()); + timestamp = true; +} //---------------------------------------------------------------------- inline void FLogger::disableTimestamp() -{ timestamp = false; } +{ + std::lock_guard lock_guard(getMutex()); + timestamp = false; +} } // namespace finalcut