Luna/libluna/src/EscapeSequence.cpp

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();
}
}