[vte] emulation: Fix cursor handling at right margin



commit 817b6834b579b4ecb6a071729daabc50def931eb
Author: Egmont Koblinger <egmont gmail com>
Date:   Sat Jul 26 14:05:01 2014 +0200

    emulation: Fix cursor handling at right margin
    
    https://bugzilla.gnome.org/show_bug.cgi?id=731155

 src/vteseq.c |   62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 60 insertions(+), 2 deletions(-)
---
diff --git a/src/vteseq.c b/src/vteseq.c
index 9c31c37..2120960 100644
--- a/src/vteseq.c
+++ b/src/vteseq.c
@@ -243,6 +243,28 @@ vte_terminal_emit_resize_window(VteTerminal *terminal,
 
 /* Some common functions */
 
+/* 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.
+ *
+ * As a rule of thumb, escape sequences that move the cursor (e.g. cursor up)
+ * or immediately update the visible contents (e.g. clear in line) disable
+ * this special mode, whereas escape sequences with no immediate visible
+ * effect (e.g. color change) leave this special mode on.  There are
+ * exceptions of course (e.g. scroll up).
+ *
+ * In VTE, a different technical approach is used.  The cursor is advanced to
+ * the invisible column on the right, but it's set back to the visible
+ * rightmost column whenever necessary (that is, before handling any of the
+ * sequences that disable the special cased mode in xterm).  (Bug 731155.)
+ */
+static void
+_vte_terminal_ensure_cursor_is_onscreen (VteTerminal *terminal)
+{
+        if (G_UNLIKELY (terminal->pvt->screen->cursor_current.col >= terminal->pvt->column_count))
+                terminal->pvt->screen->cursor_current.col = terminal->pvt->column_count - 1;
+}
+
 static void
 _vte_terminal_home_cursor (VteTerminal *terminal)
 {
@@ -926,6 +948,8 @@ _vte_sequence_handler_cb (VteTerminal *terminal, GValueArray *params)
        VteCell *pcell;
        screen = terminal->pvt->screen;
 
+        _vte_terminal_ensure_cursor_is_onscreen(terminal);
+
        /* Get the data for the row which the cursor points to. */
        rowdata = _vte_terminal_ensure_row(terminal);
         /* Clean up Tab/CJK fragments. */
@@ -960,6 +984,8 @@ _vte_sequence_handler_cd (VteTerminal *terminal, GValueArray *params)
        glong i;
        VteScreen *screen;
 
+        _vte_terminal_ensure_cursor_is_onscreen(terminal);
+
        screen = terminal->pvt->screen;
        /* If the cursor is actually on the screen, clear the rest of the
         * row the cursor is on and all of the rows below the cursor. */
@@ -1017,6 +1043,8 @@ _vte_sequence_handler_ce (VteTerminal *terminal, GValueArray *params)
        VteRowData *rowdata;
        VteScreen *screen;
 
+        _vte_terminal_ensure_cursor_is_onscreen(terminal);
+
        screen = terminal->pvt->screen;
        /* Get the data for the row which the cursor points to. */
        rowdata = _vte_terminal_ensure_row(terminal);
@@ -1194,6 +1222,8 @@ vte_sequence_handler_line_position_absolute (VteTerminal *terminal, GValueArray
         long val = 1, origin, rowmax;
        screen = terminal->pvt->screen;
 
+        _vte_terminal_ensure_cursor_is_onscreen(terminal);
+
        if ((params != NULL) && (params->n_values > 0)) {
                value = g_value_array_get_nth(params, 0);
                if (G_VALUE_HOLDS_LONG(value)) {
@@ -1222,6 +1252,8 @@ _vte_sequence_handler_dc (VteTerminal *terminal, GValueArray *params)
        VteRowData *rowdata;
        long col;
 
+        _vte_terminal_ensure_cursor_is_onscreen(terminal);
+
        screen = terminal->pvt->screen;
 
        if (_vte_ring_next(screen->row_data) > screen->cursor_current.row) {
@@ -1267,6 +1299,8 @@ vte_sequence_handler_cursor_down (VteTerminal *terminal, GValueArray *params)
         GValue *value;
         long val;
 
+        _vte_terminal_ensure_cursor_is_onscreen(terminal);
+
        screen = terminal->pvt->screen;
 
        if (screen->scrolling_restricted) {
@@ -1298,6 +1332,8 @@ vte_sequence_handler_erase_characters (VteTerminal *terminal, GValueArray *param
        VteCell *cell;
        long col, i, count;
 
+        _vte_terminal_ensure_cursor_is_onscreen(terminal);
+
        screen = terminal->pvt->screen;
 
        /* If we got a parameter, use it. */
@@ -1355,6 +1391,8 @@ _vte_sequence_handler_insert_character (VteTerminal *terminal, GValueArray *para
        VteVisualPosition save;
        VteScreen *screen;
 
+        _vte_terminal_ensure_cursor_is_onscreen(terminal);
+
        screen = terminal->pvt->screen;
 
        save = screen->cursor_current;
@@ -1385,6 +1423,8 @@ vte_sequence_handler_backspace (VteTerminal *terminal, GValueArray *params)
 {
        VteScreen *screen;
 
+        _vte_terminal_ensure_cursor_is_onscreen(terminal);
+
        screen = terminal->pvt->screen;
        if (screen->cursor_current.col > 0) {
                /* There's room to move left, so do so. */
@@ -1400,6 +1440,8 @@ vte_sequence_handler_cursor_backward (VteTerminal *terminal, GValueArray *params
         GValue *value;
         long val;
 
+        _vte_terminal_ensure_cursor_is_onscreen(terminal);
+
         screen = terminal->pvt->screen;
 
         val = 1;
@@ -1420,6 +1462,8 @@ vte_sequence_handler_cursor_forward (VteTerminal *terminal, GValueArray *params)
         GValue *value;
         long val;
 
+        _vte_terminal_ensure_cursor_is_onscreen(terminal);
+
        screen = terminal->pvt->screen;
 
         val = 1;
@@ -1464,6 +1508,8 @@ vte_sequence_handler_restore_cursor (VteTerminal *terminal, GValueArray *params)
                                           screen->insert_delta,
                                           screen->insert_delta +
                                           terminal->pvt->row_count - 1);
+
+        _vte_terminal_ensure_cursor_is_onscreen(terminal);
 }
 
 /* Save cursor (position). */
@@ -1485,6 +1531,8 @@ vte_sequence_handler_scroll_down (VteTerminal *terminal, GValueArray *params)
        long val = 1;
        GValue *value;
 
+        /* No _vte_terminal_ensure_cursor_is_onscreen() here as per xterm */
+
        if ((params != NULL) && (params->n_values > 0)) {
                value = g_value_array_get_nth(params, 0);
                if (G_VALUE_HOLDS_LONG(value)) {
@@ -1599,6 +1647,8 @@ vte_sequence_handler_scroll_up (VteTerminal *terminal, GValueArray *params)
        long val = 1;
        GValue *value;
 
+        /* No _vte_terminal_ensure_cursor_is_onscreen() here as per xterm */
+
        if ((params != NULL) && (params->n_values > 0)) {
                value = g_value_array_get_nth(params, 0);
                if (G_VALUE_HOLDS_LONG(value)) {
@@ -1614,6 +1664,8 @@ vte_sequence_handler_scroll_up (VteTerminal *terminal, GValueArray *params)
 static void
 vte_sequence_handler_line_feed (VteTerminal *terminal, GValueArray *params)
 {
+        _vte_terminal_ensure_cursor_is_onscreen(terminal);
+
        _vte_terminal_cursor_down (terminal);
 }
 
@@ -1624,6 +1676,8 @@ vte_sequence_handler_reverse_index (VteTerminal *terminal, GValueArray *params)
        long start, end;
        VteScreen *screen;
 
+        _vte_terminal_ensure_cursor_is_onscreen(terminal);
+
        screen = terminal->pvt->screen;
 
        if (screen->scrolling_restricted) {
@@ -1793,6 +1847,8 @@ vte_sequence_handler_cursor_up (VteTerminal *terminal, GValueArray *params)
         GValue *value;
         long val;
 
+        _vte_terminal_ensure_cursor_is_onscreen(terminal);
+
        screen = terminal->pvt->screen;
 
        if (screen->scrolling_restricted) {
@@ -2587,7 +2643,8 @@ vte_sequence_handler_device_status_report (VteTerminal *terminal, GValueArray *p
                                g_snprintf(buf, sizeof(buf),
                                           _VTE_CAP_CSI "%ld;%ldR",
                                            rowval + 1,
-                                          screen->cursor_current.col + 1);
+                                           CLAMP(screen->cursor_current.col + 1,
+                                                 1, terminal->pvt->column_count));
                                vte_terminal_feed_child(terminal, buf, -1);
                                break;
                        default:
@@ -2628,7 +2685,8 @@ vte_sequence_handler_dec_device_status_report (VteTerminal *terminal, GValueArra
                                g_snprintf(buf, sizeof(buf),
                                           _VTE_CAP_CSI "?%ld;%ldR",
                                            rowval + 1,
-                                          screen->cursor_current.col + 1);
+                                           CLAMP(screen->cursor_current.col + 1,
+                                                 1, terminal->pvt->column_count));
                                vte_terminal_feed_child(terminal, buf, -1);
                                break;
                        case 15:


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