Fix pancurses backend

This commit is contained in:
Alexandre Bury 2017-06-13 23:30:55 -07:00
parent 98be066b4d
commit 2cdf546455
4 changed files with 89 additions and 31 deletions

View File

@ -11,7 +11,7 @@ mod pan;
pub use self::pan::*; pub use self::pan::*;
fn find_closest(color: &Color) -> u8 { fn find_closest(color: &Color) -> i16 {
match *color { match *color {
Color::Dark(BaseColor::Black) => 0, Color::Dark(BaseColor::Black) => 0,
Color::Dark(BaseColor::Red) => 1, Color::Dark(BaseColor::Red) => 1,
@ -33,8 +33,8 @@ fn find_closest(color: &Color) -> u8 {
let r = 6 * r as u16 / 256; let r = 6 * r as u16 / 256;
let g = 6 * g as u16 / 256; let g = 6 * g as u16 / 256;
let b = 6 * b as u16 / 256; let b = 6 * b as u16 / 256;
(16 + 36 * r + 6 * g + b) as u8 (16 + 36 * r + 6 * g + b) as i16
} }
Color::RgbLowRes(r, g, b) => (16 + 36 * r + 6 * g + b) as u8, Color::RgbLowRes(r, g, b) => (16 + 36 * r + 6 * g + b) as i16,
} }
} }

View File

@ -32,8 +32,8 @@ impl Concrete {
}; };
pairs.insert(pair, target); pairs.insert(pair, target);
ncurses::init_pair(target, ncurses::init_pair(target,
find_closest(&pair.front) as i16, find_closest(&pair.front),
find_closest(&pair.back) as i16); find_closest(&pair.back));
target target
} }
@ -51,7 +51,7 @@ impl Concrete {
} }
} }
fn set_colorstyle(&self, pair: ColorPair) { fn set_colors(&self, pair: ColorPair) {
let i = self.get_or_create(pair); let i = self.get_or_create(pair);
@ -99,11 +99,15 @@ impl backend::Backend for Concrete {
fn with_color<F: FnOnce()>(&self, colors: ColorPair, f: F) { fn with_color<F: FnOnce()>(&self, colors: ColorPair, f: F) {
let current = self.current_style.get(); let current = self.current_style.get();
if current != colors {
self.set_colors(colors);
}
self.set_colorstyle(colors);
f(); f();
self.set_colorstyle(current);
self.current_style.set(current); if current != colors {
self.set_colors(current);
}
} }
fn with_effect<F: FnOnce()>(&self, effect: Effect, f: F) { fn with_effect<F: FnOnce()>(&self, effect: Effect, f: F) {

View File

@ -1,17 +1,69 @@
extern crate pancurses; extern crate pancurses;
use self::super::find_closest;
use self::super::{color_id, find_closest};
use backend; use backend;
use event::{Event, Key}; use event::{Event, Key};
use theme::{Color, ColorStyle, Effect}; use std::cell::{RefCell, Cell};
use std::collections::HashMap;
use theme::{Color, ColorStyle, ColorPair, Effect};
use utf8; use utf8;
pub struct Concrete { pub struct Concrete {
current_style: Cell<ColorPair>,
pairs: RefCell<HashMap<ColorPair, i32>>,
window: pancurses::Window, window: pancurses::Window,
} }
impl Concrete {
/// Save a new color pair.
fn insert_color(&self, pairs: &mut HashMap<ColorPair, i32>,
pair: ColorPair)
-> i32 {
let n = 1 + pairs.len() as i32;
// TODO: when COLORS_PAIRS is available...
let target = if 16 > n {
// We still have plenty of space for everyone.
n
} else {
// The world is too small for both of us.
let target = n - 1;
// Remove the mapping to n-1
pairs.retain(|_, &mut v| v != target);
target
};
pairs.insert(pair, target);
pancurses::init_pair(target as i16,
find_closest(&pair.front),
find_closest(&pair.back));
target
}
/// Checks the pair in the cache, or re-define a color if needed.
fn get_or_create(&self, pair: ColorPair) -> i32 {
let mut pairs = self.pairs.borrow_mut();
// Find if we have this color in stock
if pairs.contains_key(&pair) {
// We got it!
pairs[&pair]
} else {
self.insert_color(&mut *pairs, pair)
}
}
fn set_colors(&self, pair: ColorPair) {
let i = self.get_or_create(pair);
self.current_style.set(pair);
let style = pancurses::COLOR_PAIR(i as u32);
self.window.attron(style);
}
}
impl backend::Backend for Concrete { impl backend::Backend for Concrete {
fn init() -> Self { fn init() -> Self {
::std::env::set_var("ESCDELAY", "25"); ::std::env::set_var("ESCDELAY", "25");
@ -21,10 +73,12 @@ impl backend::Backend for Concrete {
pancurses::cbreak(); pancurses::cbreak();
pancurses::start_color(); pancurses::start_color();
pancurses::curs_set(0); pancurses::curs_set(0);
window.bkgd(pancurses::ColorPair(color_id(ColorStyle::Background) as
u8));
Concrete { window: window } Concrete {
current_style: Cell::new(ColorPair::from_256colors(0, 0)),
pairs: RefCell::new(HashMap::new()),
window: window,
}
} }
fn screen_size(&self) -> (usize, usize) { fn screen_size(&self) -> (usize, usize) {
@ -40,21 +94,18 @@ impl backend::Backend for Concrete {
pancurses::endwin(); pancurses::endwin();
} }
fn init_color_style(&mut self, style: ColorStyle, foreground: &Color, fn with_color<F: FnOnce()>(&self, colors: ColorPair, f: F) {
background: &Color) { let current = self.current_style.get();
pancurses::init_pair(color_id(style),
find_closest(foreground) as i16,
find_closest(background) as i16);
}
fn with_color<F: FnOnce()>(&self, color: ColorStyle, f: F) { if current != colors {
let (_, current_color_pair) = self.window.attrget(); self.set_colors(colors);
let color_attribute = pancurses::ColorPair(color_id(color) as u8); }
self.window.attron(color_attribute);
f(); f();
self.window
.attron(pancurses::ColorPair(current_color_pair as u8)); if current != colors {
self.set_colors(current);
}
} }
fn with_effect<F: FnOnce()>(&self, effect: Effect, f: F) { fn with_effect<F: FnOnce()>(&self, effect: Effect, f: F) {
@ -67,7 +118,12 @@ impl backend::Backend for Concrete {
self.window.attroff(style); self.window.attroff(style);
} }
fn clear(&self) { fn clear(&self, color: Color) {
let id = self.get_or_create(ColorPair {
front: color,
back: color,
});
self.window.bkgd(pancurses::ColorPair(id as u8));
self.window.clear(); self.window.clear();
} }

View File

@ -13,8 +13,6 @@ use backend;
use chan; use chan;
use event::{Event, Key}; use event::{Event, Key};
use std::cell::Cell; use std::cell::Cell;
use std::collections::HashMap;
use std::fmt;
use std::io::Write; use std::io::Write;
use std::thread; use std::thread;