nulfos/src/dev/console.rs

131 lines
2.2 KiB
Rust

use core::fmt;
use lazy_static::lazy_static;
use spin::{Mutex, MutexGuard};
use crate::hard::vga::{self, Vga};
#[macro_export]
macro_rules! print {
($($arg:tt)*) => ($crate::dev::console::print_args(format_args!($($arg)*)));
}
#[macro_export]
macro_rules! println {
() => ($crate::print!("\n"));
($($arg:tt)*) => ($crate::print!("{}\n", format_args!($($arg)*)));
}
lazy_static! {
static ref OUT: Mutex<Console> = Mutex::new(Console::init());
}
pub fn out<'r>() -> MutexGuard<'r, Console> {
OUT.lock()
}
pub struct Console {
pub cursor: Cursor,
pub vga: Vga,
}
impl Console {
pub fn init() -> Self {
let cursor = Cursor::new(vga::WIDTH, vga::HEIGHT);
let vga = Vga;
Self { cursor, vga }
}
pub fn print_(&mut self, text: &str) {
for c in text.chars() {
match c {
'\n' => self.cursor.ret(),
'\t' => self.print_(" "),
_ => {
self.vga.write_at(self.cursor.pos(), c);
self.cursor.progress();
}
}
}
}
pub fn correct(&mut self) {
self.cursor.set_col((self.cursor.col().max(1) - 1));
self.vga.write_at(self.cursor.pos(), ' ');
}
}
struct Cursor {
line: usize,
column: usize,
width: usize,
height: usize,
}
impl Cursor {
pub fn new(width: usize, height: usize) -> Self {
Self {
line: 0,
column: 0,
width,
height,
}
}
pub fn pos(&self) -> (usize, usize) {
(self.column, self.line)
}
pub fn line(&self) -> usize {
self.line
}
pub fn col(&self) -> usize {
self.column
}
pub fn set_pos(&mut self, pos: (usize, usize)) {
(self.column, self.line) = pos;
}
pub fn set_line(&mut self, line: usize) {
self.line = line;
}
pub fn set_col(&mut self, col: usize) {
self.column = col;
}
pub fn progress(&mut self) {
self.column += 1;
if self.column < self.width {
return;
}
self.column = 0;
self.line += 1;
if self.line < self.height {
return;
}
self.line = 0;
}
pub fn ret(&mut self) {
self.column = self.width;
self.progress();
}
}
impl fmt::Write for Console {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.print_(s);
Ok(())
}
}
pub fn print_args(args: fmt::Arguments) {
use core::fmt::Write;
use x86_64::instructions::interrupts;
interrupts::without_interrupts(|| {
OUT.lock().write_fmt(args).unwrap();
});
}