[vte] emulation: Implement DECRQCRA



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

    emulation: Implement DECRQCRA
    
    This will be used in the test suite later.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=745045

 src/vte.cc         |   43 ++++++++++++++++++-------
 src/vteinternal.hh |    8 ++++-
 src/vteseq.cc      |   89 +++++++++++++++++++++++++++++++++++++++++++++++-----
 3 files changed, 119 insertions(+), 21 deletions(-)
---
diff --git a/src/vte.cc b/src/vte.cc
index ea05d61..8e0f89a 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -4258,20 +4258,10 @@ VteTerminalPrivate::reply(vte::parser::Sequence const& seq,
 void
 VteTerminalPrivate::reply(vte::parser::Sequence const& seq,
                           unsigned int type,
+                          std::initializer_list<int> params,
                           char const* format,
                           ...) noexcept
 {
-        switch (type) {
-        case VTE_SEQ_OSC:
-        case VTE_SEQ_APC:
-        case VTE_SEQ_PM:
-        case VTE_SEQ_SOS:
-                break;
-        default:
-                assert(false);
-                return;
-        }
-
         char buf[128];
         va_list vargs;
         va_start(vargs, format);
@@ -4279,7 +4269,7 @@ VteTerminalPrivate::reply(vte::parser::Sequence const& seq,
         va_end(vargs);
         g_assert_cmpint(len, <, sizeof(buf));
 
-        vte::parser::u8SequenceBuilder builder{type};
+        vte::parser::ReplyBuilder builder{type, params};
         builder.set_string(std::string{buf});
 
         send(seq, builder);
@@ -6020,6 +6010,35 @@ VteTerminalPrivate::get_selected_text(GArray *attributes)
                         attributes);
 }
 
+#ifdef VTE_DEBUG
+unsigned int
+VteTerminalPrivate::checksum_area(vte::grid::row_t start_row,
+                                  vte::grid::column_t start_col,
+                                  vte::grid::row_t end_row,
+                                  vte::grid::column_t end_col)
+{
+        unsigned int checksum = 0;
+
+        auto text = get_text(start_row, start_col, end_row, end_col,
+                             true /* block */, false /* wrap */,
+                             true /* trailing whitespace */,
+                             nullptr /* not interested in attributes */);
+        if (text == nullptr)
+                return checksum;
+
+        char const* end = (char const*)text->str + text->len;
+        for (char const *p = text->str; p < end; p = g_utf8_next_char(p)) {
+                auto const c = g_utf8_get_char(p);
+                if (c == '\n')
+                        continue;
+                checksum += c;
+        }
+        g_string_free(text, true);
+
+        return checksum & 0xffff;
+}
+#endif /* VTE_DEBUG */
+
 /*
  * Compares the visual attributes of a VteCellAttr for equality, but ignores
  * attributes that tend to change from character to character or are otherwise
diff --git a/src/vteinternal.hh b/src/vteinternal.hh
index 781cc19..f6e173a 100644
--- a/src/vteinternal.hh
+++ b/src/vteinternal.hh
@@ -1215,6 +1215,11 @@ public:
         inline void insert_lines(vte::grid::row_t param);
         inline void delete_lines(vte::grid::row_t param);
 
+        unsigned int checksum_area(vte::grid::row_t start_row,
+                                   vte::grid::column_t start_col,
+                                   vte::grid::row_t end_row,
+                                   vte::grid::column_t end_col);
+
         void subscribe_accessible_events();
         void select_text(vte::grid::column_t start_col,
                          vte::grid::row_t start_row,
@@ -1235,8 +1240,9 @@ public:
                    std::initializer_list<int> params) noexcept;
         void reply(vte::parser::Sequence const& seq,
                    unsigned int type,
+                   std::initializer_list<int> params,
                    char const* format,
-                   ...) noexcept G_GNUC_PRINTF(4, 5);
+                   ...) noexcept G_GNUC_PRINTF(5, 6);
 
         /* OSC handlers */
         void set_color(vte::parser::Sequence const& seq,
diff --git a/src/vteseq.cc b/src/vteseq.cc
index 60a30a8..84fd340 100644
--- a/src/vteseq.cc
+++ b/src/vteseq.cc
@@ -245,7 +245,6 @@ VteTerminalPrivate::emit_resize_window(guint columns,
         g_signal_emit(m_terminal, signals[SIGNAL_RESIZE_WINDOW], 0, columns, rows);
 }
 
-
 /* Some common functions */
 
 /* In Xterm, upon printing a character in the last column the cursor doesn't
@@ -1361,7 +1360,7 @@ VteTerminalPrivate::set_color(vte::parser::Sequence const& seq,
                         auto c = get_color(value);
                         g_assert_nonnull(c);
 
-                        reply(seq, VTE_SEQ_OSC, "4;%d;rgb:%04x/%04x/%04x",
+                        reply(seq, VTE_REPLY_OSC, {}, "4;%d;rgb:%04x/%04x/%04x",
                               value, c->red, c->green, c->blue);
                 } else {
                         vte::color::rgb color;
@@ -1398,7 +1397,7 @@ VteTerminalPrivate::set_special_color(vte::parser::Sequence const& seq,
                         c = get_color(index_fallback);
                 g_assert_nonnull(c);
 
-                reply(seq, VTE_SEQ_OSC, "%d;rgb:%04x/%04x/%04x",
+                reply(seq, VTE_REPLY_OSC, {}, "%d;rgb:%04x/%04x/%04x",
                       osc, c->red, c->green, c->blue);
         } else {
                 vte::color::rgb color;
@@ -2777,10 +2776,84 @@ void
 VteTerminalPrivate::DECRQCRA(vte::parser::Sequence const& seq)
 {
         /*
-         * DECRQCRA - request-checksum-of-rectangular-area
+         * DECRQCRA - request checksum of rectangular area
+         * Computes a simple checksum of the characters in the rectangular
+         * area. args[0] is an identifier, which the response must use.
+         * args[1] is the page number; if it's 0 or default then the
+         * checksum is computed over all pages; if it's greater than the
+         * number of pages, then the checksum is computed only over the
+         * last page. args[2]..args[5] describe the area to compute the
+         * checksum from, denoting the top, left, bottom, right, resp
+         * (1-based). It's required that top ≤ bottom, and left ≤ right.
+         * These coordinates are interpreted according to origin mode.
          *
-         * Probably not worth implementing.
+         * NOTE: Since this effectively allows to read the screen
+         * (by using a 1x1 rectangle on each cell), we normally only
+         * send a dummy reply, and only reply with the actual checksum
+         * when in test mode.
+         *
+         * Defaults:
+         *   args[0]: no default
+         *   args[1]: 0
+         *   args[2]: 1
+         *   args[3]: no default (?)
+         *   args[4]: height of current page
+         *   args[5]: width of current page
+         *
+         * Reply: DECCKSR
+         *   @args[0]: the identifier from the request
+         *   DATA: the checksum as a 4-digit hex number
+         *
+         * References: VT525
+         *             XTERM
          */
+
+        unsigned int idx = 0;
+        int id = seq.collect1(idx);
+
+#ifndef VTE_DEBUG
+        /* Send a dummy reply */
+        return reply(seq, VTE_REPLY_DECCKSR, {id}, "0000");
+#else
+
+        /* Not in test mode? Send a dummy reply */
+        if (!g_test_mode) {
+                return reply(seq, VTE_REPLY_DECCKSR, {id}, "0000");
+        }
+
+        idx = seq.next(idx);
+
+        /* We only support 1 'page', so ignore args[1] */
+        idx = seq.next(idx);
+
+        int top = seq.collect1(idx, 1, 1, m_row_count);
+        idx = seq.next(idx);
+        int left = seq.collect1(idx, 1, 1, m_column_count); /* use 1 as default here */
+        idx = seq.next(idx);
+        int bottom = seq.collect1(idx, m_row_count, 1, m_row_count);
+        idx = seq.next(idx);
+        int right = seq.collect1(idx, m_column_count, 1, m_column_count);
+
+        if (m_modes_private.DEC_ORIGIN() &&
+            m_scrolling_restricted) {
+                top += m_scrolling_region.start;
+
+                bottom += m_scrolling_region.start;
+                bottom = std::min(bottom, m_scrolling_region.end);
+
+        }
+
+        unsigned int checksum;
+        if (bottom < top || right < left)
+                checksum = 0; /* empty area */
+        else
+                checksum = checksum_area(top -1 + m_screen->insert_delta,
+                                         left - 1,
+                                         bottom - 1 + m_screen->insert_delta,
+                                         right - 1);
+
+        reply(seq, VTE_REPLY_DECCKSR, {id}, "%04X", checksum);
+#endif /* VTE_DEBUG */
 }
 
 void
@@ -3847,11 +3920,11 @@ VteTerminalPrivate::DSR_DEC(vte::parser::Sequence const& seq)
                 /* Request memory checksum report
                  * Reply: DECCKSR
                  *   @arg[0]: PID
-                 *   DATA: hex encoded
+                 *   DATA: the checksum as a 4-digit hex number
                  *
-                 * Reply with empty DATA.
+                 * Reply with a dummy checksum.
                  */
-                reply(seq, VTE_REPLY_DECCKSR, {seq.collect1(1)});
+                reply(seq, VTE_REPLY_DECCKSR, {seq.collect1(1)}, "0000");
                 break;
 
         case 75:


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