small software-rendered rust tty
recognize DECSTBM
bendn 8 months ago
parent 8441af5 · commit eb5a55c
-rw-r--r--src/main.rs1
-rw-r--r--src/term.rs15
-rw-r--r--src/term/cells.rs80
3 files changed, 90 insertions, 6 deletions
diff --git a/src/main.rs b/src/main.rs
index fadd92b..460616c 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,4 +1,5 @@
#![feature(
+ debug_closure_helpers,
const_trait_impl,
generic_assert,
deadline_api,
diff --git a/src/term.rs b/src/term.rs
index 6afd9b4..8e42781 100644
--- a/src/term.rs
+++ b/src/term.rs
@@ -259,6 +259,21 @@ impl Terminal {
let count = p.value_or(1);
self.cells.delete_chars(count, self.cursor);
}
+ //decstbm
+ Control(ControlFunction {
+ start: b'[',
+ params: v,
+ end: b'r',
+ ..
+ }) => {
+ self.cells.margin = match v {
+ [t, b] => (t.value_or(1), b.value_or(self.cells.r())),
+ _ => (1, self.cells.r()),
+ };
+ self.cursor = (1, 1);
+ assert!(self.cells.margin.0 < self.cells.margin.1);
+ }
+
Control(ControlFunction {
start: b'[',
params: [x],
diff --git a/src/term/cells.rs b/src/term/cells.rs
index 2bea8bb..26e56b7 100644
--- a/src/term/cells.rs
+++ b/src/term/cells.rs
@@ -2,6 +2,7 @@
pub struct Cells {
pub size: (u16, u16),
pub cells: Vec<Cell>,
+ pub margin: (u16, u16),
pub row: u16,
}
#[derive(Clone, Copy, Debug)]
@@ -11,6 +12,7 @@ pub struct Style {
pub flags: u8,
}
use std::default::Default::default;
+use std::fmt::Debug;
use std::iter::{empty, repeat, repeat_n};
use crate::colors;
@@ -24,17 +26,49 @@ impl std::default::Default for Style {
}
}
-#[derive(Clone, Copy, Default, Debug)]
+#[derive(Clone, Copy, Default)]
pub struct Cell {
pub style: Style,
pub letter: Option<char>,
}
+impl Debug for Cell {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{}", self.letter.unwrap_or(' '))
+ }
+}
+impl Debug for Cells {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("Cells")
+ .field("size", &self.size)
+ .field("margin", &self.margin)
+ .field("row", &self.row)
+ .field_with("cells", |x| {
+ for r in self.cells
+ [{ self.row as usize * self.size.0 as usize }..]
+ .chunks_exact(self.size.0 as _)
+ {
+ writeln!(x, "{r:?}")?;
+ }
+ Ok(())
+ })
+ .finish()
+ }
+}
+impl Cell {
+ pub fn basic(c: char) -> Self {
+ Self {
+ letter: Some(c),
+ ..default()
+ }
+ }
+}
impl Cells {
pub fn new((c, r): (u16, u16)) -> Self {
let (c, r) = (c + 1, r + 1);
Self {
size: (c, r),
+ margin: (1, r),
cells: vec![Cell::default(); (c as usize) * (r as usize)],
row: 0,
}
@@ -80,12 +114,16 @@ impl Cells {
}
pub fn grow(&mut self, by: u16) {
self.row += by;
- self.cells.extend(repeat_n(
- Cell::default(),
- by as usize * (self.size.0) as usize,
- ));
+ let at = self.offset()
+ + (self.margin.1 as usize - 1) * self.size.0 as usize;
+ self.cells.splice(
+ at..at,
+ repeat_n(
+ Cell::default(),
+ by as usize * (self.size.0) as usize,
+ ),
+ );
}
-
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);
@@ -115,5 +153,35 @@ impl Cells {
self.cells
.drain(o + self.size.0 as usize * self.size.1 as usize..)
.for_each(drop);
+ // let at = self.offset() + self.margin.1 as usize;
+ // self.cells
+ // .drain(
+ // (o + self.size.0 as usize * self.size.1 as usize) - at..at,
+ // )
+ // .for_each(drop);
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use crate::term::cells::{Cell, Cells};
+
+ #[test]
+ fn grow() {
+ let mut cells = Cells::new((4, 4));
+ cells.row(1).fill(Cell::basic('1'));
+ cells.row(2).fill(Cell::basic('2'));
+ cells.row(3).fill(Cell::basic('3'));
+ cells.row(4).fill(Cell::basic('4'));
+ cells.row(5).fill(Cell::basic('5'));
+ dbg!(&cells);
+
+ // cells.margin.1 = 3;
+ cells.grow(1);
+ dbg!(&cells);
+ assert_eq!(
+ format!("{cells:?}"),
+ "Cells { size: (5, 5), margin: (1, 5), row: 1, cells: [2, 2, 2, 2, 2]\n[3, 3, 3, 3, 3]\n[4, 4, 4, 4, 4]\n[5, 5, 5, 5, 5]\n[ , , , , ]\n }"
+ );
}
}