aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ansi.rs156
-rw-r--r--src/display.rs18
-rw-r--r--src/renderer/mod.rs3
-rw-r--r--src/term/mod.rs23
4 files changed, 146 insertions, 54 deletions
diff --git a/src/ansi.rs b/src/ansi.rs
index a820bb31..26a342e4 100644
--- a/src/ansi.rs
+++ b/src/ansi.rs
@@ -23,6 +23,61 @@ use index::{Column, Line, Contains};
use ::Rgb;
+// Parse color arguments
+//
+// Expect that color argument looks like "rgb:xx/xx/xx" or "#xxxxxx"
+fn parse_rgb_color(color: &[u8]) -> Option<Rgb> {
+ let mut iter = color.iter();
+
+ macro_rules! next {
+ () => {
+ iter.next().map(|v| *v as char)
+ }
+ }
+
+ macro_rules! parse_hex {
+ () => {{
+ let mut digit: u8 = 0;
+ let next = next!().and_then(|v| v.to_digit(16));
+ if let Some(value) = next {
+ digit = value as u8;
+ }
+
+ let next = next!().and_then(|v| v.to_digit(16));
+ if let Some(value) = next {
+ digit <<= 4;
+ digit += value as u8;
+ }
+ digit
+ }}
+ }
+
+ match next!() {
+ Some('r') => {
+ if next!() != Some('g') { return None; }
+ if next!() != Some('b') { return None; }
+ if next!() != Some(':') { return None; }
+
+ let r = parse_hex!();
+ let val = next!();
+ if val != Some('/') { println!("val={:?}", val); return None; }
+ let g = parse_hex!();
+ if next!() != Some('/') { return None; }
+ let b = parse_hex!();
+
+ Some(Rgb { r: r, g: g, b: b})
+ }
+ Some('#') => {
+ Some(Rgb {
+ r: parse_hex!(),
+ g: parse_hex!(),
+ b: parse_hex!(),
+ })
+ }
+ _ => None
+ }
+}
+
/// The processor wraps a `vte::Parser` to ultimately call methods on a Handler
pub struct Processor {
state: ProcessorState,
@@ -260,6 +315,9 @@ pub trait Handler {
/// Set an indexed color value
fn set_color(&mut self, usize, Rgb) {}
+ /// Reset an indexed color to original value
+ fn reset_color(&mut self, usize) {}
+
/// Run the dectest routine
fn dectest(&mut self) {}
}
@@ -651,9 +709,9 @@ impl<'a, H, W> vte::Perform for Performer<'a, H, W>
return;
}
- match params[0][0] {
+ match params[0] {
// Set window title
- b'0' | b'2' => {
+ b"0" | b"2" => {
if params.len() < 2 {
return unhandled!();
}
@@ -665,10 +723,10 @@ impl<'a, H, W> vte::Perform for Performer<'a, H, W>
// Set icon name
// This is ignored, since alacritty has no concept of tabs
- b'1' => return,
+ b"1" => return,
// Set color index
- b'4' => {
+ b"4" => {
if params.len() < 3 {
return unhandled!();
}
@@ -696,51 +754,49 @@ impl<'a, H, W> vte::Perform for Performer<'a, H, W>
return unhandled!();
}
- // Parse color arguments
- //
- // Expect that color argument looks like "rgb:xx/xx/xx"
- let color = {
- let raw = params[2];
- let mut iter = raw.iter();
- macro_rules! next {
- () => {
- iter.next().map(|v| *v as char)
- }
- }
- if next!() != Some('r') { return unhandled!(); }
- if next!() != Some('g') { return unhandled!(); }
- if next!() != Some('b') { return unhandled!(); }
- if next!() != Some(':') { return unhandled!(); }
-
- macro_rules! parse_hex {
- () => {{
- let mut digit: u8 = 0;
- let next = next!().and_then(|v| v.to_digit(16));
- if let Some(value) = next {
- digit = value as u8;
- }
+ if let Some(color) = parse_rgb_color(params[2]) {
+ self.handler.set_color(index as usize, color);
+ } else {
+ unhandled!();
+ }
+ }
- let next = next!().and_then(|v| v.to_digit(16));
- if let Some(value) = next {
- digit <<= 4;
- digit += value as u8;
- }
- digit
- }}
- }
+ // Set foreground color
+ b"10" => {
+ if params.len() < 2 {
+ return unhandled!();
+ }
- let r = parse_hex!();
- let val = next!();
- if val != Some('/') { println!("val={:?}", val); return unhandled!(); }
- let g = parse_hex!();
- if next!() != Some('/') { return unhandled!(); }
- let b = parse_hex!();
+ if let Some(color) = parse_rgb_color(params[1]) {
+ self.handler.set_color(NamedColor::Foreground as usize, color);
+ } else {
+ unhandled!()
+ }
+ }
- Rgb { r: r, g: g, b: b}
- };
+ // Set background color
+ b"11" => {
+ if params.len() < 2 {
+ return unhandled!();
+ }
- self.handler.set_color(index as usize, color);
+ if let Some(color) = parse_rgb_color(params[1]) {
+ self.handler.set_color(NamedColor::Background as usize, color);
+ } else {
+ unhandled!()
+ }
+ }
+
+ // Reset foreground color
+ b"110" => {
+ self.handler.reset_color(NamedColor::Foreground as usize);
}
+
+ // Reset background color
+ b"111" => {
+ self.handler.reset_color(NamedColor::Background as usize);
+ }
+
_ => {
unhandled!();
}
@@ -1241,7 +1297,7 @@ pub mod C1 {
mod tests {
use std::io;
use index::{Line, Column};
- use super::{Processor, Handler, Attr, TermInfo, Color, StandardCharset, CharsetIndex};
+ use super::{Processor, Handler, Attr, TermInfo, Color, StandardCharset, CharsetIndex, parse_rgb_color};
use ::Rgb;
/// The /dev/null of io::Write
@@ -1409,4 +1465,14 @@ mod tests {
assert_eq!(handler.index, CharsetIndex::G1);
}
+
+ #[test]
+ fn parse_valid_rgb_color() {
+ assert_eq!(parse_rgb_color(b"rgb:11/aa/ff"), Some(Rgb { r: 0x11, g: 0xaa, b: 0xff }));
+ }
+
+ #[test]
+ fn parse_valid_rgb_color2() {
+ assert_eq!(parse_rgb_color(b"#11aaff"), Some(Rgb { r: 0x11, g: 0xaa, b: 0xff }));
+ }
}
diff --git a/src/display.rs b/src/display.rs
index d1af5411..1055944c 100644
--- a/src/display.rs
+++ b/src/display.rs
@@ -97,6 +97,7 @@ pub struct Display {
tx: mpsc::Sender<(u32, u32)>,
meter: Meter,
size_info: SizeInfo,
+ last_background_color: Rgb,
}
/// Can wakeup the render loop from other threads
@@ -209,7 +210,10 @@ impl Display {
let (tx, rx) = mpsc::channel();
// Clear screen
- renderer.with_api(config, &size_info, 0. /* visual bell intensity */, |api| api.clear());
+ let background_color = config.colors().primary.background;
+ renderer.with_api(config, &size_info, 0. /* visual bell intensity */, |api| {
+ api.clear(background_color);
+ });
Ok(Display {
window: window,
@@ -220,6 +224,7 @@ impl Display {
rx: rx,
meter: Meter::new(),
size_info: size_info,
+ last_background_color: background_color,
})
}
@@ -280,6 +285,10 @@ impl Display {
let size_info = *terminal.size_info();
let visual_bell_intensity = terminal.visual_bell.intensity();
+ let background_color = terminal.background_color();
+ let background_color_changed = background_color != self.last_background_color;
+ self.last_background_color = background_color;
+
{
let glyph_cache = &mut self.glyph_cache;
@@ -293,6 +302,11 @@ impl Display {
// TODO I wonder if the renderable cells iter could avoid the
// mutable borrow
self.renderer.with_api(config, &size_info, visual_bell_intensity, |mut api| {
+ // Clear screen to update whole background with new color
+ if background_color_changed {
+ api.clear(background_color);
+ }
+
// Draw the grid
api.render_cells(terminal.renderable_cells(config, selection), glyph_cache);
});
@@ -324,7 +338,7 @@ impl Display {
// issue of glClear being slow, less time is available for input
// handling and rendering.
self.renderer.with_api(config, &size_info, visual_bell_intensity, |api| {
- api.clear();
+ api.clear(background_color);
});
}
diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs
index 7c1c011b..3cad4a01 100644
--- a/src/renderer/mod.rs
+++ b/src/renderer/mod.rs
@@ -684,8 +684,7 @@ impl QuadRenderer {
}
impl<'a> RenderApi<'a> {
- pub fn clear(&self) {
- let color = self.config.colors().primary.background;
+ pub fn clear(&self, color: Rgb) {
unsafe {
gl::ClearColor(
(self.visual_bell_intensity + color.r as f32 / 255.0).min(1.0),
diff --git a/src/term/mod.rs b/src/term/mod.rs
index 0a51aac3..942c1994 100644
--- a/src/term/mod.rs
+++ b/src/term/mod.rs
@@ -674,7 +674,10 @@ pub struct Term {
semantic_escape_chars: String,
/// Colors used for rendering
- colors: color::List,
+ pub colors: color::List,
+
+ /// Original colors from config
+ original_colors: color::List,
cursor_style: CursorStyle,
}
@@ -774,6 +777,7 @@ impl Term {
size_info: size,
empty_cell: template,
colors: color::List::from(config.colors()),
+ original_colors: color::List::from(config.colors()),
semantic_escape_chars: config.selection().semantic_escape_chars.clone(),
cursor_style: CursorStyle::Block,
}
@@ -781,7 +785,7 @@ impl Term {
pub fn update_config(&mut self, config: &Config) {
self.semantic_escape_chars = config.selection().semantic_escape_chars.clone();
- self.colors.fill_named(config.colors());
+ self.original_colors.fill_named(config.colors());
self.visual_bell.update_config(config);
}
@@ -1123,6 +1127,11 @@ impl Term {
let template = self.empty_cell;
self.grid.clear(|c| c.reset(&template));
}
+
+ #[inline]
+ pub fn background_color(&self) -> Rgb {
+ self.colors[NamedColor::Background]
+ }
}
impl ansi::TermInfo for Term {
@@ -1606,15 +1615,19 @@ impl ansi::Handler for Term {
}
/// Set the indexed color value
- ///
- /// TODO needs access to `Config`, and `Config` should not overwrite values
- /// when reloading
#[inline]
fn set_color(&mut self, index: usize, color: Rgb) {
trace!("set_color[{}] = {:?}", index, color);
self.colors[index] = color;
}
+ /// Reset the indexed color to original value
+ #[inline]
+ fn reset_color(&mut self, index: usize) {
+ trace!("reset_color[{}]", index);
+ self.colors[index] = self.original_colors[index];
+ }
+
#[inline]
fn clear_screen(&mut self, mode: ansi::ClearMode) {
trace!("clear_screen: {:?}", mode);