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, term: [(char, Color16); 80 * 60], x: u8, } impl Term { pub fn new() -> Self { let mode = VGAE.lock(); mode.set_mode(); drop(mode); Self { dirty: false, x: 0, term: [('\0', Color16::LightGrey); 80 * 60], } } 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) { for c in data.chars() { if self.x == 79 { self.move_up(); return; } 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, Color16::White); self.x += 1; } } } } // TODO:DEADLOCK: Fix this up pub fn cprint(&mut self, data: &str) { let lex = Token::lexer(data); trace!("{:?}", lex); let mut color = Color16::Red; for toke in lex { match toke { Token::Error => // unsafe { asm!("int 54") }, {} Token::TBlack => color = Color16::Black, Token::TBlue => { color = Color16::Blue; trace!(""); } Token::TGreen => color = Color16::Green, Token::TCyan => color = Color16::Cyan, Token::TRed => color = Color16::Red, Token::TMagenta => color = Color16::Magenta, Token::TBrown => color = Color16::Brown, Token::TLightGrey => color = Color16::LightGrey, Token::TDarkGrey => color = Color16::DarkGrey, Token::TLightBlue => color = Color16::LightBlue, Token::TLightGreen => color = Color16::LightGreen, Token::TLightCyan => color = Color16::LightCyan, Token::TLightRed => color = Color16::LightRed, Token::TPink => color = Color16::Pink, Token::TYellow => color = Color16::Yellow, Token::TWhite => color = Color16::White, Token::Text(st) => { for c in st.chars() { if self.x == 79 { self.move_up(); return; } 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, 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 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, ); 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 } } self.set_dirty(false); trace!("Finished drawing"); } } } #[derive(Logos, Debug, Clone, PartialEq)] pub enum Token { #[regex(r"[\t\n\f]+", logos::skip)] #[error] Error, #[token("$BLACK$")] TBlack, #[token("$BLUE$")] TBlue, #[token("$GREEN$")] TGreen, #[token("$CYAN$")] TCyan, #[token("$RED$")] TRed, #[token("$MAGENTA$")] TMagenta, #[token("$BROWN$")] TBrown, #[token("$LIGHTGREY$")] TLightGrey, #[token("$DARKGREY$")] TDarkGrey, #[token("$LIGHTBLUE$")] TLightBlue, #[token("$LIGHTGREEN$")] TLightGreen, #[token("$LIGHTCYAN$")] TLightCyan, #[token("$LIGHTRED$")] TLightRed, #[token("$PINK$")] TPink, #[token("$YELLOW$")] TYellow, #[token("$WHITE$")] TWhite, #[regex("/[\x00-\x7F]/", text_lex)] Text(String), } fn text_lex(lex: &mut Lexer) -> String { lex.slice().into() } impl Into for Token { fn into(self) -> Color16 { match self { Token::Error => todo!(), Token::TBlack => Color16::Black, Token::TBlue => Color16::Blue, Token::TGreen => Color16::Green, Token::TCyan => Color16::Cyan, Token::TRed => Color16::Red, Token::TMagenta => Color16::Magenta, Token::TBrown => Color16::Brown, Token::TLightGrey => Color16::LightGrey, Token::TDarkGrey => Color16::DarkGrey, Token::TLightBlue => Color16::LightBlue, Token::TLightGreen => Color16::LightGreen, Token::TLightCyan => Color16::LightCyan, Token::TLightRed => Color16::LightRed, Token::TPink => Color16::Pink, Token::TYellow => Color16::Yellow, Token::TWhite => Color16::White, Token::Text(_) => todo!(), } } }