aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2019-10-31 14:33:05 -0400
committerJesse Luehrs <doy@tozt.net>2019-10-31 14:33:05 -0400
commit91726d4e0695ac4914885aada3304992e51bfb7f (patch)
tree26c44c77dbbba329a7633b3bfa6b5bd21628bafa
parent4ca747a83a82612f8fcd4e762ef701993e55b95c (diff)
downloadvt100-rust-91726d4e0695ac4914885aada3304992e51bfb7f.tar.gz
vt100-rust-91726d4e0695ac4914885aada3304992e51bfb7f.zip
implement window_contents_formatted
-rw-r--r--src/attrs.rs75
-rw-r--r--src/cell.rs4
-rw-r--r--src/grid.rs18
-rw-r--r--src/row.rs60
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) {
diff --git a/src/row.rs b/src/row.rs
index 1d9df56..e87bc04 100644
--- a/src/row.rs
+++ b/src/row.rs
@@ -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
}
}