Fix conpty rendering of control characters in the buffer (#16825)
When using the legacy console APIs, it's possible to write arbitrary codepoints into the buffer. If any of those codepoints are in the C0 or C1 range, and the buffer contents are forwarded over conpty, they can end up mistakenly interpreted as controls by the connected terminal. This PR fixes that issue by converting any C0 and C1 codepoints in the buffer into printable glyphs before forwarding them over conpty. I've used the C0 glyphs from the DOS 437 codepage and just a `?` for the C1 codepoints, since that's what you would typically have seen in the v1 console with a raster font. Although this doesn't address the main problem in #16410, it should at least fix the rendering issues they're seeing when running their app in Windows Terminal. I've confirmed that the test case in #4363 now looks the same in Windows Terminal as it does in conhost, and I've tested the Windows version of the terminal game [Gorched], and confirmed that it now works correctly in Window Terminal. [Gorched]: https://github.com/zladovan/gorched Closes #4363 Closes #6265
This commit is contained in:
parent
338c5047d7
commit
563b7312b6
|
@ -472,7 +472,25 @@ using namespace Microsoft::Console::Types;
|
|||
_bufferLine.append(cluster.GetText());
|
||||
totalWidth += cluster.GetColumns();
|
||||
}
|
||||
|
||||
// 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.
|
||||
const auto cchLine = _bufferLine.size();
|
||||
std::for_each_n(_bufferLine.begin(), cchLine, [](auto& ch) {
|
||||
static constexpr std::wstring_view C0Glyphs = L" ☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼";
|
||||
if (ch < C0Glyphs.size())
|
||||
{
|
||||
ch = til::at(C0Glyphs, ch);
|
||||
}
|
||||
else if (ch >= L'\u007F' && ch < L'\u00A0')
|
||||
{
|
||||
ch = (ch == L'\u007F' ? L'⌂' : L'?');
|
||||
}
|
||||
});
|
||||
|
||||
const auto spaceIndex = _bufferLine.find_last_not_of(L' ');
|
||||
const auto foundNonspace = spaceIndex != decltype(_bufferLine)::npos;
|
||||
|
|
Loading…
Reference in New Issue