diff options
author | Jesse Luehrs <doy@tozt.net> | 2019-10-31 14:33:05 -0400 |
---|---|---|
committer | Jesse Luehrs <doy@tozt.net> | 2019-10-31 14:33:05 -0400 |
commit | 91726d4e0695ac4914885aada3304992e51bfb7f (patch) | |
tree | 26c44c77dbbba329a7633b3bfa6b5bd21628bafa | |
parent | 4ca747a83a82612f8fcd4e762ef701993e55b95c (diff) | |
download | vt100-rust-91726d4e0695ac4914885aada3304992e51bfb7f.tar.gz vt100-rust-91726d4e0695ac4914885aada3304992e51bfb7f.zip |
implement window_contents_formatted
-rw-r--r-- | src/attrs.rs | 75 | ||||
-rw-r--r-- | src/cell.rs | 4 | ||||
-rw-r--r-- | src/grid.rs | 18 | ||||
-rw-r--r-- | src/row.rs | 60 |
4 files changed, 144 insertions, 13 deletions
diff --git a/src/attrs.rs b/src/attrs.rs index 86fec32..1e137e9 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -7,3 +7,78 @@ pub struct Attrs { pub underline: bool, pub inverse: bool, } + +impl Attrs { + pub fn escape_code_diff(&self, other: &Self) -> String { + let mut opts = vec![]; + + if self.fgcolor != other.fgcolor { + match self.fgcolor { + crate::color::Color::Default => { + opts.push(39); + } + crate::color::Color::Idx(i) => { + if i < 8 { + opts.push(i + 30); + } else if i < 16 { + opts.push(i + 82); + } else { + opts.push(38); + opts.push(5); + opts.push(i); + } + } + crate::color::Color::Rgb(r, g, b) => { + opts.push(38); + opts.push(2); + opts.push(r); + opts.push(g); + opts.push(b); + } + } + } + + if self.bgcolor != other.bgcolor { + match self.bgcolor { + crate::color::Color::Default => { + opts.push(49); + } + crate::color::Color::Idx(i) => { + if i < 8 { + opts.push(i + 40); + } else if i < 16 { + opts.push(i + 92); + } else { + opts.push(48); + opts.push(5); + opts.push(i); + } + } + crate::color::Color::Rgb(r, g, b) => { + opts.push(48); + opts.push(2); + opts.push(r); + opts.push(g); + opts.push(b); + } + } + } + + if self.bold != other.bold { + opts.push(if self.bold { 1 } else { 21 }); + } + if self.italic != other.italic { + opts.push(if self.italic { 3 } else { 23 }); + } + if self.underline != other.underline { + opts.push(if self.underline { 4 } else { 24 }); + } + if self.inverse != other.inverse { + opts.push(if self.inverse { 7 } else { 27 }); + } + + let strs: Vec<_> = + opts.iter().map(std::string::ToString::to_string).collect(); + format!("\x1b[{}m", strs.join(";")) + } +} diff --git a/src/cell.rs b/src/cell.rs index 370feb0..8c330ac 100644 --- a/src/cell.rs +++ b/src/cell.rs @@ -43,6 +43,10 @@ impl Cell { crate::unicode::str_width(&self.contents) > 1 } + pub(crate) fn attrs(&self) -> &crate::attrs::Attrs { + &self.attrs + } + pub fn fgcolor(&self) -> crate::color::Color { self.attrs.fgcolor } diff --git a/src/grid.rs b/src/grid.rs index 8b03dac..0d5a071 100644 --- a/src/grid.rs +++ b/src/grid.rs @@ -86,12 +86,20 @@ impl Grid { pub fn window_contents_formatted( &self, - _row_start: u16, - _col_start: u16, - _row_end: u16, - _col_end: u16, + row_start: u16, + col_start: u16, + row_end: u16, + col_end: u16, ) -> String { - unimplemented!() + let mut contents = String::new(); + let mut prev_attrs = crate::attrs::Attrs::default(); + for row in row_start..=(row_end.min(self.size.rows - 1)) { + let (new_contents, new_attrs) = &self.rows[row as usize] + .contents_formatted(col_start, col_end, prev_attrs); + contents += new_contents; + prev_attrs = *new_attrs; + } + contents } pub fn erase_all(&mut self) { @@ -46,18 +46,41 @@ impl Row { pub fn contents(&self, col_start: u16, col_end: u16) -> String { let mut prev_was_wide = false; - // XXX very inefficient - let mut max_col = None; - for (col, cell) in self.cells.iter().enumerate() { - if cell.has_contents() || prev_was_wide { - max_col = Some(col); + let mut contents = String::new(); + if let Some(max_col) = self.max_col() { + for col in col_start..=(col_end.min(max_col as u16)) { + if prev_was_wide { + prev_was_wide = false; + continue; + } + + let cell = &self.cells[col as usize]; + let cell_contents = cell.contents(); + let cell_contents = if cell_contents == "" { + " " + } else { + cell_contents + }; + contents += cell_contents; prev_was_wide = cell.is_wide(); } } + if !self.wrapped { + contents += "\n"; + } + contents + } - prev_was_wide = false; + pub fn contents_formatted( + &self, + col_start: u16, + col_end: u16, + attrs: crate::attrs::Attrs, + ) -> (String, crate::attrs::Attrs) { + let mut prev_was_wide = false; let mut contents = String::new(); - if let Some(max_col) = max_col { + let mut prev_attrs = attrs; + if let Some(max_col) = self.max_col() { for col in col_start..=(col_end.min(max_col as u16)) { if prev_was_wide { prev_was_wide = false; @@ -65,6 +88,13 @@ impl Row { } let cell = &self.cells[col as usize]; + + let attrs = cell.attrs(); + if &prev_attrs != attrs { + contents += &attrs.escape_code_diff(&prev_attrs); + prev_attrs = *attrs; + } + let cell_contents = cell.contents(); let cell_contents = if cell_contents == "" { " " @@ -72,12 +102,26 @@ impl Row { cell_contents }; contents += cell_contents; + prev_was_wide = cell.is_wide(); } } if !self.wrapped { contents += "\n"; } - contents + (contents, prev_attrs) + } + + fn max_col(&self) -> Option<u16> { + let mut prev_was_wide = false; + // XXX very inefficient + let mut max_col = None; + for (col, cell) in self.cells.iter().enumerate() { + if cell.has_contents() || prev_was_wide { + max_col = Some(col as u16); + prev_was_wide = cell.is_wide(); + } + } + max_col } } |