@@ -39,7 +39,7 @@ using Microsoft::Console::VirtualTerminal::StateMachine;
39
39
// - coordCursor - New location of cursor.
40
40
// - fKeepCursorVisible - TRUE if changing window origin desirable when hit right edge
41
41
// Return Value:
42
- static void AdjustCursorPosition (SCREEN_INFORMATION& screenInfo, _In_ til::point coordCursor, const bool interactive, _Inout_opt_ til::CoordType* psScrollY)
42
+ static void AdjustCursorPosition (SCREEN_INFORMATION& screenInfo, _In_ til::point coordCursor, _Inout_opt_ til::CoordType* psScrollY)
43
43
{
44
44
const auto bufferSize = screenInfo.GetBufferSize ().Dimensions ();
45
45
if (coordCursor.x < 0 )
@@ -70,42 +70,19 @@ static void AdjustCursorPosition(SCREEN_INFORMATION& screenInfo, _In_ til::point
70
70
71
71
if (coordCursor.y >= bufferSize.height )
72
72
{
73
- const auto vtIo = ServiceLocator::LocateGlobals ().getConsoleInformation ().GetVtIo ();
74
- const auto renderer = ServiceLocator::LocateGlobals ().pRender ;
75
- const auto needsConPTYWorkaround = interactive && vtIo->IsUsingVt ();
76
73
auto & buffer = screenInfo.GetTextBuffer ();
77
- const auto isActiveBuffer = buffer.IsActiveBuffer ( );
74
+ buffer.IncrementCircularBuffer (buffer. GetCurrentAttributes () );
78
75
79
- // ConPTY translates scrolling into newlines. We don't want that during cooked reads (= "cmd.exe prompts")
80
- // because the entire prompt is supposed to fit into the VT viewport, with no scrollback. If we didn't do that,
81
- // any prompt larger than the viewport will cause >1 lines to be added to scrollback, even if typing backspaces.
82
- // You can test this by removing this branch, launch Windows Terminal, and fill the entire viewport with text in cmd.exe.
83
- if (needsConPTYWorkaround)
76
+ if (buffer.IsActiveBuffer ())
84
77
{
85
- buffer.SetAsActiveBuffer (false );
86
- buffer.IncrementCircularBuffer (buffer.GetCurrentAttributes ());
87
- buffer.SetAsActiveBuffer (isActiveBuffer);
88
-
89
- if (isActiveBuffer && renderer)
78
+ if (const auto notifier = ServiceLocator::LocateAccessibilityNotifier ())
90
79
{
91
- renderer-> TriggerRedrawAll ( );
80
+ notifier-> NotifyConsoleUpdateScrollEvent ( 0 , - 1 );
92
81
}
93
- }
94
- else
95
- {
96
- buffer.IncrementCircularBuffer (buffer.GetCurrentAttributes ());
97
-
98
- if (isActiveBuffer)
82
+ if (const auto renderer = ServiceLocator::LocateGlobals ().pRender )
99
83
{
100
- if (const auto notifier = ServiceLocator::LocateAccessibilityNotifier ())
101
- {
102
- notifier->NotifyConsoleUpdateScrollEvent (0 , -1 );
103
- }
104
- if (renderer)
105
- {
106
- static constexpr til::point delta{ 0 , -1 };
107
- renderer->TriggerScroll (&delta);
108
- }
84
+ static constexpr til::point delta{ 0 , -1 };
85
+ renderer->TriggerScroll (&delta);
109
86
}
110
87
}
111
88
@@ -128,15 +105,11 @@ static void AdjustCursorPosition(SCREEN_INFORMATION& screenInfo, _In_ til::point
128
105
LOG_IF_FAILED (screenInfo.SetViewportOrigin (false , WindowOrigin, true ));
129
106
}
130
107
131
- if (interactive)
132
- {
133
- screenInfo.MakeCursorVisible (coordCursor);
134
- }
135
- LOG_IF_FAILED (screenInfo.SetCursorPosition (coordCursor, interactive));
108
+ LOG_IF_FAILED (screenInfo.SetCursorPosition (coordCursor, false ));
136
109
}
137
110
138
111
// As the name implies, this writes text without processing its control characters.
139
- static void _writeCharsLegacyUnprocessed (SCREEN_INFORMATION& screenInfo, const std::wstring_view& text, const bool interactive , til::CoordType* psScrollY)
112
+ void _writeCharsLegacyUnprocessed (SCREEN_INFORMATION& screenInfo, const std::wstring_view& text, til::CoordType* psScrollY)
140
113
{
141
114
const auto wrapAtEOL = WI_IsFlagSet (screenInfo.OutputMode , ENABLE_WRAP_AT_EOL_OUTPUT);
142
115
const auto hasAccessibilityEventing = screenInfo.HasAccessibilityEventing ();
@@ -165,18 +138,19 @@ static void _writeCharsLegacyUnprocessed(SCREEN_INFORMATION& screenInfo, const s
165
138
screenInfo.NotifyAccessibilityEventing (state.columnBegin , cursorPosition.y , state.columnEnd - 1 , cursorPosition.y );
166
139
}
167
140
168
- AdjustCursorPosition (screenInfo, cursorPosition, interactive, psScrollY);
141
+ AdjustCursorPosition (screenInfo, cursorPosition, psScrollY);
169
142
}
170
143
}
171
144
172
145
// This routine writes a string to the screen while handling control characters.
173
146
// `interactive` exists for COOKED_READ_DATA which uses it to transform control characters into visible text like "^X".
174
147
// Similarly, `psScrollY` is also used by it to track whether the underlying buffer circled. It requires this information to know where the input line moved to.
175
- void WriteCharsLegacy (SCREEN_INFORMATION& screenInfo, const std::wstring_view& text, const bool interactive, til::CoordType* psScrollY)
148
+ void WriteCharsLegacy (SCREEN_INFORMATION& screenInfo, const std::wstring_view& text, til::CoordType* psScrollY)
176
149
{
177
150
static constexpr wchar_t tabSpaces[8 ]{ L' ' , L' ' , L' ' , L' ' , L' ' , L' ' , L' ' , L' ' };
178
151
179
152
auto & textBuffer = screenInfo.GetTextBuffer ();
153
+ const auto width = textBuffer.GetSize ().Width ();
180
154
auto & cursor = textBuffer.GetCursor ();
181
155
const auto wrapAtEOL = WI_IsFlagSet (screenInfo.OutputMode , ENABLE_WRAP_AT_EOL_OUTPUT);
182
156
auto it = text.begin ();
@@ -197,15 +171,15 @@ void WriteCharsLegacy(SCREEN_INFORMATION& screenInfo, const std::wstring_view& t
197
171
{
198
172
pos.x = 0 ;
199
173
pos.y ++;
200
- AdjustCursorPosition (screenInfo, pos, interactive, psScrollY);
174
+ AdjustCursorPosition (screenInfo, pos, psScrollY);
201
175
}
202
176
}
203
177
204
178
// If ENABLE_PROCESSED_OUTPUT is set we search for C0 control characters and handle them like backspace, tab, etc.
205
- // If it's not set, we can just straight up give everything to _writeCharsLegacyUnprocessed .
179
+ // If it's not set, we can just straight up give everything to WriteCharsLegacyUnprocessed .
206
180
if (WI_IsFlagClear (screenInfo.OutputMode , ENABLE_PROCESSED_OUTPUT))
207
181
{
208
- _writeCharsLegacyUnprocessed (screenInfo, { it, end }, interactive, psScrollY);
182
+ _writeCharsLegacyUnprocessed (screenInfo, { it, end }, psScrollY);
209
183
it = end;
210
184
}
211
185
@@ -214,7 +188,7 @@ void WriteCharsLegacy(SCREEN_INFORMATION& screenInfo, const std::wstring_view& t
214
188
const auto nextControlChar = std::find_if (it, end, [](const auto & wch) { return !IS_GLYPH_CHAR (wch); });
215
189
if (nextControlChar != it)
216
190
{
217
- _writeCharsLegacyUnprocessed (screenInfo, { it, nextControlChar }, interactive, psScrollY);
191
+ _writeCharsLegacyUnprocessed (screenInfo, { it, nextControlChar }, psScrollY);
218
192
it = nextControlChar;
219
193
}
220
194
@@ -223,35 +197,24 @@ void WriteCharsLegacy(SCREEN_INFORMATION& screenInfo, const std::wstring_view& t
223
197
switch (*it)
224
198
{
225
199
case UNICODE_NULL:
226
- if (interactive)
227
- {
228
- break ;
229
- }
230
- _writeCharsLegacyUnprocessed (screenInfo, { &tabSpaces[0 ], 1 }, interactive, psScrollY);
200
+ _writeCharsLegacyUnprocessed (screenInfo, { &tabSpaces[0 ], 1 }, psScrollY);
231
201
continue ;
232
202
case UNICODE_BELL:
233
- if (interactive)
234
- {
235
- break ;
236
- }
237
203
std::ignore = screenInfo.SendNotifyBeep ();
238
204
continue ;
239
205
case UNICODE_BACKSPACE:
240
206
{
241
- // Backspace handling for interactive mode should happen in COOKED_READ_DATA
242
- // where it has full control over the text and can delete it directly.
243
- // Otherwise handling backspacing tabs/whitespace can turn up complex and bug-prone.
244
- assert (!interactive);
245
207
auto pos = cursor.GetPosition ();
246
208
pos.x = textBuffer.GetRowByOffset (pos.y ).NavigateToPrevious (pos.x );
247
- AdjustCursorPosition (screenInfo, pos, interactive, psScrollY);
209
+ AdjustCursorPosition (screenInfo, pos, psScrollY);
248
210
continue ;
249
211
}
250
212
case UNICODE_TAB:
251
213
{
252
214
const auto pos = cursor.GetPosition ();
253
- const auto tabCount = gsl::narrow_cast<size_t >(8 - (pos.x & 7 ));
254
- _writeCharsLegacyUnprocessed (screenInfo, { &tabSpaces[0 ], tabCount }, interactive, psScrollY);
215
+ const auto remaining = width - pos.x ;
216
+ const auto tabCount = gsl::narrow_cast<size_t >(std::min (remaining, 8 - (pos.x & 7 )));
217
+ _writeCharsLegacyUnprocessed (screenInfo, { &tabSpaces[0 ], tabCount }, psScrollY);
255
218
continue ;
256
219
}
257
220
case UNICODE_LINEFEED:
@@ -264,38 +227,29 @@ void WriteCharsLegacy(SCREEN_INFORMATION& screenInfo, const std::wstring_view& t
264
227
265
228
textBuffer.GetMutableRowByOffset (pos.y ).SetWrapForced (false );
266
229
pos.y = pos.y + 1 ;
267
- AdjustCursorPosition (screenInfo, pos, interactive, psScrollY);
230
+ AdjustCursorPosition (screenInfo, pos, psScrollY);
268
231
continue ;
269
232
}
270
233
case UNICODE_CARRIAGERETURN:
271
234
{
272
235
auto pos = cursor.GetPosition ();
273
236
pos.x = 0 ;
274
- AdjustCursorPosition (screenInfo, pos, interactive, psScrollY);
237
+ AdjustCursorPosition (screenInfo, pos, psScrollY);
275
238
continue ;
276
239
}
277
240
default :
278
241
break ;
279
242
}
280
243
281
- // In the interactive mode we replace C0 control characters (0x00-0x1f) with ASCII representations like ^C (= 0x03).
282
- if (interactive && *it < L' ' )
244
+ // As a special favor to incompetent apps that attempt to display control chars,
245
+ // convert to corresponding OEM Glyph Chars
246
+ const auto cp = ServiceLocator::LocateGlobals ().getConsoleInformation ().OutputCP ;
247
+ const auto ch = gsl::narrow_cast<char >(*it);
248
+ wchar_t wch = 0 ;
249
+ const auto result = MultiByteToWideChar (cp, MB_USEGLYPHCHARS, &ch, 1 , &wch, 1 );
250
+ if (result == 1 )
283
251
{
284
- const wchar_t wchs[2 ]{ L' ^' , static_cast <wchar_t >(*it + L' @' ) };
285
- _writeCharsLegacyUnprocessed (screenInfo, { &wchs[0 ], 2 }, interactive, psScrollY);
286
- }
287
- else
288
- {
289
- // As a special favor to incompetent apps that attempt to display control chars,
290
- // convert to corresponding OEM Glyph Chars
291
- const auto cp = ServiceLocator::LocateGlobals ().getConsoleInformation ().OutputCP ;
292
- const auto ch = gsl::narrow_cast<char >(*it);
293
- wchar_t wch = 0 ;
294
- const auto result = MultiByteToWideChar (cp, MB_USEGLYPHCHARS, &ch, 1 , &wch, 1 );
295
- if (result == 1 )
296
- {
297
- _writeCharsLegacyUnprocessed (screenInfo, { &wch, 1 }, interactive, psScrollY);
298
- }
252
+ _writeCharsLegacyUnprocessed (screenInfo, { &wch, 1 }, psScrollY);
299
253
}
300
254
}
301
255
}
358
312
359
313
if (WI_IsAnyFlagClear (screenInfo.OutputMode , ENABLE_VIRTUAL_TERMINAL_PROCESSING | ENABLE_PROCESSED_OUTPUT))
360
314
{
361
- WriteCharsLegacy (screenInfo, str, false , nullptr );
315
+ WriteCharsLegacy (screenInfo, str, nullptr );
362
316
}
363
317
else
364
318
{
0 commit comments