131 lines
2.2 KiB
Rust
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();
|
|
});
|
|
}
|