[vte] emulation: Implement DECRQCRA



commit cac7b40b507c8ef705c0d7a3c2fee8a4bc3ee6ef
Author: Christian Persch <chpe src gnome org>
Date:   Sun Mar 4 23:22:26 2018 +0100

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

 src/caps-list.hh   |    2 +
 src/vte.cc         |   29 +++++++++++++++++
 src/vteinternal.hh |    5 +++
 src/vteseq-list.hh |    1 +
 src/vteseq.cc      |   89 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 126 insertions(+), 0 deletions(-)
---
diff --git a/src/caps-list.hh b/src/caps-list.hh
index cc75191..0528d7b 100644
--- a/src/caps-list.hh
+++ b/src/caps-list.hh
@@ -294,6 +294,8 @@ static const vte_matcher_entry_t entries[] = {
         ENTRY(OSC "2L;%s" BEL, set_text_property_2L),
         ENTRY(OSC "21;%s" ST, set_text_property_21),
         ENTRY(OSC "2L;%s" ST, set_text_property_2L),
+
+        ENTRY(CSI "%m*y", checksum_rectangular_area),
 };
 
 #undef ENTRY
diff --git a/src/vte.cc b/src/vte.cc
index 47fc4c1..ad76242 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -6156,6 +6156,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 a58a005..2d02f8d 100644
--- a/src/vteinternal.hh
+++ b/src/vteinternal.hh
@@ -1356,6 +1356,11 @@ public:
                                          int osc,
                                          char const *terminator);
 
+        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,
diff --git a/src/vteseq-list.hh b/src/vteseq-list.hh
index 1dda448..af9fc89 100644
--- a/src/vteseq-list.hh
+++ b/src/vteseq-list.hh
@@ -1,3 +1,4 @@
+SEQUENCE_HANDLER(checksum_rectangular_area)
 SEQUENCE_HANDLER(ansi_conformance_level_1)
 SEQUENCE_HANDLER(ansi_conformance_level_2)
 SEQUENCE_HANDLER(ansi_conformance_level_3)
diff --git a/src/vteseq.cc b/src/vteseq.cc
index 4da48c4..218bedf 100644
--- a/src/vteseq.cc
+++ b/src/vteseq.cc
@@ -189,6 +189,95 @@ VteTerminalPrivate::emit_resize_window(guint columns,
 
 /* Some common functions */
 
+void
+VteTerminalPrivate::seq_checksum_rectangular_area(vte::parser::Params const& params)
+{
+        /*
+         * 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.
+         *
+         * 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
+         */
+
+        char buf[32];
+        gsize len;
+
+        int id = params.number_or_default_at(0, 0);
+
+#ifndef VTE_DEBUG
+        /* Send a dummy reply */
+        len = g_snprintf(buf, sizeof(buf), "\eP%d!~%04X\e\\", id, 0);
+        feed_child(buf, len);
+#else
+
+        /* Not in test mode? Send a dummy reply */
+        if (!g_test_mode) {
+                len = g_snprintf(buf, sizeof(buf), "\eP%d!~%04X\e\\", id, 0);
+                feed_child(buf, len);
+                return;
+        }
+
+        /* We only support 1 'page', so ignore args[1] */
+
+        int top = params.number_or_default_at(2, 1);
+        int left = params.number_or_default_at(3, 1); /* use 1 as default here */
+        int bottom = params.number_or_default_at(4, m_row_count);
+        int right = params.number_or_default_at(5, m_column_count);
+
+        top = CLAMP(top, 1, m_row_count);
+        left = CLAMP(left, 1, m_column_count);
+        bottom = CLAMP(bottom, 1, m_row_count);
+        right = CLAMP (right, 1, m_column_count);
+
+        if (m_origin_mode &&
+            m_scrolling_restricted) {
+                top += m_scrolling_region.start;
+
+                bottom += m_scrolling_region.start;
+                bottom = 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);
+
+        len = g_snprintf(buf, sizeof(buf), "\eP%d!~%04X\e\\", id, checksum);
+        feed_child(buf, len);
+#endif /* VTE_DEBUG */
+}
+
 /* In Xterm, upon printing a character in the last column the cursor doesn't
  * advance.  It's special cased that printing the following letter will first
  * wrap to the next row.


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