diff options
author | Joe Wilm <joe@jwilm.com> | 2016-10-28 08:52:56 -0700 |
---|---|---|
committer | Joe Wilm <joe@jwilm.com> | 2016-10-28 08:52:56 -0700 |
commit | 7cd8a6ca12cd37ae354084c7246060219b1e3af8 (patch) | |
tree | aa23a6355e0550161b957d61d50a663b288c6c2f /src | |
parent | e503baf2e753a1cc8c287f10fb1460635d093168 (diff) | |
parent | f8cb6d42cc0947e93d8913b894d7105afdfe1a2e (diff) | |
download | r-alacritty-7cd8a6ca12cd37ae354084c7246060219b1e3af8.tar.gz r-alacritty-7cd8a6ca12cd37ae354084c7246060219b1e3af8.tar.bz2 r-alacritty-7cd8a6ca12cd37ae354084c7246060219b1e3af8.zip |
Merge branch 'reload-colors'
Diffstat (limited to 'src')
-rw-r--r-- | src/ansi.rs | 12 | ||||
-rw-r--r-- | src/config.rs | 74 | ||||
-rw-r--r-- | src/main.rs | 76 | ||||
-rw-r--r-- | src/renderer/mod.rs | 124 | ||||
-rw-r--r-- | src/term.rs | 115 |
5 files changed, 272 insertions, 129 deletions
diff --git a/src/ansi.rs b/src/ansi.rs index 45cc66f9..c419d7e5 100644 --- a/src/ansi.rs +++ b/src/ansi.rs @@ -337,6 +337,10 @@ pub enum Color { BrightCyan, /// Bright white BrightWhite, + /// The foreground color + Foreground, + /// The background color + Background, } /// Terminal character attributes @@ -384,10 +388,6 @@ pub enum Attr { Background(Color), /// Set specific background color BackgroundSpec(Rgb), - /// Set default foreground - DefaultForeground, - /// Set default background - DefaultBackground, } impl<'a, H: Handler + TermInfo + 'a> vte::Perform for Performer<'a, H> { @@ -584,7 +584,7 @@ impl<'a, H: Handler + TermInfo + 'a> vte::Perform for Performer<'a, H> { break; } }, - 39 => Attr::DefaultForeground, + 39 => Attr::Foreground(Color::Foreground), 40 => Attr::Background(Color::Black), 41 => Attr::Background(Color::Red), 42 => Attr::Background(Color::Green), @@ -600,7 +600,7 @@ impl<'a, H: Handler + TermInfo + 'a> vte::Perform for Performer<'a, H> { break; } }, - 49 => Attr::DefaultBackground, + 49 => Attr::Background(Color::Background), 90 => Attr::Foreground(Color::BrightBlack), 91 => Attr::Foreground(Color::BrightRed), 92 => Attr::Foreground(Color::BrightGreen), diff --git a/src/config.rs b/src/config.rs index 56f96e80..f3e68dca 100644 --- a/src/config.rs +++ b/src/config.rs @@ -7,11 +7,13 @@ use std::env; use std::fs; use std::io::{self, Read}; use std::path::{Path, PathBuf}; +use std::sync::mpsc; use ::Rgb; use font::Size; use serde_yaml; use serde::{self, Error as SerdeError}; +use notify::{Watcher as WatcherApi, RecommendedWatcher as FileWatcher, op}; /// Top-level config type #[derive(Debug, Deserialize, Default)] @@ -232,7 +234,7 @@ impl Config { /// /// 1. `$HOME/.config/alacritty.yml` /// 2. `$HOME/.alacritty.yml` - pub fn load() -> Result<Config> { + pub fn load() -> Result<(Config, PathBuf)> { let home = env::var("HOME")?; // First path @@ -240,15 +242,17 @@ impl Config { path.push(".config"); path.push("alacritty.yml"); - // Fallback path - let mut alt_path = PathBuf::from(&home); - alt_path.push(".alacritty.yml"); - - match Config::load_from(&path) { + match Config::load_from(path) { Ok(c) => Ok(c), Err(e) => { match e { - Error::NotFound => Config::load_from(&alt_path), + Error::NotFound => { + // Fallback path + let mut alt_path = PathBuf::from(&home); + alt_path.push(".alacritty.yml"); + + Config::load_from(alt_path) + }, _ => Err(e), } } @@ -259,7 +263,7 @@ impl Config { /// /// The ordering returned here is expected by the terminal. Colors are simply indexed in this /// array for performance. - pub fn color_list(&self) -> [Rgb; 16] { + pub fn color_list(&self) -> [Rgb; 18] { let colors = &self.colors; [ @@ -282,6 +286,10 @@ impl Config { colors.bright.magenta, colors.bright.cyan, colors.bright.white, + + // Foreground and background + colors.primary.foreground, + colors.primary.background, ] } @@ -311,9 +319,10 @@ impl Config { self.render_timer } - fn load_from<P: AsRef<Path>>(path: P) -> Result<Config> { - let raw = Config::read_file(path)?; - Ok(serde_yaml::from_str(&raw[..])?) + fn load_from<P: Into<PathBuf>>(path: P) -> Result<(Config, PathBuf)> { + let path = path.into(); + let raw = Config::read_file(path.as_path())?; + Ok((serde_yaml::from_str(&raw[..])?, path)) } fn read_file<P: AsRef<Path>>(path: P) -> Result<String> { @@ -521,3 +530,46 @@ impl Default for Font { } } } + +pub struct Watcher(::std::thread::JoinHandle<()>); + +pub trait OnConfigReload { + fn on_config_reload(&mut self, Config); +} + +impl Watcher { + pub fn new<H: OnConfigReload + Send + 'static>(path: PathBuf, mut handler: H) -> Watcher { + Watcher(::util::thread::spawn_named("config watcher", move || { + let (tx, rx) = mpsc::channel(); + let mut watcher = FileWatcher::new(tx).unwrap(); + watcher.watch(&path).expect("watch alacritty yml"); + + let config_path = path.as_path(); + + loop { + let event = rx.recv().expect("watcher event"); + let ::notify::Event { path, op } = event; + + if let Ok(op) = op { + if op.contains(op::RENAME) { + continue; + } + + if op.contains(op::IGNORED) { + if let Some(path) = path.as_ref() { + if let Err(err) = watcher.watch(&path) { + err_println!("failed to establish watch on {:?}: {:?}", path, err); + } + + if path == config_path { + if let Ok((config, _)) = Config::load() { + handler.on_config_reload(config); + }; + } + } + } + } + } + })) + } +} diff --git a/src/main.rs b/src/main.rs index 9639fd29..b8bc5d07 100644 --- a/src/main.rs +++ b/src/main.rs @@ -75,7 +75,7 @@ use term::Term; use tty::process_should_exit; /// Channel used by resize handling on mac -static mut resize_sender: Option<mpsc::Sender<(u32, u32)>> = None; +static mut RESIZE_SENDER: Option<mpsc::Sender<(u32, u32)>> = None; #[derive(Clone)] pub struct Flag(Arc<AtomicBool>); @@ -98,7 +98,7 @@ impl Flag { /// Resize handling for Mac fn window_resize_handler(width: u32, height: u32) { unsafe { - if let Some(ref tx) = resize_sender { + if let Some(ref tx) = RESIZE_SENDER { let _ = tx.send((width, height)); } } @@ -112,19 +112,20 @@ pub struct Rgb { } mod gl { + #![allow(non_upper_case_globals)] include!(concat!(env!("OUT_DIR"), "/gl_bindings.rs")); } fn main() { // Load configuration - let config = match Config::load() { + let (config, config_path) = match Config::load() { Err(err) => match err { // Use default config when not found - config::Error::NotFound => Config::default(), + config::Error::NotFound => (Config::default(), None), // Exit when there's a problem with it _ => die!("{}", err), }, - Ok(config) => config, + Ok((config, path)) => (config, Some(path)), }; let font = config.font(); @@ -155,7 +156,7 @@ fn main() { let rasterizer = font::Rasterizer::new(dpi.x(), dpi.y(), dpr); // Create renderer - let mut renderer = QuadRenderer::new(width, height); + let mut renderer = QuadRenderer::new(&config, width, height); // Initialize glyph cache let glyph_cache = { @@ -180,7 +181,6 @@ fn main() { println!("Cell Size: ({} x {})", cell_width, cell_height); let terminal = Term::new( - &config, width as f32, height as f32, cell_width as f32, @@ -190,7 +190,7 @@ fn main() { let (tx, rx) = mpsc::channel(); unsafe { - resize_sender = Some(tx.clone()); + RESIZE_SENDER = Some(tx.clone()); } let signal_flag = Flag::new(false); @@ -214,7 +214,6 @@ fn main() { window.clone(), renderer, glyph_cache, - config.bg_color(), render_timer, rx ); @@ -226,11 +225,25 @@ fn main() { tx ); + let (config_tx, config_rx) = mpsc::channel(); + + // create a config watcher when config is loaded from disk + let _config_reloader = config_path.map(|config_path| { + config::Watcher::new(config_path, ConfigHandler { + tx: config_tx, + window: window.create_window_proxy(), + }) + }); + // Main loop loop { // Wait for something to happen processor.process_events(&window); + if let Ok(config) = config_rx.try_recv() { + display.update_config(&config); + } + // Maybe draw the terminal let terminal = terminal.lock(); signal_flag.set(false); @@ -243,28 +256,49 @@ fn main() { } } + // FIXME need file watcher to work with custom delegates before + // joining config reloader is possible + // config_reloader.join().ok(); + // shutdown event_loop_handle.join().ok(); println!("Goodbye"); } +struct ConfigHandler { + tx: mpsc::Sender<config::Config>, + window: ::glutin::WindowProxy, +} + +impl config::OnConfigReload for ConfigHandler { + fn on_config_reload(&mut self, config: Config) { + if let Err(..) = self.tx.send(config) { + err_println!("Failed to notify of new config"); + return; + } + + self.window.wakeup_event_loop(); + } +} + struct Display { window: Arc<glutin::Window>, renderer: QuadRenderer, glyph_cache: GlyphCache, render_timer: bool, - clear_red: f32, - clear_blue: f32, - clear_green: f32, rx: mpsc::Receiver<(u32, u32)>, meter: Meter, } impl Display { + pub fn update_config(&mut self, config: &Config) { + self.renderer.update_config(config); + self.render_timer = config.render_timer(); + } + pub fn new(window: Arc<glutin::Window>, renderer: QuadRenderer, glyph_cache: GlyphCache, - clear_color: Rgb, render_timer: bool, rx: mpsc::Receiver<(u32, u32)>) -> Display @@ -274,9 +308,6 @@ impl Display { renderer: renderer, glyph_cache: glyph_cache, render_timer: render_timer, - clear_red: clear_color.r as f32 / 255.0, - clear_blue: clear_color.g as f32 / 255.0, - clear_green: clear_color.b as f32 / 255.0, rx: rx, meter: Meter::new(), } @@ -295,11 +326,6 @@ impl Display { // events into one. let mut new_size = None; - // TODO should be built into renderer - unsafe { - gl::ClearColor(self.clear_red, self.clear_blue, self.clear_green, 1.0); - gl::Clear(gl::COLOR_BUFFER_BIT); - } // Check for any out-of-band resize events (mac only) while let Ok(sz) = self.rx.try_recv() { @@ -322,18 +348,16 @@ impl Display { let size_info = terminal.size_info().clone(); self.renderer.with_api(&size_info, |mut api| { // Draw the grid - let bg = terminal.bg; - api.render_grid(&bg, &terminal.render_grid(), glyph_cache); + api.render_grid(&terminal.render_grid(), glyph_cache); }); } // Draw render timer if self.render_timer { let timing = format!("{:.3} usec", self.meter.average()); - let color = Rgb { r: 0xd5, g: 0x4e, b: 0x53 }; + let color = ::term::cell::Color::Rgb(Rgb { r: 0xd5, g: 0x4e, b: 0x53 }); self.renderer.with_api(terminal.size_info(), |mut api| { - let bg = terminal.bg; - api.render_string(&bg, &timing[..], glyph_cache, &color); + api.render_string(&timing[..], glyph_cache, &color); }); } } diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index f1b30373..4e23c0ed 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -17,8 +17,7 @@ use std::io::{self, Read}; use std::mem::size_of; use std::path::{PathBuf}; use std::ptr; -use std::sync::Arc; -use std::sync::atomic::{Ordering, AtomicBool}; +use std::sync::mpsc; use cgmath; use font::{self, Rasterizer, RasterizedGlyph, FontDesc, GlyphKey, FontKey}; @@ -50,6 +49,10 @@ pub trait LoadGlyph { fn load_glyph(&mut self, rasterized: &RasterizedGlyph) -> Glyph; } +enum Msg { + ShaderReload, +} + /// Text drawing program /// /// Uniforms are prefixed with "u", and vertex attributes are prefixed with "a". @@ -70,7 +73,7 @@ pub struct ShaderProgram { /// Background pass flag /// /// Rendering is split into two passes; 1 for backgrounds, and one for text - u_background: GLint + u_background: GLint, } @@ -201,6 +204,7 @@ impl GlyphCache { } #[derive(Debug)] +#[repr(C)] struct InstanceData { // coords col: f32, @@ -230,7 +234,6 @@ struct InstanceData { #[derive(Debug)] pub struct QuadRenderer { program: ShaderProgram, - should_reload: Arc<AtomicBool>, vao: GLuint, vbo: GLuint, ebo: GLuint, @@ -238,6 +241,8 @@ pub struct QuadRenderer { atlas: Vec<Atlas>, active_tex: GLuint, batch: Batch, + colors: [Rgb; 18], + rx: mpsc::Receiver<Msg>, } #[derive(Debug)] @@ -246,6 +251,7 @@ pub struct RenderApi<'a> { batch: &'a mut Batch, atlas: &'a mut Vec<Atlas>, program: &'a mut ShaderProgram, + colors: &'a [Rgb; 18], } #[derive(Debug)] @@ -264,14 +270,16 @@ pub struct PackedVertex { pub struct Batch { tex: GLuint, instances: Vec<InstanceData>, + colors: [Rgb; 18], } impl Batch { #[inline] - pub fn new() -> Batch { + pub fn new(colors: [Rgb; 18]) -> Batch { Batch { tex: 0, instances: Vec::with_capacity(BATCH_MAX), + colors: colors, } } @@ -280,6 +288,16 @@ impl Batch { self.tex = glyph.tex_id; } + let fg = match cell.fg { + ::term::cell::Color::Rgb(rgb) => rgb, + ::term::cell::Color::Ansi(ansi) => self.colors[ansi as usize], + }; + + let bg = match cell.bg { + ::term::cell::Color::Rgb(rgb) => rgb, + ::term::cell::Color::Ansi(ansi) => self.colors[ansi as usize], + }; + let mut instance = InstanceData { col: col, row: row, @@ -294,23 +312,23 @@ impl Batch { uv_width: glyph.uv_width, uv_height: glyph.uv_height, - r: cell.fg.r as f32, - g: cell.fg.g as f32, - b: cell.fg.b as f32, + r: fg.r as f32, + g: fg.g as f32, + b: fg.b as f32, - bg_r: cell.bg.r as f32, - bg_g: cell.bg.g as f32, - bg_b: cell.bg.b as f32, + bg_r: bg.r as f32, + bg_g: bg.g as f32, + bg_b: bg.b as f32, }; if cell.flags.contains(cell::INVERSE) { - instance.r = cell.bg.r as f32; - instance.g = cell.bg.g as f32; - instance.b = cell.bg.b as f32; + instance.r = bg.r as f32; + instance.g = bg.g as f32; + instance.b = bg.b as f32; - instance.bg_r = cell.fg.r as f32; - instance.bg_g = cell.fg.g as f32; - instance.bg_b = cell.fg.b as f32; + instance.bg_r = fg.r as f32; + instance.bg_g = fg.g as f32; + instance.bg_b = fg.b as f32; } self.instances.push(instance); @@ -353,7 +371,7 @@ const ATLAS_SIZE: i32 = 1024; impl QuadRenderer { // TODO should probably hand this a transform instead of width/height - pub fn new(width: u32, height: u32) -> QuadRenderer { + pub fn new(config: &Config, width: u32, height: u32) -> QuadRenderer { let program = ShaderProgram::new(width, height).unwrap(); let mut vao: GLuint = 0; @@ -453,8 +471,7 @@ impl QuadRenderer { gl::BindBuffer(gl::ARRAY_BUFFER, 0); } - let should_reload = Arc::new(AtomicBool::new(false)); - let should_reload2 = should_reload.clone(); + let (msg_tx, msg_rx) = mpsc::channel(); if cfg!(feature = "live-shader-reload") { ::std::thread::spawn(move || { @@ -479,8 +496,8 @@ impl QuadRenderer { } } - // This is last event we see after saving in vim - should_reload2.store(true, Ordering::Relaxed); + msg_tx.send(Msg::ShaderReload) + .expect("msg send ok"); } } } @@ -489,14 +506,15 @@ impl QuadRenderer { let mut renderer = QuadRenderer { program: program, - should_reload: should_reload, vao: vao, vbo: vbo, ebo: ebo, vbo_instance: vbo_instance, atlas: Vec::new(), active_tex: 0, - batch: Batch::new(), + batch: Batch::new(config.color_list()), + colors: config.color_list(), + rx: msg_rx, }; let atlas = Atlas::new(ATLAS_SIZE); @@ -505,11 +523,20 @@ impl QuadRenderer { renderer } + pub fn update_config(&mut self, config: &Config) { + self.colors = config.color_list(); + self.batch.colors = config.color_list(); + } + pub fn with_api<F, T>(&mut self, props: &term::SizeInfo, func: F) -> T where F: FnOnce(RenderApi) -> T { - if self.should_reload.load(Ordering::Relaxed) { - self.reload_shaders(props.width as u32, props.height as u32); + while let Ok(msg) = self.rx.try_recv() { + match msg { + Msg::ShaderReload => { + self.reload_shaders(props.width as u32, props.height as u32); + } + } } unsafe { @@ -527,6 +554,7 @@ impl QuadRenderer { batch: &mut self.batch, atlas: &mut self.atlas, program: &mut self.program, + colors: &self.colors, }); unsafe { @@ -554,7 +582,6 @@ impl QuadRenderer { } pub fn reload_shaders(&mut self, width: u32, height: u32) { - self.should_reload.store(false, Ordering::Relaxed); let program = match ShaderProgram::new(width, height) { Ok(program) => program, Err(err) => { @@ -622,10 +649,9 @@ impl<'a> RenderApi<'a> { /// optimization. pub fn render_string( &mut self, - bg: &Rgb, s: &str, glyph_cache: &mut GlyphCache, - color: &Rgb, + color: &::term::cell::Color, ) { let row = 40.0; let mut col = 100.0; @@ -640,8 +666,8 @@ impl<'a> RenderApi<'a> { if let Some(glyph) = glyph_cache.get(&glyph_key, self) { let cell = Cell { c: c, - fg: *color, - bg: *bg, + fg: color.clone(), + bg: cell::Color::Rgb(Rgb { r: 0, g: 0, b: 0}), flags: cell::INVERSE, }; self.add_render_item(row, col, &cell, glyph); @@ -668,12 +694,27 @@ impl<'a> RenderApi<'a> { } } - pub fn render_grid(&mut self, bg: &Rgb, grid: &Grid<Cell>, glyph_cache: &mut GlyphCache) { + pub fn render_grid( + &mut self, + grid: &Grid<Cell>, + glyph_cache: &mut GlyphCache + ) { + // TODO should be built into renderer + let color = self.colors[::ansi::Color::Background as usize]; + unsafe { + gl::ClearColor( + color.r as f32 / 255.0, + color.g as f32 / 255.0, + color.b as f32 / 255.0, + 1.0 + ); + gl::Clear(gl::COLOR_BUFFER_BIT); + } + for (i, line) in grid.lines().enumerate() { for (j, cell) in line.cells().enumerate() { // Skip empty cells - if cell.c == ' ' && - cell.bg == *bg && + if cell.c == ' ' && cell.bg == cell::Color::Ansi(::ansi::Color::Background) && !cell.flags.contains(cell::INVERSE) { continue; @@ -760,7 +801,10 @@ impl ShaderProgram { } } - pub fn new(width: u32, height: u32) -> Result<ShaderProgram, ShaderCreationError> { + pub fn new( + width: u32, + height: u32 + ) -> Result<ShaderProgram, ShaderCreationError> { let vertex_source = if cfg!(feature = "live-shader-reload") { None } else { @@ -815,6 +859,16 @@ impl ShaderProgram { assert_uniform_valid!(projection, term_dim, cell_dim); + let mut color_uniforms: [GLint; 18] = unsafe { ::std::mem::uninitialized() }; + for i in 0..18 { + color_uniforms[i] = unsafe { + let s = format!("colors[{}]\0", i).into_bytes(); + gl::GetUniformLocation(program, cptr!(&s[..])) + }; + + assert_uniform_valid!(color_uniforms[i]); + } + let shader = ShaderProgram { id: program, u_projection: projection, diff --git a/src/term.rs b/src/term.rs index 898251d7..bcd78814 100644 --- a/src/term.rs +++ b/src/term.rs @@ -21,9 +21,7 @@ use ansi::{self, Attr, Handler}; use grid::{Grid, ClearRegion}; use index::{Cursor, Column, Line}; use tty; -use config::Config; - -use ::Rgb; +use ansi::Color; /// RAII type which manages grid state for render /// @@ -90,20 +88,26 @@ pub mod cell { } } - #[derive(Clone, Debug, Copy)] + #[derive(Debug, Clone, PartialEq, Eq)] + pub enum Color { + Rgb(Rgb), + Ansi(::ansi::Color), + } + + #[derive(Clone, Debug)] pub struct Cell { pub c: char, - pub fg: Rgb, - pub bg: Rgb, + pub fg: Color, + pub bg: Color, pub flags: Flags, } impl Cell { - pub fn new(c: char) -> Cell { + pub fn new(c: char, fg: Color, bg: Color) -> Cell { Cell { c: c.into(), - bg: Default::default(), - fg: Default::default(), + bg: bg, + fg: fg, flags: Flags::empty(), } } @@ -111,12 +115,41 @@ pub mod cell { #[inline] pub fn reset(&mut self, template: &Cell) { // memcpy template to self + *self = template.clone(); + } + } + + #[cfg(test)] + mod tests { + use super::Color; + use std::mem; + + // Ensure memory layout is well defined so components like renderer + // can exploit it. + // + // Thankfully, everything is just a u8 for now so no endianness + // considerations are needed. + #[test] + fn color_memory_layout() { + let rgb_color = Color::Rgb(::Rgb { r: 1, g: 2, b: 3 }); + let ansi_color = Color::Ansi(::ansi::Color::Foreground); + unsafe { - ::std::ptr::copy_nonoverlapping( - template as *const Cell, - self as *mut Cell, - 1 - ); + // Color::Rgb + // [discriminant(0), red, green ,blue] + let bytes: [u8; 4] = mem::transmute_copy(&rgb_color); + assert_eq!(bytes[0], 0); + assert_eq!(bytes[1], 1); + assert_eq!(bytes[2], 2); + assert_eq!(bytes[3], 3); + + // Color::Ansi + // [discriminant(1), ansi::Color, 0, 0] + let bytes: [u8; 4] = mem::transmute_copy(&ansi_color); + assert_eq!(bytes[0], 1); + assert_eq!(bytes[1], ::ansi::Color::Foreground as u8); + assert_eq!(bytes[2], 0); + assert_eq!(bytes[3], 0); } } } @@ -165,12 +198,6 @@ pub struct Term { /// Alt cursor alt_cursor: Cursor, - /// Active foreground color - pub fg: Rgb, - - /// Active background color - pub bg: Rgb, - /// Tabstops tabs: Vec<bool>, @@ -189,9 +216,6 @@ pub struct Term { /// Empty cell empty_cell: Cell, - /// Text colors - colors: [Rgb; 16], - pub dirty: bool, } @@ -225,7 +249,6 @@ impl SizeInfo { impl Term { pub fn new( - config: &Config, width: f32, height: f32, cell_width: f32, @@ -238,20 +261,18 @@ impl Term { cell_height: cell_height as f32, }; - let mut template = Cell::new(' '); - template.flags = cell::Flags::empty(); - template.bg = config.bg_color(); - template.fg = config.fg_color(); + let template = Cell::new( + ' ', + cell::Color::Ansi(Color::Foreground), + cell::Color::Ansi(Color::Background) + ); let num_cols = size.cols(); let num_lines = size.lines(); println!("num_cols, num_lines = {}, {}", num_cols, num_lines); - println!("bg: {:?}, fg: {:?}", template.bg, template.fg); - println!("colors: {:?}", config.color_list()); - - let grid = Grid::new(num_lines, num_cols, &Cell::new(' ')); + let grid = Grid::new(num_lines, num_cols, &template); let tty = tty::new(*num_lines as u8, *num_cols as u8); tty.resize(*num_lines as usize, *num_cols as usize, size.width as usize, size.height as usize); @@ -272,16 +293,13 @@ impl Term { alt: false, cursor: Cursor::default(), alt_cursor: Cursor::default(), - fg: config.fg_color(), - bg: config.bg_color(), tty: tty, tabs: tabs, mode: Default::default(), scroll_region: scroll_region, size_info: size, - template_cell: template, + template_cell: template.clone(), empty_cell: template, - colors: config.color_list(), } } @@ -323,8 +341,9 @@ impl Term { println!("num_cols, num_lines = {}, {}", num_cols, num_lines); // Resize grids to new size - self.grid.resize(num_lines, num_cols, &Cell::new(' ')); - self.alt_grid.resize(num_lines, num_cols, &Cell::new(' ')); + let template = self.template_cell.clone(); + self.grid.resize(num_lines, num_cols, &template); + self.alt_grid.resize(num_lines, num_cols, &template); // Ensure cursor is in-bounds self.cursor.line = limit(self.cursor.line, Line(0), num_lines); @@ -462,7 +481,7 @@ impl ansi::Handler for Term { } let cell = &mut self.grid[&self.cursor]; - *cell = self.template_cell; + *cell = self.template_cell.clone(); cell.c = c; self.cursor.col += 1; } @@ -779,27 +798,21 @@ impl ansi::Handler for Term { fn terminal_attribute(&mut self, attr: Attr) { debug_println!("Set Attribute: {:?}", attr); match attr { - Attr::DefaultForeground => { - self.template_cell.fg = self.fg; - }, - Attr::DefaultBackground => { - self.template_cell.bg = self.bg; - }, Attr::Foreground(named_color) => { - self.template_cell.fg = self.colors[named_color as usize]; + self.template_cell.fg = cell::Color::Ansi(named_color); }, Attr::Background(named_color) => { - self.template_cell.bg = self.colors[named_color as usize]; + self.template_cell.bg = cell::Color::Ansi(named_color); }, Attr::ForegroundSpec(rgb) => { - self.template_cell.fg = rgb; + self.template_cell.fg = cell::Color::Rgb(rgb); }, Attr::BackgroundSpec(rgb) => { - self.template_cell.bg = rgb; + self.template_cell.bg = cell::Color::Rgb(rgb); }, Attr::Reset => { - self.template_cell.fg = self.fg; - self.template_cell.bg = self.bg; + self.template_cell.fg = cell::Color::Ansi(Color::Foreground); + self.template_cell.bg = cell::Color::Ansi(Color::Background); self.template_cell.flags = cell::Flags::empty(); }, Attr::Reverse => self.template_cell.flags.insert(cell::INVERSE), |