use crate::{hardware::MOUSE, vga_e::VGAE}; use logos::{Lexer, Logos}; use vga::{colors::Color16, writers::GraphicsWriter}; const TERM_MINUS_ONE_LINE: usize = 4720; const CURSOR_COLOR: Color16 = Color16::Cyan; #[derive(Debug)] pub struct Term { dirty: bool, color: Color16, term: [(char, Color16); 80 * 60], back_buffer: [u8; 640 * 480], x: u8, } impl Term { pub fn new() -> Self { let mode = VGAE.lock(); mode.set_mode(); // let fb = mode.get_frame_buffer(); drop(mode); Self { dirty: false, x: 0, back_buffer: [0; 640 * 480], term: [('\0', Color16::LightGrey); 80 * 60], color: Color16::White, } } pub fn is_dirty(&self) -> bool { self.dirty } pub fn set_dirty(&mut self, dirty: bool) { self.dirty = dirty } pub fn print(&mut self, data: &str) { let mut lex = Token::lexer(data); for toke in lex { match toke { Token::Reset => { self.color = Color16::White; } Token::Error => {} Token::TBlack => self.color = Color16::Black, Token::TBlue => self.color = Color16::Blue, Token::TGreen => self.color = Color16::Green, Token::TCyan => self.color = Color16::Cyan, Token::TRed => self.color = Color16::Red, Token::TMagenta => self.color = Color16::Magenta, Token::TBrown => self.color = Color16::Brown, Token::TLightGrey => self.color = Color16::LightGrey, Token::TDarkGrey => self.color = Color16::DarkGrey, Token::TLightBlue => self.color = Color16::LightBlue, Token::TLightGreen => self.color = Color16::LightGreen, Token::TLightCyan => self.color = Color16::LightCyan, Token::TLightRed => self.color = Color16::LightRed, Token::TPink => self.color = Color16::Pink, Token::TYellow => self.color = Color16::Yellow, Token::TWhite => self.color = Color16::White, Token::Space => { self.term[TERM_MINUS_ONE_LINE + (self.x as usize)] = (' ', self.color); self.x += 1; } Token::Text(st) => { for c in st.chars() { if self.x == 80 { self.move_up(); } // trace!("C"); match c { '\u{08}' => { if self.x == 0 { trace!("IMPOSSIBLE BACKSPACE"); return; } trace!("BACKSPACE"); self.x -= 1; self.term[TERM_MINUS_ONE_LINE + (self.x as usize)] = ('\0', Color16::LightGrey); } '\n' => { self.move_up(); self.x = 0; } c => { self.term[TERM_MINUS_ONE_LINE + (self.x as usize)] = (c, self.color); self.x += 1; } } } } } } } pub fn move_up(&mut self) { self.term.rotate_left(80); for x in 0..80 { self.term[TERM_MINUS_ONE_LINE + x] = ('\0', Color16::LightGrey); } self.x = 0; } // pub fn initialize(&self) { // let mode = VGAE.lock(); // mode.set_mode(); // drop(mode); // } pub fn draw_term(&mut self) { if self.is_dirty() { // trace!("Redrawing"); use Color16::*; let mode = VGAE.lock(); mode.clear_screen(DarkGrey); let mut x = 0; let mut y = 0; for c in self.term { mode.draw_character(x * 8, y * 8, c.0, c.1); if x == 79 { y += 1; x = 0; } else { x += 1 } } { let mouse_coord = x86_64::instructions::interrupts::without_interrupts(|| { let cursor = MOUSE.lock(); (cursor.get_x() as usize, cursor.get_y() as usize) }); mode.draw_line( (mouse_coord.0 as isize + 0, mouse_coord.1 as isize + 0), (mouse_coord.0 as isize + 10, mouse_coord.1 as isize + 10), CURSOR_COLOR, ); mode.draw_line( (mouse_coord.0 as isize + 0, mouse_coord.1 as isize + 0), (mouse_coord.0 as isize + 5, mouse_coord.1 as isize + 0), CURSOR_COLOR, ); mode.draw_line( (mouse_coord.0 as isize + 0, mouse_coord.1 as isize + 0), (mouse_coord.0 as isize + 0, mouse_coord.1 as isize + 5), CURSOR_COLOR, ); } self.set_dirty(false); // trace!("Finished drawing"); } } } #[derive(Logos, Debug, Clone, PartialEq)] pub enum Token { #[regex(r"", logos::skip)] #[error] Error, #[token("\0RESET\0", priority = 10)] Reset, #[token("\0BLACK\0", priority = 10)] TBlack, #[regex("\0BLUE\0", priority = 10)] TBlue, #[token("\0GREEN\0", priority = 10)] TGreen, #[token("\0CYAN\0", priority = 10)] TCyan, #[token("\0RED\0", priority = 10)] TRed, #[token("\0MAGENTA\0", priority = 10)] TMagenta, #[token("\0BROWN\0", priority = 10)] TBrown, #[token("\0LIGHTGREY\0", priority = 10)] TLightGrey, #[token("\0DARKGREY\0", priority = 10)] TDarkGrey, #[token("\0LIGHTBLUE\0", priority = 10)] TLightBlue, #[token("\0LIGHTGREEN\0", priority = 10)] TLightGreen, #[token("\0LIGHTCYAN\0", priority = 10)] TLightCyan, #[token("\0LIGHTRED\0", priority = 10)] TLightRed, #[token("\0PINK\0", priority = 10)] TPink, #[token("\0YELLOW\0", priority = 10)] TYellow, #[token("\0WHITE\0", priority = 10)] TWhite, #[token(" ")] Space, #[regex("[\t\n\u{8}█!-~]+", text_lex, priority = 0)] Text(String), } fn text_lex(lex: &mut Lexer) -> String { lex.slice().into() }