Skip to content

Commit

Permalink
fix(compatibility): improve vttest (#1671)
Browse files Browse the repository at this point in the history
* Improve 'vttest' scenarios:

1. Report terminal as VT220 with sixel rather than VT400 family with
   sixel. This fixes a hang when launching vttest as it is waiting for
   a response to DECRQSS.

2. Test 6.2: Support NewLine mode (CR --> CRLF).

3. Test 6.3: Fix DSR cursor position report to honor scrolling region.

4. Test 6.7: Parse and respond to DECREQTPARM (Request Terminal
   Parameters - CSI x).  This is a VT100 sequence that xterm used to
   respond to always, but more recently only responds to when
   explicitly set to VT100 level.

* cargo fmt

* Fix failing unit test snapshot

* fix clippy error

* VT100 UK character set
  • Loading branch information
AutumnMeowMeow authored Aug 19, 2022
1 parent 639de16 commit a316577
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 12 deletions.
80 changes: 72 additions & 8 deletions zellij-server/src/panes/grid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ pub struct Grid {
pub sixel_scrolling: bool, // DECSDM
pub insert_mode: bool,
pub disable_linewrap: bool,
pub new_line_mode: bool, // Automatic newline LNM
pub clear_viewport_before_rendering: bool,
pub width: usize,
pub height: usize,
Expand Down Expand Up @@ -478,6 +479,7 @@ impl Grid {
sixel_scrolling: false,
insert_mode: false,
disable_linewrap: false,
new_line_mode: false,
alternate_screen_state: None,
clear_viewport_before_rendering: false,
active_charset: Default::default(),
Expand Down Expand Up @@ -1515,6 +1517,7 @@ impl Grid {
self.active_charset = Default::default();
self.erasure_mode = false;
self.disable_linewrap = false;
self.new_line_mode = false;
self.cursor.change_shape(CursorShape::Initial);
self.output_buffer.update_all_lines();
self.changed_colors = None;
Expand Down Expand Up @@ -2350,8 +2353,18 @@ impl Perform for Grid {
_ => {},
};
}
} else if let Some(4) = params_iter.next().map(|param| param[0]) {
self.insert_mode = false;
} else {
for param in params_iter.map(|param| param[0]) {
match param {
4 => {
self.insert_mode = false;
},
20 => {
self.new_line_mode = false;
},
_ => {},
}
}
}
} else if c == 'h' {
let first_intermediate_is_questionmark = match intermediates.get(0) {
Expand Down Expand Up @@ -2434,8 +2447,18 @@ impl Perform for Grid {
_ => {},
}
}
} else if let Some(4) = params_iter.next().map(|param| param[0]) {
self.insert_mode = true;
} else {
for param in params_iter.map(|param| param[0]) {
match param {
4 => {
self.insert_mode = true;
},
20 => {
self.new_line_mode = true;
},
_ => {},
}
}
}
} else if c == 'r' {
if params.len() > 1 {
Expand Down Expand Up @@ -2602,8 +2625,8 @@ impl Perform for Grid {
// https://vt100.net/docs/vt510-rm/DA1.html
match intermediates.get(0) {
None | Some(0) => {
// primary device attributes
let terminal_capabilities = "\u{1b}[?64;4c";
// primary device attributes - VT220 with sixel
let terminal_capabilities = "\u{1b}[?62;4c";
self.pending_messages_to_pty
.push(terminal_capabilities.as_bytes().to_vec());
},
Expand All @@ -2627,13 +2650,41 @@ impl Perform for Grid {
},
6 => {
// CPR - cursor position report
let position_report =
format!("\x1b[{};{}R", self.cursor.y + 1, self.cursor.x + 1);

// Note that this is relative to scrolling region.
let offset = match self.scroll_region {
Some((scroll_region_top, _scroll_region_bottom)) => scroll_region_top,
_ => 0,
};
let position_report = format!(
"\u{1b}[{};{}R",
self.cursor.y + 1 - offset,
self.cursor.x + 1
);
self.pending_messages_to_pty
.push(position_report.as_bytes().to_vec());
},
_ => {},
}
} else if c == 'x' {
// DECREQTPARM - Request Terminal Parameters
// https://vt100.net/docs/vt100-ug/chapter3.html#DECREQTPARM
//
// Respond with (same as xterm): Parity NONE, 8 bits,
// xmitspeed 38400, recvspeed 38400. (CLoCk MULtiplier =
// 1, STP option flags = 0)
//
// (xterm used to respond to DECREQTPARM in all modes.
// Now it seems to only do so when explicitly in VT100 mode.)
let query = next_param_or(0);
match query {
0 | 1 => {
let response = format!("\u{1b}[{};1;1;128;128;1;0x", query + 2);
self.pending_messages_to_pty
.push(response.as_bytes().to_vec());
},
_ => {},
}
} else if c == 't' {
match next_param_or(1) as usize {
14 => {
Expand Down Expand Up @@ -2678,6 +2729,19 @@ impl Perform for Grid {

fn esc_dispatch(&mut self, intermediates: &[u8], _ignore: bool, byte: u8) {
match (byte, intermediates.get(0)) {
(b'A', charset_index_symbol) => {
let charset_index: CharsetIndex = match charset_index_symbol {
Some(b'(') => CharsetIndex::G0,
Some(b')') => CharsetIndex::G1,
Some(b'*') => CharsetIndex::G2,
Some(b'+') => CharsetIndex::G3,
_ => {
// invalid, silently do nothing
return;
},
};
self.configure_charset(StandardCharset::UK, charset_index);
},
(b'B', charset_index_symbol) => {
let charset_index: CharsetIndex = match charset_index_symbol {
Some(b'(') => CharsetIndex::G0,
Expand Down
5 changes: 5 additions & 0 deletions zellij-server/src/panes/terminal_character.rs
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,7 @@ impl Default for CharsetIndex {
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum StandardCharset {
Ascii,
UK,
SpecialCharacterAndLineDrawing,
}

Expand All @@ -602,6 +603,10 @@ impl StandardCharset {
pub fn map(self, c: char) -> char {
match self {
StandardCharset::Ascii => c,
StandardCharset::UK => match c {
'#' => '£',
_ => c,
},
StandardCharset::SpecialCharacterAndLineDrawing => match c {
'`' => '◆',
'a' => '▒',
Expand Down
6 changes: 6 additions & 0 deletions zellij-server/src/panes/terminal_pane.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,12 @@ impl Pane for TerminalPane {
// needs to be adjusted.
// here we match against those cases - if need be, we adjust the input and if not
// we send back the original input
if self.grid.new_line_mode {
if let &[13] = input_bytes.as_slice() {
// LNM - carriage return is followed by linefeed
return "\u{0d}\u{0a}".as_bytes().to_vec();
};
}
if self.grid.cursor_key_mode {
match input_bytes.as_slice() {
LEFT_ARROW => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
---
source: zellij-server/src/panes/./unit/grid_tests.rs
assertion_line: 721
expression: "format!(\"{:?}\", grid.pending_messages_to_pty)"
---
[[27, 91, 63, 54, 52, 59, 52, 99], [27, 91, 56, 59, 53, 49, 59, 57, 55, 116], [27, 91, 63, 54, 99], [27, 91, 48, 110], [27, 91, 49, 59, 49, 82]]
[[27, 91, 63, 54, 50, 59, 52, 99], [27, 91, 56, 59, 53, 49, 59, 57, 55, 116], [27, 91, 63, 54, 99], [27, 91, 48, 110], [27, 91, 49, 59, 49, 82]]
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
---
source: zellij-server/src/panes/./unit/grid_tests.rs
expression: "format!(\"{:?}\", grid)"

---
00 (C): Selected as G0 (with SI) Selected as G1 (with SO)
01 (C):
Expand All @@ -10,7 +9,7 @@ expression: "format!(\"{:?}\", grid)"
04 (C): @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
05 (C): `abcdefghijklmnopqrstuvwxyz{|}~ `abcdefghijklmnopqrstuvwxyz{|}~
06 (C): Character set A (British)
07 (C): !"#$%&'()*+,-./0123456789:;<=>? !"#$%&'()*+,-./0123456789:;<=>?
07 (C): !"£$%&'()*+,-./0123456789:;<=>? !"£$%&'()*+,-./0123456789:;<=>?
08 (C): @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
09 (C): `abcdefghijklmnopqrstuvwxyz{|}~ `abcdefghijklmnopqrstuvwxyz{|}~
10 (C): Character set 0 (DEC Special graphics and line drawing)
Expand Down

0 comments on commit a316577

Please sign in to comment.