aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite/lib/tuiterm.exp
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/testsuite/lib/tuiterm.exp')
-rw-r--r--gdb/testsuite/lib/tuiterm.exp2357
1 files changed, 1399 insertions, 958 deletions
diff --git a/gdb/testsuite/lib/tuiterm.exp b/gdb/testsuite/lib/tuiterm.exp
index 0c4e3d1..e1af223 100644
--- a/gdb/testsuite/lib/tuiterm.exp
+++ b/gdb/testsuite/lib/tuiterm.exp
@@ -1,4 +1,4 @@
-# Copyright 2019-2024 Free Software Foundation, Inc.
+# Copyright 2019-2025 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -33,1249 +33,1690 @@ namespace eval Term {
variable _resize_count
- proc _log { what } {
- verbose "+++ $what"
- }
+ variable _TERM
+ set _TERM ""
- # Call BODY, then log WHAT along with the original and new cursor position.
- proc _log_cur { what body } {
- variable _cur_row
- variable _cur_col
+ variable _alternate
+ variable _alternate_setup
+ set _alternate 0
+ set _alternate_setup 0
+}
+
+proc Term::_log { what } {
+ verbose "+++ $what"
+}
- set orig_cur_row $_cur_row
- set orig_cur_col $_cur_col
+# Call BODY, then log WHAT along with the original and new cursor position.
+proc Term::_log_cur { what body } {
+ variable _cur_row
+ variable _cur_col
- uplevel $body
+ set orig_cur_row $_cur_row
+ set orig_cur_col $_cur_col
+
+ set code [catch {uplevel $body} result]
- _log "$what, cursor: ($orig_cur_row, $orig_cur_col) -> ($_cur_row, $_cur_col)"
+ _log "$what, cursor: ($orig_cur_row, $orig_cur_col) -> ($_cur_row, $_cur_col)"
+
+ if { $code == 1 } {
+ global errorInfo errorCode
+ return -code $code -errorinfo $errorInfo -errorcode $errorCode $result
+ } else {
+ return -code $code $result
}
+}
- # If ARG is empty, return DEF: otherwise ARG. This is useful for
- # defaulting arguments in CSIs.
- proc _default {arg def} {
- if {$arg == ""} {
- return $def
- }
- return $arg
+# If ARG is empty, return DEF: otherwise ARG. This is useful for
+# defaulting arguments in CSIs.
+proc Term::_default {arg def} {
+ if {$arg == ""} {
+ return $def
}
+ return $arg
+}
- # Erase in the line Y from SX to just before EX.
- proc _clear_in_line {sx ex y} {
- variable _attrs
- variable _chars
- set lattr [array get _attrs]
- while {$sx < $ex} {
- set _chars($sx,$y) [list " " $lattr]
- incr sx
- }
+# Erase in the line Y from SX to just before EX.
+proc Term::_clear_in_line {sx ex y} {
+ variable _attrs
+ variable _chars
+ set lattr [array get _attrs]
+ while {$sx < $ex} {
+ set _chars($sx,$y) [list " " $lattr]
+ incr sx
}
+}
- # Erase the lines from SY to just before EY.
- proc _clear_lines {sy ey} {
- variable _cols
- while {$sy < $ey} {
- _clear_in_line 0 $_cols $sy
- incr sy
- }
+# Erase the lines from SY to just before EY.
+proc Term::_clear_lines {sy ey} {
+ variable _cols
+ while {$sy < $ey} {
+ _clear_in_line 0 $_cols $sy
+ incr sy
}
+}
+
+# Beep.
+proc Term::_ctl_0x07 {} {
+}
+
+# Return 1 if tuiterm has the bw/auto_left_margin enabled.
+proc Term::_have_bw {} {
+ return [expr \
+ [string equal $Term::_TERM "ansiw"] \
+ || [string equal $Term::_TERM "ansis"]]
+}
- # Beep.
- proc _ctl_0x07 {} {
+# Backspace.
+proc Term::_ctl_0x08 { {bw -1} } {
+ if { $bw == -1 } {
+ set bw [_have_bw]
}
+ _log_cur "Backspace, bw == $bw" {
+ variable _cur_col
+ variable _cur_row
+ variable _cols
- # Backspace.
- proc _ctl_0x08 {} {
- _log_cur "Backspace" {
- variable _cur_col
+ if { $_cur_col > 0 } {
+ # No wrapping needed.
+ incr _cur_col -1
+ return
+ }
- if {$_cur_col > 0} {
- incr _cur_col -1
- }
+ if { ! $bw } {
+ # Wrapping not enabled.
+ return
}
+
+ if { $_cur_row == 0 } {
+ # Can't wrap.
+ return
+ }
+
+ # Wrap to previous line.
+ set _cur_col [expr $_cols - 1]
+ incr _cur_row -1
}
+}
- # Linefeed.
- proc _ctl_0x0a {} {
- _log_cur "Line feed" {
- variable _cur_row
- variable _rows
- variable _cols
- variable _chars
-
- incr _cur_row 1
- while {$_cur_row >= $_rows} {
- # Scroll the display contents. We scroll one line at
- # a time here; as _cur_row was only increased by one,
- # a single line scroll should be enough to put the
- # cursor back on the screen. But we wrap the
- # scrolling inside a while loop just to be on the safe
- # side.
- for {set y 0} {$y < [expr $_rows - 1]} {incr y} {
- set next_y [expr $y + 1]
- for {set x 0} {$x < $_cols} {incr x} {
- set _chars($x,$y) $_chars($x,$next_y)
- }
- }
+# Linefeed.
+proc Term::_ctl_0x0a {} {
+ _log_cur "Line feed" {
+ variable _cur_row
+ variable _rows
+ variable _cols
+ variable _chars
- incr _cur_row -1
+ incr _cur_row 1
+ while {$_cur_row >= $_rows} {
+ # Scroll the display contents. We scroll one line at
+ # a time here; as _cur_row was only increased by one,
+ # a single line scroll should be enough to put the
+ # cursor back on the screen. But we wrap the
+ # scrolling inside a while loop just to be on the safe
+ # side.
+ for {set y 0} {$y < [expr $_rows - 1]} {incr y} {
+ set next_y [expr $y + 1]
+ for {set x 0} {$x < $_cols} {incr x} {
+ set _chars($x,$y) $_chars($x,$next_y)
+ }
}
+
+ incr _cur_row -1
}
}
+}
- # Carriage return.
- proc _ctl_0x0d {} {
- _log_cur "Carriage return" {
- variable _cur_col
+# Carriage return.
+proc Term::_ctl_0x0d {} {
+ _log_cur "Carriage return" {
+ variable _cur_col
- set _cur_col 0
- }
+ set _cur_col 0
}
+}
- # Insert Character.
- #
- # https://vt100.net/docs/vt510-rm/ICH.html
- proc _csi_@ {args} {
- set n [_default [lindex $args 0] 1]
+# Designate G0 Character Set, USASCII (ESC ( B)
+#
+# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html (see "ESC ( C", case C = B)
+proc Term::_esc_0x28_B {} {
+ _log "ignored: G0: USASCII"
+}
- _log_cur "Insert Character ($n)" {
- variable _cur_col
- variable _cur_row
- variable _cols
- variable _chars
+# Designate G0 Character Set, DEC Special Character and Line Drawing Set (ESC ( 0)
+#
+# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html (see "ESC ( C", case C = 0)
+proc Term::_esc_0x28_0 {} {
+ _log "ignored: G0: DEC Special Character and Line Drawing Set"
+}
- # Move characters right of the cursor right by N positions,
- # starting with the rightmost one.
- for {set in_col [expr $_cols - $n - 1]} {$in_col >= $_cur_col} {incr in_col -1} {
- set out_col [expr $in_col + $n]
- set _chars($out_col,$_cur_row) $_chars($in_col,$_cur_row)
- }
+# DECKPAM (Application Keypad, ESC =)
+#
+# https://vt100.net/docs/vt510-rm/DECKPAM.html
+proc Term::_esc_0x3d {} {
+ _log "ignored: Application Keypad"
+}
+
+# DECKPNM (Normal Keypad, ESC >)
+#
+# https://vt100.net/docs/vt510-rm/DECKPNM.html
+proc Term::_esc_0x3e {} {
+ _log "ignored: Normal Keypad"
+}
- # Write N blank spaces starting from the cursor.
- _clear_in_line $_cur_col [expr $_cur_col + $n] $_cur_row
+# Insert Character.
+#
+# https://vt100.net/docs/vt510-rm/ICH.html
+proc Term::_csi_@ {args} {
+ set n [_default [lindex $args 0] 1]
+
+ _log_cur "Insert Character ($n)" {
+ variable _cur_col
+ variable _cur_row
+ variable _cols
+ variable _chars
+
+ # Move characters right of the cursor right by N positions,
+ # starting with the rightmost one.
+ for {set in_col [expr $_cols - $n - 1]} {$in_col >= $_cur_col} {incr in_col -1} {
+ set out_col [expr $in_col + $n]
+ set _chars($out_col,$_cur_row) $_chars($in_col,$_cur_row)
}
+
+ # Write N blank spaces starting from the cursor.
+ _clear_in_line $_cur_col [expr $_cur_col + $n] $_cur_row
}
+}
- # Cursor Up.
- #
- # https://vt100.net/docs/vt510-rm/CUU.html
- proc _csi_A {args} {
- set arg [_default [lindex $args 0] 1]
+# Horizontal Position Absolute.
+#
+# https://vt100.net/docs/vt510-rm/HPA.html
+proc Term::_csi_` {args} {
+ # Same as Cursor Horizontal Absolute.
+ return [Term::_csi_G {*}$args]
+}
- _log_cur "Cursor Up ($arg)" {
- variable _cur_row
+# Cursor Up.
+#
+# https://vt100.net/docs/vt510-rm/CUU.html
+proc Term::_csi_A {args} {
+ set arg [_default [lindex $args 0] 1]
- set _cur_row [expr {max ($_cur_row - $arg, 0)}]
- }
+ _log_cur "Cursor Up ($arg)" {
+ variable _cur_row
+
+ set _cur_row [expr {max ($_cur_row - $arg, 0)}]
}
+}
- # Cursor Down.
- #
- # https://vt100.net/docs/vt510-rm/CUD.html
- proc _csi_B {args} {
- set arg [_default [lindex $args 0] 1]
+# Cursor Down.
+#
+# https://vt100.net/docs/vt510-rm/CUD.html
+proc Term::_csi_B {args} {
+ set arg [_default [lindex $args 0] 1]
- _log_cur "Cursor Down ($arg)" {
- variable _cur_row
- variable _rows
+ _log_cur "Cursor Down ($arg)" {
+ variable _cur_row
+ variable _rows
- set _cur_row [expr {min ($_cur_row + $arg, $_rows - 1)}]
- }
+ set _cur_row [expr {min ($_cur_row + $arg, $_rows - 1)}]
}
+}
- # Cursor Forward.
- #
- # https://vt100.net/docs/vt510-rm/CUF.html
- proc _csi_C {args} {
- set arg [_default [lindex $args 0] 1]
+# Cursor Forward.
+#
+# https://vt100.net/docs/vt510-rm/CUF.html
+proc Term::_csi_C {args} {
+ set arg [_default [lindex $args 0] 1]
- _log_cur "Cursor Forward ($arg)" {
- variable _cur_col
- variable _cols
+ _log_cur "Cursor Forward ($arg)" {
+ variable _cur_col
+ variable _cols
- set _cur_col [expr {min ($_cur_col + $arg, $_cols - 1)}]
- }
+ set _cur_col [expr {min ($_cur_col + $arg, $_cols - 1)}]
}
+}
- # Cursor Backward.
- #
- # https://vt100.net/docs/vt510-rm/CUB.html
- proc _csi_D {args} {
- set arg [_default [lindex $args 0] 1]
+# Cursor Backward.
+#
+# https://vt100.net/docs/vt510-rm/CUB.html
+proc Term::_csi_D {args} {
+ set arg [_default [lindex $args 0] 1]
- _log_cur "Cursor Backward ($arg)" {
- variable _cur_col
+ _log_cur "Cursor Backward ($arg)" {
+ variable _cur_col
- set _cur_col [expr {max ($_cur_col - $arg, 0)}]
- }
+ set _cur_col [expr {max ($_cur_col - $arg, 0)}]
}
+}
- # Cursor Next Line.
- #
- # https://vt100.net/docs/vt510-rm/CNL.html
- proc _csi_E {args} {
- set arg [_default [lindex $args 0] 1]
+# Cursor Next Line.
+#
+# https://vt100.net/docs/vt510-rm/CNL.html
+proc Term::_csi_E {args} {
+ set arg [_default [lindex $args 0] 1]
- _log_cur "Cursor Next Line ($arg)" {
- variable _cur_col
- variable _cur_row
- variable _rows
+ _log_cur "Cursor Next Line ($arg)" {
+ variable _cur_col
+ variable _cur_row
+ variable _rows
- set _cur_col 0
- set _cur_row [expr {min ($_cur_row + $arg, $_rows - 1)}]
- }
+ set _cur_col 0
+ set _cur_row [expr {min ($_cur_row + $arg, $_rows - 1)}]
}
+}
- # Cursor Previous Line.
- #
- # https://vt100.net/docs/vt510-rm/CPL.html
- proc _csi_F {args} {
- set arg [_default [lindex $args 0] 1]
+# Cursor Previous Line.
+#
+# https://vt100.net/docs/vt510-rm/CPL.html
+proc Term::_csi_F {args} {
+ set arg [_default [lindex $args 0] 1]
- _log_cur "Cursor Previous Line ($arg)" {
- variable _cur_col
- variable _cur_row
- variable _rows
+ _log_cur "Cursor Previous Line ($arg)" {
+ variable _cur_col
+ variable _cur_row
+ variable _rows
- set _cur_col 0
- set _cur_row [expr {max ($_cur_row - $arg, 0)}]
- }
+ set _cur_col 0
+ set _cur_row [expr {max ($_cur_row - $arg, 0)}]
}
+}
- # Cursor Horizontal Absolute.
- #
- # https://vt100.net/docs/vt510-rm/CHA.html
- proc _csi_G {args} {
- set arg [_default [lindex $args 0] 1]
+# Cursor Horizontal Absolute.
+#
+# https://vt100.net/docs/vt510-rm/CHA.html
+proc Term::_csi_G {args} {
+ set arg [_default [lindex $args 0] 1]
- _log_cur "Cursor Horizontal Absolute ($arg)" {
- variable _cur_col
- variable _cols
+ _log_cur "Cursor Horizontal Absolute ($arg)" {
+ variable _cur_col
+ variable _cols
- set _cur_col [expr {min ($arg - 1, $_cols)}]
- }
+ set _cur_col [expr {min ($arg, $_cols)} - 1]
}
+}
- # Cursor Position.
- #
- # https://vt100.net/docs/vt510-rm/CUP.html
- proc _csi_H {args} {
- set row [_default [lindex $args 0] 1]
- set col [_default [lindex $args 1] 1]
+# Cursor Position.
+#
+# https://vt100.net/docs/vt510-rm/CUP.html
+proc Term::_csi_H {args} {
+ set row [_default [lindex $args 0] 1]
+ set col [_default [lindex $args 1] 1]
- _log_cur "Cursor Position ($row, $col)" {
- variable _cur_col
- variable _cur_row
+ _log_cur "Cursor Position ($row, $col)" {
+ variable _cur_col
+ variable _cur_row
- set _cur_row [expr {$row - 1}]
- set _cur_col [expr {$col - 1}]
- }
+ set _cur_row [expr {$row - 1}]
+ set _cur_col [expr {$col - 1}]
}
+}
- # Cursor Horizontal Forward Tabulation.
- #
- # https://vt100.net/docs/vt510-rm/CHT.html
- proc _csi_I {args} {
- set n [_default [lindex $args 0] 1]
+# Cursor Horizontal Forward Tabulation.
+#
+# https://vt100.net/docs/vt510-rm/CHT.html
+proc Term::_csi_I {args} {
+ set n [_default [lindex $args 0] 1]
- _log_cur "Cursor Horizontal Forward Tabulation ($n)" {
- variable _cur_col
- variable _cols
+ _log_cur "Cursor Horizontal Forward Tabulation ($n)" {
+ variable _cur_col
+ variable _cols
- incr _cur_col [expr {$n * 8 - $_cur_col % 8}]
- if {$_cur_col >= $_cols} {
- set _cur_col [expr {$_cols - 1}]
- }
+ incr _cur_col [expr {$n * 8 - $_cur_col % 8}]
+ if {$_cur_col >= $_cols} {
+ set _cur_col [expr {$_cols - 1}]
}
}
+}
- # Erase in Display.
- #
- # https://vt100.net/docs/vt510-rm/ED.html
- proc _csi_J {args} {
- set arg [_default [lindex $args 0] 0]
-
- _log_cur "Erase in Display ($arg)" {
- variable _cur_col
- variable _cur_row
- variable _rows
- variable _cols
-
- if {$arg == 0} {
- # Cursor (inclusive) to end of display.
- _clear_in_line $_cur_col $_cols $_cur_row
- _clear_lines [expr {$_cur_row + 1}] $_rows
- } elseif {$arg == 1} {
- # Beginning of display to cursor (inclusive).
- _clear_lines 0 $_cur_row
- _clear_in_line 0 [expr $_cur_col + 1] $_cur_row
- } elseif {$arg == 2} {
- # Entire display.
- _clear_lines 0 $_rows
- }
+# Erase in Display.
+#
+# https://vt100.net/docs/vt510-rm/ED.html
+proc Term::_csi_J {args} {
+ set arg [_default [lindex $args 0] 0]
+
+ _log_cur "Erase in Display ($arg)" {
+ variable _cur_col
+ variable _cur_row
+ variable _rows
+ variable _cols
+
+ if {$arg == 0} {
+ # Cursor (inclusive) to end of display.
+ _clear_in_line $_cur_col $_cols $_cur_row
+ _clear_lines [expr {$_cur_row + 1}] $_rows
+ } elseif {$arg == 1} {
+ # Beginning of display to cursor (inclusive).
+ _clear_lines 0 $_cur_row
+ _clear_in_line 0 [expr $_cur_col + 1] $_cur_row
+ } elseif {$arg == 2} {
+ # Entire display.
+ _clear_lines 0 $_rows
}
}
+}
- # Erase in Line.
- #
- # https://vt100.net/docs/vt510-rm/EL.html
- proc _csi_K {args} {
- set arg [_default [lindex $args 0] 0]
+# Erase in Line.
+#
+# https://vt100.net/docs/vt510-rm/EL.html
+proc Term::_csi_K {args} {
+ set arg [_default [lindex $args 0] 0]
- _log_cur "Erase in Line ($arg)" {
- variable _cur_col
- variable _cur_row
- variable _cols
+ _log_cur "Erase in Line ($arg)" {
+ variable _cur_col
+ variable _cur_row
+ variable _cols
- if {$arg == 0} {
- # Cursor (inclusive) to end of line.
- _clear_in_line $_cur_col $_cols $_cur_row
- } elseif {$arg == 1} {
- # Beginning of line to cursor (inclusive).
- _clear_in_line 0 [expr $_cur_col + 1] $_cur_row
- } elseif {$arg == 2} {
- # Entire line.
- _clear_in_line 0 $_cols $_cur_row
- }
+ if {$arg == 0} {
+ # Cursor (inclusive) to end of line.
+ _clear_in_line $_cur_col $_cols $_cur_row
+ } elseif {$arg == 1} {
+ # Beginning of line to cursor (inclusive).
+ _clear_in_line 0 [expr $_cur_col + 1] $_cur_row
+ } elseif {$arg == 2} {
+ # Entire line.
+ _clear_in_line 0 $_cols $_cur_row
}
}
+}
- # Insert Line
- #
- # https://vt100.net/docs/vt510-rm/IL.html
- proc _csi_L {args} {
- set arg [_default [lindex $args 0] 1]
+# Insert Line
+#
+# https://vt100.net/docs/vt510-rm/IL.html
+proc Term::_csi_L {args} {
+ set arg [_default [lindex $args 0] 1]
- _log_cur "Insert Line ($arg)" {
- variable _cur_col
- variable _cur_row
- variable _rows
- variable _cols
- variable _chars
+ _log_cur "Insert Line ($arg)" {
+ variable _cur_col
+ variable _cur_row
+ variable _rows
+ variable _cols
+ variable _chars
- set y [expr $_rows - 2]
- set next_y [expr $y + $arg]
- while {$y >= $_cur_row} {
- for {set x 0} {$x < $_cols} {incr x} {
- set _chars($x,$next_y) $_chars($x,$y)
- }
- incr y -1
- incr next_y -1
+ set y [expr $_rows - 2]
+ set next_y [expr $y + $arg]
+ while {$y >= $_cur_row} {
+ for {set x 0} {$x < $_cols} {incr x} {
+ set _chars($x,$next_y) $_chars($x,$y)
}
-
- _clear_lines $_cur_row [expr $_cur_row + $arg]
+ incr y -1
+ incr next_y -1
}
+
+ _clear_lines $_cur_row [expr $_cur_row + $arg]
}
+}
- # Delete line.
- #
- # https://vt100.net/docs/vt510-rm/DL.html
- proc _csi_M {args} {
- set count [_default [lindex $args 0] 1]
+# Delete line.
+#
+# https://vt100.net/docs/vt510-rm/DL.html
+proc Term::_csi_M {args} {
+ set count [_default [lindex $args 0] 1]
- _log_cur "Delete line ($count)" {
- variable _cur_row
- variable _rows
- variable _cols
- variable _chars
+ _log_cur "Delete line ($count)" {
+ variable _cur_row
+ variable _rows
+ variable _cols
+ variable _chars
- set y $_cur_row
- set next_y [expr {$y + $count}]
- while {$next_y < $_rows} {
- for {set x 0} {$x < $_cols} {incr x} {
- set _chars($x,$y) $_chars($x,$next_y)
- }
- incr y
- incr next_y
+ set y $_cur_row
+ set next_y [expr {$y + $count}]
+ while {$next_y < $_rows} {
+ for {set x 0} {$x < $_cols} {incr x} {
+ set _chars($x,$y) $_chars($x,$next_y)
}
- _clear_lines $y $_rows
+ incr y
+ incr next_y
}
+ _clear_lines $y $_rows
}
+}
- # Delete Character.
- #
- # https://vt100.net/docs/vt510-rm/DCH.html
- proc _csi_P {args} {
- set count [_default [lindex $args 0] 1]
+# Delete Character.
+#
+# https://vt100.net/docs/vt510-rm/DCH.html
+proc Term::_csi_P {args} {
+ set count [_default [lindex $args 0] 1]
- _log_cur "Delete character ($count)" {
- variable _cur_row
- variable _cur_col
- variable _chars
- variable _cols
+ _log_cur "Delete character ($count)" {
+ variable _cur_row
+ variable _cur_col
+ variable _chars
+ variable _cols
- # Move all characters right of the cursor N positions left.
- set out_col [expr $_cur_col]
- set in_col [expr $_cur_col + $count]
+ # Move all characters right of the cursor N positions left.
+ set out_col [expr $_cur_col]
+ set in_col [expr $_cur_col + $count]
- while {$in_col < $_cols} {
- set _chars($out_col,$_cur_row) $_chars($in_col,$_cur_row)
- incr in_col
- incr out_col
- }
-
- # Clear the rest of the line.
- _clear_in_line $out_col $_cols $_cur_row
+ while {$in_col < $_cols} {
+ set _chars($out_col,$_cur_row) $_chars($in_col,$_cur_row)
+ incr in_col
+ incr out_col
}
+
+ # Clear the rest of the line.
+ _clear_in_line $out_col $_cols $_cur_row
}
+}
- # Pan Down
- #
- # https://vt100.net/docs/vt510-rm/SU.html
- proc _csi_S {args} {
- set count [_default [lindex $args 0] 1]
+# Pan Down
+#
+# https://vt100.net/docs/vt510-rm/SU.html
+proc Term::_csi_S {args} {
+ set count [_default [lindex $args 0] 1]
- _log_cur "Pan Down ($count)" {
- variable _cur_col
- variable _cur_row
- variable _cols
- variable _rows
- variable _chars
+ _log_cur "Pan Down ($count)" {
+ variable _cur_col
+ variable _cur_row
+ variable _cols
+ variable _rows
+ variable _chars
- # The following code is written without consideration for
- # the scroll margins. At this time this comment was
- # written the tuiterm library doesn't support the scroll
- # margins. If/when that changes, then the following will
- # need to be updated.
+ # The following code is written without consideration for
+ # the scroll margins. At this time this comment was
+ # written the tuiterm library doesn't support the scroll
+ # margins. If/when that changes, then the following will
+ # need to be updated.
- set dy 0
- set y $count
+ set dy 0
+ set y $count
- while {$y < $_rows} {
- for {set x 0} {$x < $_cols} {incr x} {
- set _chars($x,$dy) $_chars($x,$y)
- }
- incr y 1
- incr dy 1
+ while {$y < $_rows} {
+ for {set x 0} {$x < $_cols} {incr x} {
+ set _chars($x,$dy) $_chars($x,$y)
}
-
- _clear_lines $dy $_rows
+ incr y 1
+ incr dy 1
}
+
+ _clear_lines $dy $_rows
}
+}
- # Pan Up
- #
- # https://vt100.net/docs/vt510-rm/SD.html
- proc _csi_T {args} {
- set count [_default [lindex $args 0] 1]
+# Pan Up
+#
+# https://vt100.net/docs/vt510-rm/SD.html
+proc Term::_csi_T {args} {
+ set count [_default [lindex $args 0] 1]
- _log_cur "Pan Up ($count)" {
- variable _cur_col
- variable _cur_row
- variable _cols
- variable _rows
- variable _chars
+ _log_cur "Pan Up ($count)" {
+ variable _cur_col
+ variable _cur_row
+ variable _cols
+ variable _rows
+ variable _chars
- # The following code is written without consideration for
- # the scroll margins. At this time this comment was
- # written the tuiterm library doesn't support the scroll
- # margins. If/when that changes, then the following will
- # need to be updated.
+ # The following code is written without consideration for
+ # the scroll margins. At this time this comment was
+ # written the tuiterm library doesn't support the scroll
+ # margins. If/when that changes, then the following will
+ # need to be updated.
- set y [expr $_rows - $count]
- set dy $_rows
+ set y [expr $_rows - $count]
+ set dy $_rows
- while {$dy >= $count} {
- for {set x 0} {$x < $_cols} {incr x} {
- set _chars($x,$dy) $_chars($x,$y)
- }
- incr y -1
- incr dy -1
+ while {$dy >= $count} {
+ for {set x 0} {$x < $_cols} {incr x} {
+ set _chars($x,$dy) $_chars($x,$y)
}
-
- _clear_lines 0 $count
+ incr y -1
+ incr dy -1
}
+
+ _clear_lines 0 $count
}
+}
- # Erase chars.
- #
- # https://vt100.net/docs/vt510-rm/ECH.html
- proc _csi_X {args} {
- set n [_default [lindex $args 0] 1]
+# Erase chars.
+#
+# https://vt100.net/docs/vt510-rm/ECH.html
+proc Term::_csi_X {args} {
+ set n [_default [lindex $args 0] 1]
- _log_cur "Erase chars ($n)" {
- # Erase characters but don't move cursor.
- variable _cur_col
- variable _cur_row
- variable _attrs
- variable _chars
+ _log_cur "Erase chars ($n)" {
+ # Erase characters but don't move cursor.
+ variable _cur_col
+ variable _cur_row
+ variable _attrs
+ variable _chars
- set lattr [array get _attrs]
- set x $_cur_col
- for {set i 0} {$i < $n} {incr i} {
- set _chars($x,$_cur_row) [list " " $lattr]
- incr x
- }
+ set lattr [array get _attrs]
+ set x $_cur_col
+ for {set i 0} {$i < $n} {incr i} {
+ set _chars($x,$_cur_row) [list " " $lattr]
+ incr x
}
}
+}
- # Cursor Backward Tabulation.
- #
- # https://vt100.net/docs/vt510-rm/CBT.html
- proc _csi_Z {args} {
- set n [_default [lindex $args 0] 1]
+# Cursor Backward Tabulation.
+#
+# https://vt100.net/docs/vt510-rm/CBT.html
+proc Term::_csi_Z {args} {
+ set n [_default [lindex $args 0] 1]
- _log_cur "Cursor Backward Tabulation ($n)" {
- variable _cur_col
+ _log_cur "Cursor Backward Tabulation ($n)" {
+ variable _cur_col
- set _cur_col [expr {max (int (($_cur_col - 1) / 8) * 8 - ($n - 1) * 8, 0)}]
- }
+ set _cur_col [expr {max (int (($_cur_col - 1) / 8) * 8 - ($n - 1) * 8, 0)}]
}
+}
- # Repeat.
- #
- # https://www.xfree86.org/current/ctlseqs.html (See `(REP)`)
- proc _csi_b {args} {
- set n [_default [lindex $args 0] 1]
+# Repeat.
+#
+# https://www.xfree86.org/current/ctlseqs.html (See `(REP)`)
+proc Term::_csi_b {args} {
+ set n [_default [lindex $args 0] 1]
- _log_cur "Repeat ($n)" {
- variable _last_char
+ _log_cur "Repeat ($n)" {
+ variable _last_char
- _insert [string repeat $_last_char $n]
- }
+ _insert [string repeat $_last_char $n]
}
+}
- # Vertical Line Position Absolute.
- #
- # https://vt100.net/docs/vt510-rm/VPA.html
- proc _csi_d {args} {
- set row [_default [lindex $args 0] 1]
+# Vertical Line Position Absolute.
+#
+# https://vt100.net/docs/vt510-rm/VPA.html
+proc Term::_csi_d {args} {
+ set row [_default [lindex $args 0] 1]
- _log_cur "Vertical Line Position Absolute ($row)" {
- variable _cur_row
- variable _rows
+ _log_cur "Vertical Line Position Absolute ($row)" {
+ variable _cur_row
+ variable _rows
- set _cur_row [expr min ($row - 1, $_rows - 1)]
- }
+ set _cur_row [expr min ($row - 1, $_rows - 1)]
}
+}
- # Reset the attributes in attributes array UPVAR_NAME to the default values.
- proc _reset_attrs { upvar_name } {
- upvar $upvar_name var
- array set var {
- intensity normal
- fg default
- bg default
- underline 0
- reverse 0
- invisible 0
- blinking 0
+# Set Mode (SM, CSI h)
+#
+# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
+proc Term::_csi_h { args } {
+ foreach item $args {
+ switch -exact -- $item {
+ 4 {
+ # Insert Mode (IRM)
+ _log "ignored: insert mode"
+ }
+ default {
+ error unsupported
+ }
}
}
+}
- # Translate the color numbers as used in proc _csi_m to a name.
- proc _color_attr { n } {
- switch -exact -- $n {
- 0 {
- return black
+# Reset Mode (RM, CSI l)
+#
+# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
+proc Term::_csi_l { args } {
+ foreach item $args {
+ switch -exact -- $item {
+ 4 {
+ # Replace Mode (IRM)
+ _log "ignored: replace mode"
}
+ default {
+ error unsupported
+ }
+ }
+ }
+}
+
+# Set Scrolling Region (DECSTBM, CSI Ps ; Ps r)
+#
+# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
+proc Term::_csi_r { top bottom } {
+ _log "ignored: set scrolling region"
+}
+
+# Window manipulation (XTWINOPS, CSI Ps ; Ps ; Ps t)
+#
+# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
+proc Term::_csi_t { arg1 arg2 arg3 } {
+ if { $arg1 == 22 && $arg2 == 0 && $arg3 == 0 } {
+ _log "ignored: Save xterm icon and window title on stack"
+ return
+ }
+
+ if { $arg1 == 23 && $arg2 == 0 && $arg3 == 0 } {
+ _log "ignored: Restore xterm icon and window title from stack"
+ return
+ }
+
+ error unsupported
+}
+
+# DECSET (CSI ? h)
+#
+# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
+proc Term::_csi_0x3f_h { args } {
+ foreach item $args {
+ switch -exact -- $item {
1 {
- return red
+ _log "ignored: Application Cursor Keys"
}
- 2 {
- return green
+ 7 {
+ _log "ignored: autowrap mode"
}
- 3 {
- return yellow
+ 1000 {
+ _log "ignored: Send Mouse X & Y on button press and release"
}
- 4 {
- return blue
+ 1006 {
+ _log "ignored: Enable SGR Mouse Mode"
}
- 5 {
- return magenta
+ 1049 {
+ _log "switch to alternate screen"
+ _set_alternate 1
}
- 6 {
- return cyan
+ default {
+ error unsupported
+ }
+ }
+ }
+}
+
+# DECRST (CSI ? l)
+#
+# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
+proc Term::_csi_0x3f_l { args } {
+ foreach item $args {
+ switch -exact -- $item {
+ 1 {
+ _log "ignored: Normal Cursor Keys"
}
7 {
- return white
+ _log "ignored: no autowrap mode"
+ }
+ 1000 {
+ _log "ignored: Don't send Mouse X & Y on button press and release"
+ }
+ 1006 {
+ _log "ignored: Disable SGR Mouse Mode"
+ }
+ 1049 {
+ _log "switch from alternate screen"
+ _set_alternate 0
+ }
+ default {
+ error "unsupported"
}
- default { error "unsupported color number: $n" }
}
}
+}
- # Select Graphic Rendition.
- #
- # https://vt100.net/docs/vt510-rm/SGR.html
- proc _csi_m {args} {
- _log_cur "Select Graphic Rendition ([join $args {, }])" {
- variable _attrs
+# Reset the attributes in attributes array UPVAR_NAME to the default values.
+proc Term::_reset_attrs { upvar_name } {
+ upvar $upvar_name var
+ array set var {
+ intensity normal
+ fg default
+ bg default
+ underline 0
+ reverse 0
+ invisible 0
+ blinking 0
+ }
+}
- foreach item $args {
- switch -exact -- $item {
- "" - 0 {
- _reset_attrs _attrs
- }
- 1 {
- set _attrs(intensity) bold
- }
- 2 {
- set _attrs(intensity) dim
- }
- 4 {
- set _attrs(underline) 1
- }
- 5 {
- set _attrs(blinking) 1
- }
- 7 {
- set _attrs(reverse) 1
- }
- 8 {
- set _attrs(invisible) 1
- }
- 22 {
- set _attrs(intensity) normal
- }
- 24 {
- set _attrs(underline) 0
- }
- 25 {
- set _attrs(blinking) 0
- }
- 27 {
- set _attrs(reverse) 0
- }
- 28 {
- set _attrs(invisible) 0
- }
- 30 - 31 - 32 - 33 - 34 - 35 - 36 - 37 {
- set _attrs(fg) [_color_attr [expr $item - 30]]
- }
- 39 {
- set _attrs(fg) default
- }
- 40 - 41 - 42 - 43 - 44 - 45 - 46 - 47 {
- set _attrs(bg) [_color_attr [expr $item - 40]]
- }
- 49 {
- set _attrs(bg) default
- }
+# Translate the color numbers as used in proc _csi_m to a name.
+proc Term::_color_attr { n } {
+ switch -exact -- $n {
+ 0 {
+ return black
+ }
+ 1 {
+ return red
+ }
+ 2 {
+ return green
+ }
+ 3 {
+ return yellow
+ }
+ 4 {
+ return blue
+ }
+ 5 {
+ return magenta
+ }
+ 6 {
+ return cyan
+ }
+ 7 {
+ return white
+ }
+ default { error "unsupported color number: $n" }
+ }
+}
+
+# Select Graphic Rendition.
+#
+# https://vt100.net/docs/vt510-rm/SGR.html
+proc Term::_csi_m {args} {
+ if { [llength $args] == 0 } {
+ # Apply default.
+ set args [list 0]
+ }
+
+ _log_cur "Select Graphic Rendition ([join $args {, }])" {
+ variable _attrs
+
+ foreach item $args {
+ switch -exact -- $item {
+ "" - 0 {
+ _reset_attrs _attrs
+ }
+ 1 {
+ set _attrs(intensity) bold
+ }
+ 2 {
+ set _attrs(intensity) dim
+ }
+ 4 {
+ set _attrs(underline) 1
+ }
+ 5 {
+ set _attrs(blinking) 1
+ }
+ 7 {
+ set _attrs(reverse) 1
+ }
+ 8 {
+ set _attrs(invisible) 1
+ }
+ 22 {
+ set _attrs(intensity) normal
+ }
+ 24 {
+ set _attrs(underline) 0
+ }
+ 25 {
+ set _attrs(blinking) 0
+ }
+ 27 {
+ set _attrs(reverse) 0
+ }
+ 28 {
+ set _attrs(invisible) 0
+ }
+ 30 - 31 - 32 - 33 - 34 - 35 - 36 - 37 {
+ set _attrs(fg) [_color_attr [expr $item - 30]]
+ }
+ 39 {
+ set _attrs(fg) default
+ }
+ 40 - 41 - 42 - 43 - 44 - 45 - 46 - 47 {
+ set _attrs(bg) [_color_attr [expr $item - 40]]
+ }
+ 49 {
+ set _attrs(bg) default
}
}
}
}
+}
+
+# Request Terminal Parameters (DECREQTPARM)
+#
+# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
+# https://vt100.net/docs/vt100-ug/chapter3.html
+proc Term::_csi_x {} {
+ # Ignore.
+}
+
+# Insert string at the cursor location.
+proc Term::_insert {str} {
+ _log_cur "Inserted string '$str'" {
+ _log "Inserting string '$str'"
- # Insert string at the cursor location.
- proc _insert {str} {
- _log_cur "Inserted string '$str'" {
- _log "Inserting string '$str'"
-
- variable _cur_col
- variable _cur_row
- variable _rows
- variable _cols
- variable _attrs
- variable _chars
- set lattr [array get _attrs]
- foreach char [split $str {}] {
- _log_cur " Inserted char '$char'" {
- set _chars($_cur_col,$_cur_row) [list $char $lattr]
- incr _cur_col
- if {$_cur_col >= $_cols} {
- set _cur_col 0
- incr _cur_row
- if {$_cur_row >= $_rows} {
- error "FIXME scroll"
- }
+ variable _cur_col
+ variable _cur_row
+ variable _rows
+ variable _cols
+ variable _attrs
+ variable _chars
+ set lattr [array get _attrs]
+ foreach char [split $str {}] {
+ _log_cur " Inserted char '$char'" {
+ set _chars($_cur_col,$_cur_row) [list $char $lattr]
+ incr _cur_col
+ if {$_cur_col >= $_cols} {
+ set _cur_col 0
+ incr _cur_row
+ if {$_cur_row >= $_rows} {
+ error "FIXME scroll"
}
}
}
}
+
+ variable _last_char
+ set _last_char [string index $str end]
}
+}
- # Move the cursor to the (0-based) COL and ROW positions.
- proc _move_cursor { col row } {
- variable _cols
- variable _rows
- variable _cur_col
- variable _cur_row
+# Move the cursor to the (0-based) COL and ROW positions.
+proc Term::_move_cursor { col row } {
+ variable _cols
+ variable _rows
+ variable _cur_col
+ variable _cur_row
- if { $col < 0 || $col >= $_cols } {
- error "_move_cursor: invalid col value: $col"
- }
+ if { $col < 0 || $col >= $_cols } {
+ error "_move_cursor: invalid col value: $col"
+ }
- if { $row < 0 || $row >= $_rows } {
- error "_move_cursor: invalid row value: $row"
- }
+ if { $row < 0 || $row >= $_rows } {
+ error "_move_cursor: invalid row value: $row"
+ }
- set _cur_col $col
- set _cur_row $row
+ set _cur_col $col
+ set _cur_row $row
+}
+
+# Enable or disable alternate screen.
+proc Term::_set_alternate { enable } {
+ variable _alternate
+ if { $enable == $_alternate } {
+ return
}
+ set _alternate $enable
- # Initialize.
- proc _setup {rows cols} {
- global stty_init
- set stty_init "rows $rows columns $cols"
+ variable _attrs
+ variable _chars
+ variable _cur_col
+ variable _cur_row
- variable _rows
- variable _cols
- variable _cur_col
- variable _cur_row
- variable _attrs
- variable _resize_count
+ variable _save_attrs
+ variable _save_chars
+ variable _save_cur_col
+ variable _save_cur_row
- set _rows $rows
- set _cols $cols
- set _cur_col 0
- set _cur_row 0
- set _resize_count 0
- _reset_attrs _attrs
-
- _clear_lines 0 $_rows
- }
-
- # Accept some output from gdb and update the screen.
- # Return 1 if successful, or 0 if a timeout occurred.
- proc accept_gdb_output { } {
- global expect_out
- gdb_expect {
- -re "^\[\x07\x08\x0a\x0d\]" {
- scan $expect_out(0,string) %c val
- set hexval [format "%02x" $val]
- _log "wait_for: _ctl_0x${hexval}"
- _ctl_0x${hexval}
- }
- -re "^\x1b(\[0-9a-zA-Z\])" {
- _log "wait_for: unsupported escape"
- error "unsupported escape"
- }
- -re "^\x1b\\\[(\[0-9;\]*)(\[a-zA-Z@\])" {
- set cmd $expect_out(2,string)
- set params [split $expect_out(1,string) ";"]
- _log "wait_for: _csi_$cmd <<<$expect_out(1,string)>>>"
- eval _csi_$cmd $params
- }
- -re "^\[^\x07\x08\x0a\x0d\x1b\]+" {
- _insert $expect_out(0,string)
- variable _last_char
- set _last_char [string index $expect_out(0,string) end]
- }
+ variable _alternate_setup
- timeout {
- # Assume a timeout means we somehow missed the
- # expected result, and carry on.
- warning "timeout in accept_gdb_output"
- dump_screen
- return 0
- }
- }
+ if { $_alternate_setup } {
+ set tmp $_save_chars
+ }
+ set _save_chars [array get _chars]
+ if { $_alternate_setup } {
+ array set _chars $tmp
+ }
- return 1
+ if { $_alternate_setup } {
+ set tmp $_save_attrs
+ }
+ set _save_attrs [array get _attrs]
+ if { $_alternate_setup } {
+ array set _attrs $tmp
}
- # Print arg using "verbose -log" if DEBUG_TUI_MATCHING == 1.
- proc debug_tui_matching { arg } {
- set debug 0
- if { [info exists ::DEBUG_TUI_MATCHING] } {
- set debug $::DEBUG_TUI_MATCHING
- }
+ if { $_alternate_setup } {
+ set tmp $_save_cur_col
+ }
+ set _save_cur_col $_cur_col
+ if { $_alternate_setup } {
+ set _cur_col $tmp
+ }
- if { ! $debug } {
- return
- }
+ if { $_alternate_setup } {
+ set tmp $_save_cur_row
+ }
+ set _save_cur_row $_cur_row
+ if { $_alternate_setup } {
+ set _cur_row $tmp
+ }
- verbose -log "$arg"
+ if { ! $_alternate_setup } {
+ variable _rows
+ variable _cols
+ _setup $_rows $_cols
+ set _alternate_setup 1
}
+}
- # Accept some output from gdb and update the screen. WAIT_FOR is
- # a regexp matching the line to wait for. Return 0 on timeout, 1
- # on success.
- proc wait_for {wait_for} {
- global gdb_prompt
- variable _cur_col
- variable _cur_row
+# Initialize.
+proc Term::_setup {rows cols} {
+ global stty_init
+ set stty_init "rows $rows columns $cols"
+
+ variable _rows
+ variable _cols
+ variable _cur_col
+ variable _cur_row
+ variable _attrs
+ variable _resize_count
+
+ set _rows $rows
+ set _cols $cols
+ set _cur_col 0
+ set _cur_row 0
+ set _resize_count 0
+ _reset_attrs _attrs
- set fn "wait_for"
+ _clear_lines 0 $_rows
+}
- set prompt_wait_for "(^|\\|)$gdb_prompt \$"
- if { $wait_for == "" } {
- set wait_for $prompt_wait_for
+# Accept some output from gdb and update the screen.
+# Return 1 if successful, or 0 if a timeout occurred.
+proc Term::accept_gdb_output { {warn 1} } {
+ global expect_out
+
+ set ctls "\x07\x08\x0a\x0d"
+ set esc "\x1b"
+ set re_ctls "\[$ctls\]"
+ set re_others "\[^$esc$ctls\]"
+ set have_esc 0
+ gdb_expect {
+ -re ^$re_ctls {
+ scan $expect_out(0,string) %c val
+ set hexval [format "%02x" $val]
+ _log "wait_for: _ctl_0x${hexval}"
+ _ctl_0x${hexval}
+ }
+ -re "^$esc" {
+ _log "wait_for: ESC"
+ set have_esc 1
+ }
+ -re "^$re_others+" {
+ _insert $expect_out(0,string)
+ }
+
+ timeout {
+ # Assume a timeout means we somehow missed the
+ # expected result, and carry on.
+ warning "timeout in accept_gdb_output"
+ dump_screen
+ return 0
}
+ }
- debug_tui_matching "$fn: regexp: '$wait_for'"
+ if { !$have_esc } {
+ return 1
+ }
- while 1 {
- if { [accept_gdb_output] == 0 } {
- return 0
- }
+ set re_csi [string_to_regexp "\["]
+ set have_csi 0
+ gdb_expect {
+ -re "^(\[0-9a-zA-Z\])" {
+ _log "wait_for: unsupported escape"
+ error "unsupported escape"
+ }
+ -re "^(\[\\(\])(\[a-zA-Z\])" {
+ scan $expect_out(1,string) %c val
+ set hexval [format "%02x" $val]
+ set cmd $expect_out(2,string)
+ eval _esc_0x${hexval}_$cmd
+ }
+ -re "^(\[=>\])" {
+ scan $expect_out(1,string) %c val
+ set hexval [format "%02x" $val]
+ _esc_0x$hexval
+ }
+ -re "^$re_csi" {
+ _log "wait_for: CSI"
+ set have_csi 1
+ }
- # If the cursor appears just after the prompt, return. It
- # isn't reliable to check this only after an insertion,
- # because curses may make "unusual" redrawing decisions.
- if {$wait_for == "$prompt_wait_for"} {
- set prev [get_line $_cur_row $_cur_col]
- } else {
- set prev [get_line $_cur_row]
- }
- if {[regexp -- $wait_for $prev]} {
- debug_tui_matching "$fn: match: '$prev'"
- if {$wait_for == "$prompt_wait_for"} {
- break
- }
- set wait_for $prompt_wait_for
- debug_tui_matching "$fn: regexp prompt: '$wait_for'"
- } else {
- debug_tui_matching "$fn: mismatch: '$prev'"
+ timeout {
+ # Assume a timeout means we somehow missed the
+ # expected result, and carry on.
+ if { $warn } {
+ warning "timeout in accept_gdb_output following ESC"
+ dump_screen
}
+ _insert "^\["
+ return 0
}
+ }
+ if { !$have_csi } {
return 1
}
- # Accept some output from gdb and update the screen. Wait for the screen
- # region X/Y/WIDTH/HEIGTH to matches REGEXP. Return 0 on timeout, 1 on
- # success.
- proc wait_for_region_contents {x y width height regexp} {
- while 1 {
- if { [accept_gdb_output] == 0 } {
- return 0
- }
-
- if { [check_region_contents_p $x $y $width $height $regexp] } {
- break
+ set re_csi_prefix {[?]}
+ set re_csi_args {[0-9;]}
+ set re_csi_cmd {[a-zA-Z@`]}
+ gdb_expect {
+ -re "^($re_csi_cmd)" {
+ set cmd $expect_out(1,string)
+ _log "wait_for: _csi_$cmd"
+ eval _csi_$cmd
+ }
+ -re "^($re_csi_args*)($re_csi_cmd)" {
+ set params [split $expect_out(1,string) ";"]
+ set cmd $expect_out(2,string)
+ _log "wait_for: _csi_$cmd <<<$params>>>"
+ eval _csi_$cmd $params
+ }
+ -re "^($re_csi_prefix?)($re_csi_args*)($re_csi_cmd)" {
+ set prefix $expect_out(1,string)
+ set params [split $expect_out(2,string) ";"]
+ set cmd $expect_out(3,string)
+ scan $prefix %c val
+ set hexval [format "%02x" $val]
+ _log "wait_for: _csi_0x${hexval}_$cmd <<<$expect_out(1,string)>>>"
+ eval _csi_0x${hexval}_$cmd $params
+ }
+
+ timeout {
+ # Assume a timeout means we somehow missed the
+ # expected result, and carry on.
+ if { $warn } {
+ warning "timeout in accept_gdb_output following CSI"
+ dump_screen
}
+ _insert "^\[\["
+ return 0
}
+ }
- return 1
+ return 1
+}
+
+# Print arg using "verbose -log" if DEBUG_TUI_MATCHING == 1.
+proc Term::debug_tui_matching { arg } {
+ set debug 0
+ if { [info exists ::DEBUG_TUI_MATCHING] } {
+ set debug $::DEBUG_TUI_MATCHING
}
- # Setup the terminal with dimensions ROWSxCOLS, TERM=ansi, and execute
- # BODY.
- proc with_tuiterm {rows cols body} {
- global env stty_init
- save_vars {env(TERM) env(NO_COLOR) stty_init} {
- setenv TERM ansi
- setenv NO_COLOR ""
- _setup $rows $cols
+ if { ! $debug } {
+ return
+ }
- uplevel $body
- }
+ verbose -log "$arg"
+}
+
+# Accept some output from gdb and update the screen. WAIT_FOR is
+# a regexp matching the line to wait for. Return 0 on timeout, 1
+# on success.
+proc Term::wait_for {wait_for} {
+ global gdb_prompt
+ variable _cur_col
+ variable _cur_row
+
+ set fn "wait_for"
+
+ set prompt_wait_for "(^|\\|)$gdb_prompt \$"
+ if { $wait_for == "" } {
+ set wait_for $prompt_wait_for
}
- # Like ::clean_restart, but ensures that gdb starts in an
- # environment where the TUI can work. ROWS and COLS are the size
- # of the terminal. EXECUTABLE, if given, is passed to
- # clean_restart.
- proc clean_restart {rows cols {executable {}}} {
- with_tuiterm $rows $cols {
- save_vars { ::GDBFLAGS } {
- # Make GDB not print the directory names. Use this setting to
- # remove the differences in test runs due to varying directory
- # names.
- append ::GDBFLAGS " -ex \"set filename-display basename\""
+ debug_tui_matching "$fn: regexp: '$wait_for'"
- if {$executable == ""} {
- ::clean_restart
- } else {
- ::clean_restart $executable
- }
- }
+ while 1 {
+ if { [accept_gdb_output] == 0 } {
+ return 0
+ }
- ::gdb_test_no_output "set pagination off"
+ # If the cursor appears just after the prompt, return. It
+ # isn't reliable to check this only after an insertion,
+ # because curses may make "unusual" redrawing decisions.
+ if {$wait_for == "$prompt_wait_for"} {
+ set prev [get_line $_cur_row $_cur_col]
+ } else {
+ set prev [get_line $_cur_row]
}
- }
- # Generate prompt on TUIterm.
- proc gen_prompt {} {
- # Generate a prompt.
- send_gdb "echo\n"
+ if { ![regexp -- $wait_for $prev] } {
+ debug_tui_matching "$fn: mismatch: '$prev'"
+ continue
+ }
- # Drain the output before the prompt.
- gdb_expect {
- -re "echo\r\n" {
+ if {$wait_for == "$prompt_wait_for"} {
+ # We've detected that the cursor is just after the prompt.
+ # Now check that there's nothing else on the line.
+ set prev [get_line $_cur_row]
+ if { ![regexp -- "(^|\\|)$gdb_prompt +($|\\||\\+)" $prev] } {
+ debug_tui_matching "$fn: mismatch: '$prev'"
+ continue
}
}
- # Interpret prompt using TUIterm.
- wait_for ""
- }
+ debug_tui_matching "$fn: match: '$prev'"
- # Setup ready for starting the tui, but don't actually start it.
- # Returns 1 on success, 0 if TUI tests should be skipped.
- proc prepare_for_tui {} {
- if { [is_remote host] } {
- # In clean_restart, we're using "setenv TERM ansi", which has
- # effect on build. If we have [is_remote host] == 0, so
- # build == host, then it also has effect on host. But for
- # [is_remote host] == 1, it has no effect on host.
- return 0
+ if {$wait_for == "$prompt_wait_for"} {
+ # Matched the prompt, we're done.
+ break
}
- if {![allow_tui_tests]} {
+ # Now try to match the prompt.
+ set wait_for $prompt_wait_for
+ debug_tui_matching "$fn: regexp prompt: '$wait_for'"
+ }
+
+ return 1
+}
+
+# Accept some output from gdb and update the screen. Wait for the screen
+# region X/Y/WIDTH/HEIGTH to matches REGEXP. Return 0 on timeout, 1 on
+# success.
+proc Term::wait_for_region_contents {x y width height regexp} {
+ while 1 {
+ if { [accept_gdb_output] == 0 } {
return 0
}
- gdb_test_no_output "set tui border-kind ascii"
- gdb_test_no_output "maint set tui-resize-message on"
- return 1
+ if { [check_region_contents_p $x $y $width $height $regexp] } {
+ break
+ }
}
- # Start the TUI. Returns 1 on success, 0 if TUI tests should be
- # skipped.
- proc enter_tui {} {
- if {![prepare_for_tui]} {
+ return 1
+}
+
+# Accept some output from gdb and update the screen. Wait for the current
+# screen line to match REGEXP and cursor position POS, unless POS is empty.
+# Return 0 on timeout, 1 on success.
+proc Term::wait_for_line { regexp {pos ""} } {
+ variable _cur_row
+ variable _cur_col
+ variable _cols
+
+ while 1 {
+ if { [accept_gdb_output] == 0 } {
return 0
}
- command_no_prompt_prefix "tui enable"
- return 1
- }
+ if { ![check_region_contents_p 0 $_cur_row $_cols 1 $regexp] } {
+ continue
+ }
- # Send the command CMD to gdb, then wait for a gdb prompt to be
- # seen in the TUI. CMD should not end with a newline -- that will
- # be supplied by this function.
- proc command {cmd} {
- global gdb_prompt
- send_gdb "$cmd\n"
- set str [string_to_regexp $cmd]
- set str "(^|\\|)$gdb_prompt $str"
- wait_for $str
- }
-
- # As proc command, but don't wait for an initial prompt. This is used for
- # initial terminal commands, where there's no prompt yet.
- proc command_no_prompt_prefix {cmd} {
- gen_prompt
- command $cmd
- }
-
- # Apply the attribute list in ATTRS to attributes array UPVAR_NAME.
- # Return a string annotating the changed attributes.
- proc apply_attrs { upvar_name attrs } {
- set res ""
- upvar $upvar_name var
- foreach { attr val } $attrs {
- if { $var($attr) != $val } {
- append res "<$attr:$val>"
- set var($attr) $val
- }
+ if { $pos == "" || $_cur_col == $pos } {
+ break
}
+ }
+
+ return 1
+}
+
+# In BODY, when using Term::with_tuiterm, use TERM instead of the default.
- return $res
+proc Term::with_term { term body } {
+ save_vars { Term::_TERM } {
+ set Term::_TERM $term
+ uplevel $body
}
+}
- # Return the text of screen line N. Lines are 0-based. If C is given,
- # stop before column C. Columns are also zero-based. If ATTRS, annotate
- # with attributes.
- proc get_line_1 {n c attrs} {
- variable _rows
- # This can happen during resizing, if the cursor seems to
- # temporarily be off-screen.
- if {$n >= $_rows} {
- return ""
+# Setup the terminal with dimensions ROWSxCOLS, TERM=ansi, and execute
+# BODY.
+proc Term::with_tuiterm {rows cols body} {
+ global env stty_init
+ variable _TERM
+ save_vars {env(TERM) env(NO_COLOR) stty_init} {
+ if { $Term::_TERM != "" } {
+ setenv TERM $Term::_TERM
+ } elseif { [ishost *-*-*bsd*] } {
+ setenv TERM ansiw
+ } else {
+ setenv TERM ansi
}
+ # Save active TERM variable.
+ set Term::_TERM $env(TERM)
- set result ""
- variable _cols
- variable _chars
- set c [_default $c $_cols]
- set x 0
- if { $attrs } {
- _reset_attrs line_attrs
- }
- while {$x < $c} {
- if { $attrs } {
- set char_attrs [lindex $_chars($x,$n) 1]
- append result [apply_attrs line_attrs $char_attrs]
+ setenv NO_COLOR ""
+ _setup $rows $cols
+
+ uplevel $body
+ }
+}
+
+# Like ::clean_restart, but ensures that gdb starts in an
+# environment where the TUI can work. ROWS and COLS are the size
+# of the terminal. EXECUTABLE, if given, is passed to
+# clean_restart.
+proc Term::clean_restart {rows cols {executable {}}} {
+ with_tuiterm $rows $cols {
+ save_vars { ::GDBFLAGS } {
+ # Make GDB not print the directory names. Use this setting to
+ # remove the differences in test runs due to varying directory
+ # names.
+ append ::GDBFLAGS " -ex \"set filename-display basename\""
+
+ if {$executable == ""} {
+ ::clean_restart
+ } else {
+ ::clean_restart $executable
}
- append result [lindex $_chars($x,$n) 0]
- incr x
}
- if { $attrs } {
- _reset_attrs zero_attrs
- set char_attrs [array get zero_attrs]
- append result [apply_attrs line_attrs $char_attrs]
+
+ ::gdb_test_no_output "set pagination off"
+ }
+}
+
+# Generate prompt on TUIterm.
+proc Term::gen_prompt {} {
+ # Generate a prompt.
+ send_gdb "echo\n"
+
+ # Drain the output before the prompt.
+ gdb_expect {
+ -re "echo\r\n" {
}
- return $result
}
- # Return the text of screen line N, without attributes. Lines are
- # 0-based. If C is given, stop before column C. Columns are also
- # zero-based.
- proc get_line {n {c ""} } {
- return [get_line_1 $n $c 0]
+ # Interpret prompt using TUIterm.
+ wait_for ""
+}
+
+# Setup ready for starting the tui, but don't actually start it.
+# Returns 1 on success, 0 if TUI tests should be skipped.
+proc Term::prepare_for_tui {} {
+ if { [is_remote host] } {
+ # In clean_restart, we're using "setenv TERM ansi", which has
+ # effect on build. If we have [is_remote host] == 0, so
+ # build == host, then it also has effect on host. But for
+ # [is_remote host] == 1, it has no effect on host.
+ return 0
}
- # As get_line, but annotate with attributes.
- proc get_line_with_attrs {n {c ""}} {
- return [get_line_1 $n $c 1]
+ if {![allow_tui_tests]} {
+ return 0
}
- # Get just the character at (X, Y).
- proc get_char {x y} {
- variable _chars
- return [lindex $_chars($x,$y) 0]
+ gdb_test_no_output "set tui border-kind ascii"
+ gdb_test_no_output "maint set tui-resize-message on"
+ # When matching GDB output using Term::wait_for, the number of
+ # matching attempts in wait_for can be influenced by CLI styling.
+ # Disable it by default to avoid this.
+ gdb_test_no_output "set style enabled off"
+ return 1
+}
+
+# Start the TUI. Returns 1 on success, 0 if TUI tests should be
+# skipped.
+proc Term::enter_tui {} {
+ if {![prepare_for_tui]} {
+ return 0
}
- # Get the entire screen as a string.
- proc get_all_lines {} {
- variable _rows
- variable _cols
- variable _chars
+ command_no_prompt_prefix "tui enable"
+ return 1
+}
- set result ""
- for {set y 0} {$y < $_rows} {incr y} {
- for {set x 0} {$x < $_cols} {incr x} {
- append result [lindex $_chars($x,$y) 0]
- }
- append result "\n"
+# Send the command CMD to gdb, then wait for a gdb prompt to be
+# seen in the TUI. CMD should not end with a newline -- that will
+# be supplied by this function.
+proc Term::command {cmd} {
+ global gdb_prompt
+ send_gdb "$cmd\n"
+ set str [string_to_regexp $cmd]
+ set str "(^|\\|)$gdb_prompt $str"
+ wait_for $str
+}
+
+# As proc command, but don't wait for an initial prompt. This is used for
+# initial terminal commands, where there's no prompt yet.
+proc Term::command_no_prompt_prefix {cmd} {
+ gen_prompt
+ command $cmd
+}
+
+# Apply the attribute list in ATTRS to attributes array UPVAR_NAME.
+# Return a string annotating the changed attributes.
+proc Term::apply_attrs { upvar_name attrs } {
+ set res ""
+ upvar $upvar_name var
+ foreach { attr val } $attrs {
+ if { $var($attr) != $val } {
+ append res "<$attr:$val>"
+ set var($attr) $val
}
+ }
+
+ return $res
+}
- return $result
+# Return the text of screen line N. Lines are 0-based. Start at column
+# X. If C is non-empty, stop before column C. Columns are also
+# zero-based. If ATTRS, annotate with attributes.
+proc Term::get_string {n x c {attrs 0}} {
+ variable _rows
+ # This can happen during resizing, if the cursor seems to
+ # temporarily be off-screen.
+ if {$n >= $_rows} {
+ return ""
}
- # Get the text just before the cursor.
- proc get_current_line {} {
- variable _cur_col
- variable _cur_row
- return [get_line $_cur_row $_cur_col]
+ set result ""
+ variable _cols
+ variable _chars
+ set c [_default $c $_cols]
+ if { $attrs } {
+ _reset_attrs line_attrs
+ }
+ while {$x < $c} {
+ if { $attrs } {
+ set char_attrs [lindex $_chars($x,$n) 1]
+ append result [apply_attrs line_attrs $char_attrs]
+ }
+ append result [lindex $_chars($x,$n) 0]
+ incr x
+ }
+ if { $attrs } {
+ _reset_attrs zero_attrs
+ set char_attrs [array get zero_attrs]
+ append result [apply_attrs line_attrs $char_attrs]
}
+ return $result
+}
- # Helper function for check_box. Returns empty string if the box
- # is found, description of why not otherwise.
- proc _check_box {x y width height} {
- set x2 [expr {$x + $width - 1}]
- set y2 [expr {$y + $height - 1}]
+# Return the text of screen line N. Lines are 0-based. Start at column
+# X. If C is non-empty, stop before column C. Columns are also
+# zero-based. Annotate with attributes.
+proc Term::get_string_with_attrs { n x c } {
+ return [get_string $n $x $c 1]
+}
- verbose -log "_check_box x=$x, y=$y, x2=$x2, y2=$y2, width=$width, height=$height"
+# Return the text of screen line N. Lines are 0-based. If C is
+# non-empty, stop before column C. Columns are also zero-based. If
+# ATTRS, annotate with attributes.
+proc Term::get_line_1 {n c attrs} {
+ return [get_string $n 0 $c $attrs]
+}
- set c [get_char $x $y]
- if {$c != "+"} {
- return "ul corner is $c, not +"
- }
+# Return the text of screen line N, without attributes. Lines are
+# 0-based. If C is given, stop before column C. Columns are also
+# zero-based.
+proc Term::get_line {n {c ""} } {
+ return [get_line_1 $n $c 0]
+}
- set c [get_char $x $y2]
- if {$c != "+"} {
- return "ll corner is $c, not +"
- }
+# As get_line, but annotate with attributes.
+proc Term::get_line_with_attrs {n {c ""}} {
+ return [get_line_1 $n $c 1]
+}
- set c [get_char $x2 $y]
- if {$c != "+"} {
- return "ur corner is $c, not +"
- }
+# Get just the character at (X, Y).
+proc Term::get_char {x y} {
+ variable _chars
+ return [lindex $_chars($x,$y) 0]
+}
- set c [get_char $x2 $y2]
- if {$c != "+"} {
- return "lr corner is $c, not +"
- }
+# Get the entire screen as a string.
+proc Term::get_all_lines {} {
+ variable _rows
+ variable _cols
+ variable _chars
- # Note we do not check the full horizonal borders of the box.
- # The top will contain a title, and the bottom may as well, if
- # it is overlapped by some other border. However, at most a
- # title should appear as '+-VERY LONG TITLE-+', so we can
- # check for the '+-' on the left, and '-+' on the right.
- set c [get_char [expr {$x + 1}] $y]
- if {$c != "-"} {
- return "ul title padding is $c, not -"
+ set result ""
+ for {set y 0} {$y < $_rows} {incr y} {
+ for {set x 0} {$x < $_cols} {incr x} {
+ append result [lindex $_chars($x,$y) 0]
}
+ append result "\n"
+ }
- set c [get_char [expr {$x2 - 1}] $y]
- if {$c != "-"} {
- return "ul title padding is $c, not -"
- }
+ return $result
+}
- # Now check the vertical borders.
- for {set i [expr {$y + 1}]} {$i < $y2 - 1} {incr i} {
- set c [get_char $x $i]
- if {$c != "|"} {
- return "left side $i is $c, not |"
- }
+# Get the text just before the cursor.
+proc Term::get_current_line {} {
+ variable _cur_col
+ variable _cur_row
+ return [get_line $_cur_row $_cur_col]
+}
- set c [get_char $x2 $i]
- if {$c != "|"} {
- return "right side $i is $c, not |"
- }
- }
+# Helper function for check_box. Returns empty string if the box
+# is found, description of why not otherwise.
+proc Term::_check_box {x y width height} {
+ set x2 [expr {$x + $width - 1}]
+ set y2 [expr {$y + $height - 1}]
- return ""
+ verbose -log "_check_box x=$x, y=$y, x2=$x2, y2=$y2, width=$width, height=$height"
+
+ set c [get_char $x $y]
+ if {$c != "+"} {
+ return "ul corner is $c, not +"
}
- # Check for a box at the given coordinates.
- proc check_box {test_name x y width height} {
- dump_box $x $y $width $height
- set why [_check_box $x $y $width $height]
- if {$why == ""} {
- pass $test_name
- } else {
- fail "$test_name ($why)"
- }
+ set c [get_char $x $y2]
+ if {$c != "+"} {
+ return "ll corner is $c, not +"
}
- # Wait until a box appears at the given coordinates.
- proc wait_for_box {test_name x y width height} {
- while 1 {
- if { [accept_gdb_output] == 0 } {
- return 0
- }
+ set c [get_char $x2 $y]
+ if {$c != "+"} {
+ return "ur corner is $c, not +"
+ }
- set why [_check_box $x $y $width $height]
- if {$why == ""} {
- pass $test_name
- break
- }
- }
+ set c [get_char $x2 $y2]
+ if {$c != "+"} {
+ return "lr corner is $c, not +"
}
- # Check whether the text contents of the terminal match the
- # regular expression. Note that text styling is not considered.
- proc check_contents {test_name regexp} {
- dump_screen
- set contents [get_all_lines]
- gdb_assert {[regexp -- $regexp $contents]} $test_name
+ # Note we do not check the full horizonal borders of the box.
+ # The top will contain a title, and the bottom may as well, if
+ # it is overlapped by some other border. However, at most a
+ # title should appear as '+-VERY LONG TITLE-+', so we can
+ # check for the '+-' on the left, and '-+' on the right.
+ set c [get_char [expr {$x + 1}] $y]
+ if {$c != "-"} {
+ return "ul title padding is $c, not -"
}
- # As check_contents, but check that the text contents of the terminal does
- # not match the regular expression.
- proc check_contents_not {test_name regexp} {
- dump_screen
- set contents [get_all_lines]
- gdb_assert {![regexp -- $regexp $contents]} $test_name
+ set c [get_char [expr {$x2 - 1}] $y]
+ if {$c != "-"} {
+ return "ul title padding is $c, not -"
}
- # Get the region of the screen described by X, Y, WIDTH,
- # and HEIGHT, and separate the lines using SEP.
- proc get_region { x y width height sep } {
- variable _chars
+ # Now check the vertical borders.
+ for {set i [expr {$y + 1}]} {$i < $y2 - 1} {incr i} {
+ set c [get_char $x $i]
+ if {$c != "|"} {
+ return "left side $i is $c, not |"
+ }
- # Grab the contents of the box, join each line together
- # using $sep.
- set result ""
- for {set yy $y} {$yy < [expr {$y + $height}]} {incr yy} {
- if {$yy > $y} {
- # Add the end of line sequence only if this isn't the
- # first line.
- append result $sep
- }
- for {set xx $x} {$xx < [expr {$x + $width}]} {incr xx} {
- append result [lindex $_chars($xx,$yy) 0]
- }
+ set c [get_char $x2 $i]
+ if {$c != "|"} {
+ return "right side $i is $c, not |"
}
- return $result
}
- # Check that the region of the screen described by X, Y, WIDTH,
- # and HEIGHT match REGEXP. This is like check_contents except
- # only part of the screen is checked. This can be used to check
- # the contents within a box (though check_box_contents is a better
- # choice for boxes with a border). Return 1 if check succeeded.
- proc check_region_contents_p { x y width height regexp } {
- variable _chars
- dump_box $x $y $width $height
+ return ""
+}
- # Now grab the contents of the box, join each line together
- # with a '\r\n' sequence and match against REGEXP.
- set result [get_region $x $y $width $height "\r\n"]
- return [regexp -- $regexp $result]
+# Check for a box at the given coordinates.
+proc Term::check_box {test_name x y width height} {
+ dump_box $x $y $width $height
+ set why [_check_box $x $y $width $height]
+ if {$why == ""} {
+ pass $test_name
+ } else {
+ fail "$test_name ($why)"
}
+}
- # Check that the region of the screen described by X, Y, WIDTH,
- # and HEIGHT match REGEXP. As check_region_contents_p, but produce
- # a pass/fail message.
- proc check_region_contents { test_name x y width height regexp } {
- set ok [check_region_contents_p $x $y $width $height $regexp]
- gdb_assert {$ok} $test_name
+# Wait until a box appears at the given coordinates.
+proc Term::wait_for_box {test_name x y width height} {
+ while 1 {
+ if { [accept_gdb_output] == 0 } {
+ return 0
+ }
+
+ set why [_check_box $x $y $width $height]
+ if {$why == ""} {
+ pass $test_name
+ break
+ }
}
+}
- # Check the contents of a box on the screen. This is a little
- # like check_contents, but doesn't check the whole screen
- # contents, only the contents of a single box. This procedure
- # includes (effectively) a call to check_box to ensure there is a
- # box where expected, if there is then the contents of the box are
- # matched against REGEXP.
- proc check_box_contents {test_name x y width height regexp} {
- variable _chars
+# Check whether the text contents of the terminal match the
+# regular expression. Note that text styling is not considered.
+proc Term::check_contents {test_name regexp} {
+ dump_screen
+ set contents [get_all_lines]
+ gdb_assert {[regexp -- $regexp $contents]} $test_name
+}
- dump_box $x $y $width $height
- set why [_check_box $x $y $width $height]
- if {$why != ""} {
- fail "$test_name (box check: $why)"
- return
+# As check_contents, but check that the text contents of the terminal does
+# not match the regular expression.
+proc Term::check_contents_not {test_name regexp} {
+ dump_screen
+ set contents [get_all_lines]
+ gdb_assert {![regexp -- $regexp $contents]} $test_name
+}
+
+# Get the region of the screen described by X, Y, WIDTH, and
+# HEIGHT, and separate the lines using SEP. If ATTRS is true then
+# include attribute information in the output.
+proc Term::get_region { x y width height sep { attrs false } } {
+ variable _chars
+
+ if { $attrs } {
+ _reset_attrs region_attrs
+ }
+
+ # Grab the contents of the box, join each line together
+ # using $sep.
+ set result ""
+ for {set yy $y} {$yy < [expr {$y + $height}]} {incr yy} {
+ if {$yy > $y} {
+ # Add the end of line sequence only if this isn't the
+ # first line.
+ append result $sep
}
+ for {set xx $x} {$xx < [expr {$x + $width}]} {incr xx} {
+ if { $attrs } {
+ set char_attrs [lindex $_chars($xx,$yy) 1]
+ append result [apply_attrs region_attrs $char_attrs]
+ }
- check_region_contents $test_name [expr {$x + 1}] [expr {$y + 1}] \
- [expr {$width - 2}] [expr {$height - 2}] $regexp
+ append result [get_char $xx $yy]
+ }
+ }
+ if { $attrs } {
+ _reset_attrs zero_attrs
+ set char_attrs [array get zero_attrs]
+ append result [apply_attrs region_attrs $char_attrs]
}
+ return $result
+}
- # A debugging function to dump the current screen, with line
- # numbers. If ATTRS, annotate with attributes.
- proc dump_screen { {attrs 0} } {
- variable _rows
- variable _cols
- variable _cur_row
- variable _cur_col
+# Check that the region of the screen described by X, Y, WIDTH,
+# and HEIGHT match REGEXP. This is like check_contents except
+# only part of the screen is checked. This can be used to check
+# the contents within a box (though check_box_contents is a better
+# choice for boxes with a border). Return 1 if check succeeded.
+proc Term::check_region_contents_p { x y width height regexp } {
+ variable _chars
+ dump_box $x $y $width $height
- verbose -log "Screen Dump (size $_cols columns x $_rows rows, cursor at column $_cur_col, row $_cur_row):"
+ # Now grab the contents of the box, join each line together
+ # with a '\r\n' sequence and match against REGEXP.
+ set result [get_region $x $y $width $height "\r\n"]
+ return [regexp -- $regexp $result]
+}
- for {set y 0} {$y < $_rows} {incr y} {
- set fmt [format %5d $y]
- verbose -log "$fmt [get_line_1 $y "" $attrs]"
- }
+# Check that the region of the screen described by X, Y, WIDTH,
+# and HEIGHT match REGEXP. As check_region_contents_p, but produce
+# a pass/fail message.
+proc Term::check_region_contents { test_name x y width height regexp } {
+ set ok [check_region_contents_p $x $y $width $height $regexp]
+ gdb_assert {$ok} $test_name
+}
+
+# Check the contents of a box on the screen. This is a little
+# like check_contents, but doesn't check the whole screen
+# contents, only the contents of a single box. This procedure
+# includes (effectively) a call to check_box to ensure there is a
+# box where expected, if there is then the contents of the box are
+# matched against REGEXP.
+proc Term::check_box_contents {test_name x y width height regexp} {
+ variable _chars
+
+ dump_box $x $y $width $height
+ set why [_check_box $x $y $width $height]
+ if {$why != ""} {
+ fail "$test_name (box check: $why)"
+ return
}
- # As dump_screen, but with attributes annotation.
- proc dump_screen_with_attrs {} {
- return [dump_screen 1]
+ check_region_contents $test_name [expr {$x + 1}] [expr {$y + 1}] \
+ [expr {$width - 2}] [expr {$height - 2}] $regexp
+}
+
+# A debugging function to dump the current screen, with line
+# numbers. If ATTRS, annotate with attributes.
+proc Term::dump_screen { {attrs 0} } {
+ variable _rows
+ variable _cols
+ variable _cur_row
+ variable _cur_col
+
+ verbose -log "Screen Dump (size $_cols columns x $_rows rows, cursor at column $_cur_col, row $_cur_row):"
+
+ for {set y 0} {$y < $_rows} {incr y} {
+ set fmt [format %5d $y]
+ verbose -log "$fmt [get_line_1 $y {} $attrs]"
}
+}
- # A debugging function to dump a box from the current screen, with line
- # numbers.
- proc dump_box { x y width height } {
- verbose -log "Box Dump ($width x $height) @ ($x, $y):"
- set region [get_region $x $y $width $height "\n"]
- set lines [split $region "\n"]
- set nr $y
- foreach line $lines {
- set fmt [format %5d $nr]
- verbose -log "$fmt $line"
- incr nr
- }
+# As dump_screen, but with attributes annotation.
+proc Term::dump_screen_with_attrs {} {
+ return [dump_screen 1]
+}
+
+# A debugging function to dump a box from the current screen, with line
+# numbers.
+proc Term::dump_box { x y width height } {
+ verbose -log "Box Dump ($width x $height) @ ($x, $y):"
+ set region [get_region $x $y $width $height "\n"]
+ set lines [split $region "\n"]
+ set nr $y
+ foreach line $lines {
+ set fmt [format %5d $nr]
+ verbose -log "$fmt $line"
+ incr nr
}
+}
- # Resize the terminal.
- proc _do_resize {rows cols} {
- variable _chars
- variable _rows
- variable _cols
+# Resize the terminal.
+proc Term::_do_resize {rows cols} {
+ variable _chars
+ variable _rows
+ variable _cols
- set old_rows [expr {min ($_rows, $rows)}]
- set old_cols [expr {min ($_cols, $cols)}]
+ set old_rows [expr {min ($_rows, $rows)}]
+ set old_cols [expr {min ($_cols, $cols)}]
- # Copy locally.
- array set local_chars [array get _chars]
- unset _chars
+ # Copy locally.
+ array set local_chars [array get _chars]
+ unset _chars
- set _rows $rows
- set _cols $cols
- _clear_lines 0 $_rows
+ set _rows $rows
+ set _cols $cols
+ _clear_lines 0 $_rows
- for {set x 0} {$x < $old_cols} {incr x} {
- for {set y 0} {$y < $old_rows} {incr y} {
- set _chars($x,$y) $local_chars($x,$y)
- }
+ for {set x 0} {$x < $old_cols} {incr x} {
+ for {set y 0} {$y < $old_rows} {incr y} {
+ set _chars($x,$y) $local_chars($x,$y)
}
}
+}
- proc resize {rows cols {wait_for_msg 1}} {
- variable _rows
- variable _cols
- variable _resize_count
+proc Term::resize {rows cols {wait_for_msg 1}} {
+ variable _rows
+ variable _cols
+ variable _resize_count
- # expect handles each argument to stty separately. This means
- # that gdb will see SIGWINCH twice. Rather than rely on this
- # behavior (which, after all, could be changed), we make it
- # explicit here. This also simplifies waiting for the redraw.
- _do_resize $rows $_cols
- stty rows $_rows < $::gdb_tty_name
- if { $wait_for_msg } {
- wait_for "@@ resize done $_resize_count, size = ${_cols}x${rows}"
- }
- incr _resize_count
- _do_resize $_rows $cols
- stty columns $_cols < $::gdb_tty_name
- if { $wait_for_msg } {
- wait_for "@@ resize done $_resize_count, size = ${_cols}x${rows}"
- }
- incr _resize_count
- }
+ # expect handles each argument to stty separately. This means
+ # that gdb will see SIGWINCH twice. Rather than rely on this
+ # behavior (which, after all, could be changed), we make it
+ # explicit here. This also simplifies waiting for the redraw.
+ _do_resize $rows $_cols
+ stty rows $_rows < $::gdb_tty_name
+ if { $wait_for_msg } {
+ wait_for "@@ resize done $_resize_count, size = ${_cols}x${rows}"
+ }
+ incr _resize_count
+ _do_resize $_rows $cols
+ stty columns $_cols < $::gdb_tty_name
+ if { $wait_for_msg } {
+ wait_for "@@ resize done $_resize_count, size = ${_cols}x${rows}"
+ }
+ incr _resize_count
}