use serde::{Deserialize, Serialize}; use crate::ScriptContext; mod tortuise { #[link(wasm_import_module = "tortuise")] unsafe extern "C" { pub safe fn add_cell( context: u64, character: u32, location: u32, z: u32, foreground_color: u32, background_color: u32, underline_color: u32, attributes: u32, ); pub safe fn window_size(context: u64) -> u32; } } #[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Serialize, Deserialize)] pub struct Cell { pub character: char, pub foreground_color: Color, pub background_color: Color, pub underline_color: Color, pub attributes: Attributes, pub x: u16, pub y: u16, pub z: u8, } #[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Serialize, Deserialize)] pub struct WindowSize { pub rows: u16, pub columns: u16, } #[derive( Copy, Clone, Debug, Default, PartialEq, Eq, Ord, PartialOrd, Hash, Serialize, Deserialize, )] pub enum Color { /// Resets the terminal color. #[default] Reset, /// Black color. Black, /// Dark grey color. DarkGrey, /// Light red color. Red, /// Dark red color. DarkRed, /// Light green color. Green, /// Dark green color. DarkGreen, /// Light yellow color. Yellow, /// Dark yellow color. DarkYellow, /// Light blue color. Blue, /// Dark blue color. DarkBlue, /// Light magenta color. Magenta, /// Dark magenta color. DarkMagenta, /// Light cyan color. Cyan, /// Dark cyan color. DarkCyan, /// White color. White, /// Grey color. Grey, /// An RGB color. See [RGB color model](https://en.wikipedia.org/wiki/RGB_color_model) for more info. /// /// Most UNIX terminals and Windows 10 supported only. /// See [Platform-specific notes](enum.Color.html#platform-specific-notes) for more info. Rgb { r: u8, g: u8, b: u8 }, /// An ANSI color. See [256 colors - cheat sheet](https://jonasjacek.github.io/colors/) for more info. /// /// Most UNIX terminals and Windows 10 supported only. /// See [Platform-specific notes](enum.Color.html#platform-specific-notes) for more info. AnsiValue(u8), } #[derive( Copy, Clone, Debug, Default, PartialEq, Eq, Ord, PartialOrd, Hash, Serialize, Deserialize, )] pub struct Attributes(u32); pub enum Attribute { /// Increases the text intensity. Bold = 1, /// Decreases the text intensity. Dim = 2, /// Emphasises the text. Italic = 4, /// Underlines the text. Underlined = 8, // Other types of underlining /// Double underlines the text. DoubleUnderlined = 16, /// Undercurls the text. Undercurled = 32, /// Underdots the text. Underdotted = 64, /// Underdashes the text. Underdashed = 128, /// Makes the text blinking (< 150 per minute). SlowBlink = 256, /// Makes the text blinking (>= 150 per minute). RapidBlink = 512, /// Swaps foreground and background colors. Reverse = 1024, /// Hides the text (also known as Conceal). Hidden = 2048, /// Crosses the text. CrossedOut = 4096, /// Sets the [Fraktur](https://en.wikipedia.org/wiki/Fraktur) typeface. /// /// Mostly used for [mathematical alphanumeric symbols](https://en.wikipedia.org/wiki/Mathematical_Alphanumeric_Symbols). Fraktur = 8192, /// Makes the text framed. Framed = 16384, /// Makes the text encircled. Encircled = 32768, /// Draws a line at the top of the text. OverLined = 65536, } fn color_to_u32(color: Color) -> u32 { match color { Color::Reset => 1 << 24, Color::Black => 1 << 24 | 1, Color::DarkGrey => 1 << 24 | 2, Color::Red => 1 << 24 | 3, Color::DarkRed => 1 << 24 | 4, Color::Green => 1 << 24 | 5, Color::DarkGreen => 1 << 24 | 6, Color::Yellow => 1 << 24 | 7, Color::DarkYellow => 1 << 24 | 8, Color::Blue => 1 << 24 | 9, Color::DarkBlue => 1 << 24 | 10, Color::Magenta => 1 << 24 | 11, Color::DarkMagenta => 1 << 24 | 12, Color::Cyan => 1 << 24 | 13, Color::DarkCyan => 1 << 24 | 14, Color::White => 1 << 24 | 15, Color::Grey => 1 << 24 | 16, Color::AnsiValue(num) => 2 << 24 | num as u32, Color::Rgb { r, g, b } => 3 << 24 | ((r as u32) << 16) | ((g as u32) << 8) | (b as u32), } } impl Attributes { pub fn none() -> Self { Self(0) } pub fn with(self, attribute: Attribute) -> Self { Self(self.0 | attribute as u32) } pub fn without(self, attribute: Attribute) -> Self { Self(self.0 & !(attribute as u32)) } pub fn set(&mut self, attribute: Attribute) { self.0 |= attribute as u32; } pub fn unset(&mut self, attribute: Attribute) { self.0 &= !(attribute as u32) } pub fn has(self, attribute: Attribute) -> bool { self.0 & (attribute as u32) != 0 } pub fn extend(&mut self, attributes: Attributes) { self.0 |= attributes.0 } pub fn is_empty(self) -> bool { self.0 == 0 } } impl ScriptContext { pub fn add_cell(&self, cell: Cell) { tortuise::add_cell( self.0, cell.character as u32, (cell.x as u32) << 16 | cell.y as u32, cell.z as u32, color_to_u32(cell.foreground_color), color_to_u32(cell.background_color), color_to_u32(cell.underline_color), cell.attributes.0, ); } pub fn window_size(&self) -> WindowSize { let size = tortuise::window_size(self.0); WindowSize { rows: (size >> 16) as u16, columns: (size & 0xffff) as u16, } } }