mirror of
https://github.com/wez/wezterm.git
synced 2024-12-23 13:21:38 +03:00
tighten up SGR parsing
Track all the rendition bits described in the SGR section here: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html Still need to hook up color matching against the color palette as described for the 256 color mode flavor.
This commit is contained in:
parent
3ec0b3f795
commit
b56209a181
221
src/term/mod.rs
221
src/term/mod.rs
@ -51,18 +51,52 @@ macro_rules! bitfield {
|
|||||||
self.attributes = (self.attributes & clear) | attr_value;
|
self.attributes = (self.attributes & clear) | attr_value;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
($getter:ident, $setter:ident, $enum:ident, $bitmask:expr, $bitshift:expr) => {
|
||||||
|
#[inline]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn $getter(&self) -> $enum {
|
||||||
|
unsafe { std::mem::transmute(((self.attributes >> $bitshift) & $bitmask) as u16)}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn $setter(&mut self, value: $enum) {
|
||||||
|
let value = value as u16;
|
||||||
|
let clear = !($bitmask << $bitshift);
|
||||||
|
let attr_value = (value & $bitmask) << $bitshift;
|
||||||
|
self.attributes = (self.attributes & clear) | attr_value;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
#[repr(u16)]
|
||||||
|
pub enum Intensity {
|
||||||
|
Normal = 0,
|
||||||
|
Bold = 1,
|
||||||
|
Half = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
#[repr(u16)]
|
||||||
|
pub enum Underline {
|
||||||
|
None = 0,
|
||||||
|
Single = 1,
|
||||||
|
Double = 2,
|
||||||
|
}
|
||||||
|
|
||||||
impl CellAttributes {
|
impl CellAttributes {
|
||||||
bitfield!(bold, set_bold, 0);
|
bitfield!(intensity, set_intensity, Intensity, 0b11, 0);
|
||||||
bitfield!(underline, set_underline, 1);
|
bitfield!(underline, set_underline, Underline, 0b1100, 2);
|
||||||
bitfield!(italic, set_italic, 2);
|
bitfield!(italic, set_italic, 4);
|
||||||
bitfield!(blink, set_blink, 3);
|
bitfield!(blink, set_blink, 5);
|
||||||
bitfield!(reverse, set_reverse, 4);
|
bitfield!(reverse, set_reverse, 6);
|
||||||
bitfield!(strikethrough, set_strikethrough, 5);
|
bitfield!(strikethrough, set_strikethrough, 7);
|
||||||
|
bitfield!(halfbright, set_halfbright, 8);
|
||||||
|
bitfield!(invisible, set_invisible, 9);
|
||||||
// Allow up to 8 different font values
|
// Allow up to 8 different font values
|
||||||
bitfield!(font, set_font, 0b111000000, 6);
|
//bitfield!(font, set_font, 0b111000000, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for CellAttributes {
|
impl Default for CellAttributes {
|
||||||
@ -335,6 +369,115 @@ impl Terminal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum CSIAction {
|
||||||
|
SetPen(CellAttributes),
|
||||||
|
SetForegroundColor(color::ColorAttribute),
|
||||||
|
SetBackgroundColor(color::ColorAttribute),
|
||||||
|
SetIntensity(Intensity),
|
||||||
|
SetUnderline(Underline),
|
||||||
|
SetItalic(bool),
|
||||||
|
SetBlink(bool),
|
||||||
|
SetReverse(bool),
|
||||||
|
SetStrikethrough(bool),
|
||||||
|
SetInvisible(bool),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CSIAction {
|
||||||
|
/// Parses out a "Set Graphics Rendition" action.
|
||||||
|
/// Returns the decoded action plus the unparsed remainder of the
|
||||||
|
/// parameter stream. Returns None if we couldn't decode one of
|
||||||
|
/// the parameter elements.
|
||||||
|
fn parse_sgr(params: &[i64]) -> Option<(CSIAction, &[i64])> {
|
||||||
|
if params.len() > 2 {
|
||||||
|
// Some special look-ahead cases for 88 and 256 color support
|
||||||
|
if params[0] == 38 && params[1] == 5 {
|
||||||
|
// 38;5;IDX -> foreground color
|
||||||
|
let color = color::ColorAttribute::PaletteIndex(params[2] as u8);
|
||||||
|
return Some((CSIAction::SetForegroundColor(color), ¶ms[3..]));
|
||||||
|
}
|
||||||
|
|
||||||
|
if params[0] == 48 && params[1] == 5 {
|
||||||
|
// 48;5;IDX -> background color
|
||||||
|
let color = color::ColorAttribute::PaletteIndex(params[2] as u8);
|
||||||
|
return Some((CSIAction::SetBackgroundColor(color), ¶ms[3..]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let p = params[0];
|
||||||
|
match p {
|
||||||
|
0 => Some((CSIAction::SetPen(CellAttributes::default()), ¶ms[1..])),
|
||||||
|
1 => Some((CSIAction::SetIntensity(Intensity::Bold), ¶ms[1..])),
|
||||||
|
2 => Some((CSIAction::SetIntensity(Intensity::Half), ¶ms[1..])),
|
||||||
|
3 => Some((CSIAction::SetItalic(true), ¶ms[1..])),
|
||||||
|
4 => Some((CSIAction::SetUnderline(Underline::Single), ¶ms[1..])),
|
||||||
|
5 => Some((CSIAction::SetBlink(true), ¶ms[1..])),
|
||||||
|
7 => Some((CSIAction::SetReverse(true), ¶ms[1..])),
|
||||||
|
8 => Some((CSIAction::SetInvisible(true), ¶ms[1..])),
|
||||||
|
9 => Some((CSIAction::SetStrikethrough(true), ¶ms[1..])),
|
||||||
|
21 => Some((CSIAction::SetUnderline(Underline::Double), ¶ms[1..])),
|
||||||
|
22 => Some((CSIAction::SetIntensity(Intensity::Normal), ¶ms[1..])),
|
||||||
|
23 => Some((CSIAction::SetItalic(false), ¶ms[1..])),
|
||||||
|
24 => Some((CSIAction::SetUnderline(Underline::None), ¶ms[1..])),
|
||||||
|
25 => Some((CSIAction::SetBlink(false), ¶ms[1..])),
|
||||||
|
27 => Some((CSIAction::SetReverse(false), ¶ms[1..])),
|
||||||
|
28 => Some((CSIAction::SetInvisible(false), ¶ms[1..])),
|
||||||
|
29 => Some((CSIAction::SetStrikethrough(false), ¶ms[1..])),
|
||||||
|
30...37 => {
|
||||||
|
Some((
|
||||||
|
CSIAction::SetForegroundColor(
|
||||||
|
color::ColorAttribute::PaletteIndex(p as u8 - 30),
|
||||||
|
),
|
||||||
|
¶ms[1..],
|
||||||
|
))
|
||||||
|
}
|
||||||
|
39 => {
|
||||||
|
Some((
|
||||||
|
CSIAction::SetForegroundColor(
|
||||||
|
color::ColorAttribute::Foreground,
|
||||||
|
),
|
||||||
|
¶ms[1..],
|
||||||
|
))
|
||||||
|
}
|
||||||
|
90...97 => {
|
||||||
|
// Bright foreground colors
|
||||||
|
Some((
|
||||||
|
CSIAction::SetForegroundColor(
|
||||||
|
color::ColorAttribute::PaletteIndex(p as u8 - 90 + 8),
|
||||||
|
),
|
||||||
|
¶ms[1..],
|
||||||
|
))
|
||||||
|
}
|
||||||
|
40...47 => {
|
||||||
|
Some((
|
||||||
|
CSIAction::SetBackgroundColor(
|
||||||
|
color::ColorAttribute::PaletteIndex(p as u8 - 40),
|
||||||
|
),
|
||||||
|
¶ms[1..],
|
||||||
|
))
|
||||||
|
}
|
||||||
|
49 => {
|
||||||
|
Some((
|
||||||
|
CSIAction::SetBackgroundColor(
|
||||||
|
color::ColorAttribute::Background,
|
||||||
|
),
|
||||||
|
¶ms[1..],
|
||||||
|
))
|
||||||
|
}
|
||||||
|
100...107 => {
|
||||||
|
// Bright background colors
|
||||||
|
Some((
|
||||||
|
CSIAction::SetBackgroundColor(
|
||||||
|
color::ColorAttribute::PaletteIndex(p as u8 - 100 + 8),
|
||||||
|
),
|
||||||
|
¶ms[1..],
|
||||||
|
))
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
impl vte::Perform for TerminalState {
|
impl vte::Perform for TerminalState {
|
||||||
/// Draw a character to the screen
|
/// Draw a character to the screen
|
||||||
fn print(&mut self, c: char) {
|
fn print(&mut self, c: char) {
|
||||||
@ -373,37 +516,53 @@ impl vte::Perform for TerminalState {
|
|||||||
);
|
);
|
||||||
match byte {
|
match byte {
|
||||||
'm' => {
|
'm' => {
|
||||||
// Set Graphic Rendition
|
let mut params = params;
|
||||||
for p in params {
|
while params.len() > 0 {
|
||||||
match p {
|
match CSIAction::parse_sgr(params) {
|
||||||
&0 => {
|
Some((CSIAction::SetPen(pen), remainder)) => {
|
||||||
self.pen = CellAttributes::default();
|
self.pen = pen;
|
||||||
|
params = remainder;
|
||||||
}
|
}
|
||||||
&30...37 => {
|
Some((CSIAction::SetForegroundColor(color), remainder)) => {
|
||||||
self.pen.foreground =
|
self.pen.foreground = color;
|
||||||
color::ColorAttribute::PaletteIndex(*p as u8 - 30);
|
params = remainder;
|
||||||
}
|
}
|
||||||
&39 => {
|
Some((CSIAction::SetBackgroundColor(color), remainder)) => {
|
||||||
self.pen.foreground = color::ColorAttribute::Foreground;
|
self.pen.background = color;
|
||||||
|
params = remainder;
|
||||||
}
|
}
|
||||||
&90...97 => {
|
Some((CSIAction::SetIntensity(level), remainder)) => {
|
||||||
// Bright foreground colors
|
self.pen.set_intensity(level);
|
||||||
self.pen.foreground =
|
params = remainder;
|
||||||
color::ColorAttribute::PaletteIndex(*p as u8 - 90 + 8);
|
|
||||||
}
|
}
|
||||||
&40...47 => {
|
Some((CSIAction::SetUnderline(level), remainder)) => {
|
||||||
self.pen.background =
|
self.pen.set_underline(level);
|
||||||
color::ColorAttribute::PaletteIndex(*p as u8 - 40);
|
params = remainder;
|
||||||
}
|
}
|
||||||
&49 => {
|
Some((CSIAction::SetItalic(on), remainder)) => {
|
||||||
self.pen.background = color::ColorAttribute::Foreground;
|
self.pen.set_italic(on);
|
||||||
|
params = remainder;
|
||||||
}
|
}
|
||||||
&100...107 => {
|
Some((CSIAction::SetBlink(on), remainder)) => {
|
||||||
// Bright background colors
|
self.pen.set_blink(on);
|
||||||
self.pen.background =
|
params = remainder;
|
||||||
color::ColorAttribute::PaletteIndex(*p as u8 - 100 + 8);
|
}
|
||||||
|
Some((CSIAction::SetReverse(on), remainder)) => {
|
||||||
|
self.pen.set_reverse(on);
|
||||||
|
params = remainder;
|
||||||
|
}
|
||||||
|
Some((CSIAction::SetStrikethrough(on), remainder)) => {
|
||||||
|
self.pen.set_strikethrough(on);
|
||||||
|
params = remainder;
|
||||||
|
}
|
||||||
|
Some((CSIAction::SetInvisible(on), remainder)) => {
|
||||||
|
self.pen.set_invisible(on);
|
||||||
|
params = remainder;
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
println!("parse_sgr: unhandled sequence {:?}", params);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user