Files
riscv64-kernel/src/virtual_console.rs
2026-03-17 18:29:00 +01:00

121 lines
3.3 KiB
Rust

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<dyn virtual_fs::VirtualNode>,
}
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::<Color>() 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()
}
}