small software-rendered rust tty
resizing
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | src/main.rs | 28 | ||||
| -rw-r--r-- | src/render.rs | 3 | ||||
| -rw-r--r-- | src/term.rs | 7 | ||||
| -rw-r--r-- | src/term/cells.rs | 57 |
5 files changed, 96 insertions, 0 deletions
@@ -26,6 +26,7 @@ debug = 2 opt-level = 3 lto = "thin" incremental = true +overflow-checks = true [profile.dev] opt-level = 3 diff --git a/src/main.rs b/src/main.rs index d64add9..fea29a7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -164,6 +164,34 @@ fn main() -> Result<()> { let mut f = File::create("x").unwrap(); loop { + while w.get_size().0 < 20 + || w.get_size().0 > 5000 + || w.get_size().1 < 20 + || w.get_size().1 > 5000 + { + sleep(Duration::from_millis(10)); + w.update(); + } + let cols = (w.get_size().0 as f32 / fw).floor() as u16 - 1; + let rows = (w.get_size().1 as f32 / fh).floor() as u16 - 1; + // dbg!(cols, rows); + if (cols + 1, rows + 1) != t.cells.size { + println!("{}x{}", rows, cols); + + unsafe { + let x = winsize { + ws_row: rows, + ws_col: cols, + ws_xpixel: w.get_size().0 as _, + ws_ypixel: w.get_size().1 as _, + }; + assert!( + ioctl(pty.as_raw_fd(), TIOCSWINSZ, &raw const x) == 0 + ); + }; + t.resize((cols, rows)); + } + t.scroll(w.get_scroll_wheel().unwrap_or_default().1); while let Ok(x) = trx.recv_timeout(Duration::from_millis(16)) { f.write_all(&x)?; diff --git a/src/render.rs b/src/render.rs index bfe5c52..3279730 100644 --- a/src/render.rs +++ b/src/render.rs @@ -17,6 +17,9 @@ pub fn render( let m = FONT.metrics(&[]); let sz = ppem * (m.max_width / m.units_per_em as f32); let mut i = Image::build(w as _, h as _).fill(colors::BACKGROUND); + if w < 60 || h < 60 { + return i; + } let c = x.cells.c() as usize; let r = x.cells.r() as usize; let vo = x.view_o.unwrap_or(x.cells.row); diff --git a/src/term.rs b/src/term.rs index ec0439c..a037a57 100644 --- a/src/term.rs +++ b/src/term.rs @@ -60,6 +60,13 @@ impl Terminal { fn decsc(&mut self) { self.saved_cursor = self.cursor; } + pub fn resize(&mut self, (c, r): (u16, u16)) { + self.cells.resize((c, r)); + self.alternate.as_mut().map(|x| x.resize((c, r))); + self.cursor = (self.cursor.0.min(c - 2), self.cursor.1.min(r - 2)); + self.view_o.as_mut().map(|x| *x = self.cells.row); + println!("successful resize {c} {r} {:?}", self.cursor) + } fn decrc(&mut self) { self.cursor = self.saved_cursor; } diff --git a/src/term/cells.rs b/src/term/cells.rs index c3ad862..707fe10 100644 --- a/src/term/cells.rs +++ b/src/term/cells.rs @@ -11,6 +11,7 @@ pub struct Style { pub color: [u8; 3], pub flags: u8, } +use std::cmp::Ordering; use std::default::Default::default; use std::fmt::Debug; use std::iter::{empty, repeat, repeat_n}; @@ -76,6 +77,7 @@ impl Cells { fn offset(&mut self) -> usize { self.row as usize * self.size.0 as usize } + #[track_caller] pub fn cells(&mut self) -> &mut [Cell] { let o = self.offset(); assert!( @@ -124,6 +126,61 @@ impl Cells { ), ); } + + pub fn resize(&mut self, (c, r): (u16, u16)) { + let (c, r) = (c + 1, r + 1); + assert!(self.cells.len() % self.c() as usize == 0); + let (oc, or) = self.size; + self.size = (c, r); + self.margin.0 = self.margin.0.min(r); + self.margin.1 = self.margin.1.min(r); + + match c.cmp(&oc) { + Ordering::Less => { + self.cells = self + .cells + .chunks_exact(oc as usize) + .flat_map(|chunk| &chunk[..c as usize]) + .copied() + .collect::<Vec<_>>(); + assert!(self.cells.len() % c as usize == 0); + } + Ordering::Equal => {} + Ordering::Greater => { + self.cells = self + .cells + .chunks_exact(oc as usize) + .flat_map(|chunk| { + chunk + .iter() + .copied() + .chain(repeat_n(default(), (c - oc) as usize)) + }) + .collect::<Vec<_>>(); + assert!(self.cells.len() % c as usize == 0); + } + }; + assert!(self.cells.len() % c as usize == 0); + match r.cmp(&or) { + Ordering::Less => { + self.row += (or - r) as usize; + } + Ordering::Equal => {} + Ordering::Greater => { + let d = self.row as isize - (r - or) as isize; + if d < 0 { + self.row = 0; + self.cells.extend(repeat_n( + Cell::default(), + d.abs() as usize * c as usize, + )); + } else { + self.row = d as usize; + } + } + } + self.cells(); + } pub fn insert_chars(&mut self, characters: u16, (x, y): (u16, u16)) { let s = &mut self.row(y)[x as usize - 1..]; s.rotate_right(characters as usize); |