Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/terminal/adapter/ITermDispatch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ namespace Microsoft::Console::VirtualTerminal
class Microsoft::Console::VirtualTerminal::ITermDispatch
{
public:
using StringHandler = std::function<bool(const wchar_t)>;
using StringHandler = std::function<bool(std::wstring_view)>;

enum class OptionalFeature
{
Expand Down
150 changes: 77 additions & 73 deletions src/terminal/adapter/MacroBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,92 +113,96 @@ bool MacroBuffer::InitParser(const size_t macroId, const DispatchTypes::MacroDel
return false;
}

bool MacroBuffer::ParseDefinition(const wchar_t ch)
bool MacroBuffer::ParseDefinition(const std::wstring_view str)
{
// Once we receive an ESC, that marks the end of the definition, but if
// an unterminated repeat is still pending, we should apply that now.
if (ch == AsciiChars::ESC)
for (const auto ch : str)
{
if (_repeatPending && !_applyPendingRepeat())
// Once we receive an ESC, that marks the end of the definition, but if
// an unterminated repeat is still pending, we should apply that now.
if (ch == AsciiChars::ESC)
{
_deleteMacro(_activeMacro());
if (_repeatPending && !_applyPendingRepeat())
{
_deleteMacro(_activeMacro());
}
return false;
}
return false;
}

// Any other control characters are just ignored.
if (ch < L' ')
{
return true;
}

// For "text encoded" macros, we'll always be in the ExpectingText state.
// For "hex encoded" macros, we'll typically be alternating between the
// ExpectingHexDigit and ExpectingSecondHexDigit states as we parse the two
// digits of each hex pair. But we also need to deal with repeat sequences,
// which start with `!`, followed by a numeric repeat count, and then a
// range of hex pairs between two `;` characters. When parsing the repeat
// count, we use the ExpectingRepeatCount state, but when parsing the hex
// pairs of the repeat, we just use the regular ExpectingHexDigit states.

auto success = true;
switch (_parseState)
{
case State::ExpectingText:
success = _appendToActiveMacro(ch);
break;
case State::ExpectingHexDigit:
if (_decodeHexDigit(ch))
// Any other control characters are just ignored.
if (ch < L' ')
{
_parseState = State::ExpectingSecondHexDigit;
}
else if (ch == L'!' && !_repeatPending)
{
_parseState = State::ExpectingRepeatCount;
_repeatCount = 0;
}
else if (ch == L';' && _repeatPending)
{
success = _applyPendingRepeat();
}
else
{
success = false;
}
break;
case State::ExpectingSecondHexDigit:
success = _decodeHexDigit(ch) && _appendToActiveMacro(_decodedChar);
_decodedChar = 0;
_parseState = State::ExpectingHexDigit;
break;
case State::ExpectingRepeatCount:
if (ch >= L'0' && ch <= L'9')
{
_repeatCount = _repeatCount * 10 + (ch - L'0');
_repeatCount = std::min<size_t>(_repeatCount, MAX_PARAMETER_VALUE);
return true;
}
else if (ch == L';')

// For "text encoded" macros, we'll always be in the ExpectingText state.
// For "hex encoded" macros, we'll typically be alternating between the
// ExpectingHexDigit and ExpectingSecondHexDigit states as we parse the two
// digits of each hex pair. But we also need to deal with repeat sequences,
// which start with `!`, followed by a numeric repeat count, and then a
// range of hex pairs between two `;` characters. When parsing the repeat
// count, we use the ExpectingRepeatCount state, but when parsing the hex
// pairs of the repeat, we just use the regular ExpectingHexDigit states.

auto success = true;
switch (_parseState)
{
_repeatPending = true;
_repeatStart = _activeMacro().length();
case State::ExpectingText:
success = _appendToActiveMacro(ch);
break;
case State::ExpectingHexDigit:
if (_decodeHexDigit(ch))
{
_parseState = State::ExpectingSecondHexDigit;
}
else if (ch == L'!' && !_repeatPending)
{
_parseState = State::ExpectingRepeatCount;
_repeatCount = 0;
}
else if (ch == L';' && _repeatPending)
{
success = _applyPendingRepeat();
}
else
{
success = false;
}
break;
case State::ExpectingSecondHexDigit:
success = _decodeHexDigit(ch) && _appendToActiveMacro(_decodedChar);
_decodedChar = 0;
_parseState = State::ExpectingHexDigit;
}
else
{
break;
case State::ExpectingRepeatCount:
if (ch >= L'0' && ch <= L'9')
{
_repeatCount = _repeatCount * 10 + (ch - L'0');
_repeatCount = std::min<size_t>(_repeatCount, MAX_PARAMETER_VALUE);
}
else if (ch == L';')
{
_repeatPending = true;
_repeatStart = _activeMacro().length();
_parseState = State::ExpectingHexDigit;
}
else
{
success = false;
}
break;
default:
success = false;
break;
}
break;
default:
success = false;
break;
}

// If there is an error in the definition, clear everything received so far.
if (!success)
{
_deleteMacro(_activeMacro());
// If there is an error in the definition, clear everything received so far.
if (!success)
{
_deleteMacro(_activeMacro());
return false;
}
}
return success;
return true;
}

bool MacroBuffer::_decodeHexDigit(const wchar_t ch) noexcept
Expand Down
2 changes: 1 addition & 1 deletion src/terminal/adapter/MacroBuffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ namespace Microsoft::Console::VirtualTerminal
void InvokeMacro(const size_t macroId, StateMachine& stateMachine);
void ClearMacrosIfInUse();
bool InitParser(const size_t macroId, const DispatchTypes::MacroDeleteControl deleteControl, const DispatchTypes::MacroEncoding encoding);
bool ParseDefinition(const wchar_t ch);
bool ParseDefinition(std::wstring_view str);

private:
bool _decodeHexDigit(const wchar_t ch) noexcept;
Expand Down
9 changes: 6 additions & 3 deletions src/terminal/adapter/SixelParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ void SixelParser::SetDisplayMode(const bool enabled) noexcept
}
}

std::function<bool(wchar_t)> SixelParser::DefineImage(const VTInt macroParameter, const DispatchTypes::SixelBackground backgroundSelect, const VTParameter backgroundColor)
std::function<bool(std::wstring_view)> SixelParser::DefineImage(const VTInt macroParameter, const DispatchTypes::SixelBackground backgroundSelect, const VTParameter backgroundColor)
{
if (_initTextBufferBoundaries())
{
Expand All @@ -89,8 +89,11 @@ std::function<bool(wchar_t)> SixelParser::DefineImage(const VTInt macroParameter
_initImageBuffer();
_state = States::Normal;
_parameters.clear();
return [&](const auto ch) {
_parseCommandChar(ch);
return [&](const std::wstring_view str) {
for (const auto ch : str)
{
_parseCommandChar(ch);
}
return true;
};
}
Expand Down
2 changes: 1 addition & 1 deletion src/terminal/adapter/SixelParser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ namespace Microsoft::Console::VirtualTerminal
SixelParser(AdaptDispatch& dispatcher, const StateMachine& stateMachine, const VTInt conformanceLevel = DefaultConformance) noexcept;
void SoftReset();
void SetDisplayMode(const bool enabled) noexcept;
std::function<bool(wchar_t)> DefineImage(const VTInt macroParameter, const DispatchTypes::SixelBackground backgroundSelect, const VTParameter backgroundColor);
std::function<bool(std::wstring_view)> DefineImage(const VTInt macroParameter, const DispatchTypes::SixelBackground backgroundSelect, const VTParameter backgroundColor);

private:
// NB: If we want to support more than 256 colors, we'll also need to
Expand Down
Loading
Loading