summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJoe Wilm <joe@jwilm.com>2017-03-01 22:24:37 -0800
committerJoe Wilm <jwilm@users.noreply.github.com>2017-03-02 09:19:01 -0800
commit119c7d2856aea24d9d29040b97b778e50c88e70d (patch)
tree2eac3ed6bb53f883d9e550b06ce9271f22155aa8 /src
parent55876522a2f4f93ea9ee0e1b4fec9d81621ae0cf (diff)
Add support for wide characters
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs20
-rw-r--r--src/term/cell.rs12
-rw-r--r--src/term/mod.rs85
3 files changed, 85 insertions, 32 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 58ebb07b..be4cae33 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -21,19 +21,18 @@
#![cfg_attr(feature = "clippy", deny(wrong_pub_self_convention))]
#![cfg_attr(feature = "nightly", feature(core_intrinsics))]
-#[macro_use]
-extern crate serde_derive;
+#[macro_use] extern crate bitflags;
+#[macro_use] extern crate clap;
+#[macro_use] extern crate lazy_static;
+#[macro_use] extern crate log;
+#[macro_use] extern crate serde_derive;
extern crate cgmath;
-#[macro_use]
-extern crate clap;
extern crate copypasta;
extern crate errno;
-extern crate font;
extern crate fnv;
+extern crate font;
extern crate glutin;
-#[macro_use]
-extern crate lazy_static;
extern crate libc;
extern crate mio;
extern crate notify;
@@ -41,16 +40,11 @@ extern crate parking_lot;
extern crate serde;
extern crate serde_json;
extern crate serde_yaml;
+extern crate unicode_width;
extern crate vte;
extern crate xdg;
#[macro_use]
-extern crate bitflags;
-
-#[macro_use]
-extern crate log;
-
-#[macro_use]
pub mod macros;
pub mod ansi;
diff --git a/src/term/cell.rs b/src/term/cell.rs
index e6b8fc9a..cb966156 100644
--- a/src/term/cell.rs
+++ b/src/term/cell.rs
@@ -18,11 +18,13 @@ use index::Column;
bitflags! {
#[derive(Serialize, Deserialize)]
pub flags Flags: u32 {
- const INVERSE = 0b00000001,
- const BOLD = 0b00000010,
- const ITALIC = 0b00000100,
- const UNDERLINE = 0b00001000,
- const WRAPLINE = 0b00010000,
+ const INVERSE = 0b00000001,
+ const BOLD = 0b00000010,
+ const ITALIC = 0b00000100,
+ const UNDERLINE = 0b00001000,
+ const WRAPLINE = 0b00010000,
+ const WIDE_CHAR = 0b00100000,
+ const WIDE_CHAR_SPACER = 0b01000000,
}
}
diff --git a/src/term/mod.rs b/src/term/mod.rs
index ac450bec..08299987 100644
--- a/src/term/mod.rs
+++ b/src/term/mod.rs
@@ -20,6 +20,8 @@ use std::cmp::min;
use std::io;
use std::time::{Duration, Instant};
+use unicode_width::UnicodeWidthChar;
+
use ansi::{self, Color, NamedColor, Attr, Handler, CharsetIndex, StandardCharset};
use grid::{BidirectionalIterator, Grid, ClearRegion, ToRange, Indexed};
use index::{self, Point, Column, Line, Linear, IndexRange, Contains, RangeInclusive, Side};
@@ -49,7 +51,7 @@ pub struct RenderableCellsIter<'a> {
config: &'a Config,
colors: &'a color::List,
selection: Option<RangeInclusive<index::Linear>>,
- cursor_original: Option<Indexed<Cell>>
+ cursor_original: (Option<Indexed<Cell>>, Option<Indexed<Cell>>),
}
impl<'a> RenderableCellsIter<'a> {
@@ -77,25 +79,52 @@ impl<'a> RenderableCellsIter<'a> {
selection: selection,
config: config,
colors: colors,
- cursor_original: None,
+ cursor_original: (None, None),
}.initialize()
}
fn initialize(mut self) -> Self {
if self.cursor_is_visible() {
- self.cursor_original = Some(Indexed {
+ self.cursor_original.0 = Some(Indexed {
line: self.cursor.line,
column: self.cursor.col,
inner: self.grid[self.cursor]
});
+ let mut spacer = false;
+ let mut location = *self.cursor;
+
+ if self.grid[self.cursor].flags.contains(cell::WIDE_CHAR) &&
+ self.cursor.col + 1 < self.grid.num_cols()
+ {
+ spacer = true;
+ location.col += 1;
+ self.cursor_original.1 = Some(Indexed {
+ line: location.line,
+ column: location.col,
+ inner: self.grid[&location]
+ });
+ }
if self.config.custom_cursor_colors() {
- let cell = &mut self.grid[self.cursor];
- cell.fg = Color::Named(NamedColor::CursorText);
- cell.bg = Color::Named(NamedColor::Cursor);
+ {
+ let cell = &mut self.grid[self.cursor];
+ cell.fg = Color::Named(NamedColor::CursorText);
+ cell.bg = Color::Named(NamedColor::Cursor);
+ }
+ if spacer {
+ let cell = &mut self.grid[&location];
+ cell.fg = Color::Named(NamedColor::CursorText);
+ cell.bg = Color::Named(NamedColor::Cursor);
+ }
} else {
- let cell = &mut self.grid[self.cursor];
- mem::swap(&mut cell.fg, &mut cell.bg);
+ {
+ let cell = &mut self.grid[self.cursor];
+ mem::swap(&mut cell.fg, &mut cell.bg);
+ }
+ if spacer {
+ let cell = &mut self.grid[&location];
+ mem::swap(&mut cell.fg, &mut cell.bg);
+ }
}
}
self
@@ -112,9 +141,14 @@ impl<'a> Drop for RenderableCellsIter<'a> {
/// Resets temporary render state on the grid
fn drop(&mut self) {
if self.cursor_is_visible() {
- if let Some(ref original) = self.cursor_original {
+ if let Some(ref original) = self.cursor_original.0 {
self.grid[self.cursor] = original.inner;
}
+ if let Some(ref original) = self.cursor_original.1 {
+ let mut location = *self.cursor;
+ location.col += 1;
+ self.grid[&location] = original.inner;
+ }
}
}
}
@@ -702,7 +736,9 @@ impl Term {
None
} else {
for cell in &line[cols.start..line_end] {
- self.push(cell.c);
+ if !cell.flags.contains(cell::WIDE_CHAR_SPACER) {
+ self.push(cell.c);
+ }
}
Some(cols.start..line_end)
@@ -1001,7 +1037,6 @@ impl ansi::Handler for Term {
#[inline]
fn input(&mut self, c: char) {
if self.input_needs_wrap {
-
if !self.mode.contains(mode::LINE_WRAP) {
return;
}
@@ -1029,9 +1064,31 @@ impl ansi::Handler for Term {
}
{
- let cell = &mut self.grid[&self.cursor.point];
- *cell = self.cursor.template;
- cell.c = self.cursor.charsets[self.active_charset].map(c);
+ // Number of cells the char will occupy
+ let width = c.width();
+
+ // Sigh, borrowck making us check the width twice. Hopefully the
+ // optimizer can fix it.
+ {
+ let cell = &mut self.grid[&self.cursor.point];
+ *cell = self.cursor.template;
+ cell.c = self.cursor.charsets[self.active_charset].map(c);
+
+ // Handle wide chars
+ if let Some(2) = width {
+ cell.flags.insert(cell::WIDE_CHAR);
+ }
+ }
+
+ // Set spacer cell for wide chars.
+ if let Some(2) = width {
+ if self.cursor.point.col + 1 < self.grid.num_cols() {
+ self.cursor.point.col += 1;
+ let spacer = &mut self.grid[&self.cursor.point];
+ *spacer = self.cursor.template;
+ spacer.flags.insert(cell::WIDE_CHAR_SPACER);
+ }
+ }
}
if (self.cursor.point.col + 1) < self.grid.num_cols() {