extern crate ransid; use std::collections::{BTreeSet, VecDeque}; use self::ransid::{Console, Event}; use syscall::Result; use display::Display; pub struct TextScreen { pub console: Console, pub display: Display, pub changed: BTreeSet, pub input: VecDeque, pub end_of_input: bool, pub cooked: VecDeque, pub requested: usize } impl TextScreen { pub fn new(display: Display) -> TextScreen { TextScreen { console: Console::new(display.width/8, display.height/16), display: display, changed: BTreeSet::new(), input: VecDeque::new(), end_of_input: false, cooked: VecDeque::new(), requested: 0 } } pub fn input(&mut self, buf: &[u8]) -> Result { if self.console.raw_mode { for &b in buf.iter() { self.input.push_back(b); } } else { for &b in buf.iter() { match b { b'\x03' => { self.end_of_input = true; self.write(b"^C\n", true)?; }, b'\x08' | b'\x7F' => { if let Some(_c) = self.cooked.pop_back() { self.write(b"\x08", true)?; } }, b'\n' | b'\r' => { self.cooked.push_back(b); while let Some(c) = self.cooked.pop_front() { self.input.push_back(c); } self.write(b"\n", true)?; }, _ => { self.cooked.push_back(b); self.write(&[b], true)?; } } } } Ok(buf.len()) } pub fn read(&mut self, buf: &mut [u8]) -> Result { let mut i = 0; while i < buf.len() && ! self.input.is_empty() { buf[i] = self.input.pop_front().unwrap(); i += 1; } if i == 0 { self.end_of_input = false; } Ok(i) } pub fn will_block(&self) -> bool { self.input.is_empty() && ! self.end_of_input } pub fn write(&mut self, buf: &[u8], sync: bool) -> Result { if self.console.cursor && self.console.x < self.console.w && self.console.y < self.console.h { let x = self.console.x; let y = self.console.y; let color = self.console.background; self.display.rect(x * 8, y * 16, 8, 16, color.data); self.changed.insert(y); } { let display = &mut self.display; let changed = &mut self.changed; self.console.write(buf, |event| { match event { Event::Char { x, y, c, color, bold, .. } => { display.char(x * 8, y * 16, c, color.data, bold, false); changed.insert(y); }, Event::Rect { x, y, w, h, color } => { display.rect(x * 8, y * 16, w * 8, h * 16, color.data); for y2 in y..y + h { changed.insert(y2); } }, Event::Scroll { rows, color } => { display.scroll(rows * 16, color.data); for y in 0..display.height/16 { changed.insert(y); } } } }); } if self.console.cursor && self.console.x < self.console.w && self.console.y < self.console.h { let x = self.console.x; let y = self.console.y; let color = self.console.foreground; self.display.rect(x * 8, y * 16, 8, 16, color.data); self.changed.insert(y); } if ! self.console.raw_mode && sync { self.sync(); } Ok(buf.len()) } pub fn sync(&mut self) { let width = self.display.width; for change in self.changed.iter() { self.display.sync(0, change * 16, width, 16); } self.changed.clear(); } pub fn redraw(&mut self) { let width = self.display.width; let height = self.display.height; self.display.sync(0, 0, width, height); self.changed.clear(); } }