Compare commits

...

1 Commits

Author SHA1 Message Date
Leonard Hecker
6d16a3e53a Remove indirect usage of IsGlyphFullWidth in ScrollRegion 2024-08-07 22:36:58 +02:00
3 changed files with 43 additions and 41 deletions

View File

@@ -359,6 +359,39 @@ void VtIo::FormatAttributes(std::wstring& target, const TextAttribute& attribute
target.append(bufW, len);
}
wchar_t VtIo::SanitizeUCS2(wchar_t ch) noexcept
{
// If any of the values in the buffer are C0 or C1 controls, we need to
// convert them to printable codepoints, otherwise they'll end up being
// evaluated as control characters by the receiving terminal. We use the
// DOS 437 code page for the C0 controls and DEL, and just a `?` for the
// C1 controls, since that's what you would most likely have seen in the
// legacy v1 console with raster fonts.
if (ch < 0x20)
{
static constexpr wchar_t lut[] = {
// clang-format off
L' ', L'', L'', L'', L'', L'', L'', L'', L'', L'', L'', L'', L'', L'', L'', L'',
L'', L'', L'', L'', L'', L'§', L'', L'', L'', L'', L'', L'', L'', L'', L'', L'',
// clang-format on
};
ch = lut[ch];
}
else if (ch == 0x7F)
{
ch = L'';
}
else if (ch > 0x7F && ch < 0xA0)
{
ch = L'?';
}
else if (til::is_surrogate(ch))
{
ch = UNICODE_REPLACEMENT;
}
return ch;
}
VtIo::Writer::Writer(VtIo* io) noexcept :
_io{ io }
{
@@ -592,7 +625,7 @@ void VtIo::Writer::WriteUTF16StripControlChars(std::wstring_view str) const
for (it = begControlChars; it != end && IsControlCharacter(*it); ++it)
{
WriteUCS2StripControlChars(*it);
WriteUCS2(SanitizeUCS2(*it));
}
}
}
@@ -626,36 +659,6 @@ void VtIo::Writer::WriteUCS2(wchar_t ch) const
_io->_back.append(buf, len);
}
void VtIo::Writer::WriteUCS2StripControlChars(wchar_t ch) const
{
// If any of the values in the buffer are C0 or C1 controls, we need to
// convert them to printable codepoints, otherwise they'll end up being
// evaluated as control characters by the receiving terminal. We use the
// DOS 437 code page for the C0 controls and DEL, and just a `?` for the
// C1 controls, since that's what you would most likely have seen in the
// legacy v1 console with raster fonts.
if (ch < 0x20)
{
static constexpr wchar_t lut[] = {
// clang-format off
L' ', L'', L'', L'', L'', L'', L'', L'', L'', L'', L'', L'', L'', L'', L'', L'',
L'', L'', L'', L'', L'', L'§', L'', L'', L'', L'', L'', L'', L'', L'', L'', L'',
// clang-format on
};
ch = lut[ch];
}
else if (ch == 0x7F)
{
ch = L'';
}
else if (ch > 0x7F && ch < 0xA0)
{
ch = L'?';
}
WriteUCS2(ch);
}
// CUP: Cursor Position
void VtIo::Writer::WriteCUP(til::point position) const
{

View File

@@ -35,7 +35,6 @@ namespace Microsoft::Console::VirtualTerminal
void WriteUTF16TranslateCRLF(std::wstring_view str) const;
void WriteUTF16StripControlChars(std::wstring_view str) const;
void WriteUCS2(wchar_t ch) const;
void WriteUCS2StripControlChars(wchar_t ch) const;
void WriteCUP(til::point position) const;
void WriteDECTCEM(bool enabled) const;
void WriteSGR1006(bool enabled) const;
@@ -54,6 +53,7 @@ namespace Microsoft::Console::VirtualTerminal
static void FormatAttributes(std::string& target, const TextAttribute& attributes);
static void FormatAttributes(std::wstring& target, const TextAttribute& attributes);
static wchar_t SanitizeUCS2(wchar_t ch) noexcept;
[[nodiscard]] HRESULT Initialize(const ConsoleArguments* const pArgs);
[[nodiscard]] HRESULT CreateAndStartSignalThread() noexcept;

View File

@@ -316,8 +316,8 @@ void ScrollRegion(SCREEN_INFORMATION& screenInfo,
const til::inclusive_rect scrollRectGiven,
const std::optional<til::inclusive_rect> clipRectGiven,
const til::point destinationOriginGiven,
const wchar_t fillCharGiven,
const TextAttribute fillAttrsGiven)
wchar_t fillCharGiven,
TextAttribute fillAttrsGiven)
{
// ------ 1. PREP SOURCE ------
// Set up the source viewport.
@@ -357,16 +357,14 @@ void ScrollRegion(SCREEN_INFORMATION& screenInfo,
return;
}
// Determine the cell we will use to fill in any revealed/uncovered space.
// We generally use exactly what was given to us.
OutputCellIterator fillData(fillCharGiven, fillAttrsGiven);
// However, if the character is null and we were given a null attribute (represented as legacy 0),
// then we'll just fill with spaces and whatever the buffer's default colors are.
if (fillCharGiven == UNICODE_NULL && fillAttrsGiven == TextAttribute{ 0 })
{
fillData = OutputCellIterator(UNICODE_SPACE, screenInfo.GetAttributes());
}
fillAttrsGiven = screenInfo.GetAttributes();
}
fillCharGiven = Microsoft::Console::VirtualTerminal::VtIo::SanitizeUCS2(UNICODE_SPACE);
// ------ 4. PREP TARGET ------
// Now it's time to think about the target. We're only given the origin of the target
@@ -422,12 +420,13 @@ void ScrollRegion(SCREEN_INFORMATION& screenInfo,
// So use the special subtraction function to get the viewports that fall
// within the fill area but outside of the target area.
const auto remaining = Viewport::Subtract(fill, target);
auto& textBuffer = screenInfo.GetTextBuffer();
// Apply the fill data to each of the viewports we're given here.
for (size_t i = 0; i < remaining.size(); i++)
{
const auto& view = remaining.at(i);
screenInfo.WriteRect(fillData, view);
textBuffer.FillRect(view.ToExclusive(), {&fillCharGiven, 1}, fillAttrsGiven);
// If the region has image content it needs to be erased.
ImageSlice::EraseBlock(screenInfo.GetTextBuffer(), view.ToExclusive());