[PR #14640] Merge the PrintString functionality into AdaptDispatch #30177

Open
opened 2026-01-31 09:39:08 +00:00 by claunia · 0 comments
Owner

Original Pull Request: https://github.com/microsoft/terminal/pull/14640

State: closed
Merged: Yes


The main purpose of this PR was to merge the ITerminalApi::PrintString
implementations into a shared method in AdaptDispatch, and avoid the
VT code path depending on WriteCharsLegacy. But this refactoring has
also fixed some bugs that existed in the original implementations.

This helps to close the gap between the Conhost and Terminal (#13408).

I started by taking the WriteCharsLegacy implementation, and stripping
out everything that didn't apply to the VT code path. What was left was
a fairly simple loop with the following steps:

  1. Check if delayed wrap is set, and if so, move to the next line.
  2. Write out as much of the string as will fit on the current line.
  3. If we reach the end of the line, set the delayed wrap flag again.
  4. Repeat the loop until the entire string has been output.

But step 2 was a little more complicated than necessary because of its
legacy history. It was copying the string into a temporary buffer,
manually estimated how much of it would fit, and then passing on that
partial buffer to the TextBuffer::Write method.

In the new implementation, we just pass the entire string directly to
TextBuffer::WriteLine, and that handles the clipping itself. The
returned OutputCellIterator tells us how much of the string is left.
This approach fixes some issues with wide characters, and should also
cope better with future buffer enhancements.

Another improvement from the new implementation is that the Terminal now
handles delayed EOL wrap correctly. However, the downside of this is
that it introduced a cursor-dropping bug that previously only affected
conhost. I hadn't originally intended to fix that, but it became more of
an issue now.

The root cause was the fact that we called cursor.StartDeferDrawing()
before outputting the text, and this was something I had adopted in the
new implementation as well. But I've now removed that, and instead just
call cursor.SetIsOn(false). This seems to avoid the cursor droppings,
and hopefully still has similar performance benefits.

The other thing worth mentioning is that I've eliminated some special
casing handling for the ENABLE_VIRTUAL_TERMINAL_PROCESSING mode and
the WC_DELAY_EOL_WRAP flag in the WriteCharsLegacy function. They
were only used for VT output, so aren't needed here anymore.

Validation Steps Performed

I've just been testing manually, writing out sample text both in ASCII
and with wide Unicode chars. I've made sure it wraps correctly when
exceeding the available space, but doesn't wrap when stopped at the last
column, and with DECAWM disabled, it doesn't wrap at all.

I've also confirmed that the test case from issue #12739 is now working
correctly, and the cursor no longer disappears in Windows Terminal when
writing to the last column (i.e. the delayed EOL wrap is working).

Closes #780
Closes #6162
Closes #6555
Closes #12440
Closes #12739

**Original Pull Request:** https://github.com/microsoft/terminal/pull/14640 **State:** closed **Merged:** Yes --- The main purpose of this PR was to merge the `ITerminalApi::PrintString` implementations into a shared method in `AdaptDispatch`, and avoid the VT code path depending on `WriteCharsLegacy`. But this refactoring has also fixed some bugs that existed in the original implementations. This helps to close the gap between the Conhost and Terminal (#13408). I started by taking the `WriteCharsLegacy` implementation, and stripping out everything that didn't apply to the VT code path. What was left was a fairly simple loop with the following steps: 1. Check if _delayed wrap_ is set, and if so, move to the next line. 2. Write out as much of the string as will fit on the current line. 3. If we reach the end of the line, set the _delayed wrap_ flag again. 4. Repeat the loop until the entire string has been output. But step 2 was a little more complicated than necessary because of its legacy history. It was copying the string into a temporary buffer, manually estimated how much of it would fit, and then passing on that partial buffer to the `TextBuffer::Write` method. In the new implementation, we just pass the entire string directly to `TextBuffer::WriteLine`, and that handles the clipping itself. The returned `OutputCellIterator` tells us how much of the string is left. This approach fixes some issues with wide characters, and should also cope better with future buffer enhancements. Another improvement from the new implementation is that the Terminal now handles delayed EOL wrap correctly. However, the downside of this is that it introduced a cursor-dropping bug that previously only affected conhost. I hadn't originally intended to fix that, but it became more of an issue now. The root cause was the fact that we called `cursor.StartDeferDrawing()` before outputting the text, and this was something I had adopted in the new implementation as well. But I've now removed that, and instead just call `cursor.SetIsOn(false)`. This seems to avoid the cursor droppings, and hopefully still has similar performance benefits. The other thing worth mentioning is that I've eliminated some special casing handling for the `ENABLE_VIRTUAL_TERMINAL_PROCESSING` mode and the `WC_DELAY_EOL_WRAP` flag in the `WriteCharsLegacy` function. They were only used for VT output, so aren't needed here anymore. ## Validation Steps Performed I've just been testing manually, writing out sample text both in ASCII and with wide Unicode chars. I've made sure it wraps correctly when exceeding the available space, but doesn't wrap when stopped at the last column, and with `DECAWM` disabled, it doesn't wrap at all. I've also confirmed that the test case from issue #12739 is now working correctly, and the cursor no longer disappears in Windows Terminal when writing to the last column (i.e. the delayed EOL wrap is working). Closes #780 Closes #6162 Closes #6555 Closes #12440 Closes #12739
claunia added the pull-request label 2026-01-31 09:39:08 +00:00
Sign in to join this conversation.
No Label pull-request
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#30177