diff options
author | Christian Duerr <contact@christianduerr.com> | 2020-01-09 23:06:41 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-01-09 23:06:41 +0000 |
commit | 3fb631b91caec163707858bd1d435015e6e6cb18 (patch) | |
tree | cfc575f224622b7c83a21281c2e23a7f8af83364 /alacritty_terminal/src/selection.rs | |
parent | 5651c3f7114dff611e616865ad02e682779979d9 (diff) | |
download | alacritty-3fb631b91caec163707858bd1d435015e6e6cb18.tar.gz alacritty-3fb631b91caec163707858bd1d435015e6e6cb18.zip |
Fix cut off full width glyphs in last column
This resolves the issue with full width glyphs getting rendered in the
last column. Since they need at least two glyphs, it is not possible to
properly render them in the last column.
Instead of rendering half of the glyph in the last column, with the
other half cut off, an additional spacer is now inserted before the wide
glyph. This means that the specific glyph in question is then three
cells wide.
Fixes #2385.
Diffstat (limited to 'alacritty_terminal/src/selection.rs')
-rw-r--r-- | alacritty_terminal/src/selection.rs | 61 |
1 files changed, 47 insertions, 14 deletions
diff --git a/alacritty_terminal/src/selection.rs b/alacritty_terminal/src/selection.rs index 5f94634f..6e6dd9c8 100644 --- a/alacritty_terminal/src/selection.rs +++ b/alacritty_terminal/src/selection.rs @@ -183,9 +183,9 @@ impl Selection { } // Clamp to visible region in grid/normal - let cols = term.dimensions().col; - let lines = term.dimensions().line.0 as isize; - let (start, end) = Selection::grid_clamp(start, end, lines, cols)?; + let num_cols = term.dimensions().col; + let num_lines = term.dimensions().line.0 as isize; + let (start, end) = Selection::grid_clamp(start, end, num_lines, num_cols)?; let span = match *self { Selection::Simple { ref region } => { @@ -214,16 +214,49 @@ impl Selection { span.map(|mut span| { let grid = term.grid(); - if span.start.col < cols - && grid[span.start.line][span.start.col].flags.contains(Flags::WIDE_CHAR_SPACER) - { - span.start.col = Column(span.start.col.saturating_sub(1)); + // Helper for checking if cell at `point` contains `flag` + let flag_at = |point: Point<usize>, flag: Flags| -> bool { + grid[point.line][point.col].flags.contains(flag) + }; + + // Include all double-width cells and placeholders at top left of selection + if span.start.col < num_cols { + // Expand from wide char spacer to wide char + if span.start.line + 1 != grid.len() || span.start.col.0 != 0 { + let prev = span.start.sub(num_cols.0, 1, true); + if flag_at(span.start, Flags::WIDE_CHAR_SPACER) + && flag_at(prev, Flags::WIDE_CHAR) + { + span.start = prev; + } + } + + // Expand from wide char to wide char spacer for linewrapping + if span.start.line + 1 != grid.len() || span.start.col.0 != 0 { + let prev = span.start.sub(num_cols.0, 1, true); + if (prev.line + 1 != grid.len() || prev.col.0 != 0) + && flag_at(prev, Flags::WIDE_CHAR_SPACER) + && !flag_at(prev.sub(num_cols.0, 1, true), Flags::WIDE_CHAR) + { + span.start = prev; + } + } } - if span.end.col.0 < cols.saturating_sub(1) - && grid[span.end.line][span.end.col].flags.contains(Flags::WIDE_CHAR) - { - span.end.col += 1; + // Include all double-width cells and placeholders at bottom right of selection + if span.end.line != 0 || span.end.col < num_cols { + // Expand from wide char spacer for linewrapping to wide char + if (span.end.line + 1 != grid.len() || span.end.col.0 != 0) + && flag_at(span.end, Flags::WIDE_CHAR_SPACER) + && !flag_at(span.end.sub(num_cols.0, 1, true), Flags::WIDE_CHAR) + { + span.end = span.end.add(num_cols.0, 1, true); + } + + // Expand from wide char to wide char spacer + if flag_at(span.end, Flags::WIDE_CHAR) { + span.end = span.end.add(num_cols.0, 1, true); + } } span @@ -445,7 +478,7 @@ mod test { assert_eq!(selection.to_span(&term(1, 1)).unwrap(), Span { start: location, end: location, - is_block: false, + is_block: false }); } @@ -463,7 +496,7 @@ mod test { assert_eq!(selection.to_span(&term(1, 1)).unwrap(), Span { start: location, end: location, - is_block: false, + is_block: false }); } @@ -586,7 +619,7 @@ mod test { assert_eq!(selection.to_span(&term(5, 10)).unwrap(), Span { start: Point::new(2, Column(4)), end: Point::new(0, Column(4)), - is_block: true, + is_block: true }); } |