diff options
author | Christian Duerr <chrisduerr@users.noreply.github.com> | 2018-12-09 15:28:22 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-09 15:28:22 +0000 |
commit | 1cebcd660bf0b6dc514341fe6bc7a392b1572849 (patch) | |
tree | 47a4012107030a73c986e9746aee4bd3a23f1807 /src/term | |
parent | 47f8f1bac6f0b41fe1ad9c4267687db7a42068de (diff) | |
download | alacritty-1cebcd660bf0b6dc514341fe6bc7a392b1572849.tar.gz alacritty-1cebcd660bf0b6dc514341fe6bc7a392b1572849.zip |
Fix rendering of zero-width characters
Instead of rendering zero-width characters as full characters, they are
now properly rendered without advancing the cursor.
Because of performance limitations, this implementation only supports up
to 5 zero-width characters per cell. However, as a result of this
limitation there should not be any performance impact.
This fixes #1317, fixes #696 and closes #1318.
Diffstat (limited to 'src/term')
-rw-r--r-- | src/term/cell.rs | 45 | ||||
-rw-r--r-- | src/term/mod.rs | 24 |
2 files changed, 60 insertions, 9 deletions
diff --git a/src/term/cell.rs b/src/term/cell.rs index ef8509dc..e6fe980e 100644 --- a/src/term/cell.rs +++ b/src/term/cell.rs @@ -15,9 +15,12 @@ use ansi::{NamedColor, Color}; use grid; use index::Column; +// Maximum number of zerowidth characters which will be stored per cell. +pub const MAX_ZEROWIDTH_CHARS: usize = 5; + bitflags! { #[derive(Serialize, Deserialize)] - pub struct Flags: u32 { + pub struct Flags: u16 { const INVERSE = 0b0_0000_0001; const BOLD = 0b0_0000_0010; const ITALIC = 0b0_0000_0100; @@ -31,12 +34,18 @@ bitflags! { } } +const fn default_extra() -> [char; MAX_ZEROWIDTH_CHARS] { + [' '; MAX_ZEROWIDTH_CHARS] +} + #[derive(Copy, Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] pub struct Cell { pub c: char, pub fg: Color, pub bg: Color, pub flags: Flags, + #[serde(default="default_extra")] + pub extra: [char; MAX_ZEROWIDTH_CHARS], } impl Default for Cell { @@ -65,7 +74,7 @@ impl LineLength for grid::Row<Cell> { } for (index, cell) in self[..].iter().rev().enumerate() { - if cell.c != ' ' { + if cell.c != ' ' || cell.extra[0] != ' ' { length = Column(self.len() - index); break; } @@ -93,6 +102,7 @@ impl Cell { pub fn new(c: char, fg: Color, bg: Color) -> Cell { Cell { + extra: [' '; MAX_ZEROWIDTH_CHARS], c, bg, fg, @@ -102,9 +112,10 @@ impl Cell { #[inline] pub fn is_empty(&self) -> bool { - self.c == ' ' && - self.bg == Color::Named(NamedColor::Background) && - !self.flags.intersects(Flags::INVERSE | Flags::UNDERLINE) + self.c == ' ' + && self.extra[0] == ' ' + && self.bg == Color::Named(NamedColor::Background) + && !self.flags.intersects(Flags::INVERSE | Flags::UNDERLINE) } #[inline] @@ -112,6 +123,30 @@ impl Cell { // memcpy template to self *self = *template; } + + #[inline] + pub fn chars(&self) -> [char; MAX_ZEROWIDTH_CHARS + 1] { + unsafe { + let mut chars = [std::mem::uninitialized(); MAX_ZEROWIDTH_CHARS + 1]; + std::ptr::write(&mut chars[0], self.c); + std::ptr::copy_nonoverlapping( + self.extra.as_ptr(), + chars.as_mut_ptr().offset(1), + self.extra.len(), + ); + chars + } + } + + #[inline] + pub fn push_extra(&mut self, c: char) { + for elem in self.extra.iter_mut() { + if elem == &' ' { + *elem = c; + break; + } + } + } } #[cfg(test)] diff --git a/src/term/mod.rs b/src/term/mod.rs index 193d7188..ed96433c 100644 --- a/src/term/mod.rs +++ b/src/term/mod.rs @@ -424,7 +424,7 @@ pub struct RenderableCell { /// A _Display_ line (not necessarily an _Active_ line) pub line: Line, pub column: Column, - pub c: char, + pub chars: [char; cell::MAX_ZEROWIDTH_CHARS + 1], pub fg: Rgb, pub bg: Rgb, pub bg_alpha: f32, @@ -488,7 +488,7 @@ impl<'a> Iterator for RenderableCellsIter<'a> { line: cell.line, column: cell.column, flags: cell.flags, - c: cell.c, + chars: cell.chars(), fg: fg_rgb, bg: bg_rgb, bg_alpha, @@ -1030,6 +1030,9 @@ impl Term { for cell in &grid_line[cols.start..line_end] { if !cell.flags.contains(cell::Flags::WIDE_CHAR_SPACER) { self.push(cell.c); + for c in (&cell.chars()[1..]).iter().filter(|c| **c != ' ') { + self.push(*c); + } } } @@ -1371,7 +1374,9 @@ impl ansi::Handler for Term { let num_cols = self.grid.num_cols(); { // If in insert mode, first shift cells to the right. - if self.mode.contains(mode::TermMode::INSERT) && self.cursor.point.col + width < num_cols { + if self.mode.contains(mode::TermMode::INSERT) + && self.cursor.point.col + width < num_cols + { let line = self.cursor.point.line; // borrowck let col = self.cursor.point.col; let line = &mut self.grid[line]; @@ -1383,6 +1388,18 @@ impl ansi::Handler for Term { ptr::copy(src, dst, (num_cols - col - width).0); } } + if width == 0 { + let mut col = self.cursor.point.col.0.saturating_sub(1); + let line = self.cursor.point.line; + if self.grid[line][Column(col)] + .flags + .contains(cell::Flags::WIDE_CHAR_SPACER) + { + col.saturating_sub(1); + } + self.grid[line][Column(col)].push_extra(c); + return; + } let cell = &mut self.grid[&self.cursor.point]; *cell = self.cursor.template; @@ -1409,7 +1426,6 @@ impl ansi::Handler for Term { } else { self.input_needs_wrap = true; } - } #[inline] |