diff options
author | Jesse Luehrs <doy@tozt.net> | 2019-11-08 04:13:08 -0500 |
---|---|---|
committer | Jesse Luehrs <doy@tozt.net> | 2019-11-08 06:46:33 -0500 |
commit | 76aeb85e99e088151c867d86858705bf38c345de (patch) | |
tree | ab4a9375980026885c707f4af71b3b49a5f1bf17 | |
parent | f5e9c72622f2fceeb083f5df872c77dd1d39cffb (diff) | |
download | vt100-rust-76aeb85e99e088151c867d86858705bf38c345de.tar.gz vt100-rust-76aeb85e99e088151c867d86858705bf38c345de.zip |
fix wide character handling in contents_formatted and contents_diff
-rw-r--r-- | CHANGELOG.md | 2 | ||||
-rw-r--r-- | src/row.rs | 30 | ||||
-rw-r--r-- | tests/text.rs | 23 | ||||
-rw-r--r-- | tests/window_contents.rs | 38 |
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 @@ -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(); |