ui: make wide chars occupy more than one cell

If setting a wide char to a Cell, mark the next one as empty in order to
skip printing it.

This prevents the following misalignment:
  |   subject
  |📎  Fwd: RE:
  |   second subject
master
Manos Pitsidianakis 2019-08-17 12:22:54 +03:00
parent af573b57f1
commit e5f8714162
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
2 changed files with 33 additions and 3 deletions

View File

@ -415,14 +415,16 @@ impl State {
.unwrap();
for x in x_start..=x_end {
let c = self.grid[(x, y)];
if c.bg() != Color::Default {
write!(self.stdout(), "{}", termion::color::Bg(c.bg().as_termion())).unwrap();
}
if c.fg() != Color::Default {
write!(self.stdout(), "{}", termion::color::Fg(c.fg().as_termion())).unwrap();
}
write!(self.stdout(), "{}", c.ch()).unwrap();
if !c.empty() {
write!(self.stdout(), "{}", c.ch()).unwrap();
}
if c.bg() != Color::Default {
write!(
self.stdout(),

View File

@ -25,6 +25,7 @@
*/
use super::position::*;
use text_processing::wcwidth;
use std::convert::From;
use std::fmt;
@ -280,6 +281,7 @@ impl fmt::Display for CellBuffer {
pub struct Cell {
ch: char,
empty: bool,
fg: Color,
bg: Color,
attrs: Attr,
@ -300,7 +302,13 @@ impl Cell {
/// assert_eq!(cell.attrs(), Attr::Default);
/// ```
pub fn new(ch: char, fg: Color, bg: Color, attrs: Attr) -> Cell {
Cell { ch, fg, bg, attrs }
Cell {
ch,
fg,
bg,
attrs,
empty: false,
}
}
/// Creates a new `Cell` with the given `char` and default style.
@ -441,6 +449,10 @@ impl Cell {
self.attrs = newattrs;
self
}
pub fn empty(&self) -> bool {
self.empty
}
}
impl Default for Cell {
@ -750,6 +762,21 @@ pub fn write_string_to_grid(
grid[(x, y)].set_fg(fg_color);
grid[(x, y)].set_bg(bg_color);
}
match wcwidth(u32::from(c)) {
Some(0) | None => {
/* Skip drawing zero width characters */
grid[(x, y)].empty = true;
}
Some(2) => {
/* Grapheme takes more than one column, so the next cell will be
* drawn over. Set it as empty to skip drawing it. */
x += 1;
inspect_bounds!(grid, area, x, y, line_break);
grid[(x, y)].empty = true;
}
_ => {}
}
x += 1;
inspect_bounds!(grid, area, x, y, line_break);
@ -769,6 +796,7 @@ pub fn clear_area(grid: &mut CellBuffer, area: Area) {
grid[(x, y)].set_ch(' ');
grid[(x, y)].set_bg(Color::Default);
grid[(x, y)].set_fg(Color::Default);
grid[(x, y)].empty = false;
}
}
}