diff --git a/src/main.rs b/src/main.rs index 06b37a0..691298c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,7 @@ use bootloader::{entry_point, BootInfo}; use core::panic::PanicInfo; use CrystalOS::std::tasks::{Executor, Task}; -use CrystalOS::{printerr, std::syscall}; +use CrystalOS::{printerr, serial_println, std::syscall}; extern crate alloc; use CrystalOS::user::bin::shell; @@ -16,6 +16,7 @@ use CrystalOS::user::bin::shell; fn panic(_info: &PanicInfo) -> ! { syscall::terminal_mode_force(); printerr!("{}", _info); + serial_println!("{}", _info); CrystalOS::hlt(); } diff --git a/src/system/kernel/render.rs b/src/system/kernel/render.rs index ef16559..e18b720 100644 --- a/src/system/kernel/render.rs +++ b/src/system/kernel/render.rs @@ -296,6 +296,7 @@ impl Renderer { if self.application_mode { for (i, row) in self.app_buffer.iter().enumerate() { for (j, col) in row.iter().enumerate() { + if col.character == 0u8 { continue; } self.screen_ref.chars[i][j].write(*col); } } diff --git a/src/system/std/render.rs b/src/system/std/render.rs index 3328d76..1138b3a 100644 --- a/src/system/std/render.rs +++ b/src/system/std/render.rs @@ -4,7 +4,7 @@ use alloc::vec::Vec; use crate::system::kernel::render::{RENDERER, ScreenChar}; use crate::std::io::Color; use num_traits::{Num, ToPrimitive}; - +use crate::serial_println; /// TODO: get a working implementation for CLI apps /// elements can be created using their from_str() method /// you can then render the element to the current frame using the render() method @@ -22,23 +22,25 @@ pub use crate::system::kernel::render::{ }; pub struct Window { - width: u32, - height: u32, - x: u32, - y: u32, + width: usize, + height: usize, + x: usize, + y: usize, bordered: bool, open: bool, + title: String, } impl Window { pub fn new() -> Window { Window { - width: BUFFER_WIDTH as u32, - height: BUFFER_HEIGHT as u32, + width: BUFFER_WIDTH, + height: BUFFER_HEIGHT, x: 0, y: 0, bordered: true, - open: true + open: true, + title: String::new(), } } @@ -50,23 +52,120 @@ impl Window { let mut frame: [[ScreenChar; BUFFER_WIDTH]; BUFFER_HEIGHT] = [[ScreenChar::null(); BUFFER_WIDTH]; BUFFER_HEIGHT]; - Ok(()) } - // pub fn render(&self, f: &Frame) -> Result<(), RenderError> { - // let mut frame: &[[ScreenChar; self.width]; self.height] = &[[ScreenChar::null(); self.width]; self.height]; + pub fn dimensions(&self) -> Dimensions { + Dimensions::new(self.width, self.height) + } + + pub fn set_dimensions(&mut self, width: usize, height: usize) { + self.width = width; + self.height = height; + } + + pub fn position(&self) -> Position { + Position::new(self.x, self.y) + } + + pub fn set_position(&mut self, x: usize, y: usize) { + self.x = x; + self.y = y; + } + + pub fn set_title(&mut self, title: &str) { + self.title = String::from(title); + } + + pub fn render(&self, f: &Frame) -> Result<(), RenderError> { + let mut frame: [[ScreenChar; BUFFER_WIDTH]; BUFFER_HEIGHT] = [[ScreenChar::null(); BUFFER_WIDTH]; BUFFER_HEIGHT]; + + for (i, row) in f.frame.iter().enumerate() { + for (j, col) in row.iter().enumerate() { + frame[i + f.position.y][j + f.position.x] = col.as_screen_char(); + }; + } + + if self.bordered { + self.outline(&mut frame)?; + } + + RENDERER.lock().render_frame(frame); + Ok(()) + } + + pub fn move_cursor(&self, x: i32, y: i32) -> Result<(), RenderError> { + RENDERER.lock().cursor_position((x + self.x as i32) as u8, (y + self.y as i32) as u8) + } + + fn outline(&self, frame: &mut [[ScreenChar; 80]; 25]) -> Result<(), RenderError> { + // draws the sides of the container + // Calculate the dimensions + let dimensions = self.dimensions(); + + // Extract coordinates for readability + let top_y = self.y as isize - 1; + let bottom_y = self.y as isize + dimensions.y as isize; + let left_x = self.x as isize - 1; + let right_x = self.x as isize + dimensions.x as isize; + let x_start = self.x as isize; + let x_end = self.x as isize + dimensions.x as isize; + let y_start = self.y as isize; + let y_end = self.y as isize + dimensions.y as isize; + + // Define ranges + let (top, bottom, left, right) = ( + (top_y, x_start..x_end), + (bottom_y, x_start..x_end), + (left_x, y_start..y_end), + (right_x, y_start..y_end), + ); + + let title = self.title.clone(); + let title_width = title.len(); + let mut title_x = left_x + (dimensions.x as isize - title_width as isize) / 2; + if title_x < left_x { + title_x = left_x; + } - - - // for (i, row) in f.frame.iter().enumerate() { - // for (j, col) in row.iter().enumerate() { - // frame[i + f.position.y][j + f.position.x] = col.as_screen_char(); - // }; - // } - // RENDERER.lock().render_frame(frame); - // Ok(()) - // } + for (y, range) in [top, bottom] { + for x in range { + if x >= 0 && x < 80 && y >= 0 && y < 25 { + frame[y as usize][x as usize] = ColouredChar::new('─').as_screen_char(); + } + } + } + + for (x, range) in [left, right] { + for y in range { + if x >= 0 && x < 80 && y >= 0 && y < 25 { + frame[y as usize][x as usize] = ColouredChar::new('│').as_screen_char(); + } + } + } + + for (i, c) in title.chars().enumerate() { + let i = i as isize; + if title_x + i >= 0 && title_x + i < 80 && top_y >= 0 && top_y < 25 { + frame[top_y as usize][(title_x + i as isize) as usize] = ColouredChar::new(c).as_screen_char(); + } + } + + // draw the corners of the container + let corners = [ + (top_y, left_x, '┌'), + (top_y, right_x, '┐'), + (bottom_y, left_x, '└'), + (bottom_y, right_x, '┘'), + ]; + for &(y, x, c) in &corners { + if x >= 0 && x < 80 && y >= 0 && y < 25 { + frame[y as usize][x as usize] = ColouredChar::new(c).as_screen_char(); + } + } + Ok(()) + } + } #[derive(Clone, Copy, Debug, PartialEq)] @@ -105,9 +204,6 @@ impl ColouredChar { } } - - - #[derive(Copy, Clone, Debug)] pub struct Position { pub x: T, diff --git a/src/user/bin/apps/calc/calc.rs b/src/user/bin/apps/calc/calc.rs index 4edb46d..ffc4c97 100755 --- a/src/user/bin/apps/calc/calc.rs +++ b/src/user/bin/apps/calc/calc.rs @@ -3,7 +3,7 @@ use alloc::{boxed::Box, format, string::String, vec::Vec}; use alloc::string::ToString; use alloc::borrow::ToOwned; use crate::std::render::Window; -use crate::{println, print, mknode, std, serial_println}; +use crate::{println, print, mknode, std}; use async_trait::async_trait; use crate::std::application::{ @@ -420,9 +420,7 @@ impl Calculator { "failed to tokenise: {:?}", e ))?; - - serial_println!("{:?}", tokens); - + let mut parser = Parser::new(tokens).unwrap(); parser.parse().map_err(|e| format!("{:?}", e)) } diff --git a/src/user/bin/apps/editor.rs b/src/user/bin/apps/editor.rs index 17d8539..ad08688 100644 --- a/src/user/bin/apps/editor.rs +++ b/src/user/bin/apps/editor.rs @@ -22,6 +22,7 @@ pub struct Editor { unsaved: bool, display: Display, lineno_width: i32, + window: Window, } enum Mode { @@ -44,6 +45,8 @@ impl core::fmt::Display for Mode { impl Editor { fn move_cursor(&mut self, dx: i32, dy: i32) { + serial_println!("trying to move"); + if dy != 0 && self.cursor_pos.y + dy >= 0 && self.cursor_pos.y + dy <= self.buffer.len() as i32 @@ -67,39 +70,30 @@ impl Editor { self.cursor_pos.x += dx; } - serial_println!("cursor: {} {} offset: {} {} ", self.cursor_pos.x, self.cursor_pos.y, self.offset_pos.x, self.offset_pos.y); - - while self.cursor_pos.x + 3 + (self.lineno_width + 2) > 80 + self.offset_pos.x { + while self.cursor_pos.x + 2 + (self.lineno_width + 2) > self.window.dimensions().x as i32 + self.offset_pos.x { self.offset_pos.x += 1; } - while self.cursor_pos.x - 3 < self.offset_pos.x && self.offset_pos.x - 3 >= 0 { + while self.cursor_pos.x - 3 < self.offset_pos.x && self.offset_pos.x - 1 >= 0 { self.offset_pos.x -= 1; } - while self.cursor_pos.y + 3 > self.offset_pos.y + 25 { + while self.cursor_pos.y + 3 > self.offset_pos.y + self.window.dimensions().y as i32 { self.offset_pos.y += 1; } - while self.cursor_pos.y - 3 < self.offset_pos.y && self.offset_pos.y - 3 >= 0 { + while self.cursor_pos.y - 1 < self.offset_pos.y && self.offset_pos.y - 1 >= 0 { self.offset_pos.y -= 1; } - serial_println!( - "moving cursor to {}, {}", - (self.cursor_pos.x - self.offset_pos.x + self.lineno_width + 2) as u8, - (self.cursor_pos.y - self.offset_pos.y) as u8 - ); + serial_println!("talking to kernel"); - // print all the values below - serial_println!("offset: {}, {}", self.offset_pos.x, self.offset_pos.y); - serial_println!("cursor: {}, {}", self.cursor_pos.x, self.cursor_pos.y); - serial_println!("line width: {}", self.lineno_width + 2); - - self.display.mv_cursor( - (self.cursor_pos.x - self.offset_pos.x + self.lineno_width + 2) as u8, - (self.cursor_pos.y - self.offset_pos.y) as u8 + self.window.move_cursor( + self.cursor_pos.x - self.offset_pos.x + self.lineno_width + 2, + self.cursor_pos.y - self.offset_pos.y ).unwrap(); + + serial_println!("done talking to kernel"); } fn delete_char(&mut self) { @@ -165,34 +159,32 @@ impl Application for Editor { mode: Mode::Normal, unsaved: false, display: Display::borrow(), - lineno_width: 0 + lineno_width: 0, + window: Window::new(), } } - async fn run(&mut self, window: Option, _args: Vec) -> Result<(), application::Error> { + async fn run(&mut self, window: Option, args: Vec) -> Result<(), application::Error> { - // if let Some(s) = args.get(0) { - // self.buffer = s.lines().map(|l| l.chars().collect()).collect::>>() - // } + if let Some(w) = window { + self.window = w; + } - self.buffer = String::from(" - /$$ /$$$$$$$$ /$$ /$$ /$$$$$$ /$$$$$$$ /$$ /$$ /$$ - /$$/|_____ $$ | $$ / $$ /$$__ $$| $$____/ /$$/| $$| $$ - /$$/ /$$/ | $$/ $$/| $$ \\ $$| $$ /$$/ \\ $$\\ $$ - /$$/ /$$/ \\ $$$$/ | $$ | $$| $$$$$$$ /$$/ \\ $$\\ $$ -| $$ /$$/ >$$ $$ | $$ | $$|_____ $$ /$$/ /$$/ /$$/ - \\ $$ /$$/ /$$/\\ $$| $$/$$ $$ /$$ \\ $$ /$$/ /$$/ /$$/ - \\ $$ /$$$$$$$$| $$ \\ $$| $$$$$$/| $$$$$$//$$/ /$$/ /$$/ - \\__/|________/|__/ |__/ \\____ $$$ \\______/|__/ |__/ |__/ - \\__/ - ").lines().map(|l| l.chars().collect()).collect::>>(); + self.window.set_dimensions(60, 23); + self.window.set_position(10, 1); + self.window.set_title("Editor"); - + if let Some(s) = args.get(0) { + self.buffer = s.lines().map(|l| l.chars().collect()).collect::>>() + } loop { // start by rendering the screen self.lineno_width = self.buffer.len().to_string().len() as i32; - self.render().unwrap().write_to_screen().unwrap(); + + if let Ok(frame) = self.render() { + self.window.render(&frame).unwrap(); + } // wait for a keyboard input let keystroke = std::io::Stdin::keystroke().await; @@ -247,12 +239,8 @@ impl Application for Editor { KeyStroke::Down => { self.move_cursor(0, 1); }, - KeyStroke::None => { - serial_println!("none"); - }, - _ => { - serial_println!("other"); - } + KeyStroke::None => {}, + _ => {} } } Mode::Command => { @@ -280,11 +268,11 @@ impl Application for Editor { impl CgComponent for Editor { fn render(&self) -> Result { - let mut frame = Frame::new(Position::zero(), Position::new(80, 25))?; + let mut frame = Frame::new(self.window.position(), self.window.dimensions())?; let width = self.lineno_width as usize; let linecolour = ColorCode::new(Color::Cyan, Color::Black); - for (i, line) in (self.offset_pos.y..self.offset_pos.y + 24).enumerate() { + for (i, line) in (self.offset_pos.y..self.offset_pos.y + self.window.dimensions().y as i32 - 1).enumerate() { if line >= self.buffer.len() as i32 { break; } @@ -297,7 +285,7 @@ impl CgComponent for Editor { let line = self.buffer[line as usize].iter().collect::(); - for (j, c) in line.chars().skip(self.offset_pos.x as usize).take(80 - (width + 2)).enumerate() { + for (j, c) in line.chars().skip(self.offset_pos.x as usize).take(self.window.dimensions().x - (width + 2)).enumerate() { frame.write(Position::new(j + width + 2, i), ColouredChar::new(c))?; } } @@ -317,7 +305,7 @@ impl CgComponent for Editor { let toolbar = line_and_col + " " + &mode + " " + &unsaved; for (i, c) in toolbar.chars().enumerate() { - frame.write(Position::new(i, 24), ColouredChar::new(c))?; + frame.write(Position::new(i, self.window.dimensions().y - 1), ColouredChar::new(c))?; } Ok(frame) @@ -328,3 +316,14 @@ impl CgComponent for Editor { } } +// self.buffer = String::from(" +// /$$ /$$$$$$$$ /$$ /$$ /$$$$$$ /$$$$$$$ /$$ /$$ /$$ +// /$$/|_____ $$ | $$ / $$ /$$__ $$| $$____/ /$$/| $$| $$ +// /$$/ /$$/ | $$/ $$/| $$ \\ $$| $$ /$$/ \\ $$\\ $$ +// /$$/ /$$/ \\ $$$$/ | $$ | $$| $$$$$$$ /$$/ \\ $$\\ $$ +// | $$ /$$/ >$$ $$ | $$ | $$|_____ $$ /$$/ /$$/ /$$/ +// \\ $$ /$$/ /$$/\\ $$| $$/$$ $$ /$$ \\ $$ /$$/ /$$/ /$$/ +// \\ $$ /$$$$$$$$| $$ \\ $$| $$$$$$/| $$$$$$//$$/ /$$/ /$$/ +// \\__/|________/|__/ |__/ \\____ $$$ \\______/|__/ |__/ |__/ +// \\__/ +// ").lines().map(|l| l.chars().collect()).collect::>>(); \ No newline at end of file diff --git a/src/user/bin/apps/grapher.rs b/src/user/bin/apps/grapher.rs index 8830ca5..1951663 100644 --- a/src/user/bin/apps/grapher.rs +++ b/src/user/bin/apps/grapher.rs @@ -136,13 +136,6 @@ impl Application for Grapher { entry_widget.update(entry); if let Ok(frame) = container.render() { - - let self_widget = container.elements.get("grapher").unwrap(); - let _self_clone = self_widget.fetch::().unwrap(); - - let entry = container.elements.get("entry_box").unwrap(); - let _entry_clone = entry.fetch::().unwrap(); - frame.write_to_screen().map_err(|_| Error::ApplicationError(String::from("failed to write to screen")))?; } } diff --git a/src/user/bin/utils/crystalfetch.rs b/src/user/bin/utils/crystalfetch.rs index daec48f..a1ce825 100644 --- a/src/user/bin/utils/crystalfetch.rs +++ b/src/user/bin/utils/crystalfetch.rs @@ -55,7 +55,7 @@ impl Application for CrystalFetch { async fn run(&mut self, window: Option, _args: Vec) -> Result<(), Error> { - let ds = Display::borrow(); + // let ds = Display::borrow(); let os = OS.lock().os.clone(); let version = OS.lock().version.clone();