From 2ffb815341c9c97568d4553745eda8e470f5c37a Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Fri, 6 Dec 2019 21:25:41 -0500 Subject: handle line wrapping with wide characters + combining characters --- src/row.rs | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) (limited to 'src') 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, @@ -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)); } -- cgit v1.2.3-54-g00ecf