#pragma once #include #include #include namespace neovision { namespace ansi { /** * @brief Ansi escape sequence parser. * * Basically acts as a state machine for parsing ansi escape sequences. */ class AnsiParser { public: enum class ParseState{ None, Control, Escape, Csi, Cssi, Sgr, Pm, Error }; private: ParseState m_state{ParseState::None}; std::vector m_csiParameters; std::wstring m_processedChars; std::wstring m_csiParameterBuffer; std::wstring m_controlPortion; std::wstring m_escapePortion; std::wstring m_csiPortion; std::wstring m_cssiPortion; std::wstring m_parameterBuffer; std::wstring m_pmPortion; void ParseNoneState(wchar_t c); void ParseControlState(wchar_t c); void ParseEscapeState(wchar_t c); void ParseCsiState(wchar_t c); public: /** * @brief Get control characters. * * @return Returns the control characters parsed so far. */ std::wstring ControlPortion() const; /** * @brief Get CSI parameters. * * @return Returns an array of all parsed CSI parameters. */ std::vector CsiParameters() const; /** * @brief Get CSI characters. * * @return Returns the CSI characters parsed so far. */ std::wstring CsiPortion() const; /** * @brief Get CSSI characters. * * @return Returns the CSSI characters parsed so far. */ std::wstring CssiPortion() const; /** * @brief Get Escape characters. * * @return Returns the escape characters parsed so far. */ std::wstring EscapePortion() const; /** * @brief Parse a character. * * @param c character to parse. * @return Returns true if parsing should continue. */ bool Parse(wchar_t c); /** * @brief Get PM characters. * * @return Returns the DEC private-mode characters parsed so far. */ std::wstring PmPortion() const; /** * @brief Get all processed characters. * * @return Returns all the characters processed since parsing began. */ std::wstring ProcessedCharacters() const; /** * @brief Resets parser. */ void Reset(); /** * @brief Get SGR characters. * * @return Returns the SGR characters parsed so far. */ std::wstring SgrPortion() const; /** * @brief Get Parse state. * * At end of parsing, call this to see if a sequence was successfully * parsed. The state will be None on success or Error on failure. * * @return Returns the parser's state. */ ParseState State() const; }; /** * @brief Represents the terminal basic control characters. */ struct ControlCharacter { /** * @brief Bell. * * Makes an audible noise. */ static constexpr const wchar_t BEL[]{L"\x07"}; /** * @brief Backspace. * * Moves the cursor left (may wrap if cursor is at start of line). */ static constexpr const wchar_t BS[]{L"\x08"}; /** * @brief Horizontal tab. * * Moves the cursor right to next multiple of 8. */ static constexpr const wchar_t HT[]{L"\x09"}; /** * @brief Line feed. * * Moves to the next line, scrolls the display up if at bottom of screen. * Usually does not move horizonally (but can). */ static constexpr const wchar_t LF[]{L"\x0a"}; /** * @brief Form feed. * * Move a printer to top of next page. Usually does not move horizontally * (but can). Effect on video terminals varies. (in most modern terminals * this moves 2 lines down) */ static constexpr const wchar_t FF[]{L"\x0c"}; /** * @brief Carriage return. * * Moves the cursor to column zero. */ static constexpr const wchar_t CR[]{L"\x0d"}; /** * @brief Activate G1 character set. */ static constexpr const wchar_t SO[]{L"\x0e"}; /** * @brief Activate G0 character set. */ static constexpr const wchar_t SI[]{L"\x0f"}; /** * @brief Cancel. * * Abort sequence. */ static constexpr const wchar_t CAN[]{L"\x18"}; /** * @brief Sustitute. * * Abort sequence. */ static constexpr const wchar_t SUB[]{L"\x1a"}; /** * @brief Escape. * * Starts all the escape sequences. */ static constexpr const wchar_t ESC[]{L"\x1b"}; /** * @brief Delete * * (ignored) */ static constexpr const wchar_t DEL[]{L"\x7f"}; /** * @brief CSI * * Equivalent to ESC [ in theory. In practice, most terminals don't seem to * recognize this. * * See the CsiSequence struct. */ static constexpr const wchar_t CSI[]{L"\x9b"}; }; /** * @brief Set of all possible control characters. */ static std::unordered_set const ControlCharacters { ControlCharacter::BEL, ControlCharacter::BS, ControlCharacter::CAN, ControlCharacter::CR, ControlCharacter::CSI, ControlCharacter::DEL, ControlCharacter::ESC, ControlCharacter::FF, ControlCharacter::HT, ControlCharacter::LF, ControlCharacter::SI, ControlCharacter::SO, ControlCharacter::SUB }; /** * @brief Basic escape sequences. * * Includes other sequence start markers, but excludes * the sequence codes themselves (which are defined below * separately, eg in the CsiSequences struct). * * Includes some Fs and Fp sequences defined in ECMA-35 and * ECMA-48. * * Expects a ControlCharacter::ESC prefix. * */ struct EscapeSequence { /** * @brief Reset. * * Clears the screen. */ static constexpr const wchar_t RIS[]{L"c"}; /** * @brief Line feed. */ static constexpr const wchar_t IND[]{L"D"}; /** * @brief Newline. */ static constexpr const wchar_t NEL[]{L"E"}; /** * @brief Horizontal tab set. * * Sets tab-stop at current column. */ static constexpr const wchar_t HTS[]{L"H"}; /** * @brief Reverse linefeed. * * Goes back to the end of the previous line. */ static constexpr const wchar_t RI[]{L"M"}; /** * @brief DEC private identification. * * On linux the kernel returns the string * ESC [ ? 6 c, claiming that it is a VT102. */ static constexpr const wchar_t DECID[]{L"Z"}; /** * @brief Save state. * * This should save cursor coords, attrs, charset (G0/G1). */ static constexpr const wchar_t DECSC[]{L"7"}; /** * @brief Restore state. * * Restores what was most recently saved by DECSC */ static constexpr const wchar_t DECRC[]{L"8"}; /** * @brief Control sequence introducer. * * Marks the start of a CSI sequence. * * See the CsiSequence struct for followup characters. */ static constexpr const wchar_t CSI[]{L"["}; /** * @brief Character set sequence introducer. * * Starts sequence selecting character set. * See the CssiSequence struct for followup characters. */ static constexpr const wchar_t CSSI[]{L"%"}; /** * @brief DEC screen alignment test. * * Fills the entire screen with E's. */ static constexpr const wchar_t DECALN[]{L"#8"}; /** * @brief DEC set G0 * * Start sequence defining G0 character set. */ static constexpr const wchar_t DECSG0[]{L"("}; /** * @brief DEC set G1 * * Start sequence defining G1 character set. */ static constexpr const wchar_t DECSG1[]{L")}"}; /** * @brief DEC numeric mode. * * Sets numeric keypad mode. */ static constexpr const wchar_t DECNM[]{L">"}; /** * @brief Dec application mode. * * Sets application keypad mode. */ static constexpr const wchar_t DECAM[]{L"="}; /** * @brief Operating system command. * * Starts an OS command sequence. In reality, various * terminal-specific features are implemented with this, * such as setting the terminal window title, injecting * hyperlinks, etc,... * * Since these vary greatly depending on what terminal is * in use, there's no struct in this header defining the * possible control sequences. Instead there's functions * you can call that implement terminal-specific features. * */ static constexpr const wchar_t OSC[]{L"]"}; }; /** * @brief Set of all possible escape sequences. */ static std::unordered_set const EscapeSequences { EscapeSequence::CSI, EscapeSequence::CSSI, EscapeSequence::DECALN, EscapeSequence::DECAM, EscapeSequence::DECID, EscapeSequence::DECNM, EscapeSequence::DECRC, EscapeSequence::DECSC, EscapeSequence::DECSG0, EscapeSequence::DECSG1, EscapeSequence::HTS, EscapeSequence::IND, EscapeSequence::NEL, EscapeSequence::OSC, EscapeSequence::RI, EscapeSequence::RIS }; /** * @brief Sequences selecting character set. * * Assumes a ControlCharacter::ESC and a EscapeSequence::CSSI prefix. */ struct CssiSequence { /** * @brief Select default character set. * * eg: ISO 646 / 8859-1 */ static constexpr const wchar_t DEFAULT[]{L"@"}; /** * @brief Select UTF-8 character set. */ static constexpr const wchar_t UTF8[]{L"G"}; /** * @brief Select UTF-8 character set (obsolete). */ static constexpr const wchar_t UTF8_OBSOLETE[]{L"8"}; }; /** * @brief Set of all possible CSSI sequences. */ static std::unordered_set const CssiSequences { CssiSequence::DEFAULT, CssiSequence::UTF8, CssiSequence::UTF8_OBSOLETE }; /** * @brief CSI sequences. * * Assumes a ControlCharacter::ESC and EscapeSequence::CSI prefix. */ struct CsiSequence { /** * @brief Insert character. * * Inserts n blank characters. * ( doesn't seem to work in most terminals, vt100.net states * this only works in VT level 4 mode only ) */ static constexpr const wchar_t ICH[]{L"@"}; /** * @brief Cursor up. * * Moves cursor up the indicated # of rows. */ static constexpr const wchar_t CUU[]{L"A"}; /** * @brief Cursor down. * * Moves cursor down the indicated # of rows. */ static constexpr const wchar_t CUD[]{L"B"}; /** * @brief Cursor forward. * * Moves cursor right indicated # of columns. */ static constexpr const wchar_t CUF[]{L"C"}; /** * @brief Cursor backwards. * * Moves cursor left indicated # of columns. */ static constexpr const wchar_t CUB[]{L"D"}; /** * @brief Cursor next line(s). * * Moves cursor down indicated # of rows, to column 1. */ static constexpr const wchar_t CNL[]{L"E"}; /** * @brief Cursor previous line(s). * * Moves cursor up indicated # of rows, to column 1. */ static constexpr const wchar_t CPL[]{L"F"}; /** * @brief Move cursor to column. * * Moves cursor to indicated column in current row. */ static constexpr const wchar_t CHA[]{L"G"}; /** * @brief Move cursor to row+column. * * Moves cursor to indicated row and column (origin at 1,1) */ static constexpr const wchar_t CUP[]{L"H"}; /** * @brief Erase display. * * Erases from cursor to end of display by default. * 1 erases from start to cursor. * 2 erases whole display. * 3 erases whole display including scrollback. * * urxvt: no support * konsole, xterm: 1 and 2 work */ static constexpr const wchar_t ED[]{L"J"}; /** * @brief Erase line(s). * * Erases from cursor to end of line by default. * 1: Erase from start of line to cursor. * 2: Erase whole line */ static constexpr const wchar_t EL[]{L"K"}; /** * @brief Insert line(s). * * Inserts the indicated # of blank lines. */ static constexpr const wchar_t IL[]{L""}; /** * @brief Delete line(s). * * Delete the indicated # of lines. */ static constexpr const wchar_t DL[]{L"M"}; /** * @brief Delete characters. * * Delete the indicated # of characters on current line. */ static constexpr const wchar_t DCH[]{L"P"}; /** * @brief Scroll up. * * Scroll whole page up by # lines. */ static constexpr const wchar_t SU[]{L"S"}; /** * @brief Scroll down. * * Scroll whole page down by # lines. */ static constexpr const wchar_t SD[]{L"T"}; /** * @brief Erase characters. * * Erase the indicated # of characters on current line. */ static constexpr const wchar_t ECH[]{L"X"}; /** * @brief Move cursor right. * * Moves cursor right the indicated # of columns. */ static constexpr const wchar_t HPR[]{L"a"}; /** * @brief VT identification * * Makes ther terminal send it's device attributes. * Basically the same as DECID, but this one is preferred. */ static constexpr const wchar_t DA[]{L"c"}; /** * @brief Move cursor to line. * * Move cursor to the indicated row, current column. */ static constexpr const wchar_t VPA[]{L"d"}; /** * @brief Cursor down. * * Move cursor down the indicated # of rows. */ static constexpr const wchar_t VPR[]{L"e"}; /** * @brief Move cursor. * * Move cursor to indicated row, column. */ static constexpr const wchar_t HVP[]{L"f"}; /** * @brief Tab clear. * * Default: clear tab stop at current position. * 3: Delete all tab stops. */ static constexpr const wchar_t TBC[]{L"g"}; /** * @brief Set mode. * * 3: DECCRM - display control characters. * 4: DECIM - insert mode. * 20: LF/NL - folow any LF/VT/FF with CR. */ static constexpr const wchar_t SM[]{L"h"}; /** * @brief Reset mode. */ static constexpr const wchar_t RM[]{L"l"}; /** * @brief End SGR sequence. * * See the SgrSequence struct for characters that should come before this. */ static constexpr const wchar_t SGR[]{L"m"}; /** * @brief Status report. * * 5: DSR (device status report) - answer: esc[0n * 6: CPR (cursor position report) - answer: esc[y;xR */ static constexpr const wchar_t DSR[]{L"n"}; /** * @brief Set keyboard LEDs. * * 0: clear all. * 1: set scroll lock. * 2: set num lock. * 3: set caps lock. * * Doesn't seem to be supported by most terminal emulators. */ static constexpr const wchar_t DECLL[]{L"q"}; /** * @brief Set scrolling region. * * parameters top;bottom rows. */ static constexpr const wchar_t DECSTBM[]{L"r"}; /** * @brief Save cursor location. */ static constexpr const wchar_t SCL[]{L"s"}; /** * @brief Restore cursor location. */ static constexpr const wchar_t RCL[]{L"u"}; /** * @brief Move to column. * * Moves cursor to indicated column in current row. */ static constexpr const wchar_t HPA[]{L"`"}; /** * @brief Start DEC private mode sequence. * * See the DecPmSequence struct. */ static constexpr const wchar_t DECPM[]{L"?"}; }; /** * @brief Set of all possible CSI sequences. */ static std::unordered_set const CsiSequences { CsiSequence::CHA, CsiSequence::CNL, CsiSequence::CPL, CsiSequence::CUB, CsiSequence::CUD, CsiSequence::CUF, CsiSequence::CUP, CsiSequence::CUU, CsiSequence::DA, CsiSequence::DCH, CsiSequence::DECLL, CsiSequence::DECPM, CsiSequence::DECSTBM, CsiSequence::DL, CsiSequence::DSR, CsiSequence::ECH, CsiSequence::ED, CsiSequence::EL, CsiSequence::HPA, CsiSequence::HPR, CsiSequence::HVP, CsiSequence::ICH, CsiSequence::IL, CsiSequence::RCL, CsiSequence::RM, CsiSequence::SCL, CsiSequence::SD, CsiSequence::SGR, CsiSequence::SM, CsiSequence::SU, CsiSequence::TBC, CsiSequence::VPA, CsiSequence::VPR }; /** * @brief Suffix for dec private mode commands. * * These are the required suffixes for the commands listed in * the DecPmSequence class. */ struct DecPmSuffix { /** * @brief Enable DEC private mode option. * * "h" for "high". */ static constexpr const wchar_t ENABLE[]{L"h"}; /** * @brief Disable DEC private mode option. * * "l" for "low". */ static constexpr const wchar_t DISABLE[]{L"l"}; }; /** * @brief Set of all possible DEC PM suffixes. */ static std::unordered_set const DecPmSuffixes{ DecPmSuffix::ENABLE, DecPmSuffix::DISABLE }; /** * @brief Dec private mode (DECSET/DECRST) sequences. * * Assumes ControlCharacter::ESC + ControlCharacter::CSI + CsiSequence::DECPM * prefix * * @note Excludes the mouse reporting modes, while they are technically DecPM * sequences, they are described in the MouseTrackMode and MouseExtCoord structs * separately. */ struct DecPmSequence { /** * @brief DECCKM * * When set, the cursor keys send an ESC O prefix, * rather than ESC [ (default off). */ static constexpr const wchar_t DECCKM_ON[]{L"1"}; /** * @brief DECCOLM * * 80/132 column mode switch. (default off=80 cols) */ static constexpr const wchar_t DECCOLM[]{L"3"}; /** * @brief Set reverse video-mode. * * Turns reverse video mode on. Inverts console colors. */ static constexpr const wchar_t DECSCNM[]{L"5"}; /** * @brief Cursor addressing mode. * * When set, cursor addressing is relative to the upper-left corner of the * scrolling region (default off). */ static constexpr const wchar_t DECCOM[]{L"6"}; /** * @brief Autowrap mode. * * Sets auto-wrap on. A graphic character after 80 (or 132) characters wraps * to the beginning of the next line automatically. (default on) */ static constexpr const wchar_t DECAWM[]{L"7"}; /** * @brief Autorepeat mode. * * Sets keyboard autorepeat on/off (default:on) * Seems to have no effect in most modern terminal emulators. */ static constexpr const wchar_t DECARM[]{L"8"}; /** * @brief Cursor visibility. * * Set cursor visible (default on). */ static constexpr const wchar_t DECTECM[]{L"25"}; }; /** * @brief Select Graphic Rendition sequence. * * Expects the CSI prefix, and 'm' suffix with args inbetween. * Eg: * * ESC[0m = reset. * * Multiple attributes can be specified, separated by a semi-colon, eg: * * ESC[1;3m = bold and italic * * Expects ControlCharacter::ESC + ControlCharacter::CSI + CsiSequence::SGR * prefix. */ struct SgrSequence { /** * @brief Reset. * * All attributes off. */ static constexpr const wchar_t RESET[]{L"0"}; /** * @brief Bold. * * Bold or increased intensity. */ static constexpr const wchar_t BOLD[]{L"1"}; /** * @brief Faint. * * May be implemented as a ligh font weight. */ static constexpr const wchar_t LIGHT[]{L"2"}; /** * @brief Italic. */ static constexpr const wchar_t ITALIC[]{L"3"}; /** * @brief Underline. */ static constexpr const wchar_t UNDERLINE[]{L"4"}; /** * @brief Slow blink. */ static constexpr const wchar_t SLOW_BLINK[]{L"5"}; /** * @brief Fast blink. * * Not widely supported - on most *nix terminals, blinks at the same speed * as slow blink. */ static constexpr const wchar_t FAST_BLINK[]{L"6"}; /** * @brief Reverse video / invert. */ static constexpr const wchar_t INVERSE[]{L"7"}; /** * @brief Conceal. * * Not supported in (u)rxvt. Works in xterm, konsole. */ static constexpr const wchar_t CONCEAL[]{L"8"}; /** * @brief Strikethrough. * * Crossed out text. * Not supported in (u)rxvt. Works in xterm, konsole. */ static constexpr const wchar_t STRIKETRHOUGH[]{L"9"}; /** * @brief Primary font. */ static constexpr const wchar_t PRIMARY_FONT[]{L"10"}; /** * @brief Alternative font. */ static constexpr const wchar_t ALTERNATE_FONT[]{L"11"}; /** * @brief Blackletter font. * * Rarely supported. */ static constexpr const wchar_t BLACKLETTER_FONT[]{L"20"}; /** * @brief Double underline. * * (Disables bold on many terminals instead - * doesn't seem to actually double-underline on any terminal emulators I've * tried). */ static constexpr const wchar_t DOUBLE_UNDERLINE[]{L"21"}; /** * @brief Normal intensity. * * Neither bold nor faint. */ static constexpr const wchar_t NORMAL_INTENSITY[]{L"22"}; /** * @brief Neither italic nor blackletter. */ static constexpr const wchar_t NOT_ITALIC_NOT_BLACKLETTER[]{L"23"}; /** * @brief Not underlined. */ static constexpr const wchar_t NOT_UNDERLINED[]{L"24"}; /** * @brief Not blinking. */ static constexpr const wchar_t NOT_BLINKING[]{L"25"}; /** * @brief Proportional spacing. * * (Not supported on anything I think?) */ static constexpr const wchar_t PROPORTIONAL_SPACING[]{L"26"}; /** * @brief Reveal. * * Not concealed. */ static constexpr const wchar_t REVEAL[]{L"28"}; /** * @brief Not crossed out. */ static constexpr const wchar_t NOT_CROSSED_OUT[]{L"29"}; /** * @brief Set foreground color to black. */ static constexpr const wchar_t FG_BLACK[]{L"30"}; /** * @brief Set foreground color to red. */ static constexpr const wchar_t FG_RED[]{L"31"}; /** * @brief Set foreground color to green. */ static constexpr const wchar_t FG_GREEN[]{L"32"}; /** * @brief Set foreground color to yellow. */ static constexpr const wchar_t FG_YELLOW[]{L"33"}; /** * @brief Set foreground color to blue. */ static constexpr const wchar_t FG_BLUE[]{L"34"}; /** * @brief Set foreground color to magenta. */ static constexpr const wchar_t FG_MAGENTA[]{L"35"}; /** * @brief Set foreground color to cyan. */ static constexpr const wchar_t FG_CYAN[]{L"36"}; /** * @brief Set foreground color to white. */ static constexpr const wchar_t FG_WHITE[]{L"37"}; /** * @brief Set foreground color. * * Next arguments are 5;n (16 color) or 2;r;g;b */ static constexpr const wchar_t SET_FG_COLOR[]{L"38"}; /** * @brief Default foreground color. * * Sets the foreground color to whatever the default is for the terminal. */ static constexpr const wchar_t SET_DEFAULT_FG_COLOR[]{L"39"}; /** * @brief Set background to black. */ static constexpr const wchar_t BG_BLACK[]{L"40"}; /** * @brief Set background to red. */ static constexpr const wchar_t BG_RED[]{L"41"}; /** * @brief Set background to green. */ static constexpr const wchar_t BG_GREEN[]{L"42"}; /** * @brief Set background to yellow. */ static constexpr const wchar_t BG_YELLOW[]{L"43"}; /** * @brief Set background to blue. */ static constexpr const wchar_t BG_BLUE[]{L"44"}; /** * @brief Set background to magenta. */ static constexpr const wchar_t BG_MAGENTA[]{L"45"}; /** * @brief Set background to cyan. */ static constexpr const wchar_t BG_CYAN[]{L"46"}; /** * @brief Set background to white. */ static constexpr const wchar_t BG_WHITE[]{L"47"}; /** * @brief Set background color. * * Next arguments are 5;n (16 color) or 2;r;g;b */ static constexpr const wchar_t SET_BG_COLOR[]{L"48"}; /** * @brief Default background color. * * Sets the background color to whatever the terminal default is. */ static constexpr const wchar_t SET_DEFAULT_BG_COLOR[]{L"49"}; /** * @brief Disable proportional spacing. * * (T.61 and T.416 ) */ static constexpr const wchar_t DISABLE_PROPORTIONAL_SPACING[]{L"50"}; /** * @brief Framed. * * (Doesn't seem to be supported on any *nix terminal emulators). */ static constexpr const wchar_t FRAMED[]{L"51"}; /** * @brief Encircled. * * (Doesn't seem to be supported on any *nix terminal emulators). */ static constexpr const wchar_t ENCIRCLED[]{L"52"}; /** * @brief Overlined. * * (Doesn't seem to be supported on any *nix terminal emulators). */ static constexpr const wchar_t OVERLINED[]{L"53"}; /** * @brief Neither framed nor encircled. * * (Doesn't seem to be supported on any *nix terminal emulators). */ static constexpr const wchar_t NO_FRAME[]{L"54"}; /** * @brief Not overlined. * * (Doesn't seem to be supported on any *nix terminal emulators). */ static constexpr const wchar_t NOT_OVERLINED[]{L"55"}; /** * @brief Set underline color. * * Next arguments are 5;n or 2;r;g;b * * Not in standard. Implemented in Kitty, VTE, mintty, iTerm2. * Does not work in xterm/(u)rxvt/konsole/... */ static constexpr const wchar_t SET_UNDERLINE_COLOR[]{L"58"}; /** * @brief Set default underline color. * * Not in standard. Implemented in Kitty, VTE, mintty, iTerm2. * Does not work in xterm/(u)rxvt/konsole/... */ static constexpr const wchar_t SET_DEFAULT_UNDERLINE_COLOR[]{L"59"}; /** * @brief Ideogram underline or right side line. * * Does not seem to be suported in any *nix terminal emulators. */ static constexpr const wchar_t IDEOGRAM_UNDERLINE[]{L"60"}; /** * @brief Double ideogram underline or right side double-line. * * Does not seem to be suported in any *nix terminal emulators. */ static constexpr const wchar_t IDEOGRAM_DOUBLE_UNDERLINE[]{L"61"}; /** * @brief Ideogram overline or left side line. * * Does not seem to be suported in any *nix terminal emulators. */ static constexpr const wchar_t IDEOGRAM_OVERLINE_UNDERLINE[]{L"62"}; /** * @brief Ideogram double overline or left side double-line. * * Does not seem to be suported in any *nix terminal emulators. */ static constexpr const wchar_t IDEOGRAM_DOUBLE_OVERLINE_UNDERLINE[]{L"63"}; /** * @brief Ideogram stress marking. * * Does not seem to be suported in any *nix terminal emulators. */ static constexpr const wchar_t IDEOGRAM_STRESS_MARKING[]{L"64"}; /** * @brief No ideogram markings. * * Does not seem to be suported in any *nix terminal emulators. */ static constexpr const wchar_t NO_IDEOGRAM_MARKINGS[]{L"65"}; /** * @brief Superscript. * * Implemented only in mintty. */ static constexpr const wchar_t SUPERSCRIPT[]{L"73"}; /** * @brief Subscript. * * Implemented only in mintty. */ static constexpr const wchar_t SUBSCRIPT[]{L"74"}; /** * @brief Neither subscript nor superscript. * * Implemented only in mintty. */ static constexpr const wchar_t NORMALSCRIPT[]{L"75"}; /** * @brief Set foreground color to bright black (grey). */ static constexpr const wchar_t FG_BRIGHT_BLACK[]{L"90"}; /** * @brief Set foreground color to bright red. */ static constexpr const wchar_t FG_BRIGHT_RED[]{L"91"}; /** * @brief Set foreground color to bright green. */ static constexpr const wchar_t FG_BRIGHT_GREEN[]{L"92"}; /** * @brief Set foreground color to bright yellow. */ static constexpr const wchar_t FG_BRIGHT_YELLOW[]{L"93"}; /** * @brief Set foreground color to bright blue. */ static constexpr const wchar_t FG_BRIGHT_BLUE[]{L"94"}; /** * @brief Set foreground color to bright magenta. */ static constexpr const wchar_t FG_BRIGHT_MAGENTA[]{L"95"}; /** * @brief Set foreground color to bright cyan. */ static constexpr const wchar_t FG_BRIGHT_CYAN[]{L"96"}; /** * @brief Set foreground color to bright white. */ static constexpr const wchar_t FG_BRIGHT_WHITE[]{L"97"}; /** * @brief Set background to bright black. */ static constexpr const wchar_t BG_BRIGHT_BLACK[]{L"100"}; /** * @brief Set background to bright red. */ static constexpr const wchar_t BG_BRIGHT_RED[]{L"101"}; /** * @brief Set background to bright green. */ static constexpr const wchar_t BG_BRIGHT_GREEN[]{L"102"}; /** * @brief Set background to bright yellow. */ static constexpr const wchar_t BG_BRIGHT_YELLOW[]{L"103"}; /** * @brief Set background to bright blue. */ static constexpr const wchar_t BG_BRIGHT_BLUE[]{L"104"}; /** * @brief Set background to bright magenta. */ static constexpr const wchar_t BG_BRIGHT_MAGENTA[]{L"105"}; /** * @brief Set background to bright cyan. */ static constexpr const wchar_t BG_BRIGHT_CYAN[]{L"106"}; /** * @brief Set background to bright white. */ static constexpr const wchar_t BG_BRIGHT_WHITE[]{L"107"}; }; static std::unordered_set const SgrSequences{ SgrSequence::ALTERNATE_FONT, SgrSequence::BG_BLACK, SgrSequence::BG_BLUE, SgrSequence::BG_BRIGHT_BLACK, SgrSequence::BG_BRIGHT_BLUE, SgrSequence::BG_BRIGHT_CYAN, SgrSequence::BG_BRIGHT_GREEN, SgrSequence::BG_BRIGHT_MAGENTA, SgrSequence::BG_BRIGHT_RED, SgrSequence::BG_BRIGHT_WHITE, SgrSequence::BG_BRIGHT_YELLOW, SgrSequence::BG_CYAN, SgrSequence::BG_GREEN, SgrSequence::BG_MAGENTA, SgrSequence::BG_RED, SgrSequence::BG_WHITE, SgrSequence::BG_YELLOW, SgrSequence::BLACKLETTER_FONT, SgrSequence::BOLD, SgrSequence::CONCEAL, SgrSequence::DISABLE_PROPORTIONAL_SPACING, SgrSequence::DOUBLE_UNDERLINE, SgrSequence::ENCIRCLED, SgrSequence::FAST_BLINK, SgrSequence::FG_BLACK, SgrSequence::FG_BLUE, SgrSequence::FG_BRIGHT_BLACK, SgrSequence::FG_BRIGHT_BLUE, SgrSequence::FG_BRIGHT_CYAN, SgrSequence::FG_BRIGHT_GREEN, SgrSequence::FG_BRIGHT_MAGENTA, SgrSequence::FG_BRIGHT_RED, SgrSequence::FG_BRIGHT_WHITE, SgrSequence::FG_BRIGHT_YELLOW, SgrSequence::FG_CYAN, SgrSequence::FG_GREEN, SgrSequence::FG_MAGENTA, SgrSequence::FG_RED, SgrSequence::FG_WHITE, SgrSequence::FG_YELLOW, SgrSequence::FRAMED, SgrSequence::IDEOGRAM_DOUBLE_OVERLINE_UNDERLINE, SgrSequence::IDEOGRAM_DOUBLE_UNDERLINE, SgrSequence::IDEOGRAM_OVERLINE_UNDERLINE, SgrSequence::IDEOGRAM_STRESS_MARKING, SgrSequence::IDEOGRAM_UNDERLINE, SgrSequence::INVERSE, SgrSequence::ITALIC, SgrSequence::LIGHT, SgrSequence::NO_FRAME, SgrSequence::NO_IDEOGRAM_MARKINGS, SgrSequence::NORMAL_INTENSITY, SgrSequence::NORMALSCRIPT, SgrSequence::NOT_BLINKING, SgrSequence::NOT_CROSSED_OUT, SgrSequence::NOT_ITALIC_NOT_BLACKLETTER, SgrSequence::NOT_OVERLINED, SgrSequence::NOT_UNDERLINED, SgrSequence::OVERLINED, SgrSequence::PRIMARY_FONT, SgrSequence::PROPORTIONAL_SPACING, SgrSequence::RESET, SgrSequence::REVEAL, SgrSequence::SET_BG_COLOR, SgrSequence::SET_DEFAULT_BG_COLOR, SgrSequence::SET_DEFAULT_FG_COLOR, SgrSequence::SET_DEFAULT_UNDERLINE_COLOR, SgrSequence::SET_FG_COLOR, SgrSequence::SET_UNDERLINE_COLOR, SgrSequence::SLOW_BLINK, SgrSequence::STRIKETRHOUGH, SgrSequence::SUBSCRIPT, SgrSequence::SUPERSCRIPT, SgrSequence::UNDERLINE }; /** * @brief Mouse tracking modes. * * Mouse tracking modes supported in various modern terminals. * They are mutually exclusive. * * All of these cause the terminal to send escape sequences to report mouse * events in various ways. * */ struct MouseTrackMode { /** * @brief X10 compatibility mode. * * Terminal only reports button presses. * * Response: CSI M Cb Cx Cy (6 characters). * * * Cb is button−1. * * Cx and Cy are the x and y coordinates of the mouse when the button * was pressed. */ static constexpr const wchar_t X10[]{L"9"}; /** * @brief Normal tracking mode. * * Reports mouse down and mouse up events. Modifier key info is also sent. * * Response: CSI M Cb Cx Cy * * * The low two bits of Cb encode button information: * * 0=MB1 pressed * * 1=MB2 pressed * * 2=MB3 pressed * * 3=release * * The next three bits encode the modifiers which were down when the button * was pressed and are added together: * * 4=Shift * * 8=Meta * * 16=Control */ static constexpr const wchar_t VT200[]{L"1000"}; /** * @brief Highlight tracking mode. * * Mouse highlight tracking notifies a program of a button press, receives * a range of lines from the program, highlights the region covered by the * mouse within that range until button release, and then sends the program * the release coordinates. Highlighting is performed only for button 1, * though other button events can be received. * * On button press, the same information as for normal tracking is generated * The terminal then waits for the program to send mouse tracking * information. All X events are ignored until the proper escape sequence is * received from the pty: CSI Ps ; Ps ; Ps ; Ps ; Ps T * The parameters are func, startx, starty, firstrow, and lastrow. * * func is non-zero to initiate highlight tracking and zero to abort. * * startx and starty give the starting x and y location for the * highlighted region. * * The ending location tracks the mouse, but will never be above row * firstrow and will always be above row lastrow. * * When the button is released, the terminal reports the ending position one * of two ways: * * if the start and end coordinates are valid text locations: * * CSI t C x C y . * * If either coordinate is past the end of the line: * * CSI T C x C y C x C y C x C y . * * The parameters are startx, starty, endx, endy, mousex, and mousey. * * startx, starty, endx, and endy give the starting and ending character * positions of the region. * * mousex and mousey give the location of the mouse at button up, which * may not be over a character. */ static constexpr const wchar_t VT200_HIGHLIGHT[]{L"1001"}; /** * @brief button event tracking mode. * * Essentially the same as normal tracking, but the terminal also reports * mouse-move events whilst a button is depressed. * Motion events are reported only if the mouse pointer has moved to a * different character cell. * * On button-motion events, xterm adds 32 to the event code * (the third character, Cb ). The other bits of the event code specify * button and modifier keys as in normal mode. * * For example, motion into cell x,y with button 1 down is reported as: * * CSI M @ C x C y. ( @ = 32 + 0 (button 1) + 32 (motion indicator) ). * * Similarly, motion with button 3 down is reported as: * * CSI M B C x C y . ( B = 32 + 2 (button 3) + 32 (motion indicator) ). */ static constexpr const wchar_t BTN_EVENT[]{L"1002"}; /** * @brief any event tracking mode. * * Same as button event tracking mode, but instead of only reporting events * when a mouse button is depressed, all events are sent at all times. * So you'd use this if you want to track any mouse movement regardless of * button state. */ static constexpr const wchar_t ANY_EVENT[]{L"1003"}; }; /** * @brief Extended mouse coordinate mode. * * The original X10 mouse protocol limits the Cx and Cy ordinates to 223 * (=255 - 32). Various terminals support more than one scheme for extending * this range, by changing the protocol encoding. * * Here is a compatibility matrix: * * * | | UTF-8 (1005) | SGR (1006) | URXVT (1015) | * |---------------|--------------|------------|--------------| * | VTE-based | x | ✓ | x | * |---------------|--------------|------------|--------------| * | urxvt | ✓ | o | ✓ | * |---------------|--------------|------------|--------------| * | xterm | ✓ | ✓ | ✓ | * |---------------|--------------|------------|--------------| * | konsole | ✓ | ✓ | ✓ | * |---------------|--------------|------------|--------------| * | st | x | ✓ | x | * |---------------|--------------|------------|--------------| * | terminology | ✓ | ✓ | ✓ | * |---------------|--------------|------------|--------------| * * x = not supported * ✓ = always supported * o = optional (support has to be compiled into the terminal at compile time). * * tl;dr You probably want to use either SGR or SGR_PIXELS depending on your * use case. */ struct MouseExtCoord { /** * @brief UTF-8 extended coordinate mode. * * Extends the range by using utf-8 encoding, effectively extending the * range up to a max of 2015 (instead of 223). */ static constexpr const wchar_t UTF8[]{L"1005"}; /** * @brief SGR extended coordinate mode. * * CSI < followed by semicolon-separated encoded button values, Px and Py * coordinates, and a final character: M for button press and m for button * release. */ static constexpr const wchar_t SGR[]{L"1006"}; /** * @brief URXVT extended coordinate mode. * * CSI followed by semicolon-separated encoded button values, Px and Py * coordinates, and the final M character. * * This uses the same button encoding as X10, but printing it as a decimal * integer rather than as a single byte. */ static constexpr const wchar_t URXVT[]{L"1015"}; /** * @brief Pixel coordinate mode. * * Same as the SGR (1006) format, but reports coordinates of pixels rather * than character cells. */ static constexpr const wchar_t SGR_PIXELS[]{L"1016"}; }; /** * @brief Set of all possible dec PM sequences (including mouse reporting) */ static std::unordered_set const DecPmSequences { DecPmSequence::DECARM, DecPmSequence::DECAWM, DecPmSequence::DECCKM_ON, DecPmSequence::DECCOLM, DecPmSequence::DECCOM, DecPmSequence::DECSCNM, DecPmSequence::DECTECM, MouseTrackMode::ANY_EVENT, MouseTrackMode::BTN_EVENT, MouseTrackMode::VT200, MouseTrackMode::VT200_HIGHLIGHT, MouseTrackMode::X10, MouseExtCoord::SGR, MouseExtCoord::SGR_PIXELS, MouseExtCoord::URXVT, MouseExtCoord::UTF8 }; /** * @brief Make escape sequence. * * @param sequence Sequence to compose. * @return Returns the assembled sequence with the ESC control wchar_t prepended. */ std::wstring MakeEscapeSequence(const std::wstring& sequence); /** * @brief Make selecting character set sequence. * * Creates a string holding a CSSI sequence with prefixes added. * * @param sequence Sequence to compose. * @return Returns the assembled sequence. */ std::wstring MakeCssiSequence(const wchar_t sequence); /** * @brief Make CSI sequence (multiple parameters). * * Creates a string holding a CSI sequence with prefixes added. * Inserts semi-colons between parameters automatically. * * @param sequenceItems csi control characters or parameters. * @return Returns the assembled sequence. */ std::wstring MakeCsiSequence(const std::vector& sequenceItems); /** * @brief Make DEC private mode Sequence. * * Creates a string holding a DEC private mode sequence with prefixes added and * given suffix holding the enable/disable (high/low) bit. * * @param sequence Sequence to compose. * @param suffix DEC PM suffix indicating whether to enable or disable the * selected DEC private mode sequence. * @return Returns the assembled sequence. */ std::wstring MakeDecPmSequence(const std::wstring& sequence, const std::wstring& suffix); /** * @brief Make SGR sequence. * * Creates an SGR sequence with prefix included, from a list of characters. * The semi-colon separated is automatically inserted between the characters * given in the array. The array should hold sgr sequence characters or their * parameters. * * @param sequenceItems sgr control characters or parameters. * @return Returns the assembled sgr sequence. */ std::wstring MakeSgrSequence(const std::vector& sequenceItems); } // namespace ansi } // namespace neovision