[vte] emulation: Implement OSC 5



commit 32243017bc520c512eaca79d7664ef5654c9f180
Author: Christian Persch <chpe src gnome org>
Date:   Tue Mar 27 19:40:13 2018 +0200

    emulation: Implement OSC 5
    
    https://bugzilla.gnome.org/show_bug.cgi?id=722751

 src/vteinternal.hh |   18 +++++-
 src/vteseq.cc      |  155 ++++++++++++++++++++++++++++++++++++----------------
 src/vtetypes.hh    |    4 +
 3 files changed, 127 insertions(+), 50 deletions(-)
---
diff --git a/src/vteinternal.hh b/src/vteinternal.hh
index 14e1bfe..a7bfeea 100644
--- a/src/vteinternal.hh
+++ b/src/vteinternal.hh
@@ -1295,10 +1295,23 @@ public:
                    char const* format,
                    ...) noexcept G_GNUC_PRINTF(5, 6);
 
+        /* OSC handler helpers */
+        bool get_osc_color_index(int osc,
+                                 int value,
+                                 int& index) const noexcept;
+        bool set_color_index(vte::parser::Sequence const& seq,
+                             vte::parser::StringTokeniser::const_iterator& token,
+                             vte::parser::StringTokeniser::const_iterator const& endtoken,
+                             int number,
+                             int index,
+                             int index_fallback,
+                             int osc) noexcept;
+
         /* OSC handlers */
         void set_color(vte::parser::Sequence const& seq,
                        vte::parser::StringTokeniser::const_iterator& token,
-                       vte::parser::StringTokeniser::const_iterator const& endtoken) noexcept;
+                       vte::parser::StringTokeniser::const_iterator const& endtoken,
+                       int osc) noexcept;
         void set_special_color(vte::parser::Sequence const& seq,
                                vte::parser::StringTokeniser::const_iterator& token,
                                vte::parser::StringTokeniser::const_iterator const& endtoken,
@@ -1307,7 +1320,8 @@ public:
                                int osc) noexcept;
         void reset_color(vte::parser::Sequence const& seq,
                          vte::parser::StringTokeniser::const_iterator& token,
-                         vte::parser::StringTokeniser::const_iterator const& endtoken) noexcept;
+                         vte::parser::StringTokeniser::const_iterator const& endtoken,
+                         int osc) noexcept;
         void set_current_directory_uri(vte::parser::Sequence const& seq,
                                        vte::parser::StringTokeniser::const_iterator& token,
                                        vte::parser::StringTokeniser::const_iterator const& endtoken) 
noexcept;
diff --git a/src/vteseq.cc b/src/vteseq.cc
index e527b08..43a87d1 100644
--- a/src/vteseq.cc
+++ b/src/vteseq.cc
@@ -1339,10 +1339,46 @@ VteTerminalPrivate::delete_lines(vte::grid::row_t param)
         m_text_deleted_flag = TRUE;
 }
 
+bool
+VteTerminalPrivate::get_osc_color_index(int osc,
+                                        int value,
+                                        int& index) const noexcept
+{
+        if (value < 0)
+                return false;
+
+        if (osc == VTE_OSC_XTERM_SET_COLOR ||
+            osc == VTE_OSC_XTERM_RESET_COLOR) {
+                if (value < VTE_DEFAULT_FG) {
+                        index = value;
+                        return true;
+                }
+
+                index = value - VTE_DEFAULT_FG;
+        } else {
+                index = value;
+        }
+
+        /* Translate OSC 5 numbers to color index.
+         *
+         * We return -1 for known but umimplemented special colors
+         * so that we can send a dummy reply when queried.
+         */
+        switch (index) {
+        case 0: index = VTE_BOLD_FG; return true; /* Bold */
+        case 1: index = -1; return true; /* Underline */
+        case 2: index = -1; return true; /* Blink */
+        case 3: index = -1; return true; /* Reverse */
+        case 4: index = -1; return true; /* Italic */
+        default: return false;
+        }
+}
+
 void
 VteTerminalPrivate::set_color(vte::parser::Sequence const& seq,
                               vte::parser::StringTokeniser::const_iterator& token,
-                              vte::parser::StringTokeniser::const_iterator const& endtoken) noexcept
+                              vte::parser::StringTokeniser::const_iterator const& endtoken,
+                              int osc) noexcept
 {
         bool any_changed = false;
 
@@ -1353,80 +1389,101 @@ VteTerminalPrivate::set_color(vte::parser::Sequence const& seq,
                 if (++token == endtoken)
                         break;
 
+                int index;
                 if (!has_value ||
-                    value < 0 ||
-                    value >= VTE_DEFAULT_FG) {
+                    !get_osc_color_index(osc, value, index)) {
                         ++token;
                         continue;
                 }
 
-                auto const str = *token;
-
-                if (str == "?"s) {
-                        auto c = get_color(value);
-                        g_assert_nonnull(c);
-
-                        reply(seq, VTE_REPLY_OSC, {}, "4;%d;rgb:%04x/%04x/%04x",
-                              value, c->red, c->green, c->blue);
-                } else {
-                        vte::color::rgb color;
-                        if (color.parse(str.data())) {
-                                set_color(value, VTE_COLOR_SOURCE_ESCAPE, color);
-                                any_changed = true;
-                        }
-                }
-
+                any_changed |= set_color_index(seq, token, endtoken, value, index, -1, osc);
                 ++token;
         }
 
         /* emit the refresh as the palette has changed and previous
-         * renders need to be updated. */
+         * renders need to be updated.
+         */
         if (any_changed)
                 emit_refresh_window();
 }
 
-void
-VteTerminalPrivate::set_special_color(vte::parser::Sequence const& seq,
-                                      vte::parser::StringTokeniser::const_iterator& token,
-                                      vte::parser::StringTokeniser::const_iterator const& endtoken,
-                                      int index,
-                                      int index_fallback,
-                                      int osc)
+bool
+VteTerminalPrivate::set_color_index(vte::parser::Sequence const& seq,
+                                    vte::parser::StringTokeniser::const_iterator& token,
+                                    vte::parser::StringTokeniser::const_iterator const& endtoken,
+                                    int number,
+                                    int index,
+                                    int index_fallback,
+                                    int osc)
 {
-        if (token == endtoken)
-                return;
+        bool palette_changed = false;
 
         auto const str = *token;
+
         if (str == "?"s) {
-                auto c = get_color(index);
-                if (c == nullptr && index_fallback != -1)
-                        c = get_color(index_fallback);
-                g_assert_nonnull(c);
+                vte::color::rgb color{0, 0, 0};
+                if (index != -1) {
+                        auto const* c = get_color(index);
+                        if (c == nullptr && index_fallback != -1)
+                                c = get_color(index_fallback);
+                        if (c != nullptr)
+                                color = *c;
+                }
 
-                reply(seq, VTE_REPLY_OSC, {}, "%d;rgb:%04x/%04x/%04x",
-                      osc, c->red, c->green, c->blue);
+                if (number != -1)
+                        reply(seq, VTE_REPLY_OSC, {}, "%d;%d;rgb:%04x/%04x/%04x",
+                              osc, number, color.red, color.green, color.blue);
+                else
+                        reply(seq, VTE_REPLY_OSC, {}, "%d;rgb:%04x/%04x/%04x",
+                              osc, color.red, color.green, color.blue);
         } else {
                 vte::color::rgb color;
-                if (color.parse(str.data())) {
+
+                if (index != -1 &&
+                    color.parse(str.data())) {
                         set_color(index, VTE_COLOR_SOURCE_ESCAPE, color);
 
-                        /* emit the refresh as the palette has changed and previous
-                         * renders need to be updated. */
-                        emit_refresh_window();
+                        palette_changed = true;
                 }
         }
+
+        return palette_changed;
+}
+
+void
+VteTerminalPrivate::set_special_color(vte::parser::Sequence const& seq,
+                                      vte::parser::StringTokeniser::const_iterator& token,
+                                      vte::parser::StringTokeniser::const_iterator const& endtoken,
+                                      int index,
+                                      int index_fallback,
+                                      int osc) noexcept
+{
+        if (token == endtoken)
+                return;
+
+        /* emit the refresh as the palette has changed and previous
+         * renders need to be updated.
+         */
+        if (set_color_index(seq, token, endtoken, -1, index, index_fallback, osc))
+                emit_refresh_window();
 }
 
 void
 VteTerminalPrivate::reset_color(vte::parser::Sequence const& seq,
                                 vte::parser::StringTokeniser::const_iterator& token,
-                                vte::parser::StringTokeniser::const_iterator const& endtoken) noexcept
+                                vte::parser::StringTokeniser::const_iterator const& endtoken,
+                                int osc) noexcept
 {
         /* Empty param? Reset all */
         if (token == endtoken ||
             token.size_remaining() == 0) {
-                for (unsigned int idx = 0; idx < VTE_DEFAULT_FG; idx++)
-                        reset_color(idx, VTE_COLOR_SOURCE_ESCAPE);
+                if (osc == VTE_OSC_XTERM_RESET_COLOR) {
+                        for (unsigned int idx = 0; idx < VTE_DEFAULT_FG; idx++)
+                                reset_color(idx, VTE_COLOR_SOURCE_ESCAPE);
+                }
+
+                reset_color(VTE_BOLD_FG, VTE_COLOR_SOURCE_ESCAPE);
+                /* Add underline/blink/reverse/italic here if/when implemented */
 
                 /* emit the refresh as the palette has changed and previous
                  * renders need to be updated. */
@@ -1441,8 +1498,10 @@ VteTerminalPrivate::reset_color(vte::parser::Sequence const& seq,
                 if (!token.number(value))
                         continue;
 
-                if (0 <= value && value < VTE_DEFAULT_FG) {
-                        reset_color(value, VTE_COLOR_SOURCE_ESCAPE);
+                int index;
+                if (get_osc_color_index(osc, value, index) &&
+                    index != -1) {
+                        reset_color(index, VTE_COLOR_SOURCE_ESCAPE);
                         any_changed = true;
                 }
 
@@ -6261,7 +6320,8 @@ VteTerminalPrivate::OSC(vte::parser::Sequence const& seq)
         }
 
         case VTE_OSC_XTERM_SET_COLOR:
-                set_color(seq, it, cend);
+        case VTE_OSC_XTERM_SET_COLOR_SPECIAL:
+                set_color(seq, it, cend, osc);
                 break;
 
         case VTE_OSC_XTERM_SET_COLOR_TEXT_FG:
@@ -6285,7 +6345,8 @@ VteTerminalPrivate::OSC(vte::parser::Sequence const& seq)
                 break;
 
         case VTE_OSC_XTERM_RESET_COLOR:
-                reset_color(seq, it, cend);
+        case VTE_OSC_XTERM_RESET_COLOR_SPECIAL:
+                reset_color(seq, it, cend, osc);
                 break;
 
         case VTE_OSC_XTERM_RESET_COLOR_TEXT_FG:
@@ -6310,7 +6371,6 @@ VteTerminalPrivate::OSC(vte::parser::Sequence const& seq)
 
         case VTE_OSC_XTERM_SET_ICON_TITLE:
         case VTE_OSC_XTERM_SET_XPROPERTY:
-        case VTE_OSC_XTERM_SET_COLOR_SPECIAL:
         case VTE_OSC_XTERM_SET_COLOR_MOUSE_CURSOR_FG:
         case VTE_OSC_XTERM_SET_COLOR_MOUSE_CURSOR_BG:
         case VTE_OSC_XTERM_SET_COLOR_TEK_FG:
@@ -6319,7 +6379,6 @@ VteTerminalPrivate::OSC(vte::parser::Sequence const& seq)
         case VTE_OSC_XTERM_LOGFILE:
         case VTE_OSC_XTERM_SET_FONT:
         case VTE_OSC_XTERM_SET_XSELECTION:
-        case VTE_OSC_XTERM_RESET_COLOR_SPECIAL:
         case VTE_OSC_XTERM_SET_COLOR_MODE:
         case VTE_OSC_XTERM_RESET_COLOR_MOUSE_CURSOR_FG:
         case VTE_OSC_XTERM_RESET_COLOR_MOUSE_CURSOR_BG:
diff --git a/src/vtetypes.hh b/src/vtetypes.hh
index 9551208..885c2fb 100644
--- a/src/vtetypes.hh
+++ b/src/vtetypes.hh
@@ -21,6 +21,8 @@
 #include <gdk/gdk.h>
 #include <errno.h>
 
+#include <cstdint>
+
 #ifdef VTE_DEBUG
 #define IFDEF_DEBUG(str) str
 #else
@@ -153,6 +155,8 @@ namespace color {
                 rgb(PangoColor const& c) { *static_cast<PangoColor*>(this) = c; }
                 rgb(GdkRGBA const* c);
                 rgb(GdkRGBA const& c) : rgb(&c) { }
+                rgb(uint16_t r, uint16_t g, uint16_t b)
+                        : PangoColor{r, g, b} { }
 
                 bool parse(char const* spec);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]