aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2021-11-19 03:40:51 -0500
committerJesse Luehrs <doy@tozt.net>2021-11-19 03:42:50 -0500
commit4227bdedde837347ecd83510b976ab13d474b2b9 (patch)
tree366e5246b9b796c28b26187471214ae18d3fb823
parentb45a23b68ea8eb27f2b616f3f1fc32532cdcf03c (diff)
downloadvt100-rust-4227bdedde837347ecd83510b976ab13d474b2b9.tar.gz
vt100-rust-4227bdedde837347ecd83510b976ab13d474b2b9.zip
fix up some more issues with row_formatted
handle cursor positioning and wrapping a bit better
-rw-r--r--CHANGELOG.md2
-rw-r--r--src/grid.rs24
-rw-r--r--src/row.rs16
-rw-r--r--src/screen.rs28
-rw-r--r--tests/data/fixtures/attrs.in1
-rw-r--r--tests/data/fixtures/attrs/10.json17
-rw-r--r--tests/data/fixtures/attrs/10.typescript1
7 files changed, 75 insertions, 14 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c863506..dc9a22a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,8 @@
* Fixed some line wrapping state issues with `contents_diff`
* Fixed cursor positioning after writing zero width characters at the end of
the line
+* Fixed `Screen::cursor_state_formatted` to draw the last character in a line
+ with the appropriate drawing attributes if it needs to redraw it
## [0.13.0] - 2021-11-17
diff --git a/src/grid.rs b/src/grid.rs
index 021a787..f550f9e 100644
--- a/src/grid.rs
+++ b/src/grid.rs
@@ -214,15 +214,19 @@ impl Grid {
self.size.cols,
i,
wrapping,
- prev_pos,
- prev_attrs,
+ Some(prev_pos),
+ Some(prev_attrs),
);
prev_pos = new_pos;
prev_attrs = new_attrs;
wrapping = row.wrapped();
}
- self.write_cursor_position_formatted(contents, Some(prev_pos));
+ self.write_cursor_position_formatted(
+ contents,
+ Some(prev_pos),
+ Some(prev_attrs),
+ );
prev_attrs
}
@@ -254,7 +258,11 @@ impl Grid {
wrapping = row.wrapped();
}
- self.write_cursor_position_formatted(contents, Some(prev_pos));
+ self.write_cursor_position_formatted(
+ contents,
+ Some(prev_pos),
+ Some(prev_attrs),
+ );
prev_attrs
}
@@ -263,6 +271,7 @@ impl Grid {
&self,
contents: &mut Vec<u8>,
prev_pos: Option<Pos>,
+ prev_attrs: Option<crate::attrs::Attrs>,
) {
// writing a character to the last column of a row doesn't wrap the
// cursor immediately - it waits until the next character is actually
@@ -285,7 +294,14 @@ impl Grid {
} else {
crate::term::MoveTo::new(pos).write_buf(contents);
}
+ cell.attrs().write_escape_code_diff(
+ contents,
+ &prev_attrs.unwrap_or_default(),
+ );
contents.extend(cell.contents().as_bytes());
+ if let Some(prev_attrs) = prev_attrs {
+ prev_attrs.write_escape_code_diff(contents, cell.attrs());
+ }
} else {
// if the cell doesn't have contents, we can't have gotten
// here by drawing a character in the last column. this means
diff --git a/src/row.rs b/src/row.rs
index cbd73ae..6f1cc0b 100644
--- a/src/row.rs
+++ b/src/row.rs
@@ -135,12 +135,24 @@ impl Row {
width: u16,
row: u16,
wrapping: bool,
- mut prev_pos: crate::grid::Pos,
- mut prev_attrs: crate::attrs::Attrs,
+ prev_pos: Option<crate::grid::Pos>,
+ prev_attrs: Option<crate::attrs::Attrs>,
) -> (crate::grid::Pos, crate::attrs::Attrs) {
let mut prev_was_wide = false;
let default_cell = crate::cell::Cell::default();
+ let mut prev_pos = if let Some(prev_pos) = prev_pos {
+ prev_pos
+ } else if wrapping {
+ crate::grid::Pos {
+ row: row - 1,
+ col: self.cols(),
+ }
+ } else {
+ crate::grid::Pos { row, col: start }
+ };
+ let mut prev_attrs = prev_attrs.unwrap_or_default();
+
let first_cell = self.get(start).unwrap();
if wrapping && first_cell == &default_cell {
contents.push(b' ');
diff --git a/src/screen.rs b/src/screen.rs
index 56bd963..57d1d1c 100644
--- a/src/screen.rs
+++ b/src/screen.rs
@@ -294,10 +294,12 @@ impl Screen {
width,
i,
wrapping,
- crate::grid::Pos { row: i, col: start },
- crate::attrs::Attrs::default(),
+ None,
+ None,
);
- wrapping = row.wrapped();
+ if start == 0 && width == self.grid.size().cols {
+ wrapping = row.wrapped();
+ }
contents
})
}
@@ -551,10 +553,12 @@ impl Screen {
/// need to restore the terminal state without the terminal contents
/// necessarily being the same.
///
- /// Note that this is more complicated than it sounds, because the cursor
- /// position's state includes more than just the data returned by
- /// `cursor_position`, since moving the cursor to the next row during text
- /// wrapping is delayed until a character is written.
+ /// Note that the bytes returned by this function may alter the active
+ /// drawing attributes, because it may require redrawing existing cells in
+ /// order to position the cursor correctly (for instance, in the case
+ /// where the cursor is past the end of a row). Therefore, you should
+ /// ensure to reset the active drawing attributes if necessary after
+ /// processing this data, for instance by using `attributes_formatted`.
#[must_use]
pub fn cursor_state_formatted(&self) -> Vec<u8> {
let mut contents = vec![];
@@ -564,7 +568,15 @@ impl Screen {
fn write_cursor_state_formatted(&self, contents: &mut Vec<u8>) {
crate::term::HideCursor::new(self.hide_cursor()).write_buf(contents);
- self.grid().write_cursor_position_formatted(contents, None);
+ self.grid()
+ .write_cursor_position_formatted(contents, None, None);
+
+ // we don't just call write_attributes_formatted here, because that
+ // would still be confusing - consider the case where the user sets
+ // their own unrelated drawing attributes (on a different parser
+ // instance) and then calls cursor_state_formatted. just documenting
+ // it and letting the user handle it on their own is more
+ // straightforward.
}
/// Returns the `Cell` object at the given location in the terminal, if it
diff --git a/tests/data/fixtures/attrs.in b/tests/data/fixtures/attrs.in
index 0edae4e..4fe65cb 100644
--- a/tests/data/fixtures/attrs.in
+++ b/tests/data/fixtures/attrs.in
@@ -7,3 +7,4 @@ f\x1b[1mo\x1b[3mo\x1b[4mo\x1b[7mo
\x1bcfoo
\x1b[1;2H\x1b[4;7mo\x1b[m
\x1b[1;1H\x1b[4;7m\x1b[X\x1b[m
+\x1bc\x1b[1;79H\x1b[31mab
diff --git a/tests/data/fixtures/attrs/10.json b/tests/data/fixtures/attrs/10.json
new file mode 100644
index 0000000..b6cb478
--- /dev/null
+++ b/tests/data/fixtures/attrs/10.json
@@ -0,0 +1,17 @@
+{
+ "contents": " ab",
+ "cells": {
+ "0,78": {
+ "contents": "a",
+ "fgcolor": "1"
+ },
+ "0,79": {
+ "contents": "b",
+ "fgcolor": "1"
+ }
+ },
+ "cursor_position": [
+ 0,
+ 80
+ ]
+} \ No newline at end of file
diff --git a/tests/data/fixtures/attrs/10.typescript b/tests/data/fixtures/attrs/10.typescript
new file mode 100644
index 0000000..ba2cb07
--- /dev/null
+++ b/tests/data/fixtures/attrs/10.typescript
@@ -0,0 +1 @@
+cab \ No newline at end of file