summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Persch <chpe@src.gnome.org>2018-03-04 23:22:26 +0100
committerChristian Persch <chpe@src.gnome.org>2018-03-04 23:22:26 +0100
commitcac7b40b507c8ef705c0d7a3c2fee8a4bc3ee6ef (patch)
tree4a6cdda0a3ce439c8d11f174d0ea3894701de118
parentbac521b55ec8df9de486c318094fa3d016b7ec8a (diff)
downloadvte-cac7b40b507c8ef705c0d7a3c2fee8a4bc3ee6ef.tar.gz
emulation: Implement DECRQCRA
This will be used in the test suite later. https://bugzilla.gnome.org/show_bug.cgi?id=745045
-rw-r--r--src/caps-list.hh2
-rw-r--r--src/vte.cc29
-rw-r--r--src/vteinternal.hh5
-rw-r--r--src/vteseq-list.hh1
-rw-r--r--src/vteseq.cc89
5 files changed, 126 insertions, 0 deletions
diff --git a/src/caps-list.hh b/src/caps-list.hh
index cc751916..0528d7bc 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 47fc4c1d..ad762425 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 a58a0056..2d02f8d7 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 1dda4486..af9fc893 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 4da48c49..218bedf4 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.