147 lines
3.6 KiB
C++
147 lines
3.6 KiB
C++
|
/**
|
||
|
* @file EscapeSequence.cpp
|
||
|
* @author apio (cloudapio.eu)
|
||
|
* @brief ANSI escape sequence parsing.
|
||
|
*
|
||
|
* @copyright Copyright (c) 2023, the Luna authors.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#include <luna/CType.h>
|
||
|
#include <luna/Check.h>
|
||
|
#include <luna/EscapeSequence.h>
|
||
|
#include <luna/NumberParsing.h>
|
||
|
|
||
|
EscapeSequenceParser::EscapeSequenceParser(u8 begin)
|
||
|
{
|
||
|
switch (begin)
|
||
|
{
|
||
|
case 0x1b: m_sequence_type = SequenceType::ESC; break;
|
||
|
case 0x9b: m_sequence_type = SequenceType::CSI; break;
|
||
|
case 0x90: m_sequence_type = SequenceType::DCS; break;
|
||
|
case 0x9d: m_sequence_type = SequenceType::OSC; break;
|
||
|
default: fail("Unrecognized escape sequence type");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Result<bool> EscapeSequenceParser::advance(u8 byte)
|
||
|
{
|
||
|
switch (m_sequence_type)
|
||
|
{
|
||
|
case SequenceType::ESC: {
|
||
|
switch (byte)
|
||
|
{
|
||
|
case '[': {
|
||
|
m_sequence_type = SequenceType::CSI;
|
||
|
return false;
|
||
|
};
|
||
|
case 'P': {
|
||
|
m_sequence_type = SequenceType::DCS;
|
||
|
return false;
|
||
|
};
|
||
|
case ']': {
|
||
|
m_sequence_type = SequenceType::OSC;
|
||
|
return false;
|
||
|
};
|
||
|
case '7': {
|
||
|
m_escape_code = EscapeCode::SaveCursor;
|
||
|
m_valid = true;
|
||
|
return true;
|
||
|
};
|
||
|
case '8': {
|
||
|
m_escape_code = EscapeCode::RestoreCursor;
|
||
|
m_valid = true;
|
||
|
return true;
|
||
|
};
|
||
|
default: {
|
||
|
m_valid = false;
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
break;
|
||
|
case SequenceType::CSI: {
|
||
|
if (_isdigit(byte))
|
||
|
{
|
||
|
m_parsing_parameter = true;
|
||
|
TRY(m_parameter.try_append(byte));
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (!m_parsing_parameter && byte == ';')
|
||
|
{
|
||
|
TRY(m_parameters.try_append(0));
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (m_parsing_parameter)
|
||
|
{
|
||
|
TRY(m_parameter.try_append(0));
|
||
|
int value = static_cast<int>(parse_unsigned_integer((const char*)m_parameter.data(), nullptr, 10));
|
||
|
m_parameter.clear();
|
||
|
TRY(m_parameters.try_append(value));
|
||
|
}
|
||
|
|
||
|
switch (byte)
|
||
|
{
|
||
|
case 'A': {
|
||
|
m_escape_code = EscapeCode::CursorUp;
|
||
|
m_valid = true;
|
||
|
return true;
|
||
|
};
|
||
|
case 'B': {
|
||
|
m_escape_code = EscapeCode::CursorDown;
|
||
|
m_valid = true;
|
||
|
return true;
|
||
|
};
|
||
|
case 'C': {
|
||
|
m_escape_code = EscapeCode::CursorForward;
|
||
|
m_valid = true;
|
||
|
return true;
|
||
|
};
|
||
|
case 'D': {
|
||
|
m_escape_code = EscapeCode::CursorBack;
|
||
|
m_valid = true;
|
||
|
return true;
|
||
|
};
|
||
|
case 'E': {
|
||
|
m_escape_code = EscapeCode::CursorNextLine;
|
||
|
m_valid = true;
|
||
|
return true;
|
||
|
};
|
||
|
case 'F': {
|
||
|
m_escape_code = EscapeCode::CursorPreviousLine;
|
||
|
m_valid = true;
|
||
|
return true;
|
||
|
};
|
||
|
case 'G': {
|
||
|
m_escape_code = EscapeCode::CursorHorizontalAbsolute;
|
||
|
m_valid = true;
|
||
|
return true;
|
||
|
};
|
||
|
case 'H': {
|
||
|
m_escape_code = EscapeCode::SetCursorPosition;
|
||
|
m_valid = true;
|
||
|
return true;
|
||
|
};
|
||
|
case 'm': {
|
||
|
m_escape_code = EscapeCode::SelectGraphicRendition;
|
||
|
m_valid = true;
|
||
|
return true;
|
||
|
};
|
||
|
case ';': {
|
||
|
return false;
|
||
|
};
|
||
|
default: {
|
||
|
m_valid = false;
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
break;
|
||
|
case SequenceType::DCS: todo();
|
||
|
case SequenceType::OSC: todo();
|
||
|
default: todo();
|
||
|
}
|
||
|
}
|