summary refs log tree commit diff
path: root/src/terminal.rs
diff options
context:
space:
mode:
authorIrene Knapp <ireneista@irenes.space>2026-03-27 11:36:40 -0700
committerIrene Knapp <ireneista@irenes.space>2026-03-27 11:36:40 -0700
commita52b286d6c8e2000c416f23eece0b930fe8ec4e9 (patch)
treec40b556fd6c63a9cad0df542c975779e84e4bc08 /src/terminal.rs
parent46b955afbce8997c39bda4e83abcaed2e954e65c (diff)
scrolling now uses the terminal scroll feature when possible
it doesn't redraw the newly blank lines in that case though, so it's broken, but that can come next

Force-Push: yes
Change-Id: I52c90249852331e5f9bbcdee4d645ee33e4c671a
Diffstat (limited to 'src/terminal.rs')
-rw-r--r--src/terminal.rs45
1 files changed, 40 insertions, 5 deletions
diff --git a/src/terminal.rs b/src/terminal.rs
index 9188c43..1ba2b01 100644
--- a/src/terminal.rs
+++ b/src/terminal.rs
@@ -81,10 +81,18 @@ impl Terminal {
     *self.width.write().await = width.try_into().unwrap();
     *self.height.write().await = height.try_into().unwrap();
 
+    self.set_scroll_region(0, height - 1).await?;
+
     Ok(())
   }
 
   pub async fn zap_full_screen(&mut self) -> Result<()> {
+    let (width, height) = self.do_report_size().await?;
+    *self.width.write().await = width.try_into().unwrap();
+    *self.height.write().await = height.try_into().unwrap();
+
+    self.set_scroll_region(0, height).await?;
+
     self.do_end_alternate_screen().await?;
     self.stdout.flush().await?;
 
@@ -113,7 +121,7 @@ impl Terminal {
   }
 
   pub async fn read_report(&mut self, escape_type: EscapeType)
-      -> Result<(char, Vec<u64>)>
+      -> Result<(char, Vec<usize>)>
   {
     let mut expected = escape_type.intro();
 
@@ -126,7 +134,7 @@ impl Terminal {
 
     let mut values = Vec::new();
 
-    let mut number: u64 = 0;
+    let mut number: usize = 0;
     let mut in_number = false;
     let mut after_semicolon = false;
 
@@ -140,9 +148,11 @@ impl Terminal {
         if c.is_ascii_digit() {
           if in_number {
             number = number * 10
-                     + <u32 as Into<u64>>::into(c.to_digit(10).unwrap());
+                     + <u32 as TryInto<usize>>::try_into(
+                           c.to_digit(10).unwrap()).unwrap();
           } else {
-            number = c.to_digit(10).unwrap().into();
+            number = <u32 as TryInto<usize>>::try_into(
+                         c.to_digit(10).unwrap()).unwrap();
 
             in_number = true;
             after_semicolon = false;
@@ -195,7 +205,7 @@ impl Terminal {
   }
 
   // dtterm? xterm
-  pub async fn do_report_size(&mut self) -> Result<(u64, u64)> {
+  pub async fn do_report_size(&mut self) -> Result<(usize, usize)> {
     self.do_escape(EscapeType::CSI, "t", &[18]).await?;
     self.stdout.flush().await?;
     let (code, values) = self.read_report(EscapeType::CSI).await?;
@@ -210,6 +220,31 @@ impl Terminal {
   pub async fn clear(&mut self) -> Result<()> {
     self.do_escape(EscapeType::CSI, "J", &[2]).await
   }
+
+  // vt420, ECMA-48
+  pub async fn scroll_up(&mut self, distance: usize) -> Result<()> {
+    self.do_escape(EscapeType::CSI, "S", &[distance]).await
+  }
+
+  // vt420, ECMA-48
+  pub async fn scroll_down(&mut self, distance: usize) -> Result<()> {
+    self.do_escape(EscapeType::CSI, "T", &[distance]).await
+  }
+
+  pub async fn scroll(&mut self, distance_up: isize) -> Result<()> {
+    if distance_up >= 0 {
+      self.scroll_up(distance_up as usize).await
+    } else {
+      self.scroll_down(-distance_up as usize).await
+    }
+  }
+
+  // vt100
+  pub async fn set_scroll_region(&mut self, top: usize, bottom: usize)
+      -> Result<()>
+  {
+    self.do_escape(EscapeType::CSI, "r", &[top, bottom]).await
+  }
 }