@@ -62,15 +62,38 @@ void InteractDispatch::WriteString(const std::wstring_view string)
6262{
6363 if (!string.empty ())
6464 {
65- const auto codepage = _api.GetOutputCodePage ();
66- InputEventQueue keyEvents;
67-
68- for (const auto & wch : string)
65+ const auto & gci = ServiceLocator::LocateGlobals ().getConsoleInformation ();
66+ #pragma warning(suppress : 26429) // Symbol 'inputBuffer' is never tested for nullness, it can be marked as not_null (f.23).
67+ const auto inputBuffer = gci.GetActiveInputBuffer ();
68+
69+ // The input *may* be keyboard input in which case we must call CharToKeyEvents.
70+ //
71+ // However, it could also be legitimate VT sequences (e.g. a bracketed paste sequence).
72+ // If we called `InputBuffer::Write` with those, we would end up indirectly
73+ // calling `TerminalInput::HandleKey` and "double encode" the sequence.
74+ // The effect of this is noticeable with the German keyboard layout, for instance,
75+ // where the [ key maps to AltGr+8, and we fail to map it back to [ later.
76+ //
77+ // It's worth noting that all of this is bad design in either case.
78+ // The way it should work is that we write INPUT_RECORDs and Strings as-is into the
79+ // InputBuffer, and only during retrieval they're converted into one or the other.
80+ // This prevents any kinds of double-encoding issues.
81+ if (inputBuffer->IsInVirtualTerminalInputMode ())
6982 {
70- CharToKeyEvents (wch, codepage, keyEvents );
83+ inputBuffer-> WriteString (string );
7184 }
85+ else
86+ {
87+ const auto codepage = _api.GetOutputCodePage ();
88+ InputEventQueue keyEvents;
7289
73- WriteInput (keyEvents);
90+ for (const auto & wch : string)
91+ {
92+ CharToKeyEvents (wch, codepage, keyEvents);
93+ }
94+
95+ inputBuffer->Write (keyEvents);
96+ }
7497 }
7598}
7699
0 commit comments