diff options
Diffstat (limited to 'src/buffer.rs')
| -rw-r--r-- | src/buffer.rs | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/src/buffer.rs b/src/buffer.rs new file mode 100644 index 0000000..78b6bd5 --- /dev/null +++ b/src/buffer.rs @@ -0,0 +1,235 @@ +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, + } + } +} |
