small software-rendered rust tty
resizing
bendn 8 months ago
parent e65b986 · commit e1ef912
-rw-r--r--Cargo.toml1
-rw-r--r--src/main.rs28
-rw-r--r--src/render.rs3
-rw-r--r--src/term.rs7
-rw-r--r--src/term/cells.rs57
5 files changed, 96 insertions, 0 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 1c5b33d..a61893a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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);