From 9bc6ec6f96bb0a48b18db4812da7295a64b939f1 Mon Sep 17 00:00:00 2001 From: Markus Gans Date: Sun, 10 Jan 2016 00:56:52 +0100 Subject: [PATCH] Better default color handling --- ChangeLog | 3 ++ doc/TODO | 6 ++- src/fbutton.cpp | 15 ++++--- src/foptiattr.cpp | 91 ++++++++++++++++++++++++++++++++++------ src/foptiattr.h | 18 ++++++++ src/ftcap_map.h | 2 +- src/fterm.cpp | 69 +++++++++++++++++------------- src/fterm.h | 2 + src/fwidget.h | 10 +++-- test/keyboard.cpp | 6 +-- test/term-attributes.cpp | 32 +++++++++++--- test/timer.cpp | 6 +-- 12 files changed, 197 insertions(+), 63 deletions(-) diff --git a/ChangeLog b/ChangeLog index e2d600b1..aad7afc8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2016-01-10 Markus Gans + * Better default color handling in FOptiAttr + 2016-01-07 Markus Gans * Add the new class FOptiAttr to control video attributes and colors for output on terminals diff --git a/doc/TODO b/doc/TODO index a165a4f8..396d2303 100644 --- a/doc/TODO +++ b/doc/TODO @@ -4,7 +4,11 @@ Bugs Improvements ~~~~~~~~~~~~ -- +- Every OSC sequence ("\033]") should have been a special prefix and + postfix sequence for screen and tmux: + + screen = "\033P" + OSC + control sequence + "\a\033\\" + tmux = "\033Ptmux:\033" + OSC + control sequence + "\033\\" Missing Features ~~~~~~~~~~~~~~~~ diff --git a/src/fbutton.cpp b/src/fbutton.cpp index 63f2ee0a..f10df8b9 100644 --- a/src/fbutton.cpp +++ b/src/fbutton.cpp @@ -412,13 +412,15 @@ void FButton::setBackgroundColor (short color) //---------------------------------------------------------------------- void FButton::setHotkeyForegroundColor (short color) { - if ( color == -1 || color >> 8 == 0 ) // valid colors -1..254 + // valid colors -1..254 + if ( color == fc::Default || color >> 8 == 0 ) button_hotkey_fg = color; } void FButton::setFocusForegroundColor (short color) { - if ( color == -1 || color >> 8 == 0 ) // valid colors -1..254 + // valid colors -1..254 + if ( color == fc::Default || color >> 8 == 0 ) button_focus_fg = color; updateButtonColor(); } @@ -426,7 +428,8 @@ void FButton::setFocusForegroundColor (short color) //---------------------------------------------------------------------- void FButton::setFocusBackgroundColor (short color) { - if ( color == -1 || color >> 8 == 0 ) // valid colors -1..254 + // valid colors -1..254 + if ( color == fc::Default || color >> 8 == 0 ) button_focus_bg = color; updateButtonColor(); } @@ -434,7 +437,8 @@ void FButton::setFocusBackgroundColor (short color) //---------------------------------------------------------------------- void FButton::setInactiveForegroundColor (short color) { - if ( color == -1 || color >> 8 == 0 ) // valid colors -1..254 + // valid colors -1..254 + if ( color == fc::Default || color >> 8 == 0 ) button_inactive_fg = color; updateButtonColor(); } @@ -442,7 +446,8 @@ void FButton::setInactiveForegroundColor (short color) //---------------------------------------------------------------------- void FButton::setInactiveBackgroundColor (short color) { - if ( color == -1 || color >> 8 == 0 ) // valid colors -1..254 + // valid colors -1..254 + if ( color == fc::Default || color >> 8 == 0 ) button_inactive_bg = color; updateButtonColor(); } diff --git a/src/foptiattr.cpp b/src/foptiattr.cpp index 6e947f7e..2880e71c 100644 --- a/src/foptiattr.cpp +++ b/src/foptiattr.cpp @@ -44,8 +44,11 @@ FOptiAttr::FOptiAttr() , F_set_foreground() , F_set_background() , F_set_color_pair() + , F_orig_pair() + , F_orig_colors() , max_color(1) , attr_without_color(0) + , ansi_default_color(false) , monochron(true) , fake_reverse(false) , cygwin_terminal(false) @@ -82,8 +85,8 @@ inline bool FOptiAttr::colorChange (char_data*& term, char_data*& next) //---------------------------------------------------------------------- inline void FOptiAttr::resetColor (char_data*& attr) { - attr->fg_color = -1; - attr->bg_color = -1; + attr->fg_color = Default; + attr->bg_color = Default; } //---------------------------------------------------------------------- @@ -194,17 +197,34 @@ void FOptiAttr::change_color (char_data*& term, char_data*& next) if ( monochron ) return; - if ( fg == -1 && term->fg_color != -1 ) + if ( fg == Default || bg == Default ) { - char* sgr_39 = const_cast("\033[39m"); - append_sequence (sgr_39); - term->fg_color = next->fg_color; - } - if ( bg == -1 && term->bg_color != -1 ) - { - char* sgr_49 = const_cast("\033[49m"); - append_sequence (sgr_49); - term->bg_color = next->bg_color; + if ( ansi_default_color ) + { + if ( fg == Default && term->fg_color != Default + && bg == Default && term->bg_color != Default ) + { + setTermDefaultColor(term); + } + else if ( fg == Default && term->fg_color != Default ) + { + char* sgr_39 = const_cast("\033[39m"); + append_sequence (sgr_39); + term->fg_color = Default; + } + else if ( bg == Default && term->bg_color != Default ) + { + char* sgr_49 = const_cast("\033[49m"); + append_sequence (sgr_49); + term->bg_color = Default; + } + } + else if ( ! setTermDefaultColor(term) ) + { + // fallback to gray on black + fg = next->fg_color = LightGray; + bg = next->bg_color = Black; + } } if ( ! fake_reverse && fg < 0 && bg < 0 ) @@ -777,6 +797,33 @@ inline bool FOptiAttr::unsetTermPCcharset (char_data*& term) return false; } +//---------------------------------------------------------------------- +bool FOptiAttr::setTermDefaultColor (char_data*& term) +{ + if ( append_sequence(F_orig_pair.cap) ) + { + term->fg_color = Default; + term->bg_color = Default; + return true; + } + else if ( append_sequence(F_orig_colors.cap) ) + { + term->fg_color = Default; + term->bg_color = Default; + return true; + } + else if ( ansi_default_color ) + { + char* sgr_39_49 = const_cast("\033[39;49m"); + append_sequence (sgr_39_49); + term->fg_color = Default; + term->bg_color = Default; + return true; + } + else + return false; +} + // public methods of FOptiAttr //---------------------------------------------------------------------- @@ -1144,6 +1191,26 @@ void FOptiAttr::set_term_color_pair (char*& cap) } } +//---------------------------------------------------------------------- +void FOptiAttr::set_orig_pair (char*& cap) +{ + if ( cap ) + { + F_orig_pair.cap = cap; + F_orig_pair.caused_reset = false; + } +} + +//---------------------------------------------------------------------- +void FOptiAttr::set_orig_orig_colors (char*& cap) +{ + if ( cap ) + { + F_orig_colors.cap = cap; + F_orig_colors.caused_reset = false; + } +} + //---------------------------------------------------------------------- void FOptiAttr::init() { diff --git a/src/foptiattr.h b/src/foptiattr.h index 04d3cfde..1c8ebf92 100644 --- a/src/foptiattr.h +++ b/src/foptiattr.h @@ -40,6 +40,13 @@ class FOptiAttr all_tests = 0x1f }; + enum default_color + { + Default = -1, + Black = 0, + LightGray = 7 + }; + typedef struct { char* cap; @@ -79,9 +86,12 @@ class FOptiAttr capability F_set_foreground; capability F_set_background; capability F_set_color_pair; + capability F_orig_pair; + capability F_orig_colors; int max_color; int attr_without_color; + bool ansi_default_color; bool monochron; bool fake_reverse; bool cygwin_terminal; @@ -164,6 +174,7 @@ class FOptiAttr bool unsetTermAltCharset (char_data*&); bool setTermPCcharset (char_data*&); bool unsetTermPCcharset (char_data*&); + bool setTermDefaultColor (char_data*&); public: explicit FOptiAttr(); // constructor @@ -173,6 +184,7 @@ class FOptiAttr void setMaxColor (int&); void setNoColorVideo (int); + void setDefaultColorSupport(); void setCygwinTerminal(); void set_enter_bold_mode (char*&); void set_exit_bold_mode (char*&); @@ -207,6 +219,8 @@ class FOptiAttr void set_foreground_color (char*&); void set_background_color (char*&); void set_term_color_pair (char*&); + void set_orig_pair (char*&); + void set_orig_orig_colors (char*&); void init(); char* change_attribute (char_data*&, char_data*&); @@ -226,6 +240,10 @@ inline void FOptiAttr::setMaxColor (int& c) inline void FOptiAttr::setNoColorVideo (int attr) { attr_without_color = attr; } +//---------------------------------------------------------------------- +inline void FOptiAttr::setDefaultColorSupport() +{ ansi_default_color = true; } + //---------------------------------------------------------------------- inline void FOptiAttr::setCygwinTerminal() { cygwin_terminal = true; } diff --git a/src/ftcap_map.h b/src/ftcap_map.h index 33027fa6..ca82066b 100644 --- a/src/ftcap_map.h +++ b/src/ftcap_map.h @@ -110,7 +110,7 @@ static tcap_map tcap[] = * to the number of lines affected * (#i) indicates the ith parameter. * - * "XX", "Us" and "Ue" are unofficial and are only used here. + * "XX", "Us" and "Ue" are unofficial and they are only used here. */ enum termcaps diff --git a/src/fterm.cpp b/src/fterm.cpp index 7d625b5b..05e53fd8 100644 --- a/src/fterm.cpp +++ b/src/fterm.cpp @@ -48,6 +48,7 @@ bool FTerm::background_color_erase; bool FTerm::automatic_left_margin; bool FTerm::automatic_right_margin; bool FTerm::eat_nl_glitch; +bool FTerm::ansi_default_color; bool FTerm::xterm; bool FTerm::rxvt_terminal; bool FTerm::urxvt_terminal; @@ -75,6 +76,7 @@ bool FTerm::ascii_console; bool FTerm::NewFont; bool FTerm::VGAFont; bool FTerm::cursor_optimisation; +bool FTerm::osc_support; uChar FTerm::x11_button_state; termios FTerm::term_init; @@ -1071,6 +1073,13 @@ void FTerm::init_termcaps() // newline ignored after 80 cols eat_nl_glitch = tgetflag(const_cast("xn")); + // terminal supports ANSI set default fg and bg color + ansi_default_color = tgetflag(const_cast("AX")); + + // terminal supports operating system commands (OSC) + // OSC = Esc + ] + osc_support = tgetflag(const_cast("XT")); + if ( isTeraTerm() ) eat_nl_glitch = true; @@ -1364,7 +1373,11 @@ void FTerm::init_termcaps() opti_attr->set_foreground_color (tcap[t_set_foreground].string); opti_attr->set_background_color (tcap[t_set_background].string); opti_attr->set_term_color_pair (tcap[t_set_color_pair].string); - opti_attr->setMaxColor(max_color); + opti_attr->set_orig_pair (tcap[t_orig_pair].string); + opti_attr->set_orig_orig_colors (tcap[t_orig_colors].string); + opti_attr->setMaxColor (max_color); + if ( ansi_default_color ) + opti_attr->setDefaultColorSupport(); if ( cygwin_terminal ) opti_attr->setCygwinTerminal(); opti_attr->init(); @@ -1469,8 +1482,8 @@ void FTerm::init() background_color_erase = false; term_attribute.code = '\0'; - term_attribute.fg_color = -1; - term_attribute.bg_color = -1; + term_attribute.fg_color = fc::Default; + term_attribute.bg_color = fc::Default; term_attribute.bold = \ term_attribute.dim = \ term_attribute.italic = \ @@ -1486,8 +1499,8 @@ void FTerm::init() term_attribute.pc_charset = false; next_attribute.code = '\0'; - next_attribute.fg_color = -1; - next_attribute.bg_color = -1; + next_attribute.fg_color = fc::Default; + next_attribute.bg_color = fc::Default; next_attribute.bold = \ next_attribute.dim = \ next_attribute.italic = \ @@ -2032,8 +2045,8 @@ void FTerm::resizeArea (term_area* area) area->bottom_shadow = bsh; default_char.code = ' '; - default_char.fg_color = fc::Black; - default_char.bg_color = fc::Black; + default_char.fg_color = fc::Default; + default_char.bg_color = fc::Default; default_char.bold = 0; default_char.dim = 0; default_char.italic = 0; @@ -2531,7 +2544,7 @@ bool FTerm::setVGAFont() VGAFont = true; - if ( xterm ) + if ( xterm || osc_support ) { // Set font in xterm to vga putstring("\033]50;vga\07"); @@ -2585,7 +2598,7 @@ bool FTerm::setNewFont() if ( NewFont ) return true; - if ( xterm || urxvt_terminal ) + if ( xterm || urxvt_terminal || osc_support ) { NewFont = true; // Set font in xterm to 8x16graph @@ -2644,7 +2657,7 @@ bool FTerm::setOldFont() NewFont = \ VGAFont = false; - if ( xterm || urxvt_terminal ) + if ( xterm || urxvt_terminal || osc_support ) { if ( xterm_font->getLength() > 2 ) // restore saved xterm font @@ -2790,8 +2803,8 @@ void FTerm::resizeVTerm() vterm->height = term_height; default_char.code = ' '; - default_char.fg_color = fc::LightGray; - default_char.bg_color = fc::Black; + default_char.fg_color = fc::Default; + default_char.bg_color = fc::Default; default_char.bold = 0; default_char.dim = 0; default_char.italic = 0; @@ -2919,7 +2932,7 @@ void FTerm::updateTerminal() void FTerm::setKDECursor (fc::kde_konsole_CursorShape style) { // Set cursor style in KDE konsole - if ( kde_konsole ) + if ( kde_konsole || osc_support ) { putstringf ("\033]50;CursorShape=%d\007", style); fflush(stdout); @@ -2931,7 +2944,7 @@ FString FTerm::getXTermFont() { FString font(""); - if ( raw_mode && non_blocking_stdin ) + if ( raw_mode && non_blocking_stdin && osc_support ) { int n; char temp[150] = {}; @@ -2996,7 +3009,7 @@ void FTerm::setXTermCursorStyle(fc::xterm_cursor_style style) void FTerm::setXTermTitle (const FString& title) { // Set the xterm title - if ( xterm || mintty_terminal || putty_terminal ) + if ( xterm || mintty_terminal || putty_terminal || osc_support ) { putstringf ("\033]0;%s\07", title.c_str()); fflush(stdout); @@ -3007,7 +3020,7 @@ void FTerm::setXTermTitle (const FString& title) void FTerm::setXTermForeground (const FString& fg) { // Set the VT100 text foreground color - if ( xterm || mintty_terminal || mlterm_terminal ) + if ( xterm || mintty_terminal || mlterm_terminal || osc_support ) { putstringf ("\033]10;%s\07", fg.c_str()); fflush(stdout); @@ -3018,7 +3031,7 @@ void FTerm::setXTermForeground (const FString& fg) void FTerm::setXTermBackground (const FString& bg) { // Set the VT100 text background color - if ( xterm || mintty_terminal || mlterm_terminal ) + if ( xterm || mintty_terminal || mlterm_terminal || osc_support ) { putstringf ("\033]11;%s\07", bg.c_str()); fflush(stdout); @@ -3029,7 +3042,7 @@ void FTerm::setXTermBackground (const FString& bg) void FTerm::setXTermCursorColor (const FString& cc) { // Set the text cursor color - if ( xterm || mintty_terminal || urxvt_terminal ) + if ( xterm || mintty_terminal || urxvt_terminal || osc_support ) { putstringf ("\033]12;%s\07", cc.c_str()); fflush(stdout); @@ -3040,7 +3053,7 @@ void FTerm::setXTermCursorColor (const FString& cc) void FTerm::setXTermMouseForeground (const FString& mfg) { // Set the mouse foreground color - if ( xterm || urxvt_terminal ) + if ( xterm || urxvt_terminal || osc_support ) { putstringf ("\033]13;%s\07", mfg.c_str()); fflush(stdout); @@ -3051,7 +3064,7 @@ void FTerm::setXTermMouseForeground (const FString& mfg) void FTerm::setXTermMouseBackground (const FString& mbg) { // Set the mouse background color - if ( xterm ) + if ( xterm || osc_support ) { putstringf ("\033]14;%s\07", mbg.c_str()); fflush(stdout); @@ -3062,7 +3075,7 @@ void FTerm::setXTermMouseBackground (const FString& mbg) void FTerm::setXTermHighlightBackground (const FString& hbg) { // Set the highlight background color - if ( xterm || urxvt_terminal ) + if ( xterm || urxvt_terminal || osc_support ) { putstringf ("\033]17;%s\07", hbg.c_str()); fflush(stdout); @@ -3073,7 +3086,7 @@ void FTerm::setXTermHighlightBackground (const FString& hbg) void FTerm::resetXTermColors() { // Reset the entire color table - if ( xterm ) + if ( xterm || osc_support ) { putstringf ("\033]104\07"); fflush(stdout); @@ -3084,7 +3097,7 @@ void FTerm::resetXTermColors() void FTerm::resetXTermForeground() { // Reset the VT100 text foreground color - if ( xterm ) + if ( xterm || osc_support ) { putstring("\033]110\07"); fflush(stdout); @@ -3095,7 +3108,7 @@ void FTerm::resetXTermForeground() void FTerm::resetXTermBackground() { // Reset the VT100 text background color - if ( xterm ) + if ( xterm || osc_support ) { putstring("\033]111\07"); fflush(stdout); @@ -3106,7 +3119,7 @@ void FTerm::resetXTermBackground() void FTerm::resetXTermCursorColor() { // Reset the text cursor color - if ( xterm ) + if ( xterm || osc_support ) { putstring("\033]112\07"); fflush(stdout); @@ -3117,7 +3130,7 @@ void FTerm::resetXTermCursorColor() void FTerm::resetXTermMouseForeground() { // Reset the mouse foreground color - if ( xterm ) + if ( xterm || osc_support ) { putstring("\033]113\07"); fflush(stdout); @@ -3128,7 +3141,7 @@ void FTerm::resetXTermMouseForeground() void FTerm::resetXTermMouseBackground() { // Reset the mouse background color - if ( xterm ) + if ( xterm || osc_support ) { putstring("\033]114\07"); fflush(stdout); @@ -3139,7 +3152,7 @@ void FTerm::resetXTermMouseBackground() void FTerm::resetXTermHighlightBackground() { // Reset the highlight background color - if ( xterm || urxvt_terminal ) + if ( xterm || urxvt_terminal || osc_support ) { putstringf ("\033]117\07"); fflush(stdout); diff --git a/src/fterm.h b/src/fterm.h index c1cfe4c9..6e943263 100644 --- a/src/fterm.h +++ b/src/fterm.h @@ -133,6 +133,8 @@ class FTerm static bool automatic_left_margin; static bool automatic_right_margin; static bool eat_nl_glitch; + static bool ansi_default_color; + static bool osc_support; static char termtype[30]; static char* term_name; static char* locale_name; diff --git a/src/fwidget.h b/src/fwidget.h index 0340df3f..6cda00f8 100644 --- a/src/fwidget.h +++ b/src/fwidget.h @@ -685,14 +685,16 @@ inline FPoint FWidget::globalToLocalPos (const FPoint& gPos) //---------------------------------------------------------------------- inline void FWidget::setForegroundColor (short color) { - if ( color == -1 || color >> 8 == 0 ) // valid colors -1..254 + // valid colors -1..254 + if ( color == fc::Default || color >> 8 == 0 ) foregroundColor = color; } //---------------------------------------------------------------------- inline void FWidget::setBackgroundColor (short color) { - if ( color == -1 || color >> 8 == 0 ) // valid colors -1..254 + // valid colors -1..254 + if ( color == fc::Default || color >> 8 == 0 ) backgroundColor = color; } @@ -807,8 +809,8 @@ inline void FWidget::setNormal() next_attribute.alt_charset = \ next_attribute.pc_charset = false; - next_attribute.fg_color = -1; - next_attribute.bg_color = -1; + next_attribute.fg_color = fc::Default; + next_attribute.bg_color = fc::Default; } //---------------------------------------------------------------------- diff --git a/test/keyboard.cpp b/test/keyboard.cpp index 1161096a..3a8130d9 100644 --- a/test/keyboard.cpp +++ b/test/keyboard.cpp @@ -22,8 +22,8 @@ keyboard::keyboard (FWidget* parent) { resetXTermForeground(); resetXTermBackground(); - wc.term_fg = -1; - wc.term_bg = -1; + wc.term_fg = fc::Default; + wc.term_bg = fc::Default; } //---------------------------------------------------------------------- @@ -44,7 +44,7 @@ void keyboard::onAccel (FAccelEvent* ev) void keyboard::draw() { setNormal(); - setColor(-1,-1); + setColor(fc::Default, fc::Default); clrscr(); gotoxy (1,1); print ("---------------\n"); diff --git a/test/term-attributes.cpp b/test/term-attributes.cpp index 002cf016..dc4ffa6f 100644 --- a/test/term-attributes.cpp +++ b/test/term-attributes.cpp @@ -26,13 +26,17 @@ class AttribDlg : public FDialog AttribDlg& operator = (const AttribDlg&); // and operator '=' void adjustSize(); + protected: + friend class AttribDemo; + public: explicit AttribDlg (FWidget* = 0); // constructor ~AttribDlg(); // destructor void onAccel (FAccelEvent*); + void onWheel (FWheelEvent*); void onClose (FCloseEvent*); - void cb_next (FWidget*, void*); - void cb_back (FWidget*, void*); + void cb_next (FWidget* = 0, void* = 0); + void cb_back (FWidget* = 0, void* = 0); }; #pragma pack(pop) @@ -82,6 +86,17 @@ void AttribDlg::onAccel (FAccelEvent* ev) ev->accept(); } +//---------------------------------------------------------------------- +void AttribDlg::onWheel (FWheelEvent* ev) +{ + int wheel = ev->getWheel(); + + if ( wheel == WheelUp ) + cb_next(); + else if ( wheel == WheelDown ) + cb_back(); +} + //---------------------------------------------------------------------- void AttribDlg::onClose (FCloseEvent* ev) { @@ -103,7 +118,7 @@ void AttribDlg::cb_next (FWidget*, void*) return; bgcolor++; if ( bgcolor >= getMaxColor() ) - bgcolor = -1; + bgcolor = fc::Default; redraw(); } @@ -113,7 +128,7 @@ void AttribDlg::cb_back (FWidget*, void*) if ( isMonochron() ) return; bgcolor--; - if ( bgcolor < -1 ) + if ( bgcolor < fc::Default ) bgcolor = short(getMaxColor() - 1); redraw(); } @@ -152,6 +167,10 @@ class AttribDemo : public FWidget explicit AttribDemo (FWidget* = 0); // constructor ~AttribDemo() // destructor { } + void onWheel (FWheelEvent* ev) + { + dynamic_cast(parentWidget())->onWheel(ev); + } }; #pragma pack(pop) @@ -189,9 +208,9 @@ void AttribDemo::printAltCharset() gotoxy (xpos + xmin - 1, ypos + ymin - 1); print("alternate charset: "); - if ( parent->bgcolor == -1 ) + if ( parent->bgcolor == fc::Default ) { - setColor (-1,-1); + setColor (fc::Default, fc::Default); } else { @@ -329,6 +348,7 @@ void AttribDemo::draw() setUpdateVTerm(true); } + //---------------------------------------------------------------------- // main part //---------------------------------------------------------------------- diff --git a/test/timer.cpp b/test/timer.cpp index fbf00991..159675cc 100644 --- a/test/timer.cpp +++ b/test/timer.cpp @@ -28,8 +28,8 @@ timer::timer (FWidget* parent) resetXTermForeground(); resetXTermBackground(); - wc.term_fg = -1; - wc.term_bg = -1; + wc.term_fg = fc::Default; + wc.term_bg = fc::Default; } //---------------------------------------------------------------------- @@ -49,7 +49,7 @@ void timer::onAccel (FAccelEvent* ev) void timer::draw() { setNormal(); - setColor(-1,-1); + setColor (fc::Default, fc::Default); clrscr(); gotoxy (1,1); print ("---------------\n");