changed backspace functionality
backspace will now skip to the last real character on a line and skip over null characters
This commit is contained in:
@@ -0,0 +1,290 @@
|
|||||||
|
use core::fmt;
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
use spin::Mutex;
|
||||||
|
use volatile::Volatile;
|
||||||
|
|
||||||
|
use alloc::borrow::ToOwned;
|
||||||
|
use alloc::vec;
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum Color {
|
||||||
|
Black = 0,
|
||||||
|
Blue = 1,
|
||||||
|
Green = 2,
|
||||||
|
Cyan = 3,
|
||||||
|
Red = 4,
|
||||||
|
Magenta = 5,
|
||||||
|
Brown = 6,
|
||||||
|
LightGray = 7,
|
||||||
|
DarkGray = 8,
|
||||||
|
LightBlue = 9,
|
||||||
|
LightGreen = 10,
|
||||||
|
LightCyan = 11,
|
||||||
|
LightRed = 12,
|
||||||
|
Pink = 13,
|
||||||
|
Yellow = 14,
|
||||||
|
White = 15,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct ColorCode(u8);
|
||||||
|
|
||||||
|
impl ColorCode {
|
||||||
|
pub fn new(foreground: Color, background: Color) -> ColorCode {
|
||||||
|
ColorCode((background as u8) << 5 | (foreground as u8))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
#[repr(C)]
|
||||||
|
struct ScreenChar {
|
||||||
|
character: u8,
|
||||||
|
colour: ColorCode,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const BUFFER_HEIGHT: usize = 25;
|
||||||
|
pub const BUFFER_WIDTH: usize = 80;
|
||||||
|
|
||||||
|
#[repr(transparent)]
|
||||||
|
struct Buffer {
|
||||||
|
chars: [[Volatile<ScreenChar>; BUFFER_WIDTH]; BUFFER_HEIGHT],
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BufferSwap {
|
||||||
|
chars: [[ScreenChar; BUFFER_WIDTH]; BUFFER_HEIGHT],
|
||||||
|
}
|
||||||
|
struct CharGrid {
|
||||||
|
chars: Vec<[ScreenChar; BUFFER_WIDTH]>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Renderer {
|
||||||
|
col_pos: usize,
|
||||||
|
pub col_code: ColorCode,
|
||||||
|
buffer: &'static mut Buffer,
|
||||||
|
userspace: BufferSwap,
|
||||||
|
upwards: CharGrid,
|
||||||
|
downwards: CharGrid,
|
||||||
|
pub sandbox: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
pub static ref RENDERER: Mutex<Renderer> = Mutex::new(Renderer {
|
||||||
|
col_pos: 0,
|
||||||
|
col_code: ColorCode::new(Color::White, Color::Black),
|
||||||
|
buffer: unsafe { &mut *(0xb8000 as *mut Buffer) },
|
||||||
|
userspace: BufferSwap {
|
||||||
|
chars: [[ScreenChar {
|
||||||
|
character: 178u8,
|
||||||
|
colour: ColorCode::new(Color::White, Color::Black),
|
||||||
|
}; BUFFER_WIDTH]; BUFFER_HEIGHT]
|
||||||
|
},
|
||||||
|
upwards: CharGrid {
|
||||||
|
chars: vec![
|
||||||
|
[ScreenChar {
|
||||||
|
character: 32u8,
|
||||||
|
colour: ColorCode::new(Color::White, Color::Black),
|
||||||
|
}; 80]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
downwards: CharGrid {
|
||||||
|
chars: vec![
|
||||||
|
[ScreenChar {
|
||||||
|
character: 32u8,
|
||||||
|
colour: ColorCode::new(Color::White, Color::Black),
|
||||||
|
}; 80]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
sandbox: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Renderer {
|
||||||
|
pub fn text_mode(&mut self) -> Result<(), ()> {
|
||||||
|
if !self.sandbox {
|
||||||
|
return Err(());
|
||||||
|
};
|
||||||
|
self.buffer_swap().unwrap();
|
||||||
|
self.sandbox = false;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sandbox_mode(&mut self) -> Result<(), ()> {
|
||||||
|
if self.sandbox {
|
||||||
|
return Err(());
|
||||||
|
};
|
||||||
|
self.buffer_swap().unwrap();
|
||||||
|
self.sandbox = true;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn buffer_swap(&mut self) -> Result<(), ()> {
|
||||||
|
for (i, _) in self.userspace.chars.clone().iter().enumerate() {
|
||||||
|
let tmp = self.buffer.chars[i].clone();
|
||||||
|
|
||||||
|
for (j, col) in self.userspace.chars[i].clone().iter().enumerate() {
|
||||||
|
self.buffer.chars[i][j].write(col.to_owned())
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j, _) in tmp.iter().enumerate() {
|
||||||
|
self.userspace.chars[i][j] = tmp[j].read().to_owned()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render_frame(&mut self, frame: [[char; BUFFER_WIDTH]; BUFFER_HEIGHT]) {
|
||||||
|
for (i, row) in frame.iter().enumerate() {
|
||||||
|
for (j, col) in row.iter().enumerate() {
|
||||||
|
if let Some(c) = self.fancy_char(*col) {
|
||||||
|
self.buffer.chars[i][j].write(ScreenChar {
|
||||||
|
character: c,
|
||||||
|
colour: self.col_code,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
self.buffer.chars[i][j].write(ScreenChar {
|
||||||
|
character: *col as u8,
|
||||||
|
colour: self.col_code,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_string(&mut self, string: &str) {
|
||||||
|
for ch in string.chars() {
|
||||||
|
if let Some(x) = self.fancy_char(ch) {
|
||||||
|
self.write_byte(x)
|
||||||
|
} else {
|
||||||
|
match ch as u8 {
|
||||||
|
0x20..=0xff | b'\n' => self.write_byte(ch as u8),
|
||||||
|
_ => self.write_byte(0xfe),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fancy_char(&self, ch: char) -> Option<u8> {
|
||||||
|
let res: u8 = match ch {
|
||||||
|
'│' => 179,
|
||||||
|
'─' => 196,
|
||||||
|
'┴' => 193,
|
||||||
|
'┤' => 180,
|
||||||
|
'═' => 205,
|
||||||
|
'║' => 186,
|
||||||
|
'╗' => 187,
|
||||||
|
'╝' => 188,
|
||||||
|
'╚' => 200,
|
||||||
|
'╔' => 201,
|
||||||
|
'»' => 175,
|
||||||
|
'┐' => 191,
|
||||||
|
'└' => 192,
|
||||||
|
'┘' => 217,
|
||||||
|
'┌' => 218,
|
||||||
|
'┼' => 197,
|
||||||
|
'░' => 176,
|
||||||
|
'▓' => 178,
|
||||||
|
'«' => 174,
|
||||||
|
'»' => 175,
|
||||||
|
_ => {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Some(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn backspace(&mut self) -> Result<(), ()> {
|
||||||
|
if self.col_pos == 0 {
|
||||||
|
self.undonewline();
|
||||||
|
}
|
||||||
|
self.col_pos -= 1;
|
||||||
|
let row = BUFFER_HEIGHT - 1;
|
||||||
|
let col = self.col_pos;
|
||||||
|
|
||||||
|
let blank = ScreenChar {
|
||||||
|
character: b' ',
|
||||||
|
colour: self.col_code,
|
||||||
|
};
|
||||||
|
self.buffer.chars[row][col].write(blank);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_byte(&mut self, byte: u8) {
|
||||||
|
match byte {
|
||||||
|
b'\n' => self.newline(),
|
||||||
|
byte => {
|
||||||
|
if self.col_pos >= BUFFER_WIDTH {
|
||||||
|
self.newline();
|
||||||
|
}
|
||||||
|
let row = BUFFER_HEIGHT - 1;
|
||||||
|
let col = self.col_pos;
|
||||||
|
let col_code = self.col_code;
|
||||||
|
self.buffer.chars[row][col].write(ScreenChar {
|
||||||
|
character: byte,
|
||||||
|
colour: col_code,
|
||||||
|
});
|
||||||
|
self.col_pos += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn newline(&mut self) {
|
||||||
|
for row in 1..BUFFER_HEIGHT {
|
||||||
|
for col in 0..BUFFER_WIDTH {
|
||||||
|
let character = self.buffer.chars[row][col].read();
|
||||||
|
self.buffer.chars[row - 1][col].write(character);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.clear_row(BUFFER_HEIGHT - 1);
|
||||||
|
self.col_pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn undonewline(&mut self) {
|
||||||
|
for row in (0..BUFFER_HEIGHT - 1).rev() {
|
||||||
|
for col in 0..BUFFER_WIDTH {
|
||||||
|
let character = self.buffer.chars[row][col].read();
|
||||||
|
self.buffer.chars[row + 1][col].write(character);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.clear_row(0);
|
||||||
|
self.col_pos = BUFFER_WIDTH;
|
||||||
|
}
|
||||||
|
pub fn clear(&mut self) {
|
||||||
|
for row in (0..BUFFER_HEIGHT - 1).rev() {
|
||||||
|
self.clear_row(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clear_row(&mut self, row: usize) {
|
||||||
|
let blank = ScreenChar {
|
||||||
|
character: b' ',
|
||||||
|
colour: self.col_code,
|
||||||
|
};
|
||||||
|
for col in 0..BUFFER_WIDTH {
|
||||||
|
self.buffer.chars[row][col].write(blank);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Write for Renderer {
|
||||||
|
fn write_str(&mut self, string: &str) -> fmt::Result {
|
||||||
|
self.write_string(string);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write(args: fmt::Arguments, cols: (Color, Color)) {
|
||||||
|
use core::fmt::Write;
|
||||||
|
use x86_64::instructions::interrupts;
|
||||||
|
interrupts::without_interrupts(|| {
|
||||||
|
let mut writer = RENDERER.lock();
|
||||||
|
writer.col_code = ColorCode::new(cols.0, cols.1);
|
||||||
|
writer.write_fmt(args).unwrap()
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -8,4 +8,4 @@ pub mod serial;
|
|||||||
pub mod tasks;
|
pub mod tasks;
|
||||||
pub mod sysinit;
|
pub mod sysinit;
|
||||||
pub mod authenticator;
|
pub mod authenticator;
|
||||||
pub mod render2;
|
pub mod render;
|
||||||
+205
-171
@@ -6,6 +6,7 @@ use volatile::Volatile;
|
|||||||
use alloc::borrow::ToOwned;
|
use alloc::borrow::ToOwned;
|
||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
use crate::std::io::Screen;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
@@ -46,132 +47,232 @@ struct ScreenChar {
|
|||||||
colour: ColorCode,
|
colour: ColorCode,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ScreenChar {
|
||||||
|
fn null() -> ScreenChar {
|
||||||
|
ScreenChar {
|
||||||
|
character: 0u8,
|
||||||
|
colour: ColorCode::new(Color::White, Color::Black),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn white(character: u8) -> ScreenChar {
|
||||||
|
ScreenChar {
|
||||||
|
character,
|
||||||
|
colour: ColorCode::new(Color::White, Color::Black),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub const BUFFER_HEIGHT: usize = 25;
|
pub const BUFFER_HEIGHT: usize = 25;
|
||||||
pub const BUFFER_WIDTH: usize = 80;
|
pub const BUFFER_WIDTH: usize = 80;
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
struct Buffer {
|
struct VGAOutput {
|
||||||
chars: [[Volatile<ScreenChar>; BUFFER_WIDTH]; BUFFER_HEIGHT],
|
chars: [[Volatile<ScreenChar>; BUFFER_WIDTH]; BUFFER_HEIGHT],
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BufferSwap {
|
|
||||||
chars: [[ScreenChar; BUFFER_WIDTH]; BUFFER_HEIGHT],
|
|
||||||
}
|
|
||||||
struct CharGrid {
|
|
||||||
chars: Vec<[ScreenChar; BUFFER_WIDTH]>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Renderer {
|
pub struct Renderer {
|
||||||
col_pos: usize,
|
col_pos: usize,
|
||||||
pub col_code: ColorCode,
|
screen_ref: &'static mut VGAOutput, // this should not be accessed unless the screen is rendering a new frame
|
||||||
buffer: &'static mut Buffer,
|
term_buffer: Vec<[ScreenChar; BUFFER_WIDTH]>, // this is the standard terminal output view
|
||||||
userspace: BufferSwap,
|
app_buffer: [[ScreenChar; BUFFER_WIDTH]; BUFFER_HEIGHT], // this is where applications render their frames to
|
||||||
upwards: CharGrid,
|
application_mode: bool, // if false: term mode; if true: app mode
|
||||||
downwards: CharGrid,
|
temp_colour: Option<ColorCode>,
|
||||||
pub sandbox: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref RENDERER: Mutex<Renderer> = Mutex::new(Renderer {
|
pub static ref RENDERER: Mutex<Renderer> = Mutex::new(Renderer {
|
||||||
col_pos: 0,
|
col_pos: 0,
|
||||||
col_code: ColorCode::new(Color::White, Color::Black),
|
screen_ref: unsafe { &mut *(0xb8000 as *mut VGAOutput) },
|
||||||
buffer: unsafe { &mut *(0xb8000 as *mut Buffer) },
|
term_buffer: vec![[ScreenChar::null(); BUFFER_WIDTH]; BUFFER_HEIGHT],
|
||||||
userspace: BufferSwap {
|
app_buffer: [[ScreenChar::null(); BUFFER_WIDTH]; BUFFER_HEIGHT],
|
||||||
chars: [[ScreenChar {
|
application_mode: false,
|
||||||
character: 178u8,
|
temp_colour: None,
|
||||||
colour: ColorCode::new(Color::White, Color::Black),
|
|
||||||
}; BUFFER_WIDTH]; BUFFER_HEIGHT]
|
|
||||||
},
|
|
||||||
upwards: CharGrid {
|
|
||||||
chars: vec![
|
|
||||||
[ScreenChar {
|
|
||||||
character: 32u8,
|
|
||||||
colour: ColorCode::new(Color::White, Color::Black),
|
|
||||||
}; 80]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
downwards: CharGrid {
|
|
||||||
chars: vec![
|
|
||||||
[ScreenChar {
|
|
||||||
character: 32u8,
|
|
||||||
colour: ColorCode::new(Color::White, Color::Black),
|
|
||||||
}; 80]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
sandbox: false,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Renderer {
|
impl Renderer {
|
||||||
pub fn text_mode(&mut self) -> Result<(), ()> {
|
// EXTERNAL API : for use by standard library and other parts of the kernel
|
||||||
if !self.sandbox {
|
pub fn render_frame(&mut self, frame: [[char; BUFFER_WIDTH]; BUFFER_HEIGHT]) { // renders the given frame to the app buffer
|
||||||
return Err(());
|
let mut processed_frame: [[ScreenChar; BUFFER_WIDTH]; BUFFER_HEIGHT] = [[ScreenChar::null(); BUFFER_WIDTH]; BUFFER_HEIGHT];
|
||||||
};
|
|
||||||
self.buffer_swap().unwrap();
|
|
||||||
self.sandbox = false;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn sandbox_mode(&mut self) -> Result<(), ()> {
|
|
||||||
if self.sandbox {
|
|
||||||
return Err(());
|
|
||||||
};
|
|
||||||
self.buffer_swap().unwrap();
|
|
||||||
self.sandbox = true;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn buffer_swap(&mut self) -> Result<(), ()> {
|
|
||||||
for (i, _) in self.userspace.chars.clone().iter().enumerate() {
|
|
||||||
let tmp = self.buffer.chars[i].clone();
|
|
||||||
|
|
||||||
for (j, col) in self.userspace.chars[i].clone().iter().enumerate() {
|
|
||||||
self.buffer.chars[i][j].write(col.to_owned())
|
|
||||||
}
|
|
||||||
|
|
||||||
for (j, _) in tmp.iter().enumerate() {
|
|
||||||
self.userspace.chars[i][j] = tmp[j].read().to_owned()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn render_frame(&mut self, frame: [[char; BUFFER_WIDTH]; BUFFER_HEIGHT]) {
|
|
||||||
for (i, row) in frame.iter().enumerate() {
|
for (i, row) in frame.iter().enumerate() {
|
||||||
for (j, col) in row.iter().enumerate() {
|
for (j, col) in row.iter().enumerate() {
|
||||||
if let Some(c) = self.fancy_char(*col) {
|
processed_frame[i][j] = match self.special_char(*col) {
|
||||||
self.buffer.chars[i][j].write(ScreenChar {
|
Some(c) => ScreenChar::white(c as u8),
|
||||||
character: c,
|
None => ScreenChar::white(*col as u8)
|
||||||
colour: self.col_code,
|
};
|
||||||
});
|
|
||||||
} else {
|
|
||||||
self.buffer.chars[i][j].write(ScreenChar {
|
|
||||||
character: *col as u8,
|
|
||||||
colour: self.col_code,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_string(&mut self, string: &str) {
|
self.app_buffer = processed_frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn application_mode(&mut self) -> Result<(), ()> {
|
||||||
|
if self.application_mode {
|
||||||
|
return Err(());
|
||||||
|
} else {
|
||||||
|
self.application_mode = true;
|
||||||
|
self.internal_render();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn terminal_mode(&mut self) -> Result<(), ()> {
|
||||||
|
if !self.application_mode {
|
||||||
|
return Err(());
|
||||||
|
} else {
|
||||||
|
self.application_mode = false;
|
||||||
|
self.internal_render();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mode_is_app(&self) -> bool {
|
||||||
|
self.application_mode
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_char(&mut self, ch: u8, col: Option<ColorCode>) { // default colour if no colour is selected for character
|
||||||
|
self.write_byte(ch, col);
|
||||||
|
self.internal_render();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_string(&mut self, string: &str, col: Option<ColorCode>) {
|
||||||
for ch in string.chars() {
|
for ch in string.chars() {
|
||||||
if let Some(x) = self.fancy_char(ch) {
|
match self.special_char(ch) {
|
||||||
self.write_byte(x)
|
Some(c) => self.write_byte(c, col),
|
||||||
} else {
|
None => match ch as u8 {
|
||||||
match ch as u8 {
|
0x20..=0xff | b'\n' => self.write_byte(ch as u8, col),
|
||||||
0x20..=0xff | b'\n' => self.write_byte(ch as u8),
|
_ => self.write_byte(0xfe, col),
|
||||||
_ => self.write_byte(0xfe),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.internal_render();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn backspace(&mut self) -> Result<(), ()> {
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if self.internal_backspace()? {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.internal_render();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear(&mut self) { // clears the screen and all scroll-back
|
||||||
|
if self.application_mode { return; };
|
||||||
|
self.term_buffer = vec![[ScreenChar::null(); BUFFER_WIDTH]; BUFFER_HEIGHT];
|
||||||
|
self.internal_render();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_colour(&mut self, cols: ColorCode) {
|
||||||
|
self.temp_colour = Some(cols);
|
||||||
|
}
|
||||||
|
pub fn reset_colour(&mut self) {
|
||||||
|
self.temp_colour = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// INTERNAL API ONLY
|
||||||
|
|
||||||
|
fn set_cursor_position(&mut self, row: usize, col: usize) {
|
||||||
|
use x86_64::instructions::port::Port;
|
||||||
|
let cursor_position: u16 = (row as u16) * 80 + (col as u16);
|
||||||
|
|
||||||
|
unsafe {// Write the high byte of the cursor position to register 14
|
||||||
|
let mut control_port = Port::<u8>::new(0x3D4);
|
||||||
|
control_port.write(14);
|
||||||
|
// Write the high byte of the cursor position to register 15
|
||||||
|
let mut data_port = Port::<u8>::new(0x3D5);
|
||||||
|
data_port.write((cursor_position >> 8) as u8);
|
||||||
|
// Write the low byte of the cursor position to register 14
|
||||||
|
control_port.write(15);
|
||||||
|
// Write the low byte of the cursor position to register 15
|
||||||
|
data_port.write((cursor_position & 0xFF) as u8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn internal_backspace(&mut self) -> Result<bool, ()> {
|
||||||
|
let mut should_break = false;
|
||||||
|
|
||||||
|
if self.col_pos == 0 {
|
||||||
|
self.internal_lastline();
|
||||||
|
}
|
||||||
|
self.col_pos -= 1;
|
||||||
|
let col = self.col_pos;
|
||||||
|
|
||||||
|
let buff_len = self.term_buffer.len();
|
||||||
|
|
||||||
|
if self.term_buffer[buff_len - 1][col].character != 0 {
|
||||||
|
should_break = true
|
||||||
|
}
|
||||||
|
|
||||||
|
self.term_buffer[buff_len - 1][col] = ScreenChar::null();
|
||||||
|
Ok(should_break)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn internal_newline(&mut self) { // moves all content one line up the screen and creates new line
|
||||||
|
if self.application_mode { return; }; // only in terminal mode
|
||||||
|
self.term_buffer.push([ScreenChar::null(); BUFFER_WIDTH]);
|
||||||
|
self.col_pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn internal_lastline(&mut self) { // goes back to previous line and shifts all lines down
|
||||||
|
if self.application_mode { return; };
|
||||||
|
self.term_buffer.pop();
|
||||||
|
self.col_pos = BUFFER_WIDTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_screen_char(&mut self, ch: ScreenChar) { // TODO: optimise so that screen is not fully re-rendered for every string written.
|
||||||
|
match ch.character as u8 {
|
||||||
|
b'\n' => self.internal_newline(),
|
||||||
|
_ => {
|
||||||
|
if self.col_pos >= BUFFER_WIDTH {
|
||||||
|
self.internal_newline();
|
||||||
|
}
|
||||||
|
let row = BUFFER_HEIGHT - 1;
|
||||||
|
let col = self.col_pos;
|
||||||
|
|
||||||
|
let buff_len = self.term_buffer.len();
|
||||||
|
self.term_buffer[buff_len - 1][col] = ch;
|
||||||
|
self.col_pos += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fancy_char(&self, ch: char) -> Option<u8> {
|
fn write_byte(&mut self, byte: u8, col: Option<ColorCode>) { // default colour if no colour is selected for character
|
||||||
|
self.write_screen_char(ScreenChar {
|
||||||
|
character: byte,
|
||||||
|
colour: match col {
|
||||||
|
Some(c) => c,
|
||||||
|
None => match self.temp_colour {
|
||||||
|
Some(c) => c,
|
||||||
|
None => ColorCode::new(Color::White, Color::Black),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn internal_render(&mut self) { // private function that can only be used from within this struct.
|
||||||
|
if self.application_mode {
|
||||||
|
for (i, row) in self.app_buffer.iter().enumerate() {
|
||||||
|
for (j, col) in row.iter().enumerate() {
|
||||||
|
self.screen_ref.chars[i][j].write(*col);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let buff_len = self.term_buffer.len();
|
||||||
|
for (i, row) in self.term_buffer[buff_len - BUFFER_HEIGHT..buff_len].iter().enumerate() {
|
||||||
|
for (j, col) in row.iter().enumerate() {
|
||||||
|
self.screen_ref.chars[i][j].write(*col);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.set_cursor_position(BUFFER_HEIGHT - 1, self.col_pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn special_char(&self, ch: char) -> Option<u8> {
|
||||||
let res: u8 = match ch {
|
let res: u8 = match ch {
|
||||||
'│' => 179,
|
'│' => 179,
|
||||||
'─' => 196,
|
'─' => 196,
|
||||||
@@ -192,89 +293,17 @@ impl Renderer {
|
|||||||
'░' => 176,
|
'░' => 176,
|
||||||
'▓' => 178,
|
'▓' => 178,
|
||||||
'«' => 174,
|
'«' => 174,
|
||||||
'»' => 175,
|
|
||||||
_ => {
|
_ => {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Some(res)
|
Some(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn backspace(&mut self) -> Result<(), ()> {
|
|
||||||
if self.col_pos == 0 {
|
|
||||||
self.undonewline();
|
|
||||||
}
|
|
||||||
self.col_pos -= 1;
|
|
||||||
let row = BUFFER_HEIGHT - 1;
|
|
||||||
let col = self.col_pos;
|
|
||||||
|
|
||||||
let blank = ScreenChar {
|
|
||||||
character: b' ',
|
|
||||||
colour: self.col_code,
|
|
||||||
};
|
|
||||||
self.buffer.chars[row][col].write(blank);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn write_byte(&mut self, byte: u8) {
|
|
||||||
match byte {
|
|
||||||
b'\n' => self.newline(),
|
|
||||||
byte => {
|
|
||||||
if self.col_pos >= BUFFER_WIDTH {
|
|
||||||
self.newline();
|
|
||||||
}
|
|
||||||
let row = BUFFER_HEIGHT - 1;
|
|
||||||
let col = self.col_pos;
|
|
||||||
let col_code = self.col_code;
|
|
||||||
self.buffer.chars[row][col].write(ScreenChar {
|
|
||||||
character: byte,
|
|
||||||
colour: col_code,
|
|
||||||
});
|
|
||||||
self.col_pos += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn newline(&mut self) {
|
|
||||||
for row in 1..BUFFER_HEIGHT {
|
|
||||||
for col in 0..BUFFER_WIDTH {
|
|
||||||
let character = self.buffer.chars[row][col].read();
|
|
||||||
self.buffer.chars[row - 1][col].write(character);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.clear_row(BUFFER_HEIGHT - 1);
|
|
||||||
self.col_pos = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn undonewline(&mut self) {
|
|
||||||
for row in (0..BUFFER_HEIGHT - 1).rev() {
|
|
||||||
for col in 0..BUFFER_WIDTH {
|
|
||||||
let character = self.buffer.chars[row][col].read();
|
|
||||||
self.buffer.chars[row + 1][col].write(character);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.clear_row(0);
|
|
||||||
self.col_pos = BUFFER_WIDTH;
|
|
||||||
}
|
|
||||||
pub fn clear(&mut self) {
|
|
||||||
for row in (0..BUFFER_HEIGHT - 1).rev() {
|
|
||||||
self.clear_row(row);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn clear_row(&mut self, row: usize) {
|
|
||||||
let blank = ScreenChar {
|
|
||||||
character: b' ',
|
|
||||||
colour: self.col_code,
|
|
||||||
};
|
|
||||||
for col in 0..BUFFER_WIDTH {
|
|
||||||
self.buffer.chars[row][col].write(blank);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Write for Renderer {
|
impl fmt::Write for Renderer {
|
||||||
fn write_str(&mut self, string: &str) -> fmt::Result {
|
fn write_str(&mut self, string: &str) -> fmt::Result {
|
||||||
self.write_string(string);
|
self.write_string(string, None);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -282,9 +311,14 @@ impl fmt::Write for Renderer {
|
|||||||
pub fn write(args: fmt::Arguments, cols: (Color, Color)) {
|
pub fn write(args: fmt::Arguments, cols: (Color, Color)) {
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
use x86_64::instructions::interrupts;
|
use x86_64::instructions::interrupts;
|
||||||
|
|
||||||
|
let colour_code = ColorCode::new(cols.0, cols.1);
|
||||||
|
|
||||||
interrupts::without_interrupts(|| {
|
interrupts::without_interrupts(|| {
|
||||||
let mut writer = RENDERER.lock();
|
let mut writer = RENDERER.lock();
|
||||||
writer.col_code = ColorCode::new(cols.0, cols.1);
|
|
||||||
writer.write_fmt(args).unwrap()
|
writer.with_colour(colour_code);
|
||||||
|
writer.write_fmt(args).unwrap();
|
||||||
|
writer.reset_colour();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1,298 +0,0 @@
|
|||||||
use core::fmt;
|
|
||||||
use lazy_static::lazy_static;
|
|
||||||
use spin::Mutex;
|
|
||||||
use volatile::Volatile;
|
|
||||||
|
|
||||||
use alloc::borrow::ToOwned;
|
|
||||||
use alloc::vec;
|
|
||||||
use alloc::vec::Vec;
|
|
||||||
use crate::std::io::Screen;
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
#[repr(u8)]
|
|
||||||
pub enum Color {
|
|
||||||
Black = 0,
|
|
||||||
Blue = 1,
|
|
||||||
Green = 2,
|
|
||||||
Cyan = 3,
|
|
||||||
Red = 4,
|
|
||||||
Magenta = 5,
|
|
||||||
Brown = 6,
|
|
||||||
LightGray = 7,
|
|
||||||
DarkGray = 8,
|
|
||||||
LightBlue = 9,
|
|
||||||
LightGreen = 10,
|
|
||||||
LightCyan = 11,
|
|
||||||
LightRed = 12,
|
|
||||||
Pink = 13,
|
|
||||||
Yellow = 14,
|
|
||||||
White = 15,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
#[repr(transparent)]
|
|
||||||
pub struct ColorCode(u8);
|
|
||||||
|
|
||||||
impl ColorCode {
|
|
||||||
pub fn new(foreground: Color, background: Color) -> ColorCode {
|
|
||||||
ColorCode((background as u8) << 5 | (foreground as u8))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
#[repr(C)]
|
|
||||||
struct ScreenChar {
|
|
||||||
character: u8,
|
|
||||||
colour: ColorCode,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ScreenChar {
|
|
||||||
fn null() -> ScreenChar {
|
|
||||||
ScreenChar {
|
|
||||||
character: 0u8,
|
|
||||||
colour: ColorCode::new(Color::White, Color::Black),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn white(character: u8) -> ScreenChar {
|
|
||||||
ScreenChar {
|
|
||||||
character,
|
|
||||||
colour: ColorCode::new(Color::White, Color::Black),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const BUFFER_HEIGHT: usize = 25;
|
|
||||||
pub const BUFFER_WIDTH: usize = 80;
|
|
||||||
|
|
||||||
#[repr(transparent)]
|
|
||||||
struct VGAOutput {
|
|
||||||
chars: [[Volatile<ScreenChar>; BUFFER_WIDTH]; BUFFER_HEIGHT],
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Renderer {
|
|
||||||
col_pos: usize,
|
|
||||||
//col_code: ColorCode, // TODO: fully replace this with a colour code used in the fmt::Write function
|
|
||||||
screen_ref: &'static mut VGAOutput, // this should not be accessed unless the screen is rendering a new frame
|
|
||||||
term_buffer: Vec<[ScreenChar; BUFFER_WIDTH]>, // this is the standard terminal output view
|
|
||||||
app_buffer: [[ScreenChar; BUFFER_WIDTH]; BUFFER_HEIGHT], // this is where applications render their frames to
|
|
||||||
application_mode: bool, // if false: term mode; if true: app mode
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
pub static ref RENDERER: Mutex<Renderer> = Mutex::new(Renderer {
|
|
||||||
col_pos: 0,
|
|
||||||
screen_ref: unsafe { &mut *(0xb8000 as *mut VGAOutput) },
|
|
||||||
term_buffer: vec![[ScreenChar::null(); BUFFER_WIDTH]; BUFFER_HEIGHT],
|
|
||||||
app_buffer: [[ScreenChar::null(); BUFFER_WIDTH]; BUFFER_HEIGHT],
|
|
||||||
application_mode: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Renderer {
|
|
||||||
// EXTERNAL API : for use by standard library and other parts of the kernel
|
|
||||||
pub fn render_frame(&mut self, frame: [[char; BUFFER_WIDTH]; BUFFER_HEIGHT]) { // renders the given frame to the app buffer
|
|
||||||
let mut processed_frame: [[ScreenChar; BUFFER_WIDTH]; BUFFER_HEIGHT] = [[ScreenChar::null(); BUFFER_WIDTH]; BUFFER_HEIGHT];
|
|
||||||
|
|
||||||
for (i, row) in frame.iter().enumerate() {
|
|
||||||
for (j, col) in row.iter().enumerate() {
|
|
||||||
processed_frame[i][j] = match self.special_char(*col) {
|
|
||||||
Some(c) => ScreenChar::white(c as u8),
|
|
||||||
None => ScreenChar::white(*col as u8)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.app_buffer = processed_frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: change standard library for alternative to these functions
|
|
||||||
pub fn application_mode(&mut self) -> Result<(), ()> {
|
|
||||||
if self.application_mode {
|
|
||||||
return Err(());
|
|
||||||
} else {
|
|
||||||
self.application_mode = true;
|
|
||||||
self.internal_render();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn terminal_mode(&mut self) -> Result<(), ()> {
|
|
||||||
if !self.application_mode {
|
|
||||||
return Err(());
|
|
||||||
} else {
|
|
||||||
self.application_mode = false;
|
|
||||||
self.internal_render();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn mode_is_app(&self) -> bool {
|
|
||||||
self.application_mode
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn write_char(&mut self, ch: u8, col: Option<ColorCode>) { // default colour if no colour is selected for character
|
|
||||||
self.write_byte(ch, col);
|
|
||||||
self.internal_render();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn write_string(&mut self, string: &str, col: Option<ColorCode>) {
|
|
||||||
for ch in string.chars() {
|
|
||||||
match self.special_char(ch) {
|
|
||||||
Some(c) => self.write_byte(c, col),
|
|
||||||
None => match ch as u8 {
|
|
||||||
0x20..=0xff | b'\n' => self.write_byte(ch as u8, col),
|
|
||||||
_ => self.write_byte(0xfe, col),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.internal_render();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn backspace(&mut self) -> Result<(), ()> {
|
|
||||||
self.internal_backspace()?;
|
|
||||||
self.internal_render();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clear(&mut self) { // clears the screen and all scroll-back
|
|
||||||
if self.application_mode { return; };
|
|
||||||
self.term_buffer = vec![[ScreenChar::null(); BUFFER_WIDTH]; BUFFER_HEIGHT];
|
|
||||||
self.internal_render();
|
|
||||||
}
|
|
||||||
|
|
||||||
// INTERNAL API ONLY
|
|
||||||
|
|
||||||
fn set_cursor_position(&mut self, row: usize, col: usize) {
|
|
||||||
use x86_64::instructions::port::Port;
|
|
||||||
let cursor_position: u16 = (row as u16) * 80 + (col as u16);
|
|
||||||
|
|
||||||
unsafe {// Write the high byte of the cursor position to register 14
|
|
||||||
let mut control_port = Port::<u8>::new(0x3D4);
|
|
||||||
control_port.write(14);
|
|
||||||
|
|
||||||
// Write the high byte of the cursor position to register 15
|
|
||||||
let mut data_port = Port::<u8>::new(0x3D5);
|
|
||||||
data_port.write((cursor_position >> 8) as u8);
|
|
||||||
|
|
||||||
// Write the low byte of the cursor position to register 14
|
|
||||||
control_port.write(15);
|
|
||||||
|
|
||||||
// Write the low byte of the cursor position to register 15
|
|
||||||
data_port.write((cursor_position & 0xFF) as u8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn internal_backspace(&mut self) -> Result<(), ()> {
|
|
||||||
if self.col_pos == 0 {
|
|
||||||
self.internal_lastline();
|
|
||||||
}
|
|
||||||
self.col_pos -= 1;
|
|
||||||
let col = self.col_pos;
|
|
||||||
|
|
||||||
let buff_len = self.term_buffer.len();
|
|
||||||
self.term_buffer[buff_len - 1][col] = ScreenChar::null();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn internal_newline(&mut self) { // moves all content one line up the screen and creates new line
|
|
||||||
if self.application_mode { return; }; // only in terminal mode
|
|
||||||
self.term_buffer.push([ScreenChar::null(); BUFFER_WIDTH]);
|
|
||||||
self.col_pos = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn internal_lastline(&mut self) { // goes back to previous line and shifts all lines down
|
|
||||||
if self.application_mode { return; };
|
|
||||||
self.term_buffer.pop();
|
|
||||||
self.col_pos = BUFFER_WIDTH;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_screen_char(&mut self, ch: ScreenChar) { // TODO: optimise so that screen is not fully re-rendered for every string written.
|
|
||||||
match ch.character as u8 {
|
|
||||||
b'\n' => self.internal_newline(),
|
|
||||||
_ => {
|
|
||||||
if self.col_pos >= BUFFER_WIDTH {
|
|
||||||
self.internal_newline();
|
|
||||||
}
|
|
||||||
let row = BUFFER_HEIGHT - 1;
|
|
||||||
let col = self.col_pos;
|
|
||||||
|
|
||||||
let buff_len = self.term_buffer.len();
|
|
||||||
self.term_buffer[buff_len - 1][col] = ch;
|
|
||||||
self.col_pos += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_byte(&mut self, byte: u8, col: Option<ColorCode>) { // default colour if no colour is selected for character
|
|
||||||
self.write_screen_char(ScreenChar {
|
|
||||||
character: byte,
|
|
||||||
colour: match col {
|
|
||||||
Some(c) => c,
|
|
||||||
None => ColorCode::new(Color::White, Color::Black),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn internal_render(&mut self) { // private function that can only be used from within this struct.
|
|
||||||
if self.application_mode {
|
|
||||||
for (i, row) in self.app_buffer.iter().enumerate() {
|
|
||||||
for (j, col) in row.iter().enumerate() {
|
|
||||||
self.screen_ref.chars[i][j].write(*col);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let buff_len = self.term_buffer.len();
|
|
||||||
for (i, row) in self.term_buffer[buff_len - BUFFER_HEIGHT..buff_len].iter().enumerate() {
|
|
||||||
for (j, col) in row.iter().enumerate() {
|
|
||||||
self.screen_ref.chars[i][j].write(*col);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.set_cursor_position(BUFFER_HEIGHT - 1, self.col_pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn special_char(&self, ch: char) -> Option<u8> {
|
|
||||||
let res: u8 = match ch {
|
|
||||||
'│' => 179,
|
|
||||||
'─' => 196,
|
|
||||||
'┴' => 193,
|
|
||||||
'┤' => 180,
|
|
||||||
'═' => 205,
|
|
||||||
'║' => 186,
|
|
||||||
'╗' => 187,
|
|
||||||
'╝' => 188,
|
|
||||||
'╚' => 200,
|
|
||||||
'╔' => 201,
|
|
||||||
'»' => 175,
|
|
||||||
'┐' => 191,
|
|
||||||
'└' => 192,
|
|
||||||
'┘' => 217,
|
|
||||||
'┌' => 218,
|
|
||||||
'┼' => 197,
|
|
||||||
'░' => 176,
|
|
||||||
'▓' => 178,
|
|
||||||
'«' => 174,
|
|
||||||
_ => {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Some(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Write for Renderer {
|
|
||||||
fn write_str(&mut self, string: &str) -> fmt::Result {
|
|
||||||
self.write_string(string, None);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn write(args: fmt::Arguments, cols: (Color, Color)) {
|
|
||||||
use core::fmt::Write;
|
|
||||||
use x86_64::instructions::interrupts;
|
|
||||||
interrupts::without_interrupts(|| {
|
|
||||||
let mut writer = RENDERER.lock();
|
|
||||||
writer.write_fmt(args).unwrap()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -13,7 +13,7 @@ use futures_util::task::AtomicWaker;
|
|||||||
use futures_util::stream::StreamExt;
|
use futures_util::stream::StreamExt;
|
||||||
use pc_keyboard::{layouts, DecodedKey, HandleControl, Keyboard, ScancodeSet1};
|
use pc_keyboard::{layouts, DecodedKey, HandleControl, Keyboard, ScancodeSet1};
|
||||||
use crate::print;
|
use crate::print;
|
||||||
use crate::kernel::render2::RENDERER;
|
use crate::kernel::render::RENDERER;
|
||||||
use alloc::{string::String};
|
use alloc::{string::String};
|
||||||
|
|
||||||
static WAKER: AtomicWaker = AtomicWaker::new();
|
static WAKER: AtomicWaker = AtomicWaker::new();
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
kernel::render2::{RENDERER, BUFFER_WIDTH, BUFFER_HEIGHT, ColorCode},
|
kernel::render::{RENDERER, BUFFER_WIDTH, BUFFER_HEIGHT, ColorCode},
|
||||||
kernel::tasks::keyboard::KEYBOARD,
|
kernel::tasks::keyboard::KEYBOARD,
|
||||||
};
|
};
|
||||||
|
|
||||||
use alloc::{boxed::Box, string::{String, ToString}, vec::Vec};
|
use alloc::{boxed::Box, string::{String, ToString}, vec::Vec};
|
||||||
|
|
||||||
pub use crate::{print, println, serial_print, serial_println};
|
pub use crate::{print, println, serial_print, serial_println};
|
||||||
|
pub use crate::kernel::render::Color;
|
||||||
|
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use spin::Mutex;
|
use spin::Mutex;
|
||||||
@@ -201,10 +202,10 @@ pub fn _log(args: core::fmt::Arguments) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use crate::kernel::render2::Color;
|
|
||||||
|
|
||||||
pub fn write(args: core::fmt::Arguments, cols: (Color, Color)) {
|
pub fn write(args: core::fmt::Arguments, cols: (Color, Color)) {
|
||||||
crate::kernel::render2::write(args, cols);
|
crate::kernel::render::write(args, cols);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mkfs() {
|
pub fn mkfs() {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::kernel::render2::{BUFFER_HEIGHT, BUFFER_WIDTH, RENDERER};
|
use crate::kernel::render::{BUFFER_HEIGHT, BUFFER_WIDTH, RENDERER};
|
||||||
use crate::std::io::Frame;
|
use crate::std::io::Frame;
|
||||||
use crate::{print, println};
|
use crate::{print, println};
|
||||||
use alloc::{
|
use alloc::{
|
||||||
|
|||||||
Reference in New Issue
Block a user