[5/6,gdb/testsuite] Implement the newline glitch in tuiterm

Message ID 20230522131545.12291-7-tdevries@suse.de
State New
Headers
Series Introduce ansi-for-tui |

Commit Message

Tom de Vries May 22, 2023, 1:15 p.m. UTC
  Implement the newline glitch in tuiterm (PR testsuite/30451).  The newline
glitch corresponds to the xenl terminfo capability.  It can be enabled by
setting Term::_newline_glitch to 1.

The functionality is as follows.

After printing a char at the end of the line, rather than wrapping the cursor
goes into a special state, called the ignore state in this implementation.

The ignore state is implemented by having the cursor positioned on the same
line, but immediately right of the last column, so effectively off-screen.

In the ignore_state:
- if a normal char is issued, the cursor wraps to the next line (so the ignore
  state is no longer active) and the char is printed.
- if a control sequence is issued, the cursor is repositioned to the last column
  (so the ignore state is no longer active) and the control sequence takes effect.
- if a tab character or other formatting controls like carriage return and newline
  are issued, they are ignored.

The most elaborate description of the newline glitch I found is here [1][2].

The idea to represent the ignore state as the cursor being off the screen I
got from here [3].

Tested on x86_64-linux.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30451

[1] https://invisible-island.net/xterm/xterm.faq.html#grep_colors
[2] https://invisible-island.net/xterm/xterm.faq.html#vt100_wrapping
[3] https://stackoverflow.com/a/31360700
---
 gdb/testsuite/gdb.tui/tuiterm.exp | 26 +++++++++
 gdb/testsuite/lib/tuiterm.exp     | 94 ++++++++++++++++++++++++++++++-
 2 files changed, 118 insertions(+), 2 deletions(-)
  

Patch

diff --git a/gdb/testsuite/gdb.tui/tuiterm.exp b/gdb/testsuite/gdb.tui/tuiterm.exp
index 8cd15cb33bb..08b492582c3 100644
--- a/gdb/testsuite/gdb.tui/tuiterm.exp
+++ b/gdb/testsuite/gdb.tui/tuiterm.exp
@@ -682,6 +682,30 @@  proc test_insert_line { } {
     } 2 0
 }
 
+proc test_newline_glitch { } {
+    setup_terminal 8 4
+
+    # This is part of a sequence that ncurses generates when we run TUI with
+    # TERM=ansi on an xterm, in other words, when the terminal does have the
+    # newline glitch, but the terminfo entry tells ncurses that it doesn't.
+    # Consequently, we get wonky output, which gives us a good test-case for
+    # the newline glitch.
+    set Term::_newline_glitch 1
+    Term::_insert "12345678"
+    Term::_insert "12345678"
+    Term::_csi_A
+    Term::_csi_B
+    Term::_insert "(gdb) "
+    Term::dump_screen
+
+    check "newline glitch" {
+	"12345678"
+	"1234567\\("
+	"gdb\\)    "
+	"        "
+    } 5 2
+}
+
 # Run proc TEST_PROC_NAME with a "small" terminal.
 
 proc run_one_test_small { test_proc_name } {
@@ -733,3 +757,5 @@  foreach_with_prefix test {
 } {
     run_one_test_large $test
 }
+
+test_newline_glitch
diff --git a/gdb/testsuite/lib/tuiterm.exp b/gdb/testsuite/lib/tuiterm.exp
index 4c0fdc9b6df..bb0681f2034 100644
--- a/gdb/testsuite/lib/tuiterm.exp
+++ b/gdb/testsuite/lib/tuiterm.exp
@@ -33,6 +33,8 @@  namespace eval Term {
 
     variable _resize_count
 
+    variable _newline_glitch
+
     proc _log { what } {
 	verbose "+++ $what"
     }
@@ -50,6 +52,19 @@  namespace eval Term {
 	_log "$what, cursor: ($orig_cur_row, $orig_cur_col) -> ($_cur_row, $_cur_col)"
     }
 
+    proc in_ignore_state {} {
+	variable _cur_col
+	variable _cols
+	return [expr $_cur_col == $_cols]
+    }
+
+    proc cancel_ignore_state {} {
+	variable _cur_col
+	if { [in_ignore_state] } {
+	    incr _cur_col -1
+	}
+    }
+
     # If ARG is empty, return DEF: otherwise ARG.  This is useful for
     # defaulting arguments in CSIs.
     proc _default {arg def} {
@@ -81,10 +96,19 @@  namespace eval Term {
 
     # Beep.
     proc _ctl_0x07 {} {
+	if { [in_ignore_state] } {
+	    _log "Beep: ignored"
+	    return
+	}
     }
 
     # Backspace.
     proc _ctl_0x08 {} {
+	if { [in_ignore_state] } {
+	    _log "Backspace: ignored"
+	    return
+	}
+
 	_log_cur "Backspace" {
 	    variable _cur_col
 
@@ -96,6 +120,11 @@  namespace eval Term {
 
     # Linefeed.
     proc _ctl_0x0a {} {
+	if { [in_ignore_state] } {
+	    _log "Line feed: ignored"
+	    return
+	}
+
 	_log_cur "Line feed" {
 	    variable _cur_row
 	    variable _rows
@@ -123,6 +152,11 @@  namespace eval Term {
 
     # Carriage return.
     proc _ctl_0x0d {} {
+	if { [in_ignore_state] } {
+	    _log "Carriage return: ignored"
+	    return
+	}
+
 	_log_cur "Carriage return" {
 	    variable _cur_col
 
@@ -134,6 +168,8 @@  namespace eval Term {
     #
     # https://vt100.net/docs/vt510-rm/ICH.html
     proc _csi_@ {args} {
+	cancel_ignore_state
+
 	set n [_default [lindex $args 0] 1]
 
 	_log_cur "Insert Character ($n)" {
@@ -158,6 +194,8 @@  namespace eval Term {
     #
     # https://vt100.net/docs/vt510-rm/CUU.html
     proc _csi_A {args} {
+	cancel_ignore_state
+
 	set arg [_default [lindex $args 0] 1]
 
 	_log_cur "Cursor Up ($arg)" {
@@ -171,6 +209,8 @@  namespace eval Term {
     #
     # https://vt100.net/docs/vt510-rm/CUD.html
     proc _csi_B {args} {
+	cancel_ignore_state
+
 	set arg [_default [lindex $args 0] 1]
 
 	_log_cur "Cursor Down ($arg)" {
@@ -185,6 +225,8 @@  namespace eval Term {
     #
     # https://vt100.net/docs/vt510-rm/CUF.html
     proc _csi_C {args} {
+	cancel_ignore_state
+
 	set arg [_default [lindex $args 0] 1]
 
 	_log_cur "Cursor Forward ($arg)" {
@@ -199,6 +241,8 @@  namespace eval Term {
     #
     # https://vt100.net/docs/vt510-rm/CUB.html
     proc _csi_D {args} {
+	cancel_ignore_state
+
 	set arg [_default [lindex $args 0] 1]
 
 	_log_cur "Cursor Backward ($arg)" {
@@ -212,6 +256,8 @@  namespace eval Term {
     #
     # https://vt100.net/docs/vt510-rm/CNL.html
     proc _csi_E {args} {
+	cancel_ignore_state
+
 	set arg [_default [lindex $args 0] 1]
 
 	_log_cur "Cursor Next Line ($arg)" {
@@ -228,6 +274,8 @@  namespace eval Term {
     #
     # https://vt100.net/docs/vt510-rm/CPL.html
     proc _csi_F {args} {
+	cancel_ignore_state
+
 	set arg [_default [lindex $args 0] 1]
 
 	_log_cur "Cursor Previous Line ($arg)" {
@@ -244,6 +292,8 @@  namespace eval Term {
     #
     # https://vt100.net/docs/vt510-rm/CHA.html
     proc _csi_G {args} {
+	cancel_ignore_state
+
 	set arg [_default [lindex $args 0] 1]
 
 	_log_cur "Cursor Horizontal Absolute ($arg)" {
@@ -258,6 +308,8 @@  namespace eval Term {
     #
     # https://vt100.net/docs/vt510-rm/CUP.html
     proc _csi_H {args} {
+	cancel_ignore_state
+
 	set row [_default [lindex $args 0] 1]
 	set col [_default [lindex $args 1] 1]
 
@@ -274,6 +326,8 @@  namespace eval Term {
     #
     # https://vt100.net/docs/vt510-rm/CHT.html
     proc _csi_I {args} {
+	cancel_ignore_state
+
 	set n [_default [lindex $args 0] 1]
 
 	_log_cur "Cursor Horizontal Forward Tabulation ($n)" {
@@ -291,6 +345,8 @@  namespace eval Term {
     #
     # https://vt100.net/docs/vt510-rm/ED.html
     proc _csi_J {args} {
+	cancel_ignore_state
+
 	set arg [_default [lindex $args 0] 0]
 
 	_log_cur "Erase in Display ($arg)" {
@@ -318,6 +374,8 @@  namespace eval Term {
     #
     # https://vt100.net/docs/vt510-rm/EL.html
     proc _csi_K {args} {
+	cancel_ignore_state
+
 	set arg [_default [lindex $args 0] 0]
 
 	_log_cur "Erase in Line ($arg)" {
@@ -342,6 +400,8 @@  namespace eval Term {
     #
     # https://vt100.net/docs/vt510-rm/IL.html
     proc _csi_L {args} {
+	cancel_ignore_state
+
 	set arg [_default [lindex $args 0] 1]
 
 	_log_cur "Insert Line ($arg)" {
@@ -369,6 +429,8 @@  namespace eval Term {
     #
     # https://vt100.net/docs/vt510-rm/DL.html
     proc _csi_M {args} {
+	cancel_ignore_state
+
 	set count [_default [lindex $args 0] 1]
 
 	_log_cur "Delete line ($count)" {
@@ -394,6 +456,8 @@  namespace eval Term {
     #
     # https://vt100.net/docs/vt510-rm/DCH.html
     proc _csi_P {args} {
+	cancel_ignore_state
+
 	set count [_default [lindex $args 0] 1]
 
 	_log_cur "Delete character ($count)" {
@@ -421,6 +485,8 @@  namespace eval Term {
     #
     # https://vt100.net/docs/vt510-rm/SU.html
     proc _csi_S {args} {
+	cancel_ignore_state
+
 	set count [_default [lindex $args 0] 1]
 
 	_log_cur "Pan Down ($count)" {
@@ -455,6 +521,8 @@  namespace eval Term {
     #
     # https://vt100.net/docs/vt510-rm/SD.html
     proc _csi_T {args} {
+	cancel_ignore_state
+
 	set count [_default [lindex $args 0] 1]
 
 	_log_cur "Pan Up ($count)" {
@@ -489,6 +557,8 @@  namespace eval Term {
     #
     # https://vt100.net/docs/vt510-rm/ECH.html
     proc _csi_X {args} {
+	cancel_ignore_state
+
 	set n [_default [lindex $args 0] 1]
 
 	_log_cur "Erase chars ($n)" {
@@ -511,6 +581,8 @@  namespace eval Term {
     #
     # https://vt100.net/docs/vt510-rm/CBT.html
     proc _csi_Z {args} {
+	cancel_ignore_state
+
 	set n [_default [lindex $args 0] 1]
 
 	_log_cur "Cursor Backward Tabulation ($n)" {
@@ -524,6 +596,8 @@  namespace eval Term {
     #
     # https://www.xfree86.org/current/ctlseqs.html (See `(REP)`)
     proc _csi_b {args} {
+	cancel_ignore_state
+
 	set n [_default [lindex $args 0] 1]
 
 	_log_cur "Repeat ($n)" {
@@ -537,6 +611,8 @@  namespace eval Term {
     #
     # https://vt100.net/docs/vt510-rm/VPA.html
     proc _csi_d {args} {
+	cancel_ignore_state
+
 	set row [_default [lindex $args 0] 1]
 
 	_log_cur "Vertical Line Position Absolute ($row)" {
@@ -563,6 +639,8 @@  namespace eval Term {
     #
     # https://vt100.net/docs/vt510-rm/SGR.html
     proc _csi_m {args} {
+	cancel_ignore_state
+
 	_log_cur "Select Graphic Rendition ([join $args {, }])" {
 	    variable _attrs
 
@@ -631,13 +709,23 @@  namespace eval Term {
 	    variable _cols
 	    variable _attrs
 	    variable _chars
+	    variable _newline_glitch
 	    set lattr [array get _attrs]
 	    foreach char [split $str {}] {
 		_log_cur "  Inserted char '$char'" {
+		    if { $_newline_glitch } {
+			if { $_cur_col == $_cols} {
+			    _wrap_cursor
+			}
+		    }
+
 		    set _chars($_cur_col,$_cur_row) [list $char $lattr]
 		    incr _cur_col
-		    if {$_cur_col >= $_cols} {
-			_wrap_cursor
+
+		    if { !$_newline_glitch } {
+			if {$_cur_col == $_cols} {
+			    _wrap_cursor
+			}
 		    }
 		}
 	    }
@@ -675,12 +763,14 @@  namespace eval Term {
 	variable _cur_row
 	variable _attrs
 	variable _resize_count
+	variable _newline_glitch
 
 	set _rows $rows
 	set _cols $cols
 	set _cur_col 0
 	set _cur_row 0
 	set _resize_count 0
+	set _newline_glitch 0
 	_reset_attrs _attrs
 
 	_clear_lines 0 $_rows