Reserve the ability to read XTVERSION

Whenever we add logic to print a control sequence that we hadn't printed
before, there is a nonzero risk that a terminal mishandles it.

Terminal-specific workarounds cause pain but are probably better than not
being able to use any new commands provided by terminals.

There is no universal way to identify a terminal. Device attributes (primary
through tertiary) typically get spoofed responses, likely not good enough
for working around bugs in specific versions of a terminal.

The de-facto standard for the terminal name and version is XTVERSION.
It's usually specific to the terminal, except for something like VTE-based
terminals, where we get this (which seems good enough also)

	printf '\x1b[>0q'; cat
	^[P>|VTE(7803)^[\

Of course querying for XTVERSION can trigger terminal bugs just as well. Let's
start querying for it now -- even without a concrete use case -- to increase
the chance we can use it during crunch time when we don't want to test
anymore. (We typically discover buggy terminals only very late in the release
cycle, most prominently after a release).
This commit is contained in:
Johannes Altmanninger
2025-03-01 12:14:17 +01:00
parent 7c2388fbfc
commit b401aee4ce
2 changed files with 29 additions and 0 deletions

View File

@@ -1306,6 +1306,30 @@ fn parse_ss3(&mut self, buffer: &mut Vec<u8>) -> Option<Key> {
Some(key)
}
fn parse_xtversion(&mut self, buffer: &mut Vec<u8>) {
assert!(buffer.len() == 3);
loop {
match self.try_readb(buffer) {
None => return,
Some(b'\x1b') => break,
Some(_) => continue,
}
}
if self.try_readb(buffer) != Some(b'\\') {
return;
}
if buffer[3] != b'|' {
return;
}
FLOG!(
reader,
format!(
"Received XTVERSION response: {}",
str2wcstring(&buffer[4..buffer.len() - 2]),
)
);
}
fn parse_dcs(&mut self, buffer: &mut Vec<u8>) -> Option<Key> {
assert!(buffer.len() == 2);
let Some(success) = self.try_readb(buffer) else {
@@ -1314,6 +1338,10 @@ fn parse_dcs(&mut self, buffer: &mut Vec<u8>) -> Option<Key> {
let success = match success {
b'0' => false,
b'1' => true,
b'>' => {
self.parse_xtversion(buffer);
return None;
}
_ => return None,
};
if self.try_readb(buffer)? != b'+' {