Skip to content
Open
Show file tree
Hide file tree
Changes from all 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