aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2019-10-29 15:46:27 -0400
committerJesse Luehrs <doy@tozt.net>2019-10-29 15:46:27 -0400
commit1f7cb68522ceb57187bcc9353bc2be405a927015 (patch)
tree58773e43f78df241f003a0c02ff3f1d5ed56db21
parent267f7452949617375c8570caf4b03b434e3350e8 (diff)
downloadvt100-rust-1f7cb68522ceb57187bcc9353bc2be405a927015.tar.gz
vt100-rust-1f7cb68522ceb57187bcc9353bc2be405a927015.zip
get some tests passing
-rw-r--r--src/attrs.rs9
-rw-r--r--src/cell.rs40
-rw-r--r--src/lib.rs6
-rw-r--r--src/pos.rs8
-rw-r--r--src/screen.rs231
5 files changed, 220 insertions, 74 deletions
diff --git a/src/attrs.rs b/src/attrs.rs
new file mode 100644
index 0000000..86fec32
--- /dev/null
+++ b/src/attrs.rs
@@ -0,0 +1,9 @@
+#[derive(Default, Clone, Copy, PartialEq, Eq, Debug)]
+pub struct Attrs {
+ pub fgcolor: crate::color::Color,
+ pub bgcolor: crate::color::Color,
+ pub bold: bool,
+ pub italic: bool,
+ pub underline: bool,
+ pub inverse: bool,
+}
diff --git a/src/cell.rs b/src/cell.rs
index b1821c6..b5210e5 100644
--- a/src/cell.rs
+++ b/src/cell.rs
@@ -1,12 +1,7 @@
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, Default)]
pub struct Cell {
contents: String,
- fgcolor: crate::color::Color,
- bgcolor: crate::color::Color,
- bold: bool,
- italic: bool,
- inverse: bool,
- underline: bool,
+ attrs: crate::attrs::Attrs,
}
impl Cell {
@@ -14,45 +9,36 @@ impl Cell {
Self::default()
}
+ pub(crate) fn set(&mut self, c: String, a: crate::attrs::Attrs) {
+ self.contents = c;
+ self.attrs = a;
+ }
+
pub fn contents(&self) -> &str {
&self.contents
}
pub fn fgcolor(&self) -> crate::color::Color {
- self.fgcolor
+ self.attrs.fgcolor
}
pub fn bgcolor(&self) -> crate::color::Color {
- self.bgcolor
+ self.attrs.bgcolor
}
pub fn bold(&self) -> bool {
- self.bold
+ self.attrs.bold
}
pub fn italic(&self) -> bool {
- self.italic
+ self.attrs.italic
}
pub fn inverse(&self) -> bool {
- self.inverse
+ self.attrs.inverse
}
pub fn underline(&self) -> bool {
- self.underline
- }
-}
-
-impl Default for Cell {
- fn default() -> Self {
- Self {
- contents: String::new(),
- fgcolor: crate::color::Color::Default,
- bgcolor: crate::color::Color::Default,
- bold: false,
- italic: false,
- inverse: false,
- underline: false,
- }
+ self.attrs.underline
}
}
diff --git a/src/lib.rs b/src/lib.rs
index 3a74ed3..e60c9e1 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -2,10 +2,12 @@
#![warn(clippy::nursery)]
#![allow(clippy::missing_const_for_fn)]
+mod attrs;
mod cell;
-pub use cell::Cell;
mod color;
-pub use color::Color;
mod pos;
mod screen;
+
+pub use cell::Cell;
+pub use color::Color;
pub use screen::Screen;
diff --git a/src/pos.rs b/src/pos.rs
index 0759527..9e3f2df 100644
--- a/src/pos.rs
+++ b/src/pos.rs
@@ -1,11 +1,5 @@
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
pub struct Pos {
pub row: u16,
pub col: u16,
}
-
-impl Default for Pos {
- fn default() -> Self {
- Self { row: 0, col: 0 }
- }
-}
diff --git a/src/screen.rs b/src/screen.rs
index 9caa0eb..cc811b7 100644
--- a/src/screen.rs
+++ b/src/screen.rs
@@ -2,16 +2,70 @@ struct State {
size: crate::pos::Pos,
cells: Vec<Vec<crate::cell::Cell>>,
cursor_position: crate::pos::Pos,
- fgcolor: crate::color::Color,
- bgcolor: crate::color::Color,
- bold: bool,
- italic: bool,
- inverse: bool,
- underline: bool,
+ attrs: crate::attrs::Attrs,
+}
+
+impl State {
+ const DEFAULT_SGR_PARAMS: &'static [i64] = &[0];
+
+ fn new(rows: u16, cols: u16) -> Self {
+ let size = crate::pos::Pos {
+ row: rows,
+ col: cols,
+ };
+ Self {
+ size,
+ cells: Self::new_cells(size),
+ cursor_position: crate::pos::Pos::default(),
+ attrs: crate::attrs::Attrs::default(),
+ }
+ }
+
+ fn new_cells(size: crate::pos::Pos) -> Vec<Vec<crate::cell::Cell>> {
+ vec![
+ vec![crate::cell::Cell::default(); size.col as usize];
+ size.row as usize
+ ]
+ }
+
+ fn cell(&self, pos: crate::pos::Pos) -> Option<&crate::cell::Cell> {
+ self.cells
+ .get(pos.row as usize)
+ .and_then(|v| v.get(pos.col as usize))
+ }
+
+ fn cell_mut(
+ &mut self,
+ pos: crate::pos::Pos,
+ ) -> Option<&mut crate::cell::Cell> {
+ self.cells
+ .get_mut(pos.row as usize)
+ .and_then(|v| v.get_mut(pos.col as usize))
+ }
+
+ fn current_cell(&self) -> Option<&crate::cell::Cell> {
+ self.cell(self.cursor_position)
+ }
+
+ fn current_cell_mut(&mut self) -> Option<&mut crate::cell::Cell> {
+ self.cell_mut(self.cursor_position)
+ }
}
impl vte::Perform for State {
- fn print(&mut self, _c: char) {}
+ fn print(&mut self, c: char) {
+ let attrs = self.attrs;
+ if let Some(cell) = self.current_cell_mut() {
+ cell.set(c.to_string(), attrs);
+ self.cursor_position.col += 1;
+ if self.cursor_position.col > self.size.col {
+ self.cursor_position.col = 0;
+ self.cursor_position.row += 1;
+ }
+ } else {
+ panic!("couldn't find current cell")
+ }
+ }
fn execute(&mut self, _b: u8) {}
@@ -31,11 +85,131 @@ impl vte::Perform for State {
fn csi_dispatch(
&mut self,
- _params: &[i64],
+ params: &[i64],
_intermediates: &[u8],
_ignore: bool,
- _c: char,
+ c: char,
) {
+ match c {
+ 'D' => {
+ let offset = params.get(0).copied().unwrap_or(1);
+ if self.cursor_position.col >= offset as u16 {
+ self.cursor_position.col -= offset as u16;
+ }
+ }
+ 'H' => {
+ let row = params.get(0).copied().unwrap_or(1);
+ let row = if row == 0 { 1 } else { row };
+ let col = params.get(1).copied().unwrap_or(1);
+ let col = if col == 0 { 1 } else { col };
+ self.cursor_position = crate::pos::Pos {
+ row: row as u16 - 1,
+ col: col as u16 - 1,
+ };
+ }
+ 'J' => match params.get(0).copied().unwrap_or(0) {
+ 0 => {}
+ 1 => {}
+ 2 => {
+ self.cells = Self::new_cells(self.size);
+ }
+ _ => {}
+ },
+ 'm' => {
+ let params = if params.is_empty() {
+ Self::DEFAULT_SGR_PARAMS
+ } else {
+ params
+ };
+ let mut i = 0;
+ while i < params.len() {
+ match params[i] {
+ 0 => self.attrs = crate::attrs::Attrs::default(),
+ 1 => self.attrs.bold = true,
+ 3 => self.attrs.italic = true,
+ 4 => self.attrs.underline = true,
+ 7 => self.attrs.inverse = true,
+ 22 => self.attrs.bold = false,
+ 23 => self.attrs.italic = false,
+ 24 => self.attrs.underline = false,
+ 27 => self.attrs.inverse = false,
+ n if n >= 30 && n <= 37 => {
+ self.attrs.fgcolor =
+ crate::color::Color::Idx((n as u8) - 30);
+ }
+ 38 => {
+ i += 1;
+ if i >= params.len() {
+ unimplemented!()
+ }
+ match params[i] {
+ 2 => {
+ i += 3;
+ if i >= params.len() {
+ unimplemented!()
+ }
+ self.attrs.fgcolor =
+ crate::color::Color::Rgb(
+ params[i - 2] as u8,
+ params[i - 1] as u8,
+ params[i] as u8,
+ );
+ }
+ 5 => {
+ i += 1;
+ if i >= params.len() {
+ unimplemented!()
+ }
+ self.attrs.fgcolor =
+ crate::color::Color::Idx(
+ params[i] as u8,
+ );
+ }
+ _ => {}
+ }
+ }
+ n if n >= 40 && n <= 47 => {
+ self.attrs.bgcolor =
+ crate::color::Color::Idx((n as u8) - 40);
+ }
+ 48 => {
+ i += 1;
+ if i >= params.len() {
+ unimplemented!()
+ }
+ match params[i] {
+ 2 => {
+ i += 3;
+ if i >= params.len() {
+ unimplemented!()
+ }
+ self.attrs.bgcolor =
+ crate::color::Color::Rgb(
+ params[i - 2] as u8,
+ params[i - 1] as u8,
+ params[i] as u8,
+ );
+ }
+ 5 => {
+ i += 1;
+ if i >= params.len() {
+ unimplemented!()
+ }
+ self.attrs.bgcolor =
+ crate::color::Color::Idx(
+ params[i] as u8,
+ );
+ }
+ _ => {}
+ }
+ }
+ _ => {}
+ }
+ i += 1;
+ }
+ }
+ _ => {}
+ }
}
fn esc_dispatch(
@@ -57,23 +231,7 @@ impl Screen {
pub fn new(rows: u16, cols: u16) -> Self {
Self {
parser: vte::Parser::new(),
- state: State {
- size: crate::pos::Pos {
- row: rows,
- col: cols,
- },
- cells: vec![
- vec![crate::cell::Cell::default(); cols as usize];
- rows as usize
- ],
- cursor_position: crate::pos::Pos::default(),
- fgcolor: crate::color::Color::default(),
- bgcolor: crate::color::Color::default(),
- bold: false,
- italic: false,
- inverse: false,
- underline: false,
- },
+ state: State::new(rows, cols),
}
}
@@ -99,10 +257,7 @@ impl Screen {
}
pub fn cell(&self, row: u16, col: u16) -> Option<&crate::cell::Cell> {
- self.state
- .cells
- .get(row as usize)
- .and_then(|v| v.get(col as usize))
+ self.state.cell(crate::pos::Pos { row, col })
}
pub fn window_contents(
@@ -133,27 +288,27 @@ impl Screen {
}
pub fn fgcolor(&self) -> crate::color::Color {
- self.state.fgcolor
+ self.state.attrs.fgcolor
}
pub fn bgcolor(&self) -> crate::color::Color {
- self.state.bgcolor
+ self.state.attrs.bgcolor
}
pub fn bold(&self) -> bool {
- self.state.bold
+ self.state.attrs.bold
}
pub fn italic(&self) -> bool {
- self.state.italic
+ self.state.attrs.italic
}
- pub fn inverse(&self) -> bool {
- self.state.inverse
+ pub fn underline(&self) -> bool {
+ self.state.attrs.underline
}
- pub fn underline(&self) -> bool {
- self.state.underline
+ pub fn inverse(&self) -> bool {
+ self.state.attrs.inverse
}
pub fn title(&self) -> Option<&str> {