aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2023-03-08 23:43:23 -0500
committerJesse Luehrs <doy@tozt.net>2023-03-09 00:29:47 -0500
commit68c36be2e26813a2a3d7210ae82824de06b3d3ee (patch)
tree19f345f7e05c6cb8c210657e6f0f671113f56f09
parenta705c1f07de2b8ec3ba4fe46377242f151b996c1 (diff)
downloadvt100-rust-68c36be2e26813a2a3d7210ae82824de06b3d3ee.tar.gz
vt100-rust-68c36be2e26813a2a3d7210ae82824de06b3d3ee.zip
implement callback for terminal resize request
-rw-r--r--CHANGELOG.md2
-rw-r--r--src/callbacks.rs3
-rw-r--r--src/screen.rs14
-rw-r--r--src/state.rs14
-rw-r--r--tests/csi.rs40
5 files changed, 73 insertions, 0 deletions
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;<rows>;<cols>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"
+ );
+}