@@ -62,15 +62,38 @@ void InteractDispatch::WriteString(const std::wstring_view string)
62
62
{
63
63
if (!string.empty ())
64
64
{
65
- const auto codepage = _api.GetConsoleOutputCP ();
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 ())
69
82
{
70
- CharToKeyEvents (wch, codepage, keyEvents );
83
+ inputBuffer-> WriteString (string );
71
84
}
85
+ else
86
+ {
87
+ const auto codepage = _api.GetOutputCodePage ();
88
+ InputEventQueue keyEvents;
72
89
73
- WriteInput (keyEvents);
90
+ for (const auto & wch : string)
91
+ {
92
+ CharToKeyEvents (wch, codepage, keyEvents);
93
+ }
94
+
95
+ inputBuffer->Write (keyEvents);
96
+ }
74
97
}
75
98
}
76
99
0 commit comments