[vte] parser: Improve glue for subparameters



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

    parser: Improve glue for subparameters
    
    ... and use it to parse SGR with subparameters.

 src/parser-arg.hh  |    8 +-
 src/parser-glue.hh |  178 +++++++++++++++++--
 src/parser-test.cc |   84 ++++++++-
 src/vteinternal.hh |    6 +-
 src/vteseq-list.hh |    1 -
 src/vteseq.cc      |  520 ++++++++++++++++++----------------------------------
 6 files changed, 426 insertions(+), 371 deletions(-)
---
diff --git a/src/parser-arg.hh b/src/parser-arg.hh
index 87d9343..ead82f0 100644
--- a/src/parser-arg.hh
+++ b/src/parser-arg.hh
@@ -152,10 +152,12 @@ static constexpr inline int vte_seq_arg_nonfinal(vte_seq_arg_t arg)
 /*
  * vte_seq_arg_value:
  * @arg:
+ * @default_value: (defaults to -1)
  *
- * Returns: the value of @arg, or -1 if @arg has default value
+ * Returns: the value of @arg, or @default_value if @arg has default value
  */
-static constexpr inline int vte_seq_arg_value(vte_seq_arg_t arg)
+static constexpr inline int vte_seq_arg_value(vte_seq_arg_t arg,
+                                              int default_value = -1)
 {
-        return (arg & VTE_SEQ_ARG_FLAG_VALUE) ? (arg & VTE_SEQ_ARG_VALUE_MASK) : -1;
+        return (arg & VTE_SEQ_ARG_FLAG_VALUE) ? (arg & VTE_SEQ_ARG_VALUE_MASK) : default_value;
 }
diff --git a/src/parser-glue.hh b/src/parser-glue.hh
index c06bf19..5a48887 100644
--- a/src/parser-glue.hh
+++ b/src/parser-glue.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2017 Christian Persch
+ * Copyright © 2017, 2018 Christian Persch
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -17,6 +17,9 @@
 
 #pragma once
 
+#include <cstdint>
+#include <algorithm>
+
 #include "parser.hh"
 
 namespace vte {
@@ -28,29 +31,180 @@ public:
 
         typedef int number;
 
-        char* ucs4_to_utf8(gunichar const* str) const;
+        char* ucs4_to_utf8(gunichar const* str) const noexcept;
 
-        void print() const;
+        void print() const noexcept;
 
-        inline unsigned int type() const { return m_seq->type; }
+        /* type:
+         *
+         *
+         * Returns: the type of the sequence, a value from the VTE_SEQ_* enum
+         */
+        inline constexpr unsigned int type() const noexcept
+        {
+                return m_seq->type;
+        }
 
-        inline unsigned int command() const { return m_seq->command; }
+        /* command:
+         *
+         * Returns: the command the sequence codes for, a value
+         *   from the VTE_CMD_* enum, or %VTE_CMD_NONE if the command is
+         *   unknown
+         */
+        inline constexpr unsigned int command() const noexcept
+        {
+                return m_seq->command;
+        }
 
-        inline unsigned int charset() const { return m_seq->charset; }
+        /* charset:
+         *
+         * This is the charset to use in a %VTE_CMD_GnDm, %VTE_CMD_GnDMm,
+         * %VTE_CMD_CnD or %VTE_CMD_DOCS command.
+         *
+         * Returns: the charset, a value from the VTE_CHARSET_* enum.
+         */
+        inline constexpr unsigned int charset() const noexcept
+        {
+                return m_seq->charset;
+        }
 
-        inline unsigned int intermediates() const { return m_seq->intermediates; }
+        /* intermediates:
+         *
+         * The intermediate bytes of the ESCAPE, CSI or DCS sequence.
+         *
+         * Returns: the immediates as flag values from the VTE_SEQ_FLAG_* enum
+         */
+        inline constexpr unsigned int intermediates() const noexcept
+        {
+                return m_seq->intermediates;
+        }
 
-        inline uint32_t terminator() const { return m_seq->terminator; }
+        /* terminator:
+         *
+         * This is the character terminating the sequence, or, for a
+         * %VTE_SEQ_GRAPHIC sequence, the graphic character.
+         *
+         * Returns: the terminating character
+         */
+        inline constexpr uint32_t terminator() const noexcept
+        {
+                return m_seq->terminator;
+        }
 
-        inline unsigned int size() const
+        /* size:
+         *
+         * Returns: the number of parameters
+         */
+        inline constexpr unsigned int size() const noexcept
         {
-                g_assert_nonnull(m_seq);
                 return m_seq->n_args;
         }
 
-        inline int operator[](int position) const
+
+        /* size:
+         *
+         * Returns: the number of parameter blocks, counting runs of subparameters
+         *   as only one parameter
+         */
+        inline constexpr unsigned int size_final() const noexcept
+        {
+                return m_seq->n_final_args;
+        }
+
+        /* capacity:
+         *
+         * Returns: the number of parameter blocks, counting runs of subparameters
+         *   as only one parameter
+         */
+        inline constexpr unsigned int capacity() const noexcept
+        {
+                return G_N_ELEMENTS(m_seq->args);
+        }
+
+        /* param:
+         * @idx:
+         * @default_v: the value to use for default parameters
+         *
+         * Returns: the value of the parameter at index @idx, or @default_v if
+         *   the parameter at this index has default value, or the index
+         *   is out of bounds
+         */
+        inline constexpr int param(unsigned int idx,
+                                   int default_v = -1) const noexcept
+        {
+                return __builtin_expect(idx < size(), 1) ? vte_seq_arg_value(m_seq->args[idx], default_v) : 
default_v;
+        }
+
+        /* param:
+         * @idx:
+         * @default_v: the value to use for default parameters
+         * @min_v: the minimum value
+         * @max_v: the maximum value
+         *
+         * Returns: the value of the parameter at index @idx, or @default_v if
+         *   the parameter at this index has default value, or the index
+         *   is out of bounds. The returned value is clamped to the
+         *   range @min_v..@max_v.
+         */
+        inline constexpr int param(unsigned int idx,
+                                   int default_v,
+                                   int min_v,
+                                   int max_v) const noexcept
+        {
+                auto v = param(idx, default_v);
+                return std::min(std::max(v, min_v), max_v);
+        }
+
+        /* param_nonfinal:
+         * @idx:
+         *
+         * Returns: whether the parameter at @idx is nonfinal, i.e.
+         * there are more subparameters after it.
+         */
+        inline constexpr bool param_nonfinal(unsigned int idx) const noexcept
+        {
+                return __builtin_expect(idx < size(), 1) ? vte_seq_arg_nonfinal(m_seq->args[idx]) : false;
+        }
+
+        /* param_default:
+         * @idx:
+         *
+         * Returns: whether the parameter at @idx has default value
+         */
+        inline constexpr bool param_default(unsigned int idx) const noexcept
+        {
+                return __builtin_expect(idx < size(), 1) ? vte_seq_arg_default(m_seq->args[idx]) : true;
+        }
+
+        /* next:
+         * @idx:
+         *
+         * Returns: the index of the next parameter block
+         */
+        inline constexpr unsigned int next(unsigned int idx) const noexcept
+        {
+                /* Find the final parameter */
+                while (param_nonfinal(idx))
+                        ++idx;
+                /* And return the index after that one */
+                return ++idx;
+        }
+
+        inline constexpr unsigned int cbegin() const noexcept
+        {
+                return 0;
+        }
+
+        inline constexpr unsigned int cend() const noexcept
+        {
+                return size();
+        }
+
+
+        //FIMXE remove this one
+        inline constexpr int operator[](int position) const
         {
-                return G_LIKELY(position < (int)size()) ? vte_seq_arg_value(m_seq->args[position]) : -1;
+                return __builtin_expect(position < (int)size(), 1) ? 
vte_seq_arg_value(m_seq->args[position]) : -1;
         }
 
         inline bool has_number_at_unchecked(unsigned int position) const
diff --git a/src/parser-test.cc b/src/parser-test.cc
index 649fd4e..a207675 100644
--- a/src/parser-test.cc
+++ b/src/parser-test.cc
@@ -28,6 +28,7 @@
 #include <glib.h>
 
 #include "parser.hh"
+#include "parser-glue.hh"
 #include "parser-charset-tables.hh"
 
 static struct vte_parser* parser;
@@ -795,21 +796,29 @@ test_seq_csi(void)
 }
 
 static void
-test_seq_csi_param(char const* str,
-                   std::vector<int> args,
-                   std::vector<bool> args_nonfinal)
+test_seq_parse(char const* str,
+               struct vte_seq** seq)
 {
-        g_assert_cmpuint(args.size(), ==, args_nonfinal.size());
-
         std::u32string s;
         s.push_back(0x9B); /* CSI */
         for (unsigned int i = 0; str[i]; i++)
                 s.push_back(str[i]);
         s.push_back(0x6d); /* m = SGR */
 
-        struct vte_seq* seq;
-        auto rv = feed_parser(s, &seq);
+        vte_parser_reset(parser);
+        auto rv = feed_parser(s, seq);
         g_assert_cmpint(rv, ==, VTE_SEQ_CSI);
+}
+
+static void
+test_seq_csi_param(char const* str,
+                   std::vector<int> args,
+                   std::vector<bool> args_nonfinal)
+{
+        g_assert_cmpuint(args.size(), ==, args_nonfinal.size());
+
+        struct vte_seq* seq;
+        test_seq_parse(str, &seq);
 
         if (seq->n_args < VTE_PARSER_ARG_MAX)
                 g_assert_cmpuint(seq->n_args, ==, args.size());
@@ -855,6 +864,66 @@ test_seq_csi_param(void)
 
 }
 
+static void
+test_seq_glue(char const* str,
+              unsigned int n_args,
+              unsigned int n_final_args,
+              vte::parser::Sequence& seq)
+{
+        test_seq_parse(str, seq.seq_ptr());
+
+        auto raw_seq = *seq.seq_ptr();
+        g_assert_cmpuint(seq.size(), ==, n_args);
+        g_assert_cmpuint(raw_seq->n_args, ==, n_args);
+        g_assert_cmpuint(seq.size_final(), ==, n_final_args);
+        g_assert_cmpuint(raw_seq->n_final_args, ==, n_final_args);
+
+        g_assert_cmpuint(seq.type(), ==, raw_seq->type);
+        g_assert_cmpuint(seq.command(), ==, raw_seq->command);
+        g_assert_cmpuint(seq.terminator(), ==, raw_seq->terminator);
+        g_assert_cmpuint(seq.intermediates(), ==, raw_seq->intermediates);
+
+        for (unsigned int i = 0; i < raw_seq->n_args; i++)
+                g_assert_cmpuint(seq.param(i), ==, vte_seq_arg_value(raw_seq->args[i]));
+}
+
+static void
+test_seq_glue(void)
+{
+        vte::parser::Sequence seq{};
+
+        test_seq_glue(":0:1000;2;:", 6, 3, seq);
+        g_assert_cmpuint(seq.cbegin(), ==, 0);
+        g_assert_cmpuint(seq.cend(), ==, 6);
+
+        auto it = seq.cbegin();
+        g_assert_cmpuint(it, ==, 0);
+        it = seq.next(it);
+        g_assert_cmpuint(it, ==,  3);
+        it = seq.next(it);
+        g_assert_cmpuint(it, ==, 4);
+        it = seq.next(it);
+        g_assert_cmpuint(it, ==, 6);
+
+        it = seq.cbegin();
+        g_assert_cmpint(seq.param(it++), ==, -1);
+        g_assert_cmpint(seq.param(it++), ==, 0);
+        g_assert_cmpint(seq.param(it++), ==, 1000);
+        g_assert_cmpint(seq.param(it++), ==, 2);
+        g_assert_cmpint(seq.param(it++), ==, -1);
+        g_assert_cmpint(seq.param(it++), ==, -1);
+        g_assert_cmpint(it, ==, seq.cend());
+
+        it = seq.cbegin();
+        g_assert_cmpint(seq.param(it, -2), ==, -2);
+        g_assert_cmpint(seq.param(it, -2, 0, 100), ==, 0);
+        it++; it++;
+        g_assert_cmpint(seq.param(it, -2), ==, seq.param(it));
+        g_assert_cmpint(seq.param(it, -2, 20, 100), ==, 100);
+        g_assert_cmpint(seq.param(it, -2, 200, 2000), ==, 1000);
+        g_assert_cmpint(seq.param(it, -2, 2000, 4000), ==, 2000);
+}
+
 int
 main(int argc,
      char* argv[])
@@ -865,6 +934,7 @@ main(int argc,
                 return 1;
 
         g_test_add_func("/vte/parser/sequences/arg", test_seq_arg);
+        g_test_add_func("/vte/parser/sequences/glue", test_seq_glue);
         g_test_add_func("/vte/parser/sequences/control", test_seq_control);
         g_test_add_func("/vte/parser/sequences/escape/invalid", test_seq_esc_invalid);
         g_test_add_func("/vte/parser/sequences/escape/charset/94", test_seq_esc_charset_94);
diff --git a/src/vteinternal.hh b/src/vteinternal.hh
index d529376..d23f6c7 100644
--- a/src/vteinternal.hh
+++ b/src/vteinternal.hh
@@ -1213,9 +1213,9 @@ public:
         inline void insert_blank_character();
 
         template<unsigned int redbits, unsigned int greenbits, unsigned int bluebits>
-        inline int32_t parse_sgr_38_48_parameters(vte::parser::Params const& params,
-                                                  unsigned int *index,
-                                                  bool might_contain_color_space_id);
+        inline bool seq_parse_sgr_color(vte::parser::Sequence const& seq,
+                                        unsigned int& idx,
+                                        uint32_t& color) const noexcept;
 
         inline void move_cursor_backward(vte::grid::column_t columns);
         inline void move_cursor_forward(vte::grid::column_t columns);
diff --git a/src/vteseq-list.hh b/src/vteseq-list.hh
index ddc666b..4393cb1 100644
--- a/src/vteseq-list.hh
+++ b/src/vteseq-list.hh
@@ -30,7 +30,6 @@ SEQUENCE_HANDLER(change_tek_cursor_color_bel)
 SEQUENCE_HANDLER(change_tek_cursor_color_st)
 SEQUENCE_HANDLER(change_tek_foreground_color_bel)
 SEQUENCE_HANDLER(change_tek_foreground_color_st)
-SEQUENCE_HANDLER(character_attributes)
 SEQUENCE_HANDLER(character_position_absolute)
 SEQUENCE_HANDLER(cursor_back_tab)
 SEQUENCE_HANDLER(cursor_backward)
diff --git a/src/vteseq.cc b/src/vteseq.cc
index 38f4aa5..730217a 100644
--- a/src/vteseq.cc
+++ b/src/vteseq.cc
@@ -1786,277 +1786,106 @@ VteTerminalPrivate::seq_vertical_tab(vte::parser::Params const& params)
         line_feed();
 }
 
-/* Parse parameters of SGR 38, 48 or 58, starting at @index within @params.
- * If @might_contain_color_space_id, a true color sequence sequence is started, and after
- * its leading number "2" at least 4 more parameters are present, then there's an (ignored)
- * color_space_id before the three color components. See the comment below in
- * seq_character_attributes() to understand the different accepted formats.
- * Returns the color index, or -1 on error.
- * Increments @index to point to the last consumed parameter (not beyond). */
-
+/*
+ * Parse parameters of SGR 38, 48 or 58, starting at @index within @seq.
+ * Returns %true if @seq contained colour parameters at @index, or %false otherwise.
+ * In each case, @idx is set to last consumed parameter,
+ * and the colour is returned in @color.
+ *
+ * The format looks like:
+ * - 256 color indexed palette:
+ *   - ^[[38:5:INDEXm  (de jure standard: ITU-T T.416 / ISO/IEC 8613-6; we also allow and ignore further 
parameters)
+ *   - ^[[38;5;INDEXm  (de facto standard, understood by probably all terminal emulators that support 256 
colors)
+ * - true colors:
+ *   - ^[[38:2:[id]:RED:GREEN:BLUE[:...]m  (de jure standard: ITU-T T.416 / ISO/IEC 8613-6)
+ *   - ^[[38:2:RED:GREEN:BLUEm             (common misinterpretation of the standard, FIXME: stop supporting 
it at some point)
+ *   - ^[[38;2;RED;GREEN;BLUEm             (de facto standard, understood by probably all terminal emulators 
that support true colors)
+ * See bugs 685759 and 791456 for details.
+ */
 template<unsigned int redbits, unsigned int greenbits, unsigned int bluebits>
-int32_t
-VteTerminalPrivate::parse_sgr_38_48_parameters(vte::parser::Params const& params,
-                                               unsigned int *index,
-                                               bool might_contain_color_space_id)
+bool
+VteTerminalPrivate::seq_parse_sgr_color(vte::parser::Sequence const& seq,
+                                        unsigned int &idx,
+                                        uint32_t& color) const noexcept
 {
-        auto n_params = params.size();
-        if (*index < n_params) {
-                int param0;
-                if (G_UNLIKELY(!params.number_at_unchecked(*index, param0)))
-                        return -1;
+        /* Note that we don't have to check if the index is after the end of
+         * the parameters list, since dereferencing is safe and returns -1.
+         */
 
-               switch (param0) {
+        if (seq.param_nonfinal(idx)) {
+                /* Colon version */
+                switch (seq.param(++idx)) {
                 case 2: {
-                        if (G_UNLIKELY(*index + 3 >= n_params))
-                               return -1;
-                        if (might_contain_color_space_id && *index + 5 <= n_params)
-                               *index += 1;
-
-                        int param1, param2, param3;
-                        if (G_UNLIKELY(!params.number_at_unchecked(*index + 1, param1) ||
-                                       !params.number_at_unchecked(*index + 2, param2) ||
-                                       !params.number_at_unchecked(*index + 3, param3)))
-                                return -1;
-
-                       if (G_UNLIKELY (param1 < 0 || param1 >= 256 || param2 < 0 || param2 >= 256 || param3 
< 0 || param3 >= 256))
-                               return -1;
-                       *index += 3;
-
-                       return VTE_RGB_COLOR(redbits, greenbits, bluebits, param1, param2, param3);
+                        auto const n = seq.next(idx) - idx;
+                        if (n < 4)
+                                return false;
+                        if (n > 4) {
+                                /* Consume a colourspace parameter; it must be default */
+                                if (!seq.param_default(++idx))
+                                        return false;
+                        }
+
+                        int red = seq.param(++idx);
+                        int green = seq.param(++idx);
+                        int blue = seq.param(++idx);
+                        if ((red & 0xff) != red ||
+                            (green & 0xff) != green ||
+                            (blue & 0xff) != blue)
+                                return false;
+
+                        color = VTE_RGB_COLOR(redbits, greenbits, bluebits, red, green, blue);
+                        return true;
                 }
                 case 5: {
-                        int param1;
-                        if (G_UNLIKELY(!params.number_at(*index + 1, param1)))
-                                return -1;
-
-                        if (G_UNLIKELY(param1 < 0 || param1 >= 256))
-                               return -1;
-                       *index += 1;
-                       return param1;
+                        auto const n = seq.next(idx) - idx;
+                        if (n < 2)
+                                return false;
+
+                        int v = seq.param(++idx);
+                        if (v < 0 || v >= 256)
+                                return false;
+
+                        color = (uint32_t)v;
+                        return true;
                 }
-               }
-       }
-       return -1;
-}
+                }
+        } else {
+                /* Semicolon version */
 
-/* Handle ANSI color setting and related stuffs (SGR).
- * @params contains the values split at semicolons, with sub arrays splitting at colons
- * wherever colons were encountered. */
-void
-VteTerminalPrivate::seq_character_attributes(vte::parser::Params const& params)
-{
-       /* Step through each numeric parameter. */
-        auto n_params = params.size();
-        unsigned int i;
-       for (i = 0; i < n_params; i++) {
-               /* If this parameter is an array, it can be a fully colon separated 38 or 48
-                * (see below for details). */
-               if (G_UNLIKELY(params.has_subparams_at_unchecked(i))) {
-                        auto subparams = params.subparams_at_unchecked(i);
-
-                        int param0, param1;
-                        if (G_UNLIKELY(!subparams.number_at(0, param0)))
-                                continue;
+                idx = seq.next(idx);
+                switch (seq.param(idx)) {
+                case 2: {
+                        /* Consume 3 more parameters */
+                        idx = seq.next(idx);
+                        int red = seq.param(idx);
+                        idx = seq.next(idx);
+                        int green = seq.param(idx);
+                        idx = seq.next(idx);
+                        int blue = seq.param(idx);
+
+                        if ((red & 0xff) != red ||
+                            (green & 0xff) != green ||
+                            (blue & 0xff) != blue)
+                                return false;
+
+                        color = VTE_RGB_COLOR(redbits, greenbits, bluebits, red, green, blue);
+                        return true;
+                }
+                case 5: {
+                        /* Consume 1 more parameter */
+                        idx = seq.next(idx);
+                        int v = seq.param(idx);
 
-                        switch (param0) {
-                        case 4:
-                                if (subparams.number_at(1, param1) && param1 >= 0 && param1 <= 3)
-                                        m_defaults.attr.set_underline(param1);
-                                break;
-                        case 38: {
-                                unsigned int index = 1;
-                                auto color = parse_sgr_38_48_parameters<8, 8, 8>(subparams, &index, true);
-                                if (G_LIKELY (color != -1))
-                                        m_defaults.attr.set_fore(color);
-                                break;
-                        }
-                        case 48: {
-                                unsigned int index = 1;
-                                auto color = parse_sgr_38_48_parameters<8, 8, 8>(subparams, &index, true);
-                                if (G_LIKELY (color != -1))
-                                        m_defaults.attr.set_back(color);
-                                break;
-                        }
-                        case 58: {
-                                unsigned int index = 1;
-                                auto color = parse_sgr_38_48_parameters<4, 5, 4>(subparams, &index, true);
-                                if (G_LIKELY (color != -1))
-                                        m_defaults.attr.set_deco(color);
-                                break;
-                        }
-                        }
+                        if ((v & 0xff) != v)
+                                return false;
 
-                       continue;
-               }
-               /* If this parameter is not a number either, skip it. */
-                int param;
-                if (!params.number_at_unchecked(i, param))
-                        continue;
+                        color = (uint32_t)v;
+                        return true;
+                }
+                }
+        }
 
-               switch (param) {
-                case -1:
-               case 0:
-                        reset_default_attributes(false);
-                       break;
-               case 1:
-                        m_defaults.attr.set_bold(true);
-                       break;
-               case 2:
-                        m_defaults.attr.set_dim(true);
-                       break;
-               case 3:
-                        m_defaults.attr.set_italic(true);
-                       break;
-               case 4:
-                        m_defaults.attr.set_underline(1);
-                       break;
-               case 5:
-                        m_defaults.attr.set_blink(true);
-                       break;
-               case 7:
-                        m_defaults.attr.set_reverse(true);
-                       break;
-               case 8:
-                        m_defaults.attr.set_invisible(true);
-                       break;
-               case 9:
-                        m_defaults.attr.set_strikethrough(true);
-                       break;
-                case 21:
-                        m_defaults.attr.set_underline(2);
-                        break;
-               case 22: /* ECMA 48. */
-                        m_defaults.attr.unset(VTE_ATTR_BOLD_MASK | VTE_ATTR_DIM_MASK);
-                       break;
-               case 23:
-                        m_defaults.attr.set_italic(false);
-                       break;
-               case 24:
-                        m_defaults.attr.set_underline(0);
-                       break;
-               case 25:
-                        m_defaults.attr.set_blink(false);
-                       break;
-               case 27:
-                        m_defaults.attr.set_reverse(false);
-                       break;
-               case 28:
-                        m_defaults.attr.set_invisible(false);
-                       break;
-               case 29:
-                        m_defaults.attr.set_strikethrough(false);
-                       break;
-               case 30:
-               case 31:
-               case 32:
-               case 33:
-               case 34:
-               case 35:
-               case 36:
-               case 37:
-                        m_defaults.attr.set_fore(VTE_LEGACY_COLORS_OFFSET + (param - 30));
-                       break;
-               case 38:
-               case 48:
-                case 58:
-               {
-                       /* The format looks like:
-                        * - 256 color indexed palette:
-                         *   - ^[[38:5:INDEXm  (de jure standard: ITU-T T.416 / ISO/IEC 8613-6; we also 
allow and ignore further parameters)
-                         *   - ^[[38;5;INDEXm  (de facto standard, understood by probably all terminal 
emulators that support 256 colors)
-                        * - true colors:
-                         *   - ^[[38:2:[id]:RED:GREEN:BLUE[:...]m  (de jure standard: ITU-T T.416 / ISO/IEC 
8613-6)
-                         *   - ^[[38:2:RED:GREEN:BLUEm             (common misinterpretation of the 
standard, FIXME: stop supporting it at some point)
-                         *   - ^[[38;2;RED;GREEN;BLUEm             (de facto standard, understood by 
probably all terminal emulators that support true colors)
-                         * See bugs 685759 and 791456 for details.
-                         * The colon version was handled above separately.
-                         * This branch here is reached when the separators are semicolons. */
-                       if ((i + 1) < n_params) {
-                                ++i;
-                                int32_t color;
-                                switch (param) {
-                                case 38:
-                                        color = parse_sgr_38_48_parameters<8 ,8 ,8>(params, &i, false);
-                                        if (G_LIKELY (color != -1))
-                                                m_defaults.attr.set_fore(color);
-                                        break;
-                                case 48:
-                                        color = parse_sgr_38_48_parameters<8, 8, 8>(params, &i, false);
-                                        if (G_LIKELY (color != -1))
-                                                m_defaults.attr.set_back(color);
-                                        break;
-                                case 58:
-                                        color = parse_sgr_38_48_parameters<4, 5, 4>(params, &i, false);
-                                        g_printerr("Parsed semicoloned deco colour: %x\n", color);
-                                        if (G_LIKELY (color != -1))
-                                                m_defaults.attr.set_deco(color);
-                                        break;
-                               }
-                       }
-                       break;
-               }
-               case 39:
-                       /* default foreground */
-                        m_defaults.attr.set_fore(VTE_DEFAULT_FG);
-                       break;
-               case 40:
-               case 41:
-               case 42:
-               case 43:
-               case 44:
-               case 45:
-               case 46:
-               case 47:
-                        m_defaults.attr.set_back(VTE_LEGACY_COLORS_OFFSET + (param - 40));
-                       break;
-            /* case 48: was handled above at 38 to avoid code duplication */
-               case 49:
-                       /* default background */
-                        m_defaults.attr.set_back(VTE_DEFAULT_BG);
-                       break;
-                case 53:
-                        m_defaults.attr.set_overline(true);
-                        break;
-                case 55:
-                        m_defaults.attr.set_overline(false);
-                        break;
-             /* case 58: was handled above at 38 to avoid code duplication */
-                case 59:
-                        /* default decoration color, that is, same as the cell's foreground */
-                        m_defaults.attr.set_deco(VTE_DEFAULT_FG);
-                        break;
-               case 90:
-               case 91:
-               case 92:
-               case 93:
-               case 94:
-               case 95:
-               case 96:
-               case 97:
-                        m_defaults.attr.set_fore(VTE_LEGACY_COLORS_OFFSET + (param - 90) +
-                                                 VTE_COLOR_BRIGHT_OFFSET);
-                       break;
-               case 100:
-               case 101:
-               case 102:
-               case 103:
-               case 104:
-               case 105:
-               case 106:
-               case 107:
-                        m_defaults.attr.set_back(VTE_LEGACY_COLORS_OFFSET + (param - 100) +
-                                                 VTE_COLOR_BRIGHT_OFFSET);
-                       break;
-               }
-       }
-       /* If we had no parameters, default to the defaults. */
-       if (i == 0) {
-                reset_default_attributes(false);
-       }
-       /* Save the new colors. */
-        m_color_defaults.attr.copy_colors(m_defaults.attr);
-        m_fill_defaults.attr.copy_colors(m_defaults.attr);
+        return false;
 }
 
 /* Move the cursor to the given column in the top row, 1-based. */
@@ -5598,130 +5427,131 @@ VteTerminalPrivate::SGR(vte::parser::Sequence const& seq)
         /*
          * SGR - select-graphics-rendition
          */
-#if 0
-        struct vte_color *dst;
-        unsigned int i, code;
-        int v;
+        auto const n_params = seq.size();
 
-        if (seq->n_args < 1) {
-                memset(&screen->state.attr, 0, sizeof(screen->state.attr));
-                return 0;
-        }
+       /* If we had no parameters, default to the defaults. */
+       if (n_params == 0) {
+                reset_default_attributes(false);
+                return;
+       }
 
-        for (i = 0; i < seq->n_args; ++i) {
-                v = seq->args[i];
-                switch (v) {
+        for (unsigned int i = 0; i < n_params; i = seq.next(i)) {
+                auto const param = seq.param(i);
+                switch (param) {
+                case -1:
+                case 0:
+                        reset_default_attributes(false);
+                        break;
                 case 1:
-                        screen->state.attr.bold = 1;
+                        m_defaults.attr.set_bold(true);
+                        break;
+                case 2:
+                        m_defaults.attr.set_dim(true);
                         break;
                 case 3:
-                        screen->state.attr.italic = 1;
+                        m_defaults.attr.set_italic(true);
                         break;
-                case 4:
-                        screen->state.attr.underline = 1;
+                case 4: {
+                        unsigned int v = 1;
+                        /* If we have a subparameter, get it */
+                        if (seq.param_nonfinal(i)) {
+                                v = seq.param(i + 1, 1, 0, 3);
+                        }
+                        m_defaults.attr.set_underline(v);
                         break;
+                }
                 case 5:
-                        screen->state.attr.blink = 1;
+                        m_defaults.attr.set_blink(true);
                         break;
                 case 7:
-                        screen->state.attr.inverse = 1;
+                        m_defaults.attr.set_reverse(true);
                         break;
                 case 8:
-                        screen->state.attr.hidden = 1;
+                        m_defaults.attr.set_invisible(true);
                         break;
-                case 22:
-                        screen->state.attr.bold = 0;
+                case 9:
+                        m_defaults.attr.set_strikethrough(true);
+                        break;
+                case 21:
+                        m_defaults.attr.set_underline(2);
+                        break;
+                case 22: /* ECMA 48. */
+                        m_defaults.attr.unset(VTE_ATTR_BOLD_MASK | VTE_ATTR_DIM_MASK);
                         break;
                 case 23:
-                        screen->state.attr.italic = 0;
+                        m_defaults.attr.set_italic(false);
                         break;
                 case 24:
-                        screen->state.attr.underline = 0;
+                        m_defaults.attr.set_underline(0);
                         break;
                 case 25:
-                        screen->state.attr.blink = 0;
+                        m_defaults.attr.set_blink(false);
                         break;
                 case 27:
-                        screen->state.attr.inverse = 0;
+                        m_defaults.attr.set_reverse(false);
                         break;
                 case 28:
-                        screen->state.attr.hidden = 0;
+                        m_defaults.attr.set_invisible(false);
+                        break;
+                case 29:
+                        m_defaults.attr.set_strikethrough(false);
                         break;
                 case 30 ... 37:
-                        screen->state.attr.fg.ccode = v - 30 +
-                                                      VTE_CCODE_BLACK;
+                        m_defaults.attr.set_fore(VTE_LEGACY_COLORS_OFFSET + (param - 30));
                         break;
+                case 38: {
+                        uint32_t fore;
+                        if (G_LIKELY((seq_parse_sgr_color<8, 8, 8>(seq, i, fore))))
+                                m_defaults.attr.set_fore(fore);
+                        break;
+                }
                 case 39:
-                        screen->state.attr.fg.ccode = 0;
+                        /* default foreground */
+                        m_defaults.attr.set_fore(VTE_DEFAULT_FG);
                         break;
                 case 40 ... 47:
-                        screen->state.attr.bg.ccode = v - 40 +
-                                                      VTE_CCODE_BLACK;
+                        m_defaults.attr.set_back(VTE_LEGACY_COLORS_OFFSET + (param - 40));
+                        break;
+                case 48: {
+                        uint32_t back;
+                        if (G_LIKELY((seq_parse_sgr_color<8, 8, 8>(seq, i, back))))
+                                m_defaults.attr.set_back(back);
                         break;
+                }
                 case 49:
-                        screen->state.attr.bg.ccode = 0;
+                        /* default background */
+                        m_defaults.attr.set_back(VTE_DEFAULT_BG);
                         break;
-                case 90 ... 97:
-                        screen->state.attr.fg.ccode = v - 90 +
-                                                      VTE_CCODE_LIGHT_BLACK;
+                case 53:
+                        m_defaults.attr.set_overline(true);
                         break;
-                case 100 ... 107:
-                        screen->state.attr.bg.ccode = v - 100 +
-                                                      VTE_CCODE_LIGHT_BLACK;
+                case 55:
+                        m_defaults.attr.set_overline(false);
                         break;
-                case 38:
-                        /* fallthrough */
-                case 48:
-
-                        if (v == 38)
-                                dst = &screen->state.attr.fg;
-                        else
-                                dst = &screen->state.attr.bg;
-
-                        ++i;
-                        if (i >= seq->n_args)
-                                break;
-
-                        switch (seq->args[i]) {
-                        case 2:
-                                /* 24bit-color support */
-
-                                i += 3;
-                                if (i >= seq->n_args)
-                                        break;
-
-                                dst->ccode = VTE_CCODE_RGB;
-                                dst->red = (seq->args[i - 2] >= 0) ? seq->args[i - 2] : 0;
-                                dst->green = (seq->args[i - 1] >= 0) ? seq->args[i - 1] : 0;
-                                dst->blue = (seq->args[i] >= 0) ? seq->args[i] : 0;
-
-                                break;
-                        case 5:
-                                /* 256-color support */
-
-                                ++i;
-                                if (i >= seq->n_args || seq->args[i] < 0)
-                                        break;
-
-                                dst->ccode = VTE_CCODE_256;
-                                code = seq->args[i];
-                                dst->c256 = code < 256 ? code : 0;
-
-                                break;
-                        }
-
+                case 58: {
+                        uint32_t deco;
+                        if (G_LIKELY((seq_parse_sgr_color<4, 5, 4>(seq, i, deco))))
+                                m_defaults.attr.set_deco(deco);
                         break;
-                case -1:
-                        /* fallthrough */
-                case 0:
-                        memset(&screen->state.attr, 0,
-                               sizeof(screen->state.attr));
+                }
+                case 59:
+                        /* default decoration color, that is, same as the cell's foreground */
+                        m_defaults.attr.set_deco(VTE_DEFAULT_FG);
+                        break;
+                case 90 ... 97:
+                        m_defaults.attr.set_fore(VTE_LEGACY_COLORS_OFFSET + (param - 90) +
+                                                 VTE_COLOR_BRIGHT_OFFSET);
+                        break;
+                case 100 ... 107:
+                        m_defaults.attr.set_back(VTE_LEGACY_COLORS_OFFSET + (param - 100) +
+                                                 VTE_COLOR_BRIGHT_OFFSET);
                         break;
                 }
         }
-#endif
 
-        seq_character_attributes(seq);
+       /* Save the new colors. */
+        m_color_defaults.attr.copy_colors(m_defaults.attr);
+        m_fill_defaults.attr.copy_colors(m_defaults.attr);
 }
 
 void



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