use alloc::boxed::Box; use io::SeekFrom; use crate::{ draw::{Color, Draw, FONT_HEIGHT, FONT_WIDTH}, vga::{self, Vga}, virtual_fs::{self, FILE_SYSTEM, VirtualFileSystem}, }; const TAB_SIZE: u64 = 4; #[derive(Debug, Clone, Copy, PartialEq, Eq)] struct Cursor { x: u64, y: u64, } impl Cursor { pub fn new() -> Self { Self { x: 0, y: 0 } } } #[derive(Debug)] pub struct VirtualConsole { cursor: Cursor, framebuffer: Box, } impl VirtualConsole { pub fn new() -> Self { VirtualConsole { cursor: Cursor::new(), framebuffer: unsafe { FILE_SYSTEM.open("/dev/fb0".as_ref()).unwrap() }, } } pub fn write_str(&mut self, s: &str) { s.chars().for_each(|c| self.write_char(c)); } pub fn write_char(&mut self, c: char) { let mut last_cursor = self.cursor; match c { '\n' => { self.cursor.x = 0; self.cursor.y += 1; } '\r' => { self.cursor.x = 0; } '\x08' if self.cursor.x > 0 => { // Backspace self.cursor.x -= 1; for y in 0..FONT_HEIGHT as u16 { for x in 0..FONT_WIDTH as u16 { unsafe { self.write_pixel_unsafe( (self.cursor.x * FONT_WIDTH as u64) as u16 + x, (self.cursor.y * FONT_HEIGHT as u64) as u16 + y, Color::BLACK, ) } } } } '\t' => { self.cursor.x = (self.cursor.x / TAB_SIZE + 1) * TAB_SIZE; } _ if c as u64 <= 42 * 32 && c >= 32 as char => { unsafe { self.draw_char_bg( (self.cursor.x * FONT_WIDTH as u64) as u16, (self.cursor.y * FONT_HEIGHT as u64) as u16, c, Color::WHITE, Color::BLACK, ) }; self.cursor.x += 1; } _ => {} } if self.cursor.x as usize * FONT_WIDTH >= vga::WIDTH { self.cursor.x = 0; self.cursor.y += 1; } if self.cursor.y as usize * FONT_HEIGHT >= vga::HEIGHT { self.line_up(); if last_cursor.y > 0 { last_cursor.y -= 1; } } if last_cursor != self.cursor { self.move_cursor_line(last_cursor); } } fn line_up(&mut self) {} fn move_cursor_line(&mut self, _last: Cursor) {} } impl Draw for VirtualConsole { unsafe fn write_pixel_unsafe(&mut self, x: u16, y: u16, color: crate::draw::Color) { self.framebuffer .seek(SeekFrom::Start( (y as u64 * self.get_width() as u64 + x as u64) * size_of::() as u64, )) .unwrap(); self.framebuffer.write(&color.as_bytes()).unwrap(); } fn get_width(&self) -> usize { Vga.get_width() } fn get_height(&self) -> usize { Vga.get_height() } }