mirror of https://github.com/vinc/moros.git
137 lines
3.4 KiB
Rust
137 lines
3.4 KiB
Rust
use crate::{print, kernel};
|
|
use alloc::string::String;
|
|
use lazy_static::lazy_static;
|
|
use pc_keyboard::{KeyCode, DecodedKey};
|
|
use spin::Mutex;
|
|
use x86_64::instructions::interrupts;
|
|
|
|
lazy_static! {
|
|
pub static ref STDIN: Mutex<String> = Mutex::new(String::new());
|
|
pub static ref ECHO: Mutex<bool> = Mutex::new(true);
|
|
pub static ref RAW: Mutex<bool> = Mutex::new(false);
|
|
}
|
|
|
|
#[cfg(feature="vga")]
|
|
#[macro_export]
|
|
macro_rules! print {
|
|
($($arg:tt)*) => ({
|
|
$crate::kernel::vga::print_fmt(format_args!($($arg)*));
|
|
});
|
|
}
|
|
|
|
#[cfg(feature="serial")]
|
|
#[macro_export]
|
|
macro_rules! print {
|
|
($($arg:tt)*) => ({
|
|
$crate::kernel::serial::print_fmt(format_args!($($arg)*));
|
|
});
|
|
}
|
|
|
|
pub fn disable_echo() {
|
|
let mut echo = ECHO.lock();
|
|
*echo = false;
|
|
}
|
|
|
|
pub fn enable_echo() {
|
|
let mut echo = ECHO.lock();
|
|
*echo = true;
|
|
}
|
|
|
|
pub fn is_echo_enabled() -> bool {
|
|
*ECHO.lock()
|
|
}
|
|
|
|
pub fn disable_raw() {
|
|
let mut raw = RAW.lock();
|
|
*raw = false;
|
|
}
|
|
|
|
pub fn enable_raw() {
|
|
let mut raw = RAW.lock();
|
|
*raw = true;
|
|
}
|
|
|
|
pub fn is_raw_enabled() -> bool {
|
|
*RAW.lock()
|
|
}
|
|
|
|
pub fn key_handle(key: DecodedKey) {
|
|
let c = match key {
|
|
DecodedKey::Unicode(c) => c,
|
|
DecodedKey::RawKey(KeyCode::ArrowLeft) => '←', // U+2190
|
|
DecodedKey::RawKey(KeyCode::ArrowUp) => '↑', // U+2191
|
|
DecodedKey::RawKey(KeyCode::ArrowRight) => '→', // U+2192
|
|
DecodedKey::RawKey(KeyCode::ArrowDown) => '↓', // U+2193
|
|
DecodedKey::RawKey(_) => '\0'
|
|
};
|
|
let mut stdin = STDIN.lock();
|
|
|
|
if c == '\x08' && !is_raw_enabled() {
|
|
// Avoid printing more backspaces than chars inserted into STDIN.
|
|
// Also, the VGA driver support only ASCII so unicode chars will
|
|
// be displayed with one square for each codepoint.
|
|
if stdin.len() > 0 {
|
|
let n = stdin.pop().unwrap().len_utf8();
|
|
if is_echo_enabled() {
|
|
for _ in 0..n {
|
|
print!("\x08");
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
// TODO: Replace non-ascii chars by ascii square symbol to keep length
|
|
// at 1 instead of being variable?
|
|
stdin.push(c);
|
|
if is_echo_enabled() {
|
|
print!("{}", c);
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn get_char() -> char {
|
|
kernel::console::disable_echo();
|
|
kernel::console::enable_raw();
|
|
loop {
|
|
kernel::time::halt();
|
|
let res = interrupts::without_interrupts(|| {
|
|
let mut stdin = STDIN.lock();
|
|
match stdin.chars().next_back() {
|
|
Some(c) => {
|
|
stdin.clear();
|
|
Some(c)
|
|
},
|
|
_ => {
|
|
None
|
|
}
|
|
}
|
|
});
|
|
if let Some(c) = res {
|
|
kernel::console::enable_echo();
|
|
kernel::console::disable_raw();
|
|
return c;
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn get_line() -> String {
|
|
loop {
|
|
kernel::time::halt();
|
|
let res = interrupts::without_interrupts(|| {
|
|
let mut stdin = STDIN.lock();
|
|
match stdin.chars().next_back() {
|
|
Some('\n') => {
|
|
let line = stdin.clone();
|
|
stdin.clear();
|
|
Some(line)
|
|
}
|
|
_ => {
|
|
None
|
|
}
|
|
}
|
|
});
|
|
if let Some(line) = res {
|
|
return line;
|
|
}
|
|
}
|
|
}
|