pubnix/lib/neovision/include/neovision/ansi.h

1625 lines
41 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include <string>
#include <unordered_set>
#include <vector>
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<std::wstring> 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<std::wstring> 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<std::wstring> 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<std::wstring> 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<std::wstring> 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<std::wstring> 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<std::wstring> 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<std::wstring> 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 button1.
* * 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<std::wstring> 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<std::wstring>& 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<std::wstring>& sequenceItems);
} // namespace ansi
} // namespace neovision