1
0
Fork 0
mirror of https://github.com/alacritty/alacritty.git synced 2024-11-18 13:55:23 -05:00

Add support for wide characters

This commit is contained in:
Joe Wilm 2017-03-01 22:24:37 -08:00 committed by Joe Wilm
parent 55876522a2
commit 119c7d2856
5 changed files with 87 additions and 32 deletions

1
Cargo.lock generated
View file

@ -22,6 +22,7 @@ dependencies = [
"serde_derive 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_yaml 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"vte 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "vte 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"xdg 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "xdg 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]

View file

@ -31,6 +31,7 @@ xdg = "2.0.0"
log = "0.3" log = "0.3"
clap = "2.20" clap = "2.20"
fnv = "1.0.5" fnv = "1.0.5"
unicode-width = "0.1.4"
clippy = { version = "0.0.104", optional = true } clippy = { version = "0.0.104", optional = true }

View file

@ -21,19 +21,18 @@
#![cfg_attr(feature = "clippy", deny(wrong_pub_self_convention))] #![cfg_attr(feature = "clippy", deny(wrong_pub_self_convention))]
#![cfg_attr(feature = "nightly", feature(core_intrinsics))] #![cfg_attr(feature = "nightly", feature(core_intrinsics))]
#[macro_use] #[macro_use] extern crate bitflags;
extern crate serde_derive; #[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; extern crate cgmath;
#[macro_use]
extern crate clap;
extern crate copypasta; extern crate copypasta;
extern crate errno; extern crate errno;
extern crate font;
extern crate fnv; extern crate fnv;
extern crate font;
extern crate glutin; extern crate glutin;
#[macro_use]
extern crate lazy_static;
extern crate libc; extern crate libc;
extern crate mio; extern crate mio;
extern crate notify; extern crate notify;
@ -41,15 +40,10 @@ extern crate parking_lot;
extern crate serde; extern crate serde;
extern crate serde_json; extern crate serde_json;
extern crate serde_yaml; extern crate serde_yaml;
extern crate unicode_width;
extern crate vte; extern crate vte;
extern crate xdg; extern crate xdg;
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate log;
#[macro_use] #[macro_use]
pub mod macros; pub mod macros;

View file

@ -23,6 +23,8 @@ bitflags! {
const ITALIC = 0b00000100, const ITALIC = 0b00000100,
const UNDERLINE = 0b00001000, const UNDERLINE = 0b00001000,
const WRAPLINE = 0b00010000, const WRAPLINE = 0b00010000,
const WIDE_CHAR = 0b00100000,
const WIDE_CHAR_SPACER = 0b01000000,
} }
} }

View file

@ -20,6 +20,8 @@ use std::cmp::min;
use std::io; use std::io;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use unicode_width::UnicodeWidthChar;
use ansi::{self, Color, NamedColor, Attr, Handler, CharsetIndex, StandardCharset}; use ansi::{self, Color, NamedColor, Attr, Handler, CharsetIndex, StandardCharset};
use grid::{BidirectionalIterator, Grid, ClearRegion, ToRange, Indexed}; use grid::{BidirectionalIterator, Grid, ClearRegion, ToRange, Indexed};
use index::{self, Point, Column, Line, Linear, IndexRange, Contains, RangeInclusive, Side}; use index::{self, Point, Column, Line, Linear, IndexRange, Contains, RangeInclusive, Side};
@ -49,7 +51,7 @@ pub struct RenderableCellsIter<'a> {
config: &'a Config, config: &'a Config,
colors: &'a color::List, colors: &'a color::List,
selection: Option<RangeInclusive<index::Linear>>, selection: Option<RangeInclusive<index::Linear>>,
cursor_original: Option<Indexed<Cell>> cursor_original: (Option<Indexed<Cell>>, Option<Indexed<Cell>>),
} }
impl<'a> RenderableCellsIter<'a> { impl<'a> RenderableCellsIter<'a> {
@ -77,26 +79,53 @@ impl<'a> RenderableCellsIter<'a> {
selection: selection, selection: selection,
config: config, config: config,
colors: colors, colors: colors,
cursor_original: None, cursor_original: (None, None),
}.initialize() }.initialize()
} }
fn initialize(mut self) -> Self { fn initialize(mut self) -> Self {
if self.cursor_is_visible() { if self.cursor_is_visible() {
self.cursor_original = Some(Indexed { self.cursor_original.0 = Some(Indexed {
line: self.cursor.line, line: self.cursor.line,
column: self.cursor.col, column: self.cursor.col,
inner: self.grid[self.cursor] 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() { if self.config.custom_cursor_colors() {
{
let cell = &mut self.grid[self.cursor]; let cell = &mut self.grid[self.cursor];
cell.fg = Color::Named(NamedColor::CursorText); cell.fg = Color::Named(NamedColor::CursorText);
cell.bg = Color::Named(NamedColor::Cursor); 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 { } else {
{
let cell = &mut self.grid[self.cursor]; let cell = &mut self.grid[self.cursor];
mem::swap(&mut cell.fg, &mut cell.bg); 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 self
} }
@ -112,9 +141,14 @@ impl<'a> Drop for RenderableCellsIter<'a> {
/// Resets temporary render state on the grid /// Resets temporary render state on the grid
fn drop(&mut self) { fn drop(&mut self) {
if self.cursor_is_visible() { 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; 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,8 +736,10 @@ impl Term {
None None
} else { } else {
for cell in &line[cols.start..line_end] { for cell in &line[cols.start..line_end] {
if !cell.flags.contains(cell::WIDE_CHAR_SPACER) {
self.push(cell.c); self.push(cell.c);
} }
}
Some(cols.start..line_end) Some(cols.start..line_end)
} }
@ -1001,7 +1037,6 @@ impl ansi::Handler for Term {
#[inline] #[inline]
fn input(&mut self, c: char) { fn input(&mut self, c: char) {
if self.input_needs_wrap { if self.input_needs_wrap {
if !self.mode.contains(mode::LINE_WRAP) { if !self.mode.contains(mode::LINE_WRAP) {
return; return;
} }
@ -1028,10 +1063,32 @@ impl ansi::Handler for Term {
self.input_needs_wrap = false; self.input_needs_wrap = false;
} }
{
// 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]; let cell = &mut self.grid[&self.cursor.point];
*cell = self.cursor.template; *cell = self.cursor.template;
cell.c = self.cursor.charsets[self.active_charset].map(c); 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() { if (self.cursor.point.col + 1) < self.grid.num_cols() {