diff options
author | Richard Palethorpe <richiejp@f-m.fm> | 2017-01-09 21:07:23 +0100 |
---|---|---|
committer | Joe Wilm <jwilm@users.noreply.github.com> | 2017-01-21 12:09:21 -0800 |
commit | 62294771905917087c484bfc57e4f6ca547d89ba (patch) | |
tree | d2c11cb7cb9e011969489b9802f5472b1f65ccd2 /src/ansi.rs | |
parent | 6d0abe26077d7ca04119b241678ea9ede9f4fe4d (diff) | |
download | alacritty-62294771905917087c484bfc57e4f6ca547d89ba.tar.gz alacritty-62294771905917087c484bfc57e4f6ca547d89ba.zip |
ansi: Designate and invoke graphic character sets
Implement the designation of graphic character sets G0-G3 to ASCII or the
Special character and line drawing glyphs. As well as the invokation/selection
of the character sets (shift in, shift out and lock shifting).
Diffstat (limited to 'src/ansi.rs')
-rw-r--r-- | src/ansi.rs | 122 |
1 files changed, 119 insertions, 3 deletions
diff --git a/src/ansi.rs b/src/ansi.rs index 81a48987..4f45fd62 100644 --- a/src/ansi.rs +++ b/src/ansi.rs @@ -238,6 +238,18 @@ pub trait Handler { /// DECKPNM - Set keypad to numeric mode (digits intead of ESCape seq) fn unset_keypad_application_mode(&mut self) {} + + /// Set one of the graphic character sets, G0 to G3, as the active charset. + /// + /// 'Invoke' one of G0 to G3 in the GL area. Also refered to as shift in, + /// shift out and locking shift depending on the set being activated + fn set_active_charset(&mut self, CharsetIndex) {} + + /// Assign a graphic character set to G0, G1, G2 or G3 + /// + /// 'Designate' a graphic character set as one of G0 to G3, so that it can + /// later be 'invoked' by `set_active_charset` + fn configure_charset(&mut self, CharsetIndex, StandardCharset) {} } /// Terminal modes @@ -436,6 +448,23 @@ pub enum Attr { Background(Color), } +/// Identifiers which can be assigned to a graphic character set +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum CharsetIndex { + /// Default set, is designated as ASCII at startup + G0, + G1, + G2, + G3, +} + +/// Standard or common character sets which can be designated as G0-G3 +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum StandardCharset { + Ascii, + SpecialCharacterAndLineDrawing, +} + impl<'a, H, W> vte::Perform for Performer<'a, H, W> where H: Handler + TermInfo + 'a, W: io::Write + 'a @@ -454,6 +483,8 @@ impl<'a, H, W> vte::Perform for Performer<'a, H, W> C0::LF | C0::VT | C0::FF => self.handler.linefeed(), C0::BEL => self.handler.bell(), C0::SUB => self.handler.substitute(), + C0::SI => self.handler.set_active_charset(CharsetIndex::G0), + C0::SO => self.handler.set_active_charset(CharsetIndex::G1), C1::NEL => self.handler.newline(), C1::HTS => self.handler.set_horizontal_tabstop(), C1::DECID => self.handler.identify_terminal(self.writer), @@ -742,19 +773,41 @@ impl<'a, H, W> vte::Perform for Performer<'a, H, W> _ignore: bool, byte: u8 ) { + macro_rules! unhandled { + () => {{ + err_println!("[unhandled] esc_dispatch params={:?}, ints={:?}, byte={:?} ({:02x})", + params, intermediates, byte as char, byte); + return; + }} + } + + macro_rules! configure_charset { + ($charset:path) => {{ + let index: CharsetIndex = match intermediates.first().cloned() { + Some(b'(') => CharsetIndex::G0, + Some(b')') => CharsetIndex::G1, + Some(b'*') => CharsetIndex::G2, + Some(b'+') => CharsetIndex::G3, + _ => unhandled!(), + }; + self.handler.configure_charset(index, $charset) + }} + } + match byte { + b'B' => configure_charset!(StandardCharset::Ascii), b'D' => self.handler.linefeed(), b'E' => self.handler.newline(), b'H' => self.handler.set_horizontal_tabstop(), b'M' => self.handler.reverse_index(), b'Z' => self.handler.identify_terminal(self.writer), b'c' => self.handler.reset_state(), + b'0' => configure_charset!(StandardCharset::SpecialCharacterAndLineDrawing), b'7' => self.handler.save_cursor_position(), b'8' => self.handler.restore_cursor_position(), b'=' => self.handler.set_keypad_application_mode(), b'>' => self.handler.unset_keypad_application_mode(), - _ => err_println!("[unhandled] esc_dispatch params={:?}, ints={:?}, byte={:?} ({:02x})", - params, intermediates, byte as char, byte), + _ => unhandled!(), } } } @@ -969,7 +1022,7 @@ pub mod C1 { mod tests { use std::io; use index::{Line, Column}; - use super::{Processor, Handler, Attr, TermInfo, Color}; + use super::{Processor, Handler, Attr, TermInfo, Color, StandardCharset, CharsetIndex}; use ::Rgb; /// The /dev/null of io::Write @@ -1074,4 +1127,67 @@ mod tests { parser.advance(&mut handler, *byte, &mut Void); } } + + struct CharsetHandler { + index: CharsetIndex, + charset: StandardCharset, + } + + impl Default for CharsetHandler { + fn default() -> CharsetHandler { + CharsetHandler { + index: CharsetIndex::G0, + charset: StandardCharset::Ascii, + } + } + } + + impl Handler for CharsetHandler { + fn configure_charset(&mut self, index: CharsetIndex, charset: StandardCharset) { + self.index = index; + self.charset = charset; + } + + fn set_active_charset(&mut self, index: CharsetIndex) { + self.index = index; + } + } + + impl TermInfo for CharsetHandler { + fn lines(&self) -> Line { Line(200) } + fn cols(&self) -> Column { Column(90) } + } + + #[test] + fn parse_designate_g0_as_line_drawing() { + static BYTES: &'static [u8] = &[0x1b, b'(', b'0']; + let mut parser = Processor::new(); + let mut handler = CharsetHandler::default(); + + for byte in &BYTES[..] { + parser.advance(&mut handler, *byte, &mut Void); + } + + assert_eq!(handler.index, CharsetIndex::G0); + assert_eq!(handler.charset, StandardCharset::SpecialCharacterAndLineDrawing); + } + + #[test] + fn parse_designate_g1_as_line_drawing_and_invoke() { + static BYTES: &'static [u8] = &[0x1b, 0x29, 0x30, 0x0e]; + let mut parser = Processor::new(); + let mut handler = CharsetHandler::default(); + + for byte in &BYTES[..3] { + parser.advance(&mut handler, *byte, &mut Void); + } + + assert_eq!(handler.index, CharsetIndex::G1); + assert_eq!(handler.charset, StandardCharset::SpecialCharacterAndLineDrawing); + + let mut handler = CharsetHandler::default(); + parser.advance(&mut handler, BYTES[3], &mut Void); + + assert_eq!(handler.index, CharsetIndex::G1); + } } |