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:
parent
55876522a2
commit
119c7d2856
5 changed files with 87 additions and 32 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -22,6 +22,7 @@ dependencies = [
|
|||
"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_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)",
|
||||
"xdg 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
|
|
@ -31,6 +31,7 @@ xdg = "2.0.0"
|
|||
log = "0.3"
|
||||
clap = "2.20"
|
||||
fnv = "1.0.5"
|
||||
unicode-width = "0.1.4"
|
||||
|
||||
clippy = { version = "0.0.104", optional = true }
|
||||
|
||||
|
|
20
src/lib.rs
20
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,15 +40,10 @@ 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;
|
||||
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in a new issue