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
parent
af573b57f1
commit
e5f8714162
|
@ -415,14 +415,16 @@ impl State {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
for x in x_start..=x_end {
|
for x in x_start..=x_end {
|
||||||
let c = self.grid[(x, y)];
|
let c = self.grid[(x, y)];
|
||||||
|
|
||||||
if c.bg() != Color::Default {
|
if c.bg() != Color::Default {
|
||||||
write!(self.stdout(), "{}", termion::color::Bg(c.bg().as_termion())).unwrap();
|
write!(self.stdout(), "{}", termion::color::Bg(c.bg().as_termion())).unwrap();
|
||||||
}
|
}
|
||||||
if c.fg() != Color::Default {
|
if c.fg() != Color::Default {
|
||||||
write!(self.stdout(), "{}", termion::color::Fg(c.fg().as_termion())).unwrap();
|
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 {
|
if c.bg() != Color::Default {
|
||||||
write!(
|
write!(
|
||||||
self.stdout(),
|
self.stdout(),
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use super::position::*;
|
use super::position::*;
|
||||||
|
use text_processing::wcwidth;
|
||||||
|
|
||||||
use std::convert::From;
|
use std::convert::From;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -280,6 +281,7 @@ impl fmt::Display for CellBuffer {
|
||||||
pub struct Cell {
|
pub struct Cell {
|
||||||
ch: char,
|
ch: char,
|
||||||
|
|
||||||
|
empty: bool,
|
||||||
fg: Color,
|
fg: Color,
|
||||||
bg: Color,
|
bg: Color,
|
||||||
attrs: Attr,
|
attrs: Attr,
|
||||||
|
@ -300,7 +302,13 @@ impl Cell {
|
||||||
/// assert_eq!(cell.attrs(), Attr::Default);
|
/// assert_eq!(cell.attrs(), Attr::Default);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn new(ch: char, fg: Color, bg: Color, attrs: Attr) -> Cell {
|
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.
|
/// Creates a new `Cell` with the given `char` and default style.
|
||||||
|
@ -441,6 +449,10 @@ impl Cell {
|
||||||
self.attrs = newattrs;
|
self.attrs = newattrs;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn empty(&self) -> bool {
|
||||||
|
self.empty
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Cell {
|
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_fg(fg_color);
|
||||||
grid[(x, y)].set_bg(bg_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;
|
x += 1;
|
||||||
|
|
||||||
inspect_bounds!(grid, area, x, y, line_break);
|
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_ch(' ');
|
||||||
grid[(x, y)].set_bg(Color::Default);
|
grid[(x, y)].set_bg(Color::Default);
|
||||||
grid[(x, y)].set_fg(Color::Default);
|
grid[(x, y)].set_fg(Color::Default);
|
||||||
|
grid[(x, y)].empty = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue