aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2019-12-06 21:25:41 -0500
committerJesse Luehrs <doy@tozt.net>2019-12-06 23:28:04 -0500
commit2ffb815341c9c97568d4553745eda8e470f5c37a (patch)
tree445ba5a1cdeb2740fac73b20295aee1e11114eee
parent0dcb7be129f4bb8f97a62cc3676be1eee7858b74 (diff)
downloadvt100-rust-2ffb815341c9c97568d4553745eda8e470f5c37a.tar.gz
vt100-rust-2ffb815341c9c97568d4553745eda8e470f5c37a.zip
handle line wrapping with wide characters + combining characters
-rw-r--r--src/row.rs50
-rw-r--r--tests/data/fixtures/combining.in1
-rw-r--r--tests/data/fixtures/combining/14.json17
-rw-r--r--tests/data/fixtures/combining/14.typescript1
4 files changed, 67 insertions, 2 deletions
diff --git a/src/row.rs b/src/row.rs
index 8f96c27..a0d44a4 100644
--- a/src/row.rs
+++ b/src/row.rs
@@ -191,8 +191,30 @@ impl Row {
prev_attrs = *attrs;
}
- contents.extend(cell.contents().as_bytes());
prev_pos.col += if cell.is_wide() { 2 } else { 1 };
+ if prev_pos.col >= self.cols()
+ && !self.wrapped
+ && cell.is_wide()
+ && cell.contents().chars().count() > 1
+ {
+ // alternately, we could backspace enough to overwrite
+ // the second to last character, then ICH and rewrite
+ // the second to last character and then reposition,
+ // but that's a lot more complicated and not sure if
+ // it's worth it for this much of an edge case
+ let cell_contents = cell.contents();
+ let mut chars = cell_contents.chars();
+ let base = chars.next().unwrap();
+ let mut bytes = [0; 4];
+ contents.extend(base.encode_utf8(&mut bytes).bytes());
+ crate::term::Backspace::default().write_buf(contents);
+ for c in chars {
+ contents
+ .extend(c.encode_utf8(&mut bytes).bytes());
+ }
+ } else {
+ contents.extend(cell.contents().as_bytes());
+ }
} else if erase.is_none() {
erase = Some((pos.col, attrs));
}
@@ -216,6 +238,7 @@ impl Row {
// while it's true that most of the logic in this is identical to
// write_contents_formatted, i can't figure out how to break out the
// common parts without making things noticeably slower.
+ #[allow(clippy::too_many_lines)]
pub fn write_contents_diff(
&self,
contents: &mut Vec<u8>,
@@ -312,8 +335,31 @@ impl Row {
prev_attrs = *attrs;
}
- contents.extend(cell.contents().as_bytes());
prev_pos.col += if cell.is_wide() { 2 } else { 1 };
+ if prev_pos.col >= self.cols()
+ && !self.wrapped
+ && cell.is_wide()
+ && cell.contents().chars().count() > 1
+ {
+ // alternately, we could backspace enough to overwrite
+ // the second to last character, then ICH and rewrite
+ // the second to last character and then reposition,
+ // but that's a lot more complicated and not sure if
+ // it's worth it for this much of an edge case
+ let cell_contents = cell.contents();
+ let mut chars = cell_contents.chars();
+ let base = chars.next().unwrap();
+ let mut bytes = [0; 4];
+ contents.extend(base.encode_utf8(&mut bytes).bytes());
+ crate::term::Backspace::default().write_buf(contents);
+ prev_pos.col -= 1;
+ for c in chars {
+ contents
+ .extend(c.encode_utf8(&mut bytes).bytes());
+ }
+ } else {
+ contents.extend(cell.contents().as_bytes());
+ }
} else if erase.is_none() {
erase = Some((pos.col, attrs));
}
diff --git a/tests/data/fixtures/combining.in b/tests/data/fixtures/combining.in
index b9c62ca..5f62920 100644
--- a/tests/data/fixtures/combining.in
+++ b/tests/data/fixtures/combining.in
@@ -11,3 +11,4 @@ a
\u{0301}
\x1b[H\x1b[Ja\u{0301}
\x1b[H\x1b[J\x1b[2C\u{0301}
+\x1b[H\x1b[J\x1b[1;79Ha\x08\u{301}
diff --git a/tests/data/fixtures/combining/14.json b/tests/data/fixtures/combining/14.json
new file mode 100644
index 0000000..bdc1fe2
--- /dev/null
+++ b/tests/data/fixtures/combining/14.json
@@ -0,0 +1,17 @@
+{
+ "contents": " á",
+ "cells": {
+ "0,78": {
+ "contents": "á",
+ "is_wide": true
+ },
+ "0,79": {
+ "contents": "",
+ "is_wide_continuation": true
+ }
+ },
+ "cursor_position": [
+ 0,
+ 79
+ ]
+} \ No newline at end of file
diff --git a/tests/data/fixtures/combining/14.typescript b/tests/data/fixtures/combining/14.typescript
new file mode 100644
index 0000000..513bc90
--- /dev/null
+++ b/tests/data/fixtures/combining/14.typescript
@@ -0,0 +1 @@
+á \ No newline at end of file