From ac6aa6cb1659dd716701e2af41756ed3fe5faf0d Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Fri, 8 Nov 2019 03:35:44 -0500 Subject: clearing cells sets the background color --- CHANGELOG.md | 6 ++ src/cell.rs | 3 +- src/grid.rs | 34 +++---- src/row.rs | 12 ++- src/screen.rs | 20 +++-- tests/csi.rs | 284 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 329 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a4010e..bfb122b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +### Fixed + +* Clearing cells now correctly sets the cell background color. + ## [0.3.1] - 2019-11-06 ### Fixed diff --git a/src/cell.rs b/src/cell.rs index 285d37a..54f433d 100644 --- a/src/cell.rs +++ b/src/cell.rs @@ -23,9 +23,10 @@ impl Cell { } } - pub(crate) fn clear(&mut self) { + pub(crate) fn clear(&mut self, bgcolor: crate::attrs::Color) { self.contents.clear(); self.attrs.clear(); + self.attrs.bgcolor = bgcolor; } /// Returns the text contents of the cell. diff --git a/src/grid.rs b/src/grid.rs index fa6b4b9..ad2fa22 100644 --- a/src/grid.rs +++ b/src/grid.rs @@ -34,7 +34,7 @@ impl Grid { self.pos = Pos::default(); self.saved_pos = Pos::default(); for row in self.rows_mut() { - row.clear(); + row.clear(crate::attrs::Color::Default); } self.scroll_top = 0; self.scroll_bottom = self.size.rows - 1; @@ -197,48 +197,48 @@ impl Grid { contents } - pub fn erase_all(&mut self) { + pub fn erase_all(&mut self, bgcolor: crate::attrs::Color) { for row in self.rows_mut() { - row.clear(); + row.clear(bgcolor); } } - pub fn erase_all_forward(&mut self) { + pub fn erase_all_forward(&mut self, bgcolor: crate::attrs::Color) { let pos = self.pos; for row in self.rows_mut().skip(pos.row as usize + 1) { - row.clear(); + row.clear(bgcolor); } - self.erase_row_forward(); + self.erase_row_forward(bgcolor); } - pub fn erase_all_backward(&mut self) { + pub fn erase_all_backward(&mut self, bgcolor: crate::attrs::Color) { let pos = self.pos; for row in self.rows_mut().take(pos.row as usize) { - row.clear(); + row.clear(bgcolor); } - self.erase_row_backward(); + self.erase_row_backward(bgcolor); } - pub fn erase_row(&mut self) { - self.current_row_mut().clear(); + pub fn erase_row(&mut self, bgcolor: crate::attrs::Color) { + self.current_row_mut().clear(bgcolor); } - pub fn erase_row_forward(&mut self) { + pub fn erase_row_forward(&mut self, bgcolor: crate::attrs::Color) { let pos = self.pos; let row = self.current_row_mut(); row.wrap(false); for cell in row.cells_mut().skip(pos.col as usize) { - cell.clear(); + cell.clear(bgcolor); } } - pub fn erase_row_backward(&mut self) { + pub fn erase_row_backward(&mut self, bgcolor: crate::attrs::Color) { let pos = self.pos; let row = self.current_row_mut(); for cell in row.cells_mut().take(pos.col as usize + 1) { - cell.clear(); + cell.clear(bgcolor); } } @@ -262,13 +262,13 @@ impl Grid { row.resize(size.cols as usize, crate::cell::Cell::default()); } - pub fn erase_cells(&mut self, count: u16) { + pub fn erase_cells(&mut self, count: u16, bgcolor: crate::attrs::Color) { let pos = self.pos; let row = self.current_row_mut(); for cell in row.cells_mut().skip(pos.col as usize).take(count as usize) { - cell.clear(); + cell.clear(bgcolor); } } diff --git a/src/row.rs b/src/row.rs index 7b2ab99..b563b33 100644 --- a/src/row.rs +++ b/src/row.rs @@ -14,9 +14,9 @@ impl Row { } } - pub fn clear(&mut self) { + pub fn clear(&mut self, bgcolor: crate::attrs::Color) { for cell in &mut self.cells { - cell.clear(); + cell.clear(bgcolor); } self.wrapped = false; } @@ -113,8 +113,10 @@ impl Row { contents.extend(if cell.has_contents() { cell.contents().as_bytes() + } else if cell.bgcolor() == crate::attrs::Color::Default { + &b"\x1b[C"[..] } else { - b"\x1b[C" + &b"\x1b[X\x1b[C"[..] }); prev_was_wide = cell.is_wide(); @@ -172,7 +174,9 @@ impl Row { for (col, cell) in self.cells.iter().skip(start as usize).enumerate().rev() { - if cell.has_contents() { + if cell.has_contents() + || cell.bgcolor() != crate::attrs::Color::Default + { let width: u16 = col.try_into().unwrap(); return width + 1; } diff --git a/src/screen.rs b/src/screen.rs index 6ff11ad..1a748e0 100644 --- a/src/screen.rs +++ b/src/screen.rs @@ -458,6 +458,7 @@ impl Screen { fn text(&mut self, c: char) { let pos = self.grid().pos(); if pos.col > 0 { + let bgcolor = self.attrs.bgcolor; let prev_cell = self .cell_mut(crate::grid::Pos { row: pos.row, @@ -465,7 +466,7 @@ impl Screen { }) .unwrap(); if prev_cell.is_wide() { - prev_cell.clear(); + prev_cell.clear(bgcolor); } } @@ -625,10 +626,11 @@ impl Screen { // CSI J fn ed(&mut self, mode: u16) { + let bgcolor = self.attrs.bgcolor; match mode { - 0 => self.grid_mut().erase_all_forward(), - 1 => self.grid_mut().erase_all_backward(), - 2 => self.grid_mut().erase_all(), + 0 => self.grid_mut().erase_all_forward(bgcolor), + 1 => self.grid_mut().erase_all_backward(bgcolor), + 2 => self.grid_mut().erase_all(bgcolor), _ => {} } } @@ -640,10 +642,11 @@ impl Screen { // CSI K fn el(&mut self, mode: u16) { + let bgcolor = self.attrs.bgcolor; match mode { - 0 => self.grid_mut().erase_row_forward(), - 1 => self.grid_mut().erase_row_backward(), - 2 => self.grid_mut().erase_row(), + 0 => self.grid_mut().erase_row_forward(bgcolor), + 1 => self.grid_mut().erase_row_backward(bgcolor), + 2 => self.grid_mut().erase_row(bgcolor), _ => {} } } @@ -680,7 +683,8 @@ impl Screen { // CSI X fn ech(&mut self, count: u16) { - self.grid_mut().erase_cells(count); + let bgcolor = self.attrs.bgcolor; + self.grid_mut().erase_cells(count, bgcolor); } // CSI d diff --git a/tests/csi.rs b/tests/csi.rs index 1310dac..e0cfa39 100644 --- a/tests/csi.rs +++ b/tests/csi.rs @@ -88,6 +88,7 @@ fn relative_movement() { assert_eq!(parser.screen().cursor_position(), (0, 0)); } +#[allow(clippy::cognitive_complexity)] #[test] fn ed() { let mut parser = vt100::Parser::new(24, 80); @@ -155,8 +156,167 @@ fn ed() { parser.screen().contents(), "foo\n\n\n\n bar\n\n\n\n\n ba" ); + + parser.process(b"\x1bc\x1b[5;5H"); + assert_eq!( + parser.screen().cell(3, 3).unwrap().bgcolor(), + vt100::Color::Default + ); + assert_eq!( + parser.screen().cell(4, 3).unwrap().bgcolor(), + vt100::Color::Default + ); + assert_eq!( + parser.screen().cell(4, 4).unwrap().bgcolor(), + vt100::Color::Default + ); + assert_eq!( + parser.screen().cell(4, 5).unwrap().bgcolor(), + vt100::Color::Default + ); + assert_eq!( + parser.screen().cell(5, 5).unwrap().bgcolor(), + vt100::Color::Default + ); + assert_eq!( + parser.screen().contents_formatted(), + b"\x1b[?25h\x1b[H\x1b[J\x1b[5;5H" + ); + + parser.process(b"\x1b[41m\x1b[J"); + assert_eq!( + parser.screen().cell(3, 3).unwrap().bgcolor(), + vt100::Color::Default + ); + assert_eq!( + parser.screen().cell(4, 3).unwrap().bgcolor(), + vt100::Color::Default + ); + assert_eq!( + parser.screen().cell(4, 4).unwrap().bgcolor(), + vt100::Color::Idx(1) + ); + assert_eq!( + parser.screen().cell(4, 5).unwrap().bgcolor(), + vt100::Color::Idx(1) + ); + assert_eq!( + parser.screen().cell(5, 5).unwrap().bgcolor(), + vt100::Color::Idx(1) + ); + assert_eq!( + parser.screen().contents_formatted(), + format!( + "\x1b[?25h\x1b[H\x1b[J{}{}\x1b[41m{}\r\n{}{}\x1b[5;5H", + "\r\n".repeat(4), + "\x1b[C".repeat(4), + "\x1b[X\x1b[C".repeat(76), + format!("{}\r\n", "\x1b[X\x1b[C".repeat(80)).repeat(18), + "\x1b[X\x1b[C".repeat(80), + ) + .as_bytes() + ); + + parser.process(b"\x1bc\x1b[5;5H"); + assert_eq!( + parser.screen().cell(4, 3).unwrap().bgcolor(), + vt100::Color::Default + ); + assert_eq!( + parser.screen().cell(4, 4).unwrap().bgcolor(), + vt100::Color::Default + ); + assert_eq!( + parser.screen().cell(4, 5).unwrap().bgcolor(), + vt100::Color::Default + ); + assert_eq!( + parser.screen().contents_formatted(), + b"\x1b[?25h\x1b[H\x1b[J\x1b[5;5H" + ); + + parser.process(b"\x1b[41m\x1b[1J"); + assert_eq!( + parser.screen().cell(3, 3).unwrap().bgcolor(), + vt100::Color::Idx(1) + ); + assert_eq!( + parser.screen().cell(4, 3).unwrap().bgcolor(), + vt100::Color::Idx(1) + ); + assert_eq!( + parser.screen().cell(4, 4).unwrap().bgcolor(), + vt100::Color::Idx(1) + ); + assert_eq!( + parser.screen().cell(4, 5).unwrap().bgcolor(), + vt100::Color::Default + ); + assert_eq!( + parser.screen().cell(5, 5).unwrap().bgcolor(), + vt100::Color::Default + ); + assert_eq!( + parser.screen().contents_formatted(), + format!( + "\x1b[?25h\x1b[H\x1b[J\x1b[41m{}{}\x1b[5;5H", + format!("{}\r\n", "\x1b[X\x1b[C".repeat(80)).repeat(4), + "\x1b[X\x1b[C".repeat(5), + ) + .as_bytes() + ); + + parser.process(b"\x1bc\x1b[5;5H"); + assert_eq!( + parser.screen().cell(4, 3).unwrap().bgcolor(), + vt100::Color::Default + ); + assert_eq!( + parser.screen().cell(4, 4).unwrap().bgcolor(), + vt100::Color::Default + ); + assert_eq!( + parser.screen().cell(4, 5).unwrap().bgcolor(), + vt100::Color::Default + ); + assert_eq!( + parser.screen().contents_formatted(), + b"\x1b[?25h\x1b[H\x1b[J\x1b[5;5H" + ); + + parser.process(b"\x1b[41m\x1b[2J"); + assert_eq!( + parser.screen().cell(3, 3).unwrap().bgcolor(), + vt100::Color::Idx(1) + ); + assert_eq!( + parser.screen().cell(4, 3).unwrap().bgcolor(), + vt100::Color::Idx(1) + ); + assert_eq!( + parser.screen().cell(4, 4).unwrap().bgcolor(), + vt100::Color::Idx(1) + ); + assert_eq!( + parser.screen().cell(4, 5).unwrap().bgcolor(), + vt100::Color::Idx(1) + ); + assert_eq!( + parser.screen().cell(5, 5).unwrap().bgcolor(), + vt100::Color::Idx(1) + ); + assert_eq!( + parser.screen().contents_formatted(), + format!( + "\x1b[?25h\x1b[H\x1b[J\x1b[41m{}{}\x1b[5;5H", + format!("{}\r\n", "\x1b[X\x1b[C".repeat(80)).repeat(23), + "\x1b[X\x1b[C".repeat(80), + ) + .as_bytes() + ); } +#[allow(clippy::cognitive_complexity)] #[test] fn el() { let mut parser = vt100::Parser::new(24, 80); @@ -227,6 +387,130 @@ fn el() { parser.screen().contents(), " 1234567890\n12345678901234567890" ); + + parser.process(b"\x1bc\x1b[5;5H"); + assert_eq!( + parser.screen().cell(4, 3).unwrap().bgcolor(), + vt100::Color::Default + ); + assert_eq!( + parser.screen().cell(4, 4).unwrap().bgcolor(), + vt100::Color::Default + ); + assert_eq!( + parser.screen().cell(4, 5).unwrap().bgcolor(), + vt100::Color::Default + ); + assert_eq!( + parser.screen().contents_formatted(), + b"\x1b[?25h\x1b[H\x1b[J\x1b[5;5H" + ); + + parser.process(b"\x1b[41m\x1b[K"); + assert_eq!( + parser.screen().cell(4, 3).unwrap().bgcolor(), + vt100::Color::Default + ); + assert_eq!( + parser.screen().cell(4, 4).unwrap().bgcolor(), + vt100::Color::Idx(1) + ); + assert_eq!( + parser.screen().cell(4, 5).unwrap().bgcolor(), + vt100::Color::Idx(1) + ); + assert_eq!( + parser.screen().contents_formatted(), + format!( + "\x1b[?25h\x1b[H\x1b[J{}{}\x1b[41m{}\x1b[5;5H", + "\r\n".repeat(4), + "\x1b[C".repeat(4), + "\x1b[X\x1b[C".repeat(76) + ) + .as_bytes() + ); + + parser.process(b"\x1bc\x1b[5;5H"); + assert_eq!( + parser.screen().cell(4, 3).unwrap().bgcolor(), + vt100::Color::Default + ); + assert_eq!( + parser.screen().cell(4, 4).unwrap().bgcolor(), + vt100::Color::Default + ); + assert_eq!( + parser.screen().cell(4, 5).unwrap().bgcolor(), + vt100::Color::Default + ); + assert_eq!( + parser.screen().contents_formatted(), + b"\x1b[?25h\x1b[H\x1b[J\x1b[5;5H" + ); + + parser.process(b"\x1b[41m\x1b[1K"); + assert_eq!( + parser.screen().cell(4, 3).unwrap().bgcolor(), + vt100::Color::Idx(1) + ); + assert_eq!( + parser.screen().cell(4, 4).unwrap().bgcolor(), + vt100::Color::Idx(1) + ); + assert_eq!( + parser.screen().cell(4, 5).unwrap().bgcolor(), + vt100::Color::Default + ); + assert_eq!( + parser.screen().contents_formatted(), + format!( + "\x1b[?25h\x1b[H\x1b[J{}\x1b[41m{}\x1b[5;5H", + "\r\n".repeat(4), + "\x1b[X\x1b[C".repeat(5), + ) + .as_bytes() + ); + + parser.process(b"\x1bc\x1b[5;5H"); + assert_eq!( + parser.screen().cell(4, 3).unwrap().bgcolor(), + vt100::Color::Default + ); + assert_eq!( + parser.screen().cell(4, 4).unwrap().bgcolor(), + vt100::Color::Default + ); + assert_eq!( + parser.screen().cell(4, 5).unwrap().bgcolor(), + vt100::Color::Default + ); + assert_eq!( + parser.screen().contents_formatted(), + b"\x1b[?25h\x1b[H\x1b[J\x1b[5;5H" + ); + + parser.process(b"\x1b[41m\x1b[2K"); + assert_eq!( + parser.screen().cell(4, 3).unwrap().bgcolor(), + vt100::Color::Idx(1) + ); + assert_eq!( + parser.screen().cell(4, 4).unwrap().bgcolor(), + vt100::Color::Idx(1) + ); + assert_eq!( + parser.screen().cell(4, 5).unwrap().bgcolor(), + vt100::Color::Idx(1) + ); + assert_eq!( + parser.screen().contents_formatted(), + format!( + "\x1b[?25h\x1b[H\x1b[J{}\x1b[41m{}\x1b[5;5H", + "\r\n".repeat(4), + "\x1b[X\x1b[C".repeat(80), + ) + .as_bytes() + ); } #[test] -- cgit v1.2.3-54-g00ecf