diff options
-rw-r--r-- | src/ansi.rs | 156 | ||||
-rw-r--r-- | src/display.rs | 18 | ||||
-rw-r--r-- | src/renderer/mod.rs | 3 | ||||
-rw-r--r-- | src/term/mod.rs | 23 |
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); |