Skip to content

Commit

Permalink
update handler
Browse files Browse the repository at this point in the history
  • Loading branch information
raphamorim committed Apr 7, 2023
1 parent d18adab commit c5cd391
Show file tree
Hide file tree
Showing 7 changed files with 173 additions and 57 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,9 +240,11 @@ Basic features are under development for MacOs right now.

| Platform | Development Status |
| --- | --- |
| MacOs | In development 👷 |
| Linux | In development 👷 * |
| Windows | Not started yet |
| MacOs _as desktop application_ | In development 👷 |
| Linux _as desktop application_ | In development 👷 * |
| Windows _as desktop application_ | Not started yet |
| Web Browser _(tests on Chrome and Firefox)_ | Not started yet |
| Nintendo Switch | Not started yet |

_* Development and tests are targeting Wayland, probably is not stable on X11 yet._

Expand Down
6 changes: 6 additions & 0 deletions colors/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ pub type ColorWGPU = wgpu::Color;
pub type ColorArray = [f32; 4];
pub type ColorComposition = (ColorArray, ColorWGPU);

pub struct ColorRgb {
pub r: u8,
pub g: u8,
pub b: u8,
}

#[derive(Debug, Clone, Copy)]
pub enum Format {
SRGB0_255,
Expand Down
61 changes: 33 additions & 28 deletions rio/src/crosswords/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use crate::performer::handler::Handler;
use attr::*;
use bitflags::bitflags;
use colors::AnsiColor;
use colors::{ColorRgb, Colors};
use grid::row::Row;
use pos::CharsetIndex;
use pos::{Column, Cursor, Line, Pos};
Expand Down Expand Up @@ -83,6 +84,7 @@ pub struct Crosswords<U> {
tabs: TabStops,
#[allow(dead_code)]
event_proxy: U,
colors: Colors,
window_title: Option<String>,
damage: TermDamageState,
}
Expand Down Expand Up @@ -280,6 +282,7 @@ impl<U> Crosswords<U> {
active_charset: CharsetIndex::default(),
scroll_region,
event_proxy,
colors: Colors::default(),
window_title: Option::Some(String::from("")),
tabs: TabStops::new(cols),
mode: Mode::SHOW_CURSOR
Expand Down Expand Up @@ -343,11 +346,6 @@ impl<U> Crosswords<U> {
self.damage.resize(num_cols, num_lines);
}

#[inline]
pub fn mode(&self) -> &Mode {
&self.mode
}

#[inline]
pub fn wrapline(&mut self) {
if !self.mode.contains(Mode::LINE_WRAP) {
Expand Down Expand Up @@ -483,15 +481,6 @@ impl<U> Crosswords<U> {
visible_rows
}

pub fn grid(&self) -> &Grid<Square> {
&self.grid
}

/// Mutable access to the raw grid data structure.
pub fn grid_mut(&mut self) -> &mut Grid<Square> {
&mut self.grid
}

pub fn swap_alt(&mut self) {
if !self.mode.contains(Mode::ALT_SCREEN) {
// Set alt screen cursor to the current primary screen cursor.
Expand Down Expand Up @@ -695,21 +684,20 @@ impl<U> Handler for Crosswords<U> {
let end = std::cmp::min(start + count, Column(self.grid.columns()));

// Cleared cells have current background color set.
// let bg = self.grid.cursor.template.bg;
let bg = self.grid.cursor.template.bg;
let line = cursor.pos.row;
self.damage.damage_line(line.0 as usize, start.0, end.0);
let row = &mut self.grid[line];
for cell in &mut row[start..end] {
// *cell = bg.into();
*cell = Square::default();
*cell = bg.into();
}
}

#[inline]
fn delete_chars(&mut self, count: usize) {
let columns = self.grid.columns();
let cursor = &self.grid.cursor;
// let bg = cursor.template.bg;
let bg = cursor.template.bg;

// Ensure deleting within terminal bounds.
let count = std::cmp::min(count, columns);
Expand All @@ -731,8 +719,7 @@ impl<U> Handler for Crosswords<U> {
// 1 cell.
let end = columns - count;
for cell in &mut row[end..] {
// *cell = bg.into();
*cell = Square::default();
*cell = bg.into();
}
}

Expand Down Expand Up @@ -937,7 +924,7 @@ impl<U> Handler for Crosswords<U> {

#[inline]
fn clear_screen(&mut self, mode: ClearMode) {
// let bg = self.grid.cursor.template.bg;
let bg = self.grid.cursor.template.bg;

let screen_lines = self.grid.screen_lines();

Expand All @@ -954,8 +941,7 @@ impl<U> Handler for Crosswords<U> {
// Clear up to the current column in the current line.
let end = std::cmp::min(cursor.col + 1, Column(self.grid.columns()));
for cell in &mut self.grid[cursor.row][..end] {
// *cell = bg.into();
*cell = Square::default();
*cell = bg.into();
}

// let range = Line(0)..=cursor.row;
Expand All @@ -964,8 +950,7 @@ impl<U> Handler for Crosswords<U> {
ClearMode::Below => {
let cursor = self.grid.cursor.pos;
for cell in &mut self.grid[cursor.row][cursor.col..] {
// *cell = bg.into();
*cell = Square::default();
*cell = bg.into();
}

if (cursor.row.0 as usize) < screen_lines - 1 {
Expand Down Expand Up @@ -1028,6 +1013,27 @@ impl<U> Handler for Crosswords<U> {
}
}

/// Set the indexed color value.
// #[inline]
// fn set_color(&mut self, index: usize, color: ColorRgb) {
// // Damage terminal if the color changed and it's not the cursor.
// if index != NamedColor::Cursor as usize && self.colors[index] != Some(color) {
// // self.mark_fully_damaged();
// }

// self.colors[index] = Some(color);
// }

// #[inline]
// fn reset_color(&mut self, index: usize) {
// // Damage terminal if the color changed and it's not the cursor.
// if index != NamedColor::Cursor as usize && self.colors[index].is_some() {
// // self.mark_fully_damaged();
// }

// self.colors[index] = None;
// }

#[inline]
fn bell(&mut self) {
println!("[unimplemented] Bell");
Expand Down Expand Up @@ -1081,7 +1087,7 @@ impl<U> Handler for Crosswords<U> {
#[inline]
fn clear_line(&mut self, mode: u16) {
let cursor = &self.grid.cursor;
let _bg = cursor.template.bg;
let bg = cursor.template.bg;
let pos = &cursor.pos;
let (left, right) = match mode {
// Right
Expand All @@ -1103,8 +1109,7 @@ impl<U> Handler for Crosswords<U> {
let position = pos.row;
let row = &mut self.grid[position];
for square in &mut row[left..right] {
// *square = bg.into();
*square = Square::default();
*square = bg.into();
}
// let range = self.grid.cursor.pos.row..=self.grid.cursor.pos.row;
// self.selection = self.selection.take().filter(|s| !s.intersects_range(range));
Expand Down
10 changes: 10 additions & 0 deletions rio/src/crosswords/square.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,13 @@ impl ResetDiscriminant<AnsiColor> for Square {
self.bg
}
}

impl From<AnsiColor> for Square {
#[inline]
fn from(color: AnsiColor) -> Self {
Self {
bg: color,
..Square::default()
}
}
}
140 changes: 119 additions & 21 deletions rio/src/performer/handler.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::ansi::mode::Mode;
use crate::crosswords::pos::{CharsetIndex, Column, Line, StandardCharset};
use colors::ColorRgb;
use std::time::{Duration, Instant};

use crate::crosswords::attr::Attr;
Expand All @@ -26,6 +27,81 @@ const SYNC_START_ESCAPE_START: [u8; SYNC_ESCAPE_START_LEN] =
const SYNC_END_ESCAPE_START: [u8; SYNC_ESCAPE_START_LEN] =
[b'\x1b', b'P', b'=', b'2', b's'];

fn xparse_color(color: &[u8]) -> Option<ColorRgb> {
if !color.is_empty() && color[0] == b'#' {
parse_legacy_color(&color[1..])
} else if color.len() >= 4 && &color[..4] == b"rgb:" {
parse_rgb_color(&color[4..])
} else {
None
}
}

/// Parse colors in `rgb:r(rrr)/g(ggg)/b(bbb)` format.
fn parse_rgb_color(color: &[u8]) -> Option<ColorRgb> {
let colors = std::str::from_utf8(color)
.ok()?
.split('/')
.collect::<Vec<_>>();

if colors.len() != 3 {
return None;
}

// Scale values instead of filling with `0`s.
let scale = |input: &str| {
if input.len() > 4 {
None
} else {
let max = u32::pow(16, input.len() as u32) - 1;
let value = u32::from_str_radix(input, 16).ok()?;
Some((255 * value / max) as u8)
}
};

Some(ColorRgb {
r: scale(colors[0])?,
g: scale(colors[1])?,
b: scale(colors[2])?,
})
}

/// Parse colors in `#r(rrr)g(ggg)b(bbb)` format.
fn parse_legacy_color(color: &[u8]) -> Option<ColorRgb> {
let item_len = color.len() / 3;

// Truncate/Fill to two byte precision.
let color_from_slice = |slice: &[u8]| {
let col = usize::from_str_radix(std::str::from_utf8(slice).ok()?, 16).ok()? << 4;
Some((col >> (4 * slice.len().saturating_sub(1))) as u8)
};

Some(ColorRgb {
r: color_from_slice(&color[0..item_len])?,
g: color_from_slice(&color[item_len..item_len * 2])?,
b: color_from_slice(&color[item_len * 2..])?,
})
}

fn parse_number(input: &[u8]) -> Option<u8> {
if input.is_empty() {
return None;
}
let mut num: u8 = 0;
for c in input {
let c = *c as char;
if let Some(digit) = c.to_digit(10) {
num = match num.checked_mul(10).and_then(|v| v.checked_add(digit as u8)) {
Some(v) => v,
None => return None,
}
} else {
return None;
}
}
Some(num)
}

pub trait Handler {
/// OSC to set window title.
fn set_title(&mut self, _: Option<String>) {}
Expand Down Expand Up @@ -187,7 +263,7 @@ pub trait Handler {
fn configure_charset(&mut self, _: CharsetIndex, _: StandardCharset) {}

/// Set an indexed color value.
// fn set_color(&mut self, _: usize, _: Rgb) {}
fn set_color(&mut self, _: usize, _: ColorRgb) {}

/// Respond to a color query escape sequence.
fn dynamic_color_sequence(&mut self, _: String, _: usize, _: &str) {}
Expand Down Expand Up @@ -477,7 +553,7 @@ impl<U: Handler> vte::Perform for Performer<'_, U> {
fn osc_dispatch(&mut self, params: &[&[u8]], bell_terminated: bool) {
println!("[osc_dispatch] params={params:?} bell_terminated={bell_terminated}");

let _terminator = if bell_terminated { "\x07" } else { "\x1b\\" };
let terminator = if bell_terminated { "\x07" } else { "\x1b\\" };

fn unhandled(params: &[&[u8]]) {
let mut buf = String::new();
Expand Down Expand Up @@ -516,27 +592,31 @@ impl<U: Handler> vte::Perform for Performer<'_, U> {
b"4" => {
if params.len() <= 1 || params.len() % 2 == 0 {
unhandled(params);
// return;
return;
}

// for chunk in params[1..].chunks(2) {
// let index = match parse_number(chunk[0]) {
// Some(index) => index,
// None => {
// unhandled(params);
// continue;
// },
// };

// if let Some(c) = xparse_color(chunk[1]) {
// self.handler.set_color(index as usize, c);
// } else if chunk[1] == b"?" {
// let prefix = format!("4;{index}");
// self.handler.dynamic_color_sequence(prefix, index as usize, terminator);
// } else {
// unhandled(params);
// }
// }
for chunk in params[1..].chunks(2) {
let index = match parse_number(chunk[0]) {
Some(index) => index,
None => {
unhandled(params);
continue;
}
};

if let Some(c) = xparse_color(chunk[1]) {
self.handler.set_color(index as usize, c);
} else if chunk[1] == b"?" {
let prefix = format!("4;{index}");
self.handler.dynamic_color_sequence(
prefix,
index as usize,
terminator,
);
} else {
unhandled(params);
}
}
}

b"10" | b"11" | b"12" => {
Expand Down Expand Up @@ -572,6 +652,24 @@ impl<U: Handler> vte::Perform for Performer<'_, U> {
unhandled(params);
}

b"104" => {
// Reset all color indexes when no parameters are given.
if params.len() == 1 || params[1].is_empty() {
for i in 0..256 {
self.handler.reset_color(i);
}
return;
}

// Reset color indexes given as parameters.
for param in &params[1..] {
match parse_number(param) {
Some(index) => self.handler.reset_color(index as usize),
None => unhandled(params),
}
}
}

// Reset foreground color.
b"110" => self.handler.reset_color(NamedColor::Foreground as usize),

Expand Down
3 changes: 0 additions & 3 deletions rio/src/renderer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,6 @@ impl Renderer {
let square = &row.inner[column];
let text = self.process_row(square, style);
row_text.push(text);
// for c in square.zerowidth().into_iter().flatten() {
// text.push(*c);
// }

// Render last column and break row
if column == (columns - 1) {
Expand Down

0 comments on commit c5cd391

Please sign in to comment.