aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2019-11-08 04:13:08 -0500
committerJesse Luehrs <doy@tozt.net>2019-11-08 06:46:33 -0500
commit76aeb85e99e088151c867d86858705bf38c345de (patch)
treeab4a9375980026885c707f4af71b3b49a5f1bf17
parentf5e9c72622f2fceeb083f5df872c77dd1d39cffb (diff)
downloadvt100-rust-76aeb85e99e088151c867d86858705bf38c345de.tar.gz
vt100-rust-76aeb85e99e088151c867d86858705bf38c345de.zip
fix wide character handling in contents_formatted and contents_diff
-rw-r--r--CHANGELOG.md2
-rw-r--r--src/row.rs30
-rw-r--r--tests/text.rs23
-rw-r--r--tests/window_contents.rs38
4 files changed, 85 insertions, 8 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bfb122b..aecda1b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,8 @@
### Fixed
* Clearing cells now correctly sets the cell background color.
+* Fixed a couple bugs in wide character handling in `contents_formatted` and
+ `contents_diff`.
## [0.3.1] - 2019-11-06
diff --git a/src/row.rs b/src/row.rs
index b563b33..0b834ce 100644
--- a/src/row.rs
+++ b/src/row.rs
@@ -98,8 +98,12 @@ impl Row {
let mut contents = vec![];
let mut prev_attrs = attrs;
- let cols = width.min(self.content_width(start));
- for cell in self.cells().skip(start as usize).take(cols as usize) {
+ let mut cols = 0;
+ for cell in self
+ .cells()
+ .skip(start as usize)
+ .take(width.min(self.content_width(start)) as usize)
+ {
if prev_was_wide {
prev_was_wide = false;
continue;
@@ -120,6 +124,7 @@ impl Row {
});
prev_was_wide = cell.is_wide();
+ cols += if prev_was_wide { 2 } else { 1 };
}
(contents, prev_attrs, cols)
@@ -132,23 +137,30 @@ impl Row {
width: u16,
attrs: crate::attrs::Attrs,
) -> (Vec<u8>, crate::attrs::Attrs, u16) {
+ let mut prev_was_wide = false;
let mut skip = 0;
let mut contents = vec![];
let mut prev_attrs = attrs;
- let mut final_col = 0;
+ let mut cols = 0;
- for (idx, (cell, prev_cell)) in self
+ for (cell, prev_cell) in self
.cells()
.zip(prev.cells())
.skip(start as usize)
.take(width as usize)
- .enumerate()
{
+ if prev_was_wide {
+ prev_was_wide = false;
+ continue;
+ }
+
if cell == prev_cell {
- skip += 1;
+ prev_was_wide = cell.is_wide();
+ skip += if prev_was_wide { 2 } else { 1 };
} else {
if skip > 0 {
contents.extend(format!("\x1b[{}C", skip).as_bytes());
+ cols += skip;
skip = 0;
}
@@ -163,11 +175,13 @@ impl Row {
} else {
b"\x1b[X\x1b[C"
});
- final_col = idx + 1;
+
+ prev_was_wide = cell.is_wide();
+ cols += if prev_was_wide { 2 } else { 1 };
}
}
- (contents, prev_attrs, final_col.try_into().unwrap())
+ (contents, prev_attrs, cols)
}
fn content_width(&self, start: u16) -> u16 {
diff --git a/tests/text.rs b/tests/text.rs
index 24170b8..24c700e 100644
--- a/tests/text.rs
+++ b/tests/text.rs
@@ -46,7 +46,9 @@ fn newlines() {
#[test]
fn wide() {
let mut parser = vt100::Parser::new(24, 80);
+ let screen1 = parser.screen().clone();
parser.process("aデbネ".as_bytes());
+ let screen2 = parser.screen().clone();
assert_eq!(parser.screen().cell(0, 0).unwrap().contents(), "a");
assert_eq!(parser.screen().cell(0, 1).unwrap().contents(), "デ");
assert_eq!(parser.screen().cell(0, 2).unwrap().contents(), "");
@@ -56,6 +58,27 @@ fn wide() {
assert_eq!(parser.screen().cell(0, 6).unwrap().contents(), "");
assert_eq!(parser.screen().cell(1, 0).unwrap().contents(), "");
assert_eq!(parser.screen().contents(), "aデbネ");
+ assert_eq!(parser.screen().cursor_position(), (0, 6));
+ assert_eq!(
+ parser.screen().contents_formatted(),
+ "\x1b[?25h\x1b[H\x1b[Jaデbネ".as_bytes()
+ );
+ assert_eq!(
+ parser.screen().contents_diff(&screen1),
+ "\x1b[m\x1b[1;1Haデbネ".as_bytes()
+ );
+
+ parser.process(b"\x1b[1;1H\x1b[3Cc");
+ assert_eq!(parser.screen().contents(), "aデcネ");
+ assert_eq!(parser.screen().cursor_position(), (0, 4));
+ assert_eq!(
+ parser.screen().contents_formatted(),
+ "\x1b[?25h\x1b[H\x1b[Jaデcネ\x1b[1;5H".as_bytes()
+ );
+ assert_eq!(
+ parser.screen().contents_diff(&screen2),
+ "\x1b[m\x1b[1;1H\x1b[3Cc".as_bytes()
+ );
}
#[test]
diff --git a/tests/window_contents.rs b/tests/window_contents.rs
index 9b49421..29b76f8 100644
--- a/tests/window_contents.rs
+++ b/tests/window_contents.rs
@@ -76,6 +76,44 @@ fn empty_cells() {
}
#[test]
+fn cursor_positioning() {
+ let mut parser = vt100::Parser::new(24, 80);
+ let screen1 = parser.screen().clone();
+
+ parser.process(b":\x1b[K");
+ let screen2 = parser.screen().clone();
+ assert_eq!(parser.screen().cursor_position(), (0, 1));
+ assert_eq!(
+ parser.screen().contents_formatted(),
+ b"\x1b[?25h\x1b[H\x1b[J:"
+ );
+ assert_eq!(parser.screen().contents_diff(&screen1), b"\x1b[m\x1b[1;1H:");
+
+ parser.process(b"a");
+ let screen3 = parser.screen().clone();
+ assert_eq!(parser.screen().cursor_position(), (0, 2));
+ assert_eq!(
+ parser.screen().contents_formatted(),
+ b"\x1b[?25h\x1b[H\x1b[J:a"
+ );
+ assert_eq!(
+ parser.screen().contents_diff(&screen2),
+ b"\x1b[m\x1b[1;1H\x1b[1Ca"
+ );
+
+ parser.process(b"\x1b[1;2H\x1b[K");
+ assert_eq!(parser.screen().cursor_position(), (0, 1));
+ assert_eq!(
+ parser.screen().contents_formatted(),
+ b"\x1b[?25h\x1b[H\x1b[J:"
+ );
+ assert_eq!(
+ parser.screen().contents_diff(&screen3),
+ b"\x1b[m\x1b[1;1H\x1b[1C\x1b[X\x1b[C\x1b[1;2H"
+ );
+}
+
+#[test]
fn rows() {
let mut parser = vt100::Parser::new(24, 80);
let screen1 = parser.screen().clone();