From 3d2a0c6dd20b24cc38968a085ae8fcf3a62fdb59 Mon Sep 17 00:00:00 2001 From: Markus Gans Date: Sat, 6 Jun 2020 21:10:06 +0200 Subject: [PATCH] Lazy terminal initialization on show() --- ChangeLog | 4 + doc/first-steps.md | 12 +- examples/background-color.cpp | 5 + examples/keyboard.cpp | 3 + examples/mouse.cpp | 46 ++++---- examples/opti-move.cpp | 73 +++++++++--- examples/term-attributes.cpp | 46 ++++++-- examples/termcap.cpp | 21 +++- examples/timer.cpp | 3 + examples/ui.cpp | 23 ++-- src/fapplication.cpp | 189 +++++++++++++++++-------------- src/fbutton.cpp | 5 +- src/fcheckbox.cpp | 2 +- src/fcolorpalette.cpp | 2 +- src/fcombobox.cpp | 5 +- src/fdialog.cpp | 2 +- src/flabel.cpp | 12 +- src/flistbox.cpp | 1 - src/foptimove.cpp | 18 +-- src/fradiobutton.cpp | 2 +- src/fscrollbar.cpp | 1 + src/fterm.cpp | 156 +++++++++++++++---------- src/ftermfreebsd.cpp | 11 +- src/ftermopenbsd.cpp | 11 +- src/ftermxterminal.cpp | 11 +- src/ftogglebutton.cpp | 40 +------ src/fvterm.cpp | 55 ++++++--- src/fwidget.cpp | 123 ++++++++++++-------- src/include/final/fapplication.h | 17 ++- src/include/final/fbutton.h | 14 +-- src/include/final/flabel.h | 5 +- src/include/final/fterm.h | 24 ++-- src/include/final/ftermcap.h | 10 ++ src/include/final/ftermdata.h | 11 ++ src/include/final/fvterm.h | 12 +- src/include/final/fwidget.h | 16 +-- test/conemu.h | 10 ++ test/foptimove-test.cpp | 8 +- test/ftermdata-test.cpp | 6 + 39 files changed, 626 insertions(+), 389 deletions(-) diff --git a/ChangeLog b/ChangeLog index f0701d49..43fb315a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2020-06-06 Markus Gans + * Now, the terminal is not initialized before the method show() + is called. Or you force it explicitly via the FApplication object. + 2020-05-30 Markus Gans * With the two new methods FApplication::setDarkTheme() and FApplication::setDefaultTheme() you can now change the theme diff --git a/doc/first-steps.md b/doc/first-steps.md index f184b0dd..f352f815 100644 --- a/doc/first-steps.md +++ b/doc/first-steps.md @@ -1135,12 +1135,13 @@ class dialogWidget : public FDialog setGeometry (FPoint{28, 2}, FSize{24, 21}); scrollview.setGeometry(FPoint{1, 1}, FSize{22, 11}); scrollview.setScrollSize(FSize{60, 27}); - const auto& wc = getFWidgetColors(); - setColor (wc.label_inactive_fg, wc.dialog_bg); + // Attention: getColorTheme() requires an initialized terminal + const auto& wc = getColorTheme(); + setColor (wc->label_inactive_fg, wc->dialog_bg); scrollview.clearArea(); - FColorPair red (fc::LightRed, wc.dialog_bg); - FColorPair black (fc::Black, wc.dialog_bg); - FColorPair cyan (fc::Cyan, wc.dialog_bg); + FColorPair red (fc::LightRed, wc->dialog_bg); + FColorPair black (fc::Black, wc->dialog_bg); + FColorPair cyan (fc::Cyan, wc->dialog_bg); static std::vector d { @@ -1188,6 +1189,7 @@ class dialogWidget : public FDialog int main (int argc, char* argv[]) { FApplication app(argc, argv); + app.initTerminal(); // Terminal initialization dialogWidget dialog(&app); FWidget::setMainWidget(&dialog); dialog.show(); diff --git a/examples/background-color.cpp b/examples/background-color.cpp index 60938a7e..fe14f5f7 100644 --- a/examples/background-color.cpp +++ b/examples/background-color.cpp @@ -217,8 +217,13 @@ void Background::cb_choice (const finalcut::FWidget*, const FDataPtr) int main (int argc, char* argv[]) { + // Create the application object finalcut::FApplication app(argc, argv); + // Force terminal initialization without calling show() + app.initTerminal(); + + // The following lines require an initialized terminal if ( finalcut::FTerm::canChangeColorPalette() ) app.setBackgroundColor(finalcut::fc::LightMagenta); diff --git a/examples/keyboard.cpp b/examples/keyboard.cpp index a92330fc..c3e06279 100644 --- a/examples/keyboard.cpp +++ b/examples/keyboard.cpp @@ -95,6 +95,9 @@ int main (int argc, char* argv[]) { // Create the application object finalcut::FApplication app{argc, argv}; + + // Force terminal initialization without calling show() + app.initTerminal(); app.setForegroundColor(finalcut::fc::Default); app.setBackgroundColor(finalcut::fc::Default); diff --git a/examples/mouse.cpp b/examples/mouse.cpp index f9dc68f2..7f4614e2 100644 --- a/examples/mouse.cpp +++ b/examples/mouse.cpp @@ -78,16 +78,6 @@ ColorChooser::ColorChooser (finalcut::FWidget* parent) setFixedSize (FSize{8, 12}); unsetFocusable(); - if ( parent ) - { - const FColor fg = parent->getForegroundColor(); - const FColor bg = parent->getBackgroundColor(); - FWidget::setForegroundColor(fg); - FWidget::setBackgroundColor(bg); - headline.setForegroundColor(fg); - headline.setBackgroundColor(bg); - } - // Text label headline.setGeometry (FPoint{1, 1}, FSize{8, 1}); headline.setEmphasis(); @@ -122,6 +112,8 @@ void ColorChooser::setSize (const FSize& size, bool adjust) //---------------------------------------------------------------------- void ColorChooser::draw() { + useParentWidgetColor(); + headline.setBackgroundColor(getBackgroundColor()); setColor(); drawBorder(); @@ -232,16 +224,6 @@ Brushes::Brushes (finalcut::FWidget* parent) setFixedSize (FSize{8, 4}); unsetFocusable(); - if ( parent ) - { - const FColor fg = parent->getForegroundColor(); - const FColor bg = parent->getBackgroundColor(); - FWidget::setForegroundColor(fg); - FWidget::setBackgroundColor(bg); - headline.setForegroundColor(fg); - headline.setBackgroundColor(bg); - } - // Text label headline.setGeometry(FPoint{1, 1}, FSize{8, 1}); headline.setEmphasis(); @@ -265,6 +247,8 @@ void Brushes::setSize (const FSize& size, bool adjust) void Brushes::draw() { int pos{0}; + useParentWidgetColor(); + headline.setBackgroundColor(getBackgroundColor()); setColor(); drawBorder(); print() << FPoint{2, 3} @@ -361,6 +345,7 @@ class MouseDraw final : public finalcut::FDialog void draw() override; void drawBrush (int, int, bool = false); void drawCanvas(); + void createCanvas(); void adjustSize() override; // Event handler @@ -390,10 +375,6 @@ MouseDraw::MouseDraw (finalcut::FWidget* parent) ); brush.setPos (FPoint{1, 12}); - - FSize no_shadow{0, 0}; - finalcut::FRect scroll_geometry{0, 0, 1, 1}; - createArea (scroll_geometry, no_shadow, canvas); } //---------------------------------------------------------------------- @@ -407,6 +388,10 @@ void MouseDraw::setGeometry ( const FPoint& p, const FSize& s, bool adjust) const std::size_t w = s.getWidth(); const std::size_t h = s.getHeight(); const finalcut::FRect scroll_geometry (FPoint{0, 0}, FSize{w - 11, h - 3}); + + if ( ! canvas ) + return; + const FSize no_shadow{0, 0}; const int old_w = canvas->width; const int old_h = canvas->height; @@ -504,6 +489,10 @@ void MouseDraw::drawCanvas() if ( ! hasPrintArea() ) finalcut::FVTerm::getPrintArea(); + // Create canvas after initializing the desktop and color theme + if ( ! canvas ) + createCanvas(); + if ( ! (hasPrintArea() && canvas) ) return; @@ -534,6 +523,15 @@ void MouseDraw::drawCanvas() printarea->has_changes = true; } +//---------------------------------------------------------------------- +void MouseDraw::createCanvas() +{ + FSize no_shadow{0, 0}; + finalcut::FRect scroll_geometry{0, 0, 1, 1}; + createArea (scroll_geometry, no_shadow, canvas); + adjustSize(); +} + //---------------------------------------------------------------------- void MouseDraw::adjustSize() { diff --git a/examples/opti-move.cpp b/examples/opti-move.cpp index ed6061a1..f6d4d56e 100644 --- a/examples/opti-move.cpp +++ b/examples/opti-move.cpp @@ -133,62 +133,103 @@ void move (int xold, int yold, int xnew, int ynew) } //---------------------------------------------------------------------- -class DirectLogger : public finalcut::FLog +class DirectLogger final : public finalcut::FLog { public: + // Constructor + DirectLogger(); + + // Destructor + ~DirectLogger() override; + void info (const std::string& entry) override { output << entry << "\r" << std::endl; } void warn (const std::string&) override - { } + { + // An implementation is not required in this context + } void error (const std::string&) override - { } + { + // An implementation is not required in this context + } + void debug (const std::string&) override - { } + { + // An implementation is not required in this context + } + void setOutputStream (const std::ostream& os) override { output.rdbuf(os.rdbuf()); } void setLineEnding (LineEnding) override - { } + { + // An implementation is not required in this context + } + void enableTimestamp() override - { } + { + // An implementation is not required in this context + } + void disableTimestamp() override - { } + { + // An implementation is not required in this context + } + private: // Data member std::ostream output{std::cerr.rdbuf()}; }; +//---------------------------------------------------------------------- +DirectLogger::DirectLogger() // constructor +{ } + +//---------------------------------------------------------------------- +DirectLogger::~DirectLogger() // destructor +{ } + + //---------------------------------------------------------------------- // main part //---------------------------------------------------------------------- int main (int argc, char* argv[]) { + // Disable mouse + finalcut::FStartOptions::getFStartOptions().mouse_support = false; + // Create the application object - finalcut::FApplication TermApp{argc, argv}; + finalcut::FApplication term_app{argc, argv}; + + // Force terminal initialization without calling show() + term_app.initTerminal(); // Pointer to the global virtual terminal object - app = &TermApp; + app = &term_app; + + if ( app->isQuit() ) + return 0; // Get screen dimension - int xmax = int(TermApp.getDesktopWidth() - 1); - int ymax = int(TermApp.getDesktopHeight() - 1); + int xmax = int(term_app.getDesktopWidth() - 1); + int ymax = int(term_app.getDesktopHeight() - 1); finalcut::FString line{std::size_t(xmax) + 1, '-'}; // Place the cursor in the upper left corner - TermApp.setTermXY(0, 0); + term_app.setTermXY(0, 0); // Reset all terminal attributes - TermApp.setNormal(); + term_app.setNormal(); // Clear the screen - TermApp.clearArea(); + term_app.clearArea(); // Show the determined terminal name and text resolution std::cout << "Terminal: " << finalcut::FTerm::getTermType() << "\r\n"; @@ -230,8 +271,10 @@ int main (int argc, char* argv[]) std::shared_ptr log = finalcut::FApplication::getLog(); const finalcut::FOptiMove& opti_move = *finalcut::FTerm::getFOptiMove(); finalcut::printDurations(opti_move); + delete &log; // Waiting for keypress keyPressed(); - app = nullptr; // End of TermApp object scope + app = nullptr; // End of term_app object scope + return 0; } diff --git a/examples/term-attributes.cpp b/examples/term-attributes.cpp index c8528bba..f11a2249 100644 --- a/examples/term-attributes.cpp +++ b/examples/term-attributes.cpp @@ -62,11 +62,15 @@ class AttribDlg final : public finalcut::FDialog void cb_back (const finalcut::FWidget* = nullptr, const FDataPtr = nullptr); private: + // Constants + static constexpr FColor UNDEFINED = static_cast(-2); + // Method void adjustSize() override; + void draw() override; // Data members - FColor bgcolor{getColorTheme()->label_bg}; + FColor bgcolor{UNDEFINED}; finalcut::FButton next_button{"&Next >", this}; finalcut::FButton back_button{"< &Back", this}; }; @@ -75,10 +79,6 @@ class AttribDlg final : public finalcut::FDialog AttribDlg::AttribDlg (finalcut::FWidget* parent) : finalcut::FDialog{parent} { - FDialog::setText ( "A terminal attributes test (" - + finalcut::FString{finalcut::FTerm::getTermType()} - + ")"); - next_button.setGeometry ( FPoint{int(getWidth()) - 13, int(getHeight()) - 4} , FSize{10, 1} ); next_button.addAccelerator (fc::Fkey_right); @@ -194,6 +194,26 @@ void AttribDlg::adjustSize() finalcut::FDialog::adjustSize(); } +//---------------------------------------------------------------------- +void AttribDlg::draw() +{ + if ( bgcolor == UNDEFINED ) + { + // Get the color after initializing the color theme in show() + if ( finalcut::FTerm::isMonochron() ) + bgcolor = fc::Default; + else + bgcolor = getColorTheme()->label_bg; + + // Get the terminal type after the terminal detection in show() + FDialog::setText ( "A terminal attributes test (" + + finalcut::FString{finalcut::FTerm::getTermType()} + + ")"); + } + + FDialog::draw(); +} + //---------------------------------------------------------------------- // class AttribDemo @@ -238,18 +258,13 @@ class AttribDemo final : public finalcut::FWidget void draw() override; // Data member - FColor last_color{FColor(finalcut::FTerm::getMaxColor())}; + FColor last_color{1}; }; //---------------------------------------------------------------------- AttribDemo::AttribDemo (finalcut::FWidget* parent) : finalcut::FWidget{parent} { - if ( finalcut::FTerm::isMonochron() ) - last_color = 1; - else if ( last_color > 16 ) - last_color = 16; - unsetFocusable(); } @@ -417,8 +432,15 @@ void AttribDemo::printProtected() //---------------------------------------------------------------------- void AttribDemo::draw() { - // test alternate character set const auto& wc = getColorTheme(); + last_color = FColor(finalcut::FTerm::getMaxColor()); + + if ( finalcut::FTerm::isMonochron() ) + last_color = 1; + else if ( last_color > 16 ) + last_color = 16; + + // test alternate character set printAltCharset(); const std::vector > effect diff --git a/examples/termcap.cpp b/examples/termcap.cpp index f7532212..6f2c1675 100644 --- a/examples/termcap.cpp +++ b/examples/termcap.cpp @@ -296,15 +296,30 @@ void string() //---------------------------------------------------------------------- int main (int argc, char* argv[]) { - const bool disable_alt_screen{true}; - finalcut::FApplication TermApp {argc, argv, disable_alt_screen}; + // Disabling the switch to the alternative screen + finalcut::FTerm::useAlternateScreen(false); + + // Disable color palette changes and terminal data requests + auto& start_options = finalcut::FStartOptions::getFStartOptions(); + start_options.color_change = false; + start_options.terminal_data_request = false; + + // Create the application object as root widget + finalcut::FApplication term_app {argc, argv}; + + // Force terminal initialization without calling show() + term_app.initTerminal(); + + if ( term_app.isQuit() ) + return 0; std::cout << "--------\r\nFTermcap\r\n--------\r\n\n"; std::cout << "Terminal: " << finalcut::FTerm::getTermType() << "\r\n"; - debug (TermApp); + debug (term_app); booleans(); numeric(); string(); + return 0; } diff --git a/examples/timer.cpp b/examples/timer.cpp index 81a94fbf..3b444c8c 100644 --- a/examples/timer.cpp +++ b/examples/timer.cpp @@ -101,6 +101,9 @@ int main (int argc, char* argv[]) { // Create the application object finalcut::FApplication app{argc, argv}; + + // Force terminal initialization without calling show() + app.initTerminal(); app.setForegroundColor(fc::Default); app.setBackgroundColor(fc::Default); diff --git a/examples/ui.cpp b/examples/ui.cpp index 9e696d09..a9a14a6b 100644 --- a/examples/ui.cpp +++ b/examples/ui.cpp @@ -1049,17 +1049,6 @@ int main (int argc, char* argv[]) // Create the application object app finalcut::FApplication app{argc, argv}; app.setNonBlockingRead(); - finalcut::FTerm::redefineDefaultColors(true); - finalcut::FTerm::setTermTitle (title); - - // Force vt100 encoding - //finalcut::FTerm::setEncoding(finalcut::fc::VT100); - - // Sets the terminal size to 94×30 - //finalcut::FTerm::setTermSize(FSize{94, 30}); - - // Enable the final cut graphical font - //finalcut::FTerm::setNewFont(); // Create main dialog object d MyDialog d{&app}; @@ -1075,6 +1064,18 @@ int main (int argc, char* argv[]) // Show the dialog d d.show(); + finalcut::FTerm::redefineDefaultColors(true); + finalcut::FTerm::setTermTitle (title); + + // Force vt100 encoding + //finalcut::FTerm::setEncoding(finalcut::fc::VT100); + + // Sets the terminal size to 94×30 + //finalcut::FTerm::setTermSize(FSize{94, 30}); + + // Enable the final cut graphical font + //finalcut::FTerm::setNewFont(); + // Start the application // and return the result to the operating system return app.exec(); diff --git a/src/fapplication.cpp b/src/fapplication.cpp index 1278b856..130cc68e 100644 --- a/src/fapplication.cpp +++ b/src/fapplication.cpp @@ -58,7 +58,7 @@ FWidget* FApplication::keyboard_widget {nullptr}; // has the keyboard foc FKeyboard* FApplication::keyboard {nullptr}; // keyboard access FMouseControl* FApplication::mouse {nullptr}; // mouse control int FApplication::loop_level {0}; // event loop level -int FApplication::quit_code {0}; +int FApplication::quit_code {EXIT_SUCCESS}; bool FApplication::quit_now {false}; @@ -68,13 +68,14 @@ bool FApplication::quit_now {false}; // constructors and destructor //---------------------------------------------------------------------- -FApplication::FApplication ( const int& _argc - , char* _argv[] - , bool disable_alt_screen ) - : FWidget{processParameters(_argc, _argv), disable_alt_screen} +FApplication::FApplication (const int& _argc, char* _argv[]) + : FWidget{processParameters(_argc, _argv)} , app_argc{_argc} , app_argv{_argv} { + if ( quit_now ) + return; + if ( app_object ) { auto ftermdata = FTerm::getFTermData(); @@ -84,6 +85,7 @@ FApplication::FApplication ( const int& _argc return; } + // First define the application object app_object = this; if ( ! (_argc && _argv) ) @@ -145,10 +147,10 @@ int FApplication::exec() // run if ( quit_now ) { quit_now = false; - return EXIT_FAILURE; + return quit_code; } - quit_code = 0; + quit_code = EXIT_SUCCESS; enterLoop(); return quit_code; } @@ -263,23 +265,10 @@ bool FApplication::removeQueuedEvent (const FObject* receiver) } //---------------------------------------------------------------------- -void FApplication::processExternalUserEvent() +void FApplication::initTerminal() { - // This method can be overloaded and replaced by own code -} - -//---------------------------------------------------------------------- -FWidget* FApplication::processParameters (const int& argc, char* argv[]) -{ - if ( argc > 0 && argv[1] && ( std::strcmp(argv[1], "--help") == 0 - || std::strcmp(argv[1], "-h") == 0 ) ) - { - showParameterUsage(); - } - - getStartOptions().setDefault(); - cmd_options (argc, argv); - return nullptr; + if ( ! isQuit() ) + FWidget::initTerminal(); } //---------------------------------------------------------------------- @@ -313,56 +302,6 @@ void FApplication::setDarkTheme() setColorTheme(); } -//---------------------------------------------------------------------- -void FApplication::showParameterUsage() -{ - std::cout \ - << "Generic options:\n" - << " -h, --help " - << " Display this help and exit\n" - << "\n" - << "The Final Cut options:\n" - << " --encoding " - << " Sets the character encoding mode\n" - << " " - << " {utf8, vt100, pc, ascii}\n" - << " --no-mouse " - << " Disable mouse support\n" - << " --no-optimized-cursor " - << " Disable cursor optimization\n" - << " --no-terminal-detection " - << " Disable terminal detection\n" - << " --no-terminal-data-request" - << " Do not determine terminal font and title\n" - << " --no-color-change " - << " Do not redefine the color palette\n" - << " --no-sgr-optimizer " - << " Do not optimize SGR sequences\n" - << " --vgafont " - << " Set the standard vga 8x16 font\n" - << " --newfont " - << " Enables the graphical font\n" - << " --dark-theme " - << " Enables the dark theme\n" - -#if defined(__FreeBSD__) || defined(__DragonFly__) - << "\n" - << "FreeBSD console options:\n" - << " --no-esc-for-alt-meta " - << " Do not send a ESC prefix for the alt/meta key\n" - << " --no-cursorstyle-change " - << " Do not change the current cursor style\n" -#elif defined(__NetBSD__) || defined(__OpenBSD__) - << "\n" - << "NetBSD/OpenBSD console options:\n" - << " --no-esc-for-alt-meta " - << " Do not send a ESC prefix for the alt/meta key\n" -#endif - - << std::endl; // newline character + flushes the output stream - std::exit(EXIT_SUCCESS); -} - //---------------------------------------------------------------------- void FApplication::closeConfirmationDialog (FWidget* w, FCloseEvent* ev) { @@ -384,6 +323,15 @@ void FApplication::closeConfirmationDialog (FWidget* w, FCloseEvent* ev) } } + +// protected methods of FApplication +//---------------------------------------------------------------------- +void FApplication::processExternalUserEvent() +{ + // This method can be overloaded and replaced by own code +} + + // private methods of FApplication //---------------------------------------------------------------------- void FApplication::init (uInt64 key_time, uInt64 dblclick_time) @@ -476,45 +424,49 @@ void FApplication::cmd_options (const int& argc, char* argv[]) else if ( encoding.includes("help") ) showParameterUsage(); else - FTerm::exitWithMessage ( "Unknown encoding " - + std::string(encoding.c_str()) ); + { + auto ftermdata = FTerm::getFTermData(); + ftermdata->setExitMessage ( "Unknown encoding " + + std::string(encoding.c_str()) ); + exit(EXIT_FAILURE); + } } - if ( std::strcmp(long_options[idx].name, "no-mouse") == 0 ) + if ( std::strcmp(long_options[idx].name, "no-mouse") == 0 ) getStartOptions().mouse_support = false; - if ( std::strcmp(long_options[idx].name, "no-optimized-cursor") == 0 ) + if ( std::strcmp(long_options[idx].name, "no-optimized-cursor") == 0 ) getStartOptions().cursor_optimisation = false; - if ( std::strcmp(long_options[idx].name, "no-terminal-detection") == 0 ) + if ( std::strcmp(long_options[idx].name, "no-terminal-detection") == 0 ) getStartOptions().terminal_detection = false; - if ( std::strcmp(long_options[idx].name, "no-terminal-data-request") == 0 ) + if ( std::strcmp(long_options[idx].name, "no-terminal-data-request") == 0 ) getStartOptions().terminal_data_request = false; - if ( std::strcmp(long_options[idx].name, "no-color-change") == 0 ) + if ( std::strcmp(long_options[idx].name, "no-color-change") == 0 ) getStartOptions().color_change = false; - if ( std::strcmp(long_options[idx].name, "no-sgr-optimizer") == 0 ) + if ( std::strcmp(long_options[idx].name, "no-sgr-optimizer") == 0 ) getStartOptions().sgr_optimizer = false; - if ( std::strcmp(long_options[idx].name, "vgafont") == 0 ) + if ( std::strcmp(long_options[idx].name, "vgafont") == 0 ) getStartOptions().vgafont = true; - if ( std::strcmp(long_options[idx].name, "newfont") == 0 ) + if ( std::strcmp(long_options[idx].name, "newfont") == 0 ) getStartOptions().newfont = true; - if ( std::strcmp(long_options[idx].name, "dark-theme") == 0 ) + if ( std::strcmp(long_options[idx].name, "dark-theme") == 0 ) getStartOptions().dark_theme = true; #if defined(__FreeBSD__) || defined(__DragonFly__) - if ( std::strcmp(long_options[idx].name, "no-esc-for-alt-meta") == 0 ) + if ( std::strcmp(long_options[idx].name, "no-esc-for-alt-meta") == 0 ) getStartOptions().meta_sends_escape = false; - if ( std::strcmp(long_options[idx].name, "no-cursorstyle-change") == 0 ) + if ( std::strcmp(long_options[idx].name, "no-cursorstyle-change") == 0 ) getStartOptions().change_cursorstyle = false; #elif defined(__NetBSD__) || defined(__OpenBSD__) - if ( std::strcmp(long_options[idx].name, "no-esc-for-alt-meta") == 0 ) + if ( std::strcmp(long_options[idx].name, "no-esc-for-alt-meta") == 0 ) getStartOptions().meta_sends_escape = false; #endif } @@ -527,6 +479,55 @@ inline FStartOptions& FApplication::getStartOptions() return FStartOptions::getFStartOptions(); } +//---------------------------------------------------------------------- +void FApplication::showParameterUsage() +{ + std::cout \ + << "Generic options:\n" + << " -h, --help " + << " Display this help and exit\n" + << "\n" + << "The Final Cut options:\n" + << " --encoding " + << " Sets the character encoding mode\n" + << " " + << " {utf8, vt100, pc, ascii}\n" + << " --no-mouse " + << " Disable mouse support\n" + << " --no-optimized-cursor " + << " Disable cursor optimization\n" + << " --no-terminal-detection " + << " Disable terminal detection\n" + << " --no-terminal-data-request" + << " Do not determine terminal font and title\n" + << " --no-color-change " + << " Do not redefine the color palette\n" + << " --no-sgr-optimizer " + << " Do not optimize SGR sequences\n" + << " --vgafont " + << " Set the standard vga 8x16 font\n" + << " --newfont " + << " Enables the graphical font\n" + << " --dark-theme " + << " Enables the dark theme\n" + +#if defined(__FreeBSD__) || defined(__DragonFly__) + << "\n" + << "FreeBSD console options:\n" + << " --no-esc-for-alt-meta " + << " Do not send a ESC prefix for the alt/meta key\n" + << " --no-cursorstyle-change " + << " Do not change the current cursor style\n" +#elif defined(__NetBSD__) || defined(__OpenBSD__) + << "\n" + << "NetBSD/OpenBSD console options:\n" + << " --no-esc-for-alt-meta " + << " Do not send a ESC prefix for the alt/meta key\n" +#endif + + << std::endl; // newline character + flushes the output stream +} + //---------------------------------------------------------------------- inline void FApplication::destroyLog() { @@ -1119,6 +1120,20 @@ void FApplication::sendWheelEvent ( const FPoint& widgetMousePos } } +//---------------------------------------------------------------------- +FWidget* FApplication::processParameters (const int& argc, char* argv[]) +{ + if ( argc > 0 && argv[1] && ( std::strcmp(argv[1], "--help") == 0 + || std::strcmp(argv[1], "-h") == 0 ) ) + { + showParameterUsage(); + FApplication::exit(EXIT_SUCCESS); + } + + cmd_options (argc, argv); + return nullptr; +} + //---------------------------------------------------------------------- void FApplication::processMouseEvent() { diff --git a/src/fbutton.cpp b/src/fbutton.cpp index f970fa0a..9e321441 100644 --- a/src/fbutton.cpp +++ b/src/fbutton.cpp @@ -402,8 +402,9 @@ void FButton::onFocusOut (FFocusEvent*) void FButton::init() { const auto& wc = getColorTheme(); - setForegroundColor (wc->button_active_fg); - setBackgroundColor (wc->button_active_bg); + button_fg = wc->button_active_fg; + button_bg = wc->button_active_bg; + resetColors(); setShadow(); if ( ! text.isEmpty() ) diff --git a/src/fcheckbox.cpp b/src/fcheckbox.cpp index 1e6f6c27..44ba8b57 100644 --- a/src/fcheckbox.cpp +++ b/src/fcheckbox.cpp @@ -74,7 +74,7 @@ void FCheckBox::draw() void FCheckBox::drawCheckButton() { print() << FPoint{1, 1}; - useParentWidgetColor(); + setColor(); if ( FTerm::isMonochron() ) { diff --git a/src/fcolorpalette.cpp b/src/fcolorpalette.cpp index ab003a40..d061d767 100644 --- a/src/fcolorpalette.cpp +++ b/src/fcolorpalette.cpp @@ -180,7 +180,7 @@ void default16DarkColorPalette::setColorPalette() setPalette (fc::Red, 0xa5, 0x40, 0x40); setPalette (fc::Magenta, 0xb2, 0x18, 0xb2); setPalette (fc::Brown, 0xe8, 0x87, 0x1f); - setPalette (fc::LightGray, 0xd2, 0xd2, 0xd2); + setPalette (fc::LightGray, 0xdc, 0xdc, 0xdc); setPalette (fc::DarkGray, 0x27, 0x33, 0x39); setPalette (fc::LightBlue, 0xb0, 0xb0, 0xb8); setPalette (fc::LightGreen, 0x5e, 0xeb, 0x5c); diff --git a/src/fcombobox.cpp b/src/fcombobox.cpp index c3471847..c08ffc1e 100644 --- a/src/fcombobox.cpp +++ b/src/fcombobox.cpp @@ -124,8 +124,11 @@ void FDropDownListBox::init() void FDropDownListBox::draw() { // Fill the background + const auto& wc = getColorTheme(); - setColor (wc->menu_active_fg, wc->menu_active_bg); + setForegroundColor (wc->list_fg); + setBackgroundColor (wc->list_bg); + setColor(); if ( FTerm::isMonochron() ) setReverse(true); diff --git a/src/fdialog.cpp b/src/fdialog.cpp index c34a3d5c..2ea2a16a 100644 --- a/src/fdialog.cpp +++ b/src/fdialog.cpp @@ -166,7 +166,7 @@ void FDialog::show() FWindow::show(); - if ( isModal() ) + if ( isModal() && ! FApplication::isQuit() ) { auto fapp = FApplication::getApplicationObject(); fapp->enterLoop(); diff --git a/src/flabel.cpp b/src/flabel.cpp index 51d5881a..1ad9fa9a 100644 --- a/src/flabel.cpp +++ b/src/flabel.cpp @@ -115,6 +115,15 @@ void FLabel::setAlignment (fc::text_alignment align) alignment = align; } +//---------------------------------------------------------------------- +void FLabel::resetColors() +{ + useParentWidgetColor(); + const auto& wc = getColorTheme(); + emphasis_color = wc->label_emphasis_fg; + ellipsis_color = wc->label_ellipsis_fg; +} + //---------------------------------------------------------------------- bool FLabel::setEnable (bool enable) { @@ -247,6 +256,7 @@ void FLabel::cb_accelWidgetDestroyed (const FWidget*, const FDataPtr) void FLabel::init() { unsetFocusable(); + useParentWidgetColor(); } //---------------------------------------------------------------------- @@ -290,7 +300,7 @@ void FLabel::draw() if ( text.isEmpty() ) return; - useParentWidgetColor(); + if ( FTerm::isMonochron() ) { diff --git a/src/flistbox.cpp b/src/flistbox.cpp index 8211a6a1..6f990743 100644 --- a/src/flistbox.cpp +++ b/src/flistbox.cpp @@ -721,7 +721,6 @@ void FListBox::draw() useParentWidgetColor(); - if ( FTerm::isMonochron() ) setReverse(true); diff --git a/src/foptimove.cpp b/src/foptimove.cpp index dcafbcf0..8bef544c 100644 --- a/src/foptimove.cpp +++ b/src/foptimove.cpp @@ -268,7 +268,7 @@ void FOptiMove::set_cursor_right (const char cap[]) //---------------------------------------------------------------------- void FOptiMove::set_cursor_address (const char cap[]) { - if ( cap ) + if ( cap && FTermcap::isInitialized() ) { const char* temp = FTermcap::encodeMotionParameter(cap, 23, 23); F_cursor_address.cap = cap; @@ -286,7 +286,7 @@ void FOptiMove::set_cursor_address (const char cap[]) //---------------------------------------------------------------------- void FOptiMove::set_column_address (const char cap[]) { - if ( cap ) + if ( cap && FTermcap::isInitialized() ) { const char* temp = FTermcap::encodeParameter(cap, 23); F_column_address.cap = cap; @@ -304,7 +304,7 @@ void FOptiMove::set_column_address (const char cap[]) //---------------------------------------------------------------------- void FOptiMove::set_row_address (const char cap[]) { - if ( cap ) + if ( cap && FTermcap::isInitialized() ) { const char* temp = FTermcap::encodeParameter(cap, 23); F_row_address.cap = cap; @@ -322,7 +322,7 @@ void FOptiMove::set_row_address (const char cap[]) //---------------------------------------------------------------------- void FOptiMove::set_parm_up_cursor (const char cap[]) { - if ( cap ) + if ( cap && FTermcap::isInitialized() ) { const char* temp = FTermcap::encodeParameter(cap, 23); F_parm_up_cursor.cap = cap; @@ -340,7 +340,7 @@ void FOptiMove::set_parm_up_cursor (const char cap[]) //---------------------------------------------------------------------- void FOptiMove::set_parm_down_cursor (const char cap[]) { - if ( cap ) + if ( cap && FTermcap::isInitialized() ) { const char* temp = FTermcap::encodeParameter(cap, 23); F_parm_down_cursor.cap = cap; @@ -358,7 +358,7 @@ void FOptiMove::set_parm_down_cursor (const char cap[]) //---------------------------------------------------------------------- void FOptiMove::set_parm_left_cursor (const char cap[]) { - if ( cap ) + if ( cap && FTermcap::isInitialized() ) { const char* temp = FTermcap::encodeParameter(cap, 23); F_parm_left_cursor.cap = cap; @@ -376,7 +376,7 @@ void FOptiMove::set_parm_left_cursor (const char cap[]) //---------------------------------------------------------------------- void FOptiMove::set_parm_right_cursor (const char cap[]) { - if ( cap ) + if ( cap && FTermcap::isInitialized() ) { const char* temp = FTermcap::encodeParameter(cap, 23); F_parm_right_cursor.cap = cap; @@ -394,7 +394,7 @@ void FOptiMove::set_parm_right_cursor (const char cap[]) //---------------------------------------------------------------------- void FOptiMove::set_erase_chars (const char cap[]) { - if ( cap ) + if ( cap && FTermcap::isInitialized() ) { const char* temp = FTermcap::encodeParameter(cap, 23); F_erase_chars.cap = cap; @@ -412,7 +412,7 @@ void FOptiMove::set_erase_chars (const char cap[]) //---------------------------------------------------------------------- void FOptiMove::set_repeat_char (const char cap[]) { - if ( cap ) + if ( cap && FTermcap::isInitialized() ) { const char* temp = FTermcap::encodeParameter(cap, ' ', 23); F_repeat_char.cap = cap; diff --git a/src/fradiobutton.cpp b/src/fradiobutton.cpp index 08707354..5f511b6b 100644 --- a/src/fradiobutton.cpp +++ b/src/fradiobutton.cpp @@ -74,7 +74,7 @@ void FRadioButton::draw() void FRadioButton::drawRadioButton() { print() << FPoint{1, 1}; - useParentWidgetColor(); + setColor(); if ( FTerm::isMonochron() ) { diff --git a/src/fscrollbar.cpp b/src/fscrollbar.cpp index c8e6c7e8..257aeca9 100644 --- a/src/fscrollbar.cpp +++ b/src/fscrollbar.cpp @@ -453,6 +453,7 @@ void FScrollbar::draw() drawButtons(); current_slider_pos = -1; + max_color = FTerm::getMaxColor(); drawBar(); } diff --git a/src/fterm.cpp b/src/fterm.cpp index 663a5dad..4fd68cce 100644 --- a/src/fterm.cpp +++ b/src/fterm.cpp @@ -62,13 +62,16 @@ namespace finalcut { -// global FTerm object +// Global FTerm object static FTerm* init_term_object{nullptr}; -// global init state +// Global init state static bool term_initialized{false}; -// static class attributes +// Counts the number of object instances +static uInt object_counter{0}; + +// Static class attributes FTermData* FTerm::data {nullptr}; FSystem* FTerm::fsys {nullptr}; FOptiMove* FTerm::opti_move {nullptr}; @@ -101,10 +104,12 @@ FMouseControl* FTerm::mouse {nullptr}; // constructors and destructor //---------------------------------------------------------------------- -FTerm::FTerm (bool disable_alt_screen) +FTerm::FTerm() { - if ( ! term_initialized ) - init (disable_alt_screen); + if ( object_counter == 0 ) + allocationValues(); // Allocation of global objects + + object_counter++; } //---------------------------------------------------------------------- @@ -112,6 +117,14 @@ FTerm::~FTerm() // destructor { if ( init_term_object == this ) finish(); // Resetting console settings + + object_counter--; + + if ( object_counter == 0 ) + { + printExitMessage(); + deallocationValues(); // Deallocation of global objects + } } @@ -119,6 +132,9 @@ FTerm::~FTerm() // destructor //---------------------------------------------------------------------- std::size_t FTerm::getLineNumber() { + if ( ! data ) + data = FTerm::getFTermData(); + const auto& term_geometry = data->getTermGeometry(); if ( term_geometry.getHeight() == 0 ) @@ -130,6 +146,9 @@ std::size_t FTerm::getLineNumber() //---------------------------------------------------------------------- std::size_t FTerm::getColumnNumber() { + if ( ! data ) + data = FTerm::getFTermData(); + const auto& term_geometry = data->getTermGeometry(); if ( term_geometry.getWidth() == 0 ) @@ -217,7 +236,7 @@ FSystem* FTerm::getFSystem() } catch (const std::bad_alloc&) { - badAllocOutput ("FTermData"); + badAllocOutput ("FSystemImpl"); std::abort(); } } @@ -640,6 +659,14 @@ void FTerm::setDblclickInterval (const uInt64 timeout) mouse->setDblclickInterval(timeout); } +//---------------------------------------------------------------------- +void FTerm::useAlternateScreen (bool enable) +{ + // Sets alternate screen usage + + getFTermData()->useAlternateScreen(enable); +} + //---------------------------------------------------------------------- bool FTerm::setUTF8 (bool enable) // UTF-8 (Unicode) { @@ -1293,22 +1320,6 @@ void FTerm::changeTermSizeFinished() data->setTermResized(false); } -//---------------------------------------------------------------------- -void FTerm::exitWithMessage (const FString& message) -{ - // Exit the programm - if ( init_term_object ) - init_term_object->finish(); - - std::fflush (stderr); - std::fflush (stdout); - - if ( ! message.isEmpty() ) - FApplication::getLog()->warn(message.c_str()); - - std::exit (EXIT_FAILURE); -} - // private methods of FTerm //---------------------------------------------------------------------- @@ -1318,16 +1329,13 @@ inline FStartOptions& FTerm::getStartOptions() } //---------------------------------------------------------------------- -void FTerm::init_global_values (bool disable_alt_screen) +void FTerm::init_global_values() { // Initialize global values // Preset to false data->setNewFont(false); - // Sets alternate screen usage - data->useAlternateScreen(! disable_alt_screen); - // Initialize xterm object getFTermXTerminal()->init(); @@ -1653,13 +1661,21 @@ void FTerm::init_optiAttr() } //---------------------------------------------------------------------- -void FTerm::init_font() +bool FTerm::init_font() { if ( getStartOptions().vgafont && ! setVGAFont() ) - exitWithMessage ("VGAfont is not supported by this terminal"); + { + data->setExitMessage("VGAfont is not supported by this terminal"); + FApplication::exit(EXIT_FAILURE); + } if ( getStartOptions().newfont && ! setNewFont() ) - exitWithMessage ("Newfont is not supported by this terminal"); + { + data->setExitMessage("Newfont is not supported by this terminal"); + FApplication::exit(EXIT_FAILURE); + } + + return ( ! FApplication::isQuit() ); } //---------------------------------------------------------------------- @@ -2112,6 +2128,7 @@ void FTerm::useAlternateScreenBuffer() { putstring (TCAP(fc::t_enter_ca_mode)); std::fflush(stdout); + getFTermData()->setAlternateScreenInUse(true); } } @@ -2128,6 +2145,7 @@ void FTerm::useNormalScreenBuffer() { putstring (TCAP(fc::t_exit_ca_mode)); std::fflush(stdout); + getFTermData()->setAlternateScreenInUse(false); } // restore cursor to position of last save_cursor @@ -2209,17 +2227,17 @@ inline void FTerm::deallocationValues() const defaultPutChar* putchar_ptr = &(putchar()); delete putchar_ptr; + destroyColorPaletteTheme(); FStartOptions::destroyObject(); } //---------------------------------------------------------------------- -void FTerm::init (bool disable_alt_screen) +void FTerm::init() { init_term_object = this; // Initialize global values for all objects - allocationValues(); - init_global_values(disable_alt_screen); + init_global_values(); // Initialize the terminal if ( ! init_terminal() ) @@ -2294,7 +2312,8 @@ void FTerm::init (bool disable_alt_screen) // Activate the VGA or the new graphic font // (depending on the initialization values) - init_font(); + if ( ! init_font() ) + return; // Turn off hardware echo FTermios::unsetHardwareEcho(); @@ -2474,14 +2493,6 @@ void FTerm::finish() if ( data->isNewFont() || data->isVGAFont() ) setOldFont(); - - // Print exit message - const auto& exit_message = data->getExitMessage(); - - if ( ! exit_message.isEmpty() ) - FApplication::getLog()->info(exit_message.c_str()); - - deallocationValues(); } //---------------------------------------------------------------------- @@ -2512,6 +2523,48 @@ void FTerm::destroyColorPaletteTheme() delete theme; } +//---------------------------------------------------------------------- +void FTerm::printExitMessage() +{ + // Print exit message + const auto& exit_message = data->getExitMessage(); + + if ( ! exit_message.isEmpty() ) + std::cerr << "Exit: " << exit_message << std::endl; +} + +//---------------------------------------------------------------------- +void FTerm::terminalSizeChange() +{ + if ( ! data ) + return; + + if ( data->hasTermResized() ) + return; + + // Initialize a resize event to the root element + data->setTermResized(true); +} + +//---------------------------------------------------------------------- +void FTerm::processTermination (int signum) +{ + init_term_object->finish(); + std::fflush (stderr); + std::fflush (stdout); + + if ( data ) + { + FStringStream msg{}; + msg << "Program stopped: signal " << signum + << " (" << strsignal(signum) << ")"; + data->setExitMessage(msg.str()); + printExitMessage(); + } + + std::terminate(); +} + //---------------------------------------------------------------------- void FTerm::setSignalHandler() { @@ -2542,14 +2595,7 @@ void FTerm::signal_handler (int signum) switch (signum) { case SIGWINCH: - if ( ! data ) - break; - - if ( data->hasTermResized() ) - break; - - // initialize a resize event to the root element - data->setTermResized(true); + terminalSizeChange(); break; case SIGTERM: @@ -2558,15 +2604,7 @@ void FTerm::signal_handler (int signum) case SIGABRT: case SIGILL: case SIGSEGV: - init_term_object->finish(); - std::fflush (stderr); - std::fflush (stdout); - *FApplication::getLog() << FLog::Error - << "\nProgram stopped: signal " - << signum - << " (" << strsignal(signum) << ")" - << std::endl; - std::terminate(); + processTermination(signum); default: break; diff --git a/src/ftermfreebsd.cpp b/src/ftermfreebsd.cpp index 324af019..99359ba1 100644 --- a/src/ftermfreebsd.cpp +++ b/src/ftermfreebsd.cpp @@ -30,11 +30,12 @@ #include "final/ftypes.h" #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(UNIT_TEST) -#define initCheck(ret_value) \ - if ( ! isInitialized() ) \ - { \ - warnNotInitialized(); \ - return ret_value; \ +#define initCheck(ret_value) \ + if ( ! isInitialized() ) \ + { \ + if ( ! FApplication::isQuit() ) \ + warnNotInitialized(); \ + return ret_value; \ } #endif diff --git a/src/ftermopenbsd.cpp b/src/ftermopenbsd.cpp index e8e2499a..e962d470 100644 --- a/src/ftermopenbsd.cpp +++ b/src/ftermopenbsd.cpp @@ -27,11 +27,12 @@ #include "final/ftermopenbsd.h" #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(UNIT_TEST) -#define initCheck(ret_value) \ - if ( ! isInitialized() ) \ - { \ - warnNotInitialized(); \ - return ret_value; \ +#define initCheck(ret_value) \ + if ( ! isInitialized() ) \ + { \ + if ( ! FApplication::isQuit() ) \ + warnNotInitialized(); \ + return ret_value; \ } #endif diff --git a/src/ftermxterminal.cpp b/src/ftermxterminal.cpp index 14569b33..c120e63a 100644 --- a/src/ftermxterminal.cpp +++ b/src/ftermxterminal.cpp @@ -36,11 +36,12 @@ #include "final/ftermxterminal.h" #include "final/fsize.h" -#define initCheck(ret_value) \ - if ( ! isInitialized() ) \ - { \ - warnNotInitialized(); \ - return ret_value; \ +#define initCheck(ret_value) \ + if ( ! isInitialized() ) \ + { \ + if ( ! FApplication::isQuit() ) \ + warnNotInitialized(); \ + return ret_value; \ } namespace finalcut diff --git a/src/ftogglebutton.cpp b/src/ftogglebutton.cpp index 6f665eb4..7da98051 100644 --- a/src/ftogglebutton.cpp +++ b/src/ftogglebutton.cpp @@ -148,29 +148,12 @@ bool FToggleButton::setNoUnderline (bool enable) bool FToggleButton::setEnable (bool enable) { FWidget::setEnable(enable); - const auto& wc = getColorTheme(); + resetColors(); if ( enable ) - { setHotkeyAccelerator(); - - if ( hasFocus() ) - { - setForegroundColor (wc->toggle_button_active_focus_fg); - setBackgroundColor (wc->toggle_button_active_focus_bg); - } - else - { - setForegroundColor (wc->toggle_button_active_fg); - setBackgroundColor (wc->toggle_button_active_bg); - } - } else - { delAccelerator(); - setForegroundColor (wc->toggle_button_inactive_fg); - setBackgroundColor (wc->toggle_button_inactive_bg); - } return enable; } @@ -179,25 +162,10 @@ bool FToggleButton::setEnable (bool enable) bool FToggleButton::setFocus (bool enable) { FWidget::setFocus(enable); + resetColors(); - if ( isEnabled() ) - { - const auto& wc = getColorTheme(); - - if ( enable ) - { - if ( isRadioButton() ) - focus_inside_group = false; - - setForegroundColor (wc->toggle_button_active_focus_fg); - setBackgroundColor (wc->toggle_button_active_focus_bg); - } - else - { - setForegroundColor (wc->toggle_button_active_fg); - setBackgroundColor (wc->toggle_button_active_bg); - } - } + if ( isEnabled() && hasFocus() && isRadioButton() ) + focus_inside_group = false; return enable; } diff --git a/src/fvterm.cpp b/src/fvterm.cpp index b5ea316e..aaf33999 100644 --- a/src/fvterm.cpp +++ b/src/fvterm.cpp @@ -54,6 +54,7 @@ bool FVTerm::terminal_update_complete{false}; bool FVTerm::terminal_update_pending{false}; bool FVTerm::force_terminal_update{false}; bool FVTerm::no_terminal_updates{false}; +bool FVTerm::cursor_hideable{false}; int FVTerm::skipped_terminal_update{}; uInt FVTerm::erase_char_length{}; uInt FVTerm::repeat_char_length{}; @@ -80,10 +81,10 @@ FChar FVTerm::i_ch{}; // constructors and destructor //---------------------------------------------------------------------- -FVTerm::FVTerm (bool initialize, bool disable_alt_screen) +FVTerm::FVTerm() { - if ( initialize ) - init (disable_alt_screen); + if ( ! init_object ) + init(); } //---------------------------------------------------------------------- @@ -171,6 +172,9 @@ void FVTerm::hideCursor (bool enable) { // Hides or shows the input cursor on the terminal + if ( ! cursor_hideable ) + return; + const char* visibility_str = FTerm::cursorsVisibilityString (enable); if ( visibility_str ) @@ -644,6 +648,9 @@ void FVTerm::flush() { // Flush the output buffer + if ( ! output_buffer ) + return; + while ( ! output_buffer->empty() ) { const static FTerm::defaultPutChar& FTermPutchar = FTerm::putchar(); @@ -798,6 +805,9 @@ void FVTerm::removeArea (FTermArea*& area) //---------------------------------------------------------------------- void FVTerm::restoreVTerm (const FRect& box) { + if ( ! vterm ) + return; + int x = box.getX() - 1; int y = box.getY() - 1; int w = int(box.getWidth()); @@ -1339,6 +1349,23 @@ void FVTerm::finishTerminalUpdate() terminal_update_complete = true; } +//---------------------------------------------------------------------- +void FVTerm::initTerminal() +{ + if ( fterm ) + fterm->initTerminal(); + + // Get FKeyboard object + keyboard = FTerm::getFKeyboard(); + + // Hide the input cursor + cursor_hideable = FTerm::isCursorHideable(); + hideCursor(); + + // Initialize character lengths + init_characterLengths(FTerm::getFOptiMove()); +} + // private methods of FVTerm //---------------------------------------------------------------------- @@ -1897,7 +1924,7 @@ const FChar FVTerm::getOverlappedCharacter (const FPoint& pos, FVTerm* obj) } //---------------------------------------------------------------------- -void FVTerm::init (bool disable_alt_screen) +void FVTerm::init() { init_object = this; vterm = nullptr; @@ -1906,16 +1933,20 @@ void FVTerm::init (bool disable_alt_screen) try { - fterm = new FTerm (disable_alt_screen); + fterm = new FTerm(); term_pos = new FPoint(-1, -1); output_buffer = new std::queue; } catch (const std::bad_alloc&) { badAllocOutput ("FTerm, FPoint, or std::queue"); - std::abort(); + return; } + // Presetting of the current locale for full-width character support. + // The final setting is made later in FTerm::init_locale(). + std::setlocale (LC_ALL, ""); + // term_attribute stores the current state of the terminal term_attribute.ch = '\0'; term_attribute.fg_color = fc::Default; @@ -1937,15 +1968,6 @@ void FVTerm::init (bool disable_alt_screen) createArea (term_geometry, shadow_size, vdesktop); vdesktop->visible = true; active_area = vdesktop; - - // Get FKeyboard object - keyboard = FTerm::getFKeyboard(); - - // Hide the input cursor - hideCursor(); - - // Initialize character lengths - init_characterLengths (FTerm::getFOptiMove()); } //---------------------------------------------------------------------- @@ -1978,7 +2000,8 @@ void FVTerm::finish() // Clear the terminal setNormal(); - if ( FTerm::hasAlternateScreen() ) + if ( FTerm::hasAlternateScreen() + && FTerm::getFTermData()->isInAlternateScreen() ) clearTerm(); flush(); diff --git a/src/fwidget.cpp b/src/fwidget.cpp index 22bbf124..fdbbcc66 100644 --- a/src/fwidget.cpp +++ b/src/fwidget.cpp @@ -49,8 +49,8 @@ FWidget::FWidgetList* FWidget::window_list{nullptr}; FWidget::FWidgetList* FWidget::dialog_list{nullptr}; FWidget::FWidgetList* FWidget::always_on_top_list{nullptr}; FWidget::FWidgetList* FWidget::close_widget{nullptr}; +bool FWidget::init_terminal{false}; bool FWidget::init_desktop{false}; -bool FWidget::hideable{false}; uInt FWidget::modal_dialog_counter{}; //---------------------------------------------------------------------- @@ -59,8 +59,8 @@ uInt FWidget::modal_dialog_counter{}; // constructors and destructor //---------------------------------------------------------------------- -FWidget::FWidget (FWidget* parent, bool disable_alt_screen) - : FVTerm{ ! (bool(parent) || root_widget), disable_alt_screen} +FWidget::FWidget (FWidget* parent) + : FVTerm{} , FObject{parent} { // init bit field with 0 @@ -83,22 +83,18 @@ FWidget::FWidget (FWidget* parent, bool disable_alt_screen) return; } - root_widget = this; - show_root_widget = nullptr; - redraw_root_widget = nullptr; - modal_dialog_counter = 0; - statusbar = nullptr; initRootWidget(); } else { - flags.visible_cursor = ! hideable; woffset = parent->wclient_offset; - double_flatline_mask.top.resize (getWidth(), false); - double_flatline_mask.right.resize (getHeight(), false); - double_flatline_mask.bottom.resize (getWidth(), false); - double_flatline_mask.left.resize (getHeight(), false); } + + flags.visible_cursor = false; + double_flatline_mask.top.resize (getWidth(), false); + double_flatline_mask.right.resize (getHeight(), false); + double_flatline_mask.bottom.resize (getWidth(), false); + double_flatline_mask.left.resize (getHeight(), false); } //---------------------------------------------------------------------- @@ -658,9 +654,10 @@ bool FWidget::setCursorPos (const FPoint& pos) woffsetY += (1 - area->widget->getTopPadding()); } + bool visible = ! isCursorHideable() || flags.visible_cursor; setAreaCursor ( { woffsetX + pos.getX() , woffsetY + pos.getY() } - , flags.visible_cursor + , visible , area ); return true; } @@ -1032,20 +1029,12 @@ void FWidget::show() { // Make the widget visible and draw it - if ( ! isVisible() ) + if ( ! isVisible() || FApplication::isQuit() ) return; - if ( ! init_desktop ) - { - // Sets the initial screen settings - FTerm::initScreenSettings(); - // Initializing vdesktop - const auto& r = getRootWidget(); - setColor(r->getForegroundColor(), r->getBackgroundColor()); - clearArea (getVirtualDesktop()); - // Destop is now initialized - init_desktop = true; - } + // Initialize desktop on first call + if ( ! init_desktop && root_widget ) + root_widget->initDesktop(); if ( ! show_root_widget ) { @@ -1320,6 +1309,49 @@ void FWidget::setTermOffsetWithPadding() , int(r->getHeight()) - 1 - r->getBottomPadding() ); } +//---------------------------------------------------------------------- +void FWidget::initTerminal() +{ + if ( hasParent() || init_terminal ) + return; + + // Initialize the physical and virtual terminal + FVTerm::initTerminal(); + + // Initialize default widget colors (after terminal detection) + initColorTheme(); + + // Set default foreground and background color of the desktop/terminal + auto color_theme = getColorTheme(); + root_widget->foreground_color = color_theme->term_fg; + root_widget->background_color = color_theme->term_bg; + resetColors(); + + // The terminal is now initialized + init_terminal = true; +} + +//---------------------------------------------------------------------- +void FWidget::initDesktop() +{ + if ( hasParent() || init_desktop ) + return; + + if ( ! init_terminal ) + initTerminal(); + + // Sets the initial screen settings + FTerm::initScreenSettings(); + + // Initializing vdesktop + const auto& r = getRootWidget(); + setColor(r->getForegroundColor(), r->getBackgroundColor()); + clearArea (getVirtualDesktop()); + + // Destop is now initialized + init_desktop = true; +} + //---------------------------------------------------------------------- void FWidget::adjustSize() { @@ -1713,6 +1745,18 @@ void FWidget::onClose (FCloseEvent* ev) // private methods of FWidget +//---------------------------------------------------------------------- +void FWidget::determineDesktopSize() +{ + // Determine width and height of the terminal + + detectTermSize(); + wsize.setRect(1, 1, getDesktopWidth(), getDesktopHeight()); + adjust_wsize = wsize; + woffset.setRect(0, 0, getDesktopWidth(), getDesktopHeight()); + wclient_offset = woffset; +} + //---------------------------------------------------------------------- void FWidget::initRootWidget() { @@ -1730,29 +1774,18 @@ void FWidget::initRootWidget() return; } - hideable = FTerm::isCursorHideable(); - flags.visible_cursor = ! hideable; + // Root widget basic initialization + root_widget = this; + show_root_widget = nullptr; + redraw_root_widget = nullptr; + modal_dialog_counter = 0; + statusbar = nullptr; // Determine width and height of the terminal - detectTermSize(); - wsize.setRect(1, 1, getDesktopWidth(), getDesktopHeight()); - adjust_wsize = wsize; - woffset.setRect(0, 0, getDesktopWidth(), getDesktopHeight()); - wclient_offset = woffset; + determineDesktopSize(); - double_flatline_mask.top.resize (getWidth(), false); - double_flatline_mask.right.resize (getHeight(), false); - double_flatline_mask.bottom.resize (getWidth(), false); - double_flatline_mask.left.resize (getHeight(), false); - - // Initialize default widget colors + // Initialize default widget colors (before terminal detection) initColorTheme(); - - // Default foreground and background color of the desktop/terminal - auto color_theme = getColorTheme(); - foreground_color = color_theme->term_fg; - background_color = color_theme->term_bg; - init_desktop = false; } //---------------------------------------------------------------------- diff --git a/src/include/final/fapplication.h b/src/include/final/fapplication.h index aeeadb68..875a17eb 100644 --- a/src/include/final/fapplication.h +++ b/src/include/final/fapplication.h @@ -94,7 +94,7 @@ class FApplication : public FWidget typedef std::shared_ptr FLogPtr; // Constructor - FApplication (const int&, char*[], bool = false); + FApplication (const int&, char*[]); // Disable copy constructor FApplication (const FApplication&) = delete; @@ -122,27 +122,24 @@ class FApplication : public FWidget int exec(); // run int enterLoop(); void exitLoop(); - static void exit (int = 0); + static void exit (int = EXIT_SUCCESS); void quit(); static bool sendEvent (FObject*, FEvent*); void queueEvent (FObject*, FEvent*); void sendQueuedEvents(); bool eventInQueue(); bool removeQueuedEvent (const FObject*); - virtual void processExternalUserEvent(); - static FWidget* processParameters (const int&, char*[]); + void initTerminal(); static void setDefaultTheme(); static void setDarkTheme(); - static void showParameterUsage () - #if defined(__clang__) || defined(__GNUC__) - __attribute__((noreturn)) - #endif - ; static void closeConfirmationDialog (FWidget*, FCloseEvent*); // Callback method void cb_exitApp (const FWidget*, const FDataPtr); + protected: + virtual void processExternalUserEvent(); + private: // Typedefs typedef std::pair EventPair; @@ -152,6 +149,7 @@ class FApplication : public FWidget void init (uInt64, uInt64); static void cmd_options (const int&, char*[]); static FStartOptions& getStartOptions(); + static void showParameterUsage(); void destroyLog(); void findKeyboardWidget(); bool isKeyPressed() const; @@ -186,6 +184,7 @@ class FApplication : public FWidget , const FPoint& , int ); void sendWheelEvent (const FPoint&, const FPoint&); + static FWidget* processParameters (const int&, char*[]); void processMouseEvent(); void processResizeEvent(); void processCloseWidget(); diff --git a/src/include/final/fbutton.h b/src/include/final/fbutton.h index 16d60716..0fef4af5 100644 --- a/src/include/final/fbutton.h +++ b/src/include/final/fbutton.h @@ -158,13 +158,13 @@ class FButton : public FWidget bool click_animation{true}; int click_time{150}; int space_char{int(' ')}; - FColor button_fg{getColorTheme()->button_active_fg}; - FColor button_bg{getColorTheme()->button_active_bg}; - FColor button_hotkey_fg{getColorTheme()->button_hotkey_fg}; - FColor button_focus_fg{getColorTheme()->button_active_focus_fg}; - FColor button_focus_bg{getColorTheme()->button_active_focus_bg}; - FColor button_inactive_fg{getColorTheme()->button_inactive_fg}; - FColor button_inactive_bg{getColorTheme()->button_inactive_bg}; + FColor button_fg{fc::Default}; + FColor button_bg{fc::Default}; + FColor button_hotkey_fg{fc::Default}; + FColor button_focus_fg{fc::Default}; + FColor button_focus_bg{fc::Default}; + FColor button_inactive_fg{fc::Default}; + FColor button_inactive_bg{fc::Default}; std::size_t hotkeypos{NOT_SET}; std::size_t indent{0}; std::size_t center_offset{0}; diff --git a/src/include/final/flabel.h b/src/include/final/flabel.h index 20d55bbc..f6ad464f 100644 --- a/src/include/final/flabel.h +++ b/src/include/final/flabel.h @@ -98,6 +98,7 @@ class FLabel : public FWidget bool setEmphasis (bool); bool setEmphasis(); bool unsetEmphasis(); + void resetColors() override; bool setReverseMode (bool); bool setReverseMode(); bool unsetReverseMode(); @@ -145,8 +146,8 @@ class FLabel : public FWidget std::size_t align_offset{0}; std::size_t hotkeypos{NOT_SET}; std::size_t column_width{0}; - FColor emphasis_color{getColorTheme()->label_emphasis_fg}; - FColor ellipsis_color{getColorTheme()->label_ellipsis_fg}; + FColor emphasis_color{fc::Default}; + FColor ellipsis_color{fc::Default}; bool multiline{false}; bool emphasis{false}; bool reverse_mode{false}; diff --git a/src/include/final/fterm.h b/src/include/final/fterm.h index ff8fd129..d35e8b7e 100644 --- a/src/include/final/fterm.h +++ b/src/include/final/fterm.h @@ -166,7 +166,7 @@ class FTerm final typedef FColorPalette::FSetPalette FSetPalette; // Constructor - explicit FTerm (bool = false); + explicit FTerm(); // Disable copy constructor FTerm (const FTerm&) = delete; @@ -189,7 +189,6 @@ class FTerm final static int getMaxColor(); static FColorPalettePtr& getColorPaletteTheme(); charSubstitution& getCharSubstitutionMap(); - static FTermData* getFTermData(); static FSystem* getFSystem(); static FOptiMove* getFOptiMove(); @@ -257,6 +256,7 @@ class FTerm final static void unsetInsertCursor(); static void redefineDefaultColors (bool); static void setDblclickInterval (const uInt64); + static void useAlternateScreen (bool); static bool setUTF8 (bool); static bool setUTF8(); static bool unsetUTF8(); @@ -299,18 +299,15 @@ class FTerm final static int putchar_ASCII (int); static int putchar_UTF8 (int); + void initTerminal(); static void initScreenSettings(); static const char* changeAttribute (FChar*&, FChar*&); static void changeTermSizeFinished(); - static void exitWithMessage (const FString&) - #if defined(__clang__) || defined(__GNUC__) - __attribute__((noreturn)) - #endif - ; + private: // Methods static FStartOptions& getStartOptions(); - static void init_global_values (bool); + static void init_global_values(); static void init_terminal_device_path(); static void oscPrefix(); static void oscPostfix(); @@ -324,7 +321,7 @@ class FTerm final static void init_quirks(); static void init_optiMove(); static void init_optiAttr(); - static void init_font(); + static bool init_font(); static void init_locale(); static void init_encoding(); static void init_encoding_set(); @@ -352,7 +349,7 @@ class FTerm final static void useNormalScreenBuffer(); void allocationValues(); void deallocationValues(); - void init (bool); + void init(); bool init_terminal(); void initOSspecifics(); void initTermspecifics(); @@ -361,6 +358,9 @@ class FTerm final void finishOSspecifics1(); void finish_encoding(); void destroyColorPaletteTheme(); + static void printExitMessage(); + static void terminalSizeChange(); + [[noreturn]] static void processTermination (int); static void setSignalHandler(); static void resetSignalHandler(); static void signal_handler (int); @@ -467,6 +467,10 @@ inline void FTerm::putstringf (const char format[], Args&&... args) fsys->tputs (&buf[0], 1, FTerm::putchar_ASCII); } +//---------------------------------------------------------------------- +inline void FTerm::initTerminal() +{ init(); } + } // namespace finalcut diff --git a/src/include/final/ftermcap.h b/src/include/final/ftermcap.h index 3d26e3ac..59523473 100644 --- a/src/include/final/ftermcap.h +++ b/src/include/final/ftermcap.h @@ -108,6 +108,9 @@ class FTermcap final template static int paddingPrint (const CharT&, int, fn_putc); + // Inquiry + static bool isInitialized(); + // Methods static void init(); @@ -129,6 +132,7 @@ class FTermcap final // Constant static constexpr std::size_t BUF_SIZE{2048}; + // Methods static void termcap(); static void termcapError (int); @@ -194,6 +198,12 @@ int FTermcap::paddingPrint (const CharT& str, int affcnt, fn_putc putc) return _tputs (C_STR(str), affcnt, putc); } +//---------------------------------------------------------------------- +inline bool FTermcap::isInitialized() +{ + return bool(fsystem && fterm_data && term_detection); +} + } // namespace finalcut diff --git a/src/include/final/ftermdata.h b/src/include/final/ftermdata.h index d14e3d52..cf1124ab 100644 --- a/src/include/final/ftermdata.h +++ b/src/include/final/ftermdata.h @@ -93,6 +93,7 @@ class FTermData final bool hasCursorOptimisation() const; bool isCursorHidden() const; bool hasAlternateScreen() const; + bool isInAlternateScreen() const; bool hasASCIIConsole() const; bool hasVT100Console() const; bool hasUTF8Console() const; @@ -111,6 +112,7 @@ class FTermData final void supportCursorOptimisation (bool); void setCursorHidden (bool); void useAlternateScreen (bool); + void setAlternateScreenInUse (bool); void setASCIIConsole (bool); void setVT100Console (bool); void setUTF8Console (bool); @@ -151,6 +153,7 @@ class FTermData final bool cursor_optimisation{true}; bool hidden_cursor{false}; // Global cursor hidden state bool use_alternate_screen{true}; + bool alternate_screen{false}; bool ascii_console{false}; bool vt100_console{false}; bool utf8_console{false}; @@ -236,6 +239,10 @@ inline bool FTermData::isCursorHidden() const inline bool FTermData::hasAlternateScreen() const { return use_alternate_screen; } +//---------------------------------------------------------------------- +inline bool FTermData::isInAlternateScreen() const +{ return alternate_screen; } + //---------------------------------------------------------------------- inline bool FTermData::hasASCIIConsole() const { return ascii_console; } @@ -300,6 +307,10 @@ inline void FTermData::setCursorHidden (bool hidden_state) inline void FTermData::useAlternateScreen (bool use) { use_alternate_screen = use; } +//---------------------------------------------------------------------- +inline void FTermData::setAlternateScreenInUse (bool in_use) +{ alternate_screen = in_use; } + //---------------------------------------------------------------------- inline void FTermData::setASCIIConsole (bool ascii) { ascii_console = ascii; } diff --git a/src/include/final/fvterm.h b/src/include/final/fvterm.h index 497d3d11..a6082c29 100644 --- a/src/include/final/fvterm.h +++ b/src/include/final/fvterm.h @@ -118,7 +118,7 @@ class FVTerm }; // Constructor - explicit FVTerm (bool, bool = false); + explicit FVTerm(); // Disable copy constructor FVTerm (const FVTerm&) = delete; @@ -293,9 +293,9 @@ class FVTerm bool hasPrintArea() const; bool hasChildPrintArea() const; bool isVirtualWindow() const; + bool isCursorHideable() const; // Methods - void createArea ( const FRect& , const FSize& , FTermArea*& ); @@ -317,6 +317,7 @@ class FVTerm void processTerminalUpdate(); static void startTerminalUpdate(); static void finishTerminalUpdate(); + void initTerminal(); private: // Enumerations @@ -373,7 +374,7 @@ class FVTerm , FVTerm* ); static const FChar getCoveredCharacter (const FPoint&, FVTerm*); static const FChar getOverlappedCharacter (const FPoint&, FVTerm*); - void init (bool); + void init(); static void init_characterLengths (const FOptiMove*); void finish(); static void putAreaLine (const FChar*, FChar*, int); @@ -445,6 +446,7 @@ class FVTerm static uInt clr_bol_length; static uInt clr_eol_length; static uInt cursor_address_length; + static bool cursor_hideable; }; @@ -970,6 +972,10 @@ inline bool FVTerm::hasChildPrintArea() const inline bool FVTerm::isVirtualWindow() const { return vwin; } +//---------------------------------------------------------------------- +inline bool FVTerm::isCursorHideable() const +{ return cursor_hideable; } + } // namespace finalcut diff --git a/src/include/final/fwidget.h b/src/include/final/fwidget.h index fcc6fdfd..d89f331b 100644 --- a/src/include/final/fwidget.h +++ b/src/include/final/fwidget.h @@ -173,7 +173,7 @@ class FWidget : public FVTerm, public FObject }; // Constructor - explicit FWidget (FWidget* = nullptr, bool = false); + explicit FWidget (FWidget* = nullptr); // Disable copy constructor FWidget (const FWidget&) = delete; @@ -374,6 +374,8 @@ class FWidget : public FVTerm, public FObject void setTermOffsetWithPadding(); // Methods + void initTerminal(); + void initDesktop(); virtual void adjustSize(); void adjustSizeGlobal(); void hideArea (const FSize&); @@ -447,6 +449,7 @@ class FWidget : public FVTerm, public FObject }; // Methods + void determineDesktopSize(); void initRootWidget(); void finish(); void insufficientSpaceAdjust(); @@ -507,8 +510,8 @@ class FWidget : public FVTerm, public FObject static FWidgetList* always_on_top_list; static FWidgetList* close_widget; static uInt modal_dialog_counter; + static bool init_terminal; static bool init_desktop; - static bool hideable; // Friend classes friend class FToggleButton; @@ -876,14 +879,7 @@ inline bool FWidget::setDisable() //---------------------------------------------------------------------- inline bool FWidget::setVisibleCursor (bool enable) -{ - if ( enable ) - flags.visible_cursor = true; - else - flags.visible_cursor = ( hideable ) ? false : true; - - return flags.visible_cursor; -} +{ return (flags.visible_cursor = enable); } //---------------------------------------------------------------------- inline bool FWidget::setVisibleCursor() diff --git a/test/conemu.h b/test/conemu.h index 8c92f4a2..1105e4e8 100644 --- a/test/conemu.h +++ b/test/conemu.h @@ -80,6 +80,16 @@ class ConEmu , PROT_READ | PROT_WRITE , MAP_SHARED | MAP_ANONYMOUS, -1 , 0 ); + + if ( ptr == MAP_FAILED ) + { + std::cerr << "mmap error: " + << strerror(errno) + << " (" << errno << ")" + << std::endl; + return; + } + shared_state = static_cast(ptr); *shared_state = false; } diff --git a/test/foptimove-test.cpp b/test/foptimove-test.cpp index deaed59e..750e1479 100644 --- a/test/foptimove-test.cpp +++ b/test/foptimove-test.cpp @@ -61,8 +61,7 @@ void check_c_string ( const char* s1 class FOptiMoveTest : public CPPUNIT_NS::TestFixture { public: - FOptiMoveTest() - { } + FOptiMoveTest(); protected: void classNameTest(); @@ -104,6 +103,11 @@ class FOptiMoveTest : public CPPUNIT_NS::TestFixture CPPUNIT_TEST_SUITE_END(); }; +//---------------------------------------------------------------------- +FOptiMoveTest::FOptiMoveTest() +{ + finalcut::FTermcap::init(); +} //---------------------------------------------------------------------- void FOptiMoveTest::classNameTest() diff --git a/test/ftermdata-test.cpp b/test/ftermdata-test.cpp index 0991896c..e8f1b3f1 100644 --- a/test/ftermdata-test.cpp +++ b/test/ftermdata-test.cpp @@ -108,6 +108,7 @@ void FTermDataTest::defaultDataTest() CPPUNIT_ASSERT ( data.hasCursorOptimisation() == true ); CPPUNIT_ASSERT ( data.isCursorHidden() == false ); CPPUNIT_ASSERT ( data.hasAlternateScreen() == true ); + CPPUNIT_ASSERT ( data.isInAlternateScreen() == false ); CPPUNIT_ASSERT ( data.hasASCIIConsole() == false ); CPPUNIT_ASSERT ( data.hasVT100Console() == false ); CPPUNIT_ASSERT ( data.hasUTF8Console() == false ); @@ -223,6 +224,11 @@ void FTermDataTest::dataTest() data.useAlternateScreen (false); CPPUNIT_ASSERT ( data.hasAlternateScreen() == false ); + CPPUNIT_ASSERT ( data.isInAlternateScreen() == false ); + data.setAlternateScreenInUse (true); + CPPUNIT_ASSERT ( data.isInAlternateScreen() == true ); + + CPPUNIT_ASSERT ( data.hasASCIIConsole() == false ); data.setASCIIConsole (true); CPPUNIT_ASSERT ( data.hasASCIIConsole() == true );