1
0
Fork 0
forked from AbleOS/ableos
ableos-idl/ableos/src/vterm.rs

262 lines
8.1 KiB
Rust
Raw Normal View History

2022-08-05 01:14:13 -05:00
/*
* Copyright (c) 2022, Able <able@ablecorp.us>
*
* SPDX-License-Identifier: MPL-2.0
*/
#![deny(missing_docs)]
//! The VTerm is a terminal with nice
use crate::{hardware::MOUSE, vga_e::VGAE};
2022-08-05 01:14:13 -05:00
use ab_glyph::{Font, FontRef, Glyph};
use logos::{Lexer, Logos};
2022-08-05 01:14:13 -05:00
use spin::Lazy;
2022-07-31 01:54:01 -05:00
use vga::{colors::Color16, writers::GraphicsWriter};
const TERM_MINUS_ONE_LINE: usize = 4720;
2022-08-02 01:52:03 -05:00
const CURSOR_COLOR: Color16 = Color16::Cyan;
2022-07-31 01:54:01 -05:00
#[derive(Debug)]
2022-08-05 01:14:13 -05:00
/// A VTerm
pub struct VTerm {
2022-07-31 01:54:01 -05:00
dirty: bool,
2022-08-02 06:00:21 -05:00
color: Color16,
term: [(char, Color16); 80 * 60],
2022-08-03 02:09:34 -05:00
back_buffer: [u8; 640 * 480],
2022-07-31 05:22:39 -05:00
x: u8,
2022-07-31 01:54:01 -05:00
}
2022-08-05 01:14:13 -05:00
impl VTerm {
/// Construct a new VTerm
2022-07-31 01:54:01 -05:00
pub fn new() -> Self {
trace!("Setting vga mode");
2022-07-31 05:22:39 -05:00
let mode = VGAE.lock();
mode.set_mode();
2022-08-03 02:09:34 -05:00
// let fb = mode.get_frame_buffer();
2022-07-31 05:22:39 -05:00
drop(mode);
2022-07-31 01:54:01 -05:00
Self {
dirty: false,
x: 0,
2022-08-03 02:09:34 -05:00
back_buffer: [0; 640 * 480],
2022-08-05 01:14:13 -05:00
term: [('\0', Color16::DarkGrey); 80 * 60],
2022-08-02 06:00:21 -05:00
color: Color16::White,
2022-07-31 01:54:01 -05:00
}
}
2022-08-05 01:14:13 -05:00
/// Check the dirty state of the VTerm
2022-07-31 01:54:01 -05:00
pub fn is_dirty(&self) -> bool {
self.dirty
}
2022-08-05 01:14:13 -05:00
/// Set the dirty state of the VTerm
2022-07-31 01:54:01 -05:00
pub fn set_dirty(&mut self, dirty: bool) {
self.dirty = dirty
}
2022-08-05 01:14:13 -05:00
/// Append a &str to the VTerm
pub fn print(&mut self, data: &str) {
2022-08-02 06:00:21 -05:00
let mut lex = Token::lexer(data);
for toke in lex {
match toke {
2022-08-02 06:00:21 -05:00
Token::Reset => {
self.color = Color16::White;
}
Token::Error => {}
Token::TBlack => self.color = Color16::Black,
Token::TBlue => self.color = Color16::Blue,
Token::TGreen => self.color = Color16::Green,
Token::TCyan => self.color = Color16::Cyan,
Token::TRed => self.color = Color16::Red,
Token::TMagenta => self.color = Color16::Magenta,
Token::TBrown => self.color = Color16::Brown,
Token::TLightGrey => self.color = Color16::LightGrey,
Token::TDarkGrey => self.color = Color16::DarkGrey,
Token::TLightBlue => self.color = Color16::LightBlue,
Token::TLightGreen => self.color = Color16::LightGreen,
Token::TLightCyan => self.color = Color16::LightCyan,
Token::TLightRed => self.color = Color16::LightRed,
Token::TPink => self.color = Color16::Pink,
Token::TYellow => self.color = Color16::Yellow,
Token::TWhite => self.color = Color16::White,
2022-08-05 01:14:13 -05:00
// Token::Space => {
// self.term[TERM_MINUS_ONE_LINE + (self.x as usize)] = (' ', self.color);
// self.x += 1;
// }
Token::Text(st) => {
for c in st.chars() {
2022-08-02 06:00:21 -05:00
if self.x == 80 {
2022-08-05 01:14:13 -05:00
// trace!("X too big moving up");
self.move_up();
}
2022-08-03 02:09:34 -05:00
// trace!("C");
match c {
2022-08-05 01:14:13 -05:00
'\0' => {
self.term[TERM_MINUS_ONE_LINE + (self.x as usize)] =
(c, self.color);
self.x += 1;
}
'\u{08}' => {
if self.x == 0 {
2022-08-03 02:09:34 -05:00
trace!("IMPOSSIBLE BACKSPACE");
return;
}
self.x -= 1;
self.term[TERM_MINUS_ONE_LINE + (self.x as usize)] =
('\0', Color16::LightGrey);
}
'\n' => {
self.move_up();
self.x = 0;
}
c => {
2022-08-02 06:00:21 -05:00
self.term[TERM_MINUS_ONE_LINE + (self.x as usize)] =
(c, self.color);
self.x += 1;
}
}
}
}
}
}
}
2022-08-05 01:14:13 -05:00
/// Move the VTerm up by one line
2022-07-31 01:54:01 -05:00
pub fn move_up(&mut self) {
self.term.rotate_left(80);
for x in 0..80 {
2022-08-05 01:14:13 -05:00
self.term[TERM_MINUS_ONE_LINE + x] = ('\0', Color16::DarkGrey);
2022-07-31 01:54:01 -05:00
}
2022-07-31 05:22:39 -05:00
self.x = 0;
2022-07-31 01:54:01 -05:00
}
2022-08-05 01:14:13 -05:00
/// Redraw the VTerm to the VGA buffer
2022-07-31 01:54:01 -05:00
pub fn draw_term(&mut self) {
if self.is_dirty() {
2022-08-03 02:09:34 -05:00
// trace!("Redrawing");
2022-08-02 01:52:03 -05:00
use Color16::*;
2022-07-31 01:54:01 -05:00
let mode = VGAE.lock();
2022-08-02 01:52:03 -05:00
mode.clear_screen(DarkGrey);
2022-07-31 01:54:01 -05:00
let mut x = 0;
let mut y = 0;
for c in self.term {
mode.draw_character(x * 8, y * 8, c.0, c.1);
2022-08-05 01:14:13 -05:00
// mode.draw_unicode_char(x, y, c.0, c.1);
2022-07-31 01:54:01 -05:00
if x == 79 {
y += 1;
2022-08-05 01:14:13 -05:00
2022-07-31 01:54:01 -05:00
x = 0;
} else {
x += 1
}
}
2022-08-02 01:52:03 -05:00
2022-08-02 06:00:21 -05:00
{
let mouse_coord = x86_64::instructions::interrupts::without_interrupts(|| {
let cursor = MOUSE.lock();
(cursor.get_x() as usize, cursor.get_y() as usize)
});
mode.draw_line(
(mouse_coord.0 as isize + 0, mouse_coord.1 as isize + 0),
(mouse_coord.0 as isize + 10, mouse_coord.1 as isize + 10),
CURSOR_COLOR,
);
mode.draw_line(
(mouse_coord.0 as isize + 0, mouse_coord.1 as isize + 0),
(mouse_coord.0 as isize + 5, mouse_coord.1 as isize + 0),
CURSOR_COLOR,
);
mode.draw_line(
(mouse_coord.0 as isize + 0, mouse_coord.1 as isize + 0),
(mouse_coord.0 as isize + 0, mouse_coord.1 as isize + 5),
CURSOR_COLOR,
);
}
2022-08-05 01:14:13 -05:00
drop(mode);
/*
let mut x = 0;
let mut y = 0;
for c in ['b'; 80 * 60]
// "abcdefghijklmnopqrstuvwxyzabcdefghijk\nabcd jkjhgkjhgkjhgefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz12"
// .chars()
{
if c == '\n' {
y += 1;
x = 0;
continue;
}
self.draw_char(x, y, c, Color16::Red);
if x == 80 {
y += 1;
x = 1;
} else {
x += 1;
}
}
*/
2022-07-31 03:03:59 -05:00
self.set_dirty(false);
2022-08-03 02:09:34 -05:00
// trace!("Finished drawing");
2022-07-31 01:54:01 -05:00
}
}
}
#[derive(Logos, Debug, Clone, PartialEq)]
2022-08-05 01:14:13 -05:00
enum Token {
2022-08-02 06:00:21 -05:00
#[regex(r"", logos::skip)]
#[error]
Error,
2022-08-02 06:00:21 -05:00
#[token("\0RESET\0", priority = 10)]
Reset,
#[token("\0BLACK\0", priority = 10)]
TBlack,
2022-08-02 06:00:21 -05:00
#[regex("\0BLUE\0", priority = 10)]
TBlue,
2022-08-02 06:00:21 -05:00
#[token("\0GREEN\0", priority = 10)]
TGreen,
2022-08-02 06:00:21 -05:00
#[token("\0CYAN\0", priority = 10)]
TCyan,
2022-08-02 06:00:21 -05:00
#[token("\0RED\0", priority = 10)]
TRed,
2022-08-02 06:00:21 -05:00
#[token("\0MAGENTA\0", priority = 10)]
TMagenta,
2022-08-02 06:00:21 -05:00
#[token("\0BROWN\0", priority = 10)]
TBrown,
2022-08-02 06:00:21 -05:00
#[token("\0LIGHTGREY\0", priority = 10)]
TLightGrey,
2022-08-02 06:00:21 -05:00
#[token("\0DARKGREY\0", priority = 10)]
TDarkGrey,
2022-08-02 06:00:21 -05:00
#[token("\0LIGHTBLUE\0", priority = 10)]
TLightBlue,
2022-08-02 06:00:21 -05:00
#[token("\0LIGHTGREEN\0", priority = 10)]
TLightGreen,
2022-08-02 06:00:21 -05:00
#[token("\0LIGHTCYAN\0", priority = 10)]
TLightCyan,
2022-08-02 06:00:21 -05:00
#[token("\0LIGHTRED\0", priority = 10)]
TLightRed,
2022-08-02 06:00:21 -05:00
#[token("\0PINK\0", priority = 10)]
TPink,
2022-08-02 06:00:21 -05:00
#[token("\0YELLOW\0", priority = 10)]
TYellow,
2022-08-02 06:00:21 -05:00
#[token("\0WHITE\0", priority = 10)]
TWhite,
2022-08-05 01:14:13 -05:00
// #[token(" ")]
2022-08-02 06:00:21 -05:00
2022-08-05 01:14:13 -05:00
// Space,
#[regex("[\t\n\u{8}█!-\u{10FFFF} ]+", text_lex, priority = 0)]
/// A printable string
Text(String),
}
fn text_lex(lex: &mut Lexer<Token>) -> String {
lex.slice().into()
}