From 68c36be2e26813a2a3d7210ae82824de06b3d3ee Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Wed, 8 Mar 2023 23:43:23 -0500 Subject: implement callback for terminal resize request --- CHANGELOG.md | 2 ++ src/callbacks.rs | 3 +++ src/screen.rs | 14 ++++++++++++++ src/state.rs | 14 ++++++++++++++ tests/csi.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 73 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 477fc5a..f9fb38a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ * `Parser::process_cb`, which works the same as `Parser::process` except that it calls callbacks during parsing when it finds a terminal escape which is potentially useful but not something that affects the screen itself. +* Support for xterm window resize request escape codes, via the new callback + mechanism. ### Removed diff --git a/src/callbacks.rs b/src/callbacks.rs index 256eb58..70331eb 100644 --- a/src/callbacks.rs +++ b/src/callbacks.rs @@ -7,6 +7,9 @@ pub trait Callbacks { /// This callback is called when the terminal requests an visual bell /// (typically with `\eg`). fn visual_bell(&mut self, _: &mut crate::Screen) {} + /// This callback is called when the terminal requests a resize + /// (typically with `\e[8;;t`). + fn resize(&mut self, _: &mut crate::Screen, _request: (u16, u16)) {} /// This callback is called when the terminal receives invalid input /// (such as an invalid UTF-8 character or an used control character). fn error(&mut self, _: &mut crate::Screen) {} diff --git a/src/screen.rs b/src/screen.rs index 9da62c7..c64f8e9 100644 --- a/src/screen.rs +++ b/src/screen.rs @@ -1447,6 +1447,19 @@ impl Screen { self.grid_mut().set_scroll_region(top - 1, bottom - 1); } + // CSI t + #[allow(clippy::unused_self)] + fn xtwinops(&self, params: &vte::Params) { + let mut iter = params.iter(); + let op = iter.next().and_then(|x| x.first().copied()); + match op { + Some(8) => {} + _ => { + log::debug!("unhandled XTWINOPS: {}", param_str(params)); + } + } + } + // osc codes fn osc0(&mut self, s: &[u8]) { @@ -1544,6 +1557,7 @@ impl vte::Perform for Screen { params, self.grid().size(), )), + 't' => self.xtwinops(params), _ => { if log::log_enabled!(log::Level::Debug) { log::debug!( diff --git a/src/state.rs b/src/state.rs index c84fa2b..5471bdd 100644 --- a/src/state.rs +++ b/src/state.rs @@ -42,6 +42,20 @@ impl<'a, T: crate::callbacks::Callbacks> vte::Perform for State<'a, T> { ignore: bool, c: char, ) { + if intermediates.first().is_none() && c == 't' { + let mut iter = params.iter(); + let op = iter.next().and_then(|x| x.first().copied()); + if op == Some(8) { + let (screen_rows, screen_cols) = self.screen.size(); + let rows = iter.next().map_or(screen_rows, |x| { + *x.first().unwrap_or(&screen_rows) + }); + let cols = iter.next().map_or(screen_cols, |x| { + *x.first().unwrap_or(&screen_cols) + }); + self.callbacks.resize(self.screen, (rows, cols)); + } + } self.screen.csi_dispatch(params, intermediates, ignore, c); } diff --git a/tests/csi.rs b/tests/csi.rs index 7a409b6..460a03d 100644 --- a/tests/csi.rs +++ b/tests/csi.rs @@ -44,3 +44,43 @@ fn il_dl() { fn scroll() { helpers::fixture("scroll"); } + +#[test] +fn xtwinops() { + struct Callbacks; + impl vt100::Callbacks for Callbacks { + fn resize( + &mut self, + screen: &mut vt100::Screen, + (rows, cols): (u16, u16), + ) { + screen.set_size(rows, cols); + } + } + + let mut vt = vt100::Parser::default(); + assert_eq!(vt.screen().size(), (24, 80)); + vt.process_cb(b"\x1b[8;24;80t", &mut Callbacks); + assert_eq!(vt.screen().size(), (24, 80)); + vt.process_cb(b"\x1b[8t", &mut Callbacks); + assert_eq!(vt.screen().size(), (24, 80)); + vt.process_cb(b"\x1b[8;80;24t", &mut Callbacks); + assert_eq!(vt.screen().size(), (80, 24)); + vt.process_cb(b"\x1b[8;24t", &mut Callbacks); + assert_eq!(vt.screen().size(), (24, 24)); + + let mut vt = vt100::Parser::default(); + assert_eq!(vt.screen().size(), (24, 80)); + vt.process_cb(b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", &mut Callbacks); + assert_eq!(vt.screen().rows(0, 80).next().unwrap(), "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + assert_eq!(vt.screen().rows(0, 80).nth(1).unwrap(), "aaaaaaaaaa"); + vt.process_cb( + b"\x1b[H\x1b[8;24;15tbbbbbbbbbbbbbbbbbbbb\x1b[8;24;80tcccccccccccccccccccc", + &mut Callbacks, + ); + assert_eq!(vt.screen().rows(0, 80).next().unwrap(), "bbbbbbbbbbbbbbb"); + assert_eq!( + vt.screen().rows(0, 80).nth(1).unwrap(), + "bbbbbcccccccccccccccccccc" + ); +} -- cgit v1.2.3-54-g00ecf