Issue with line-wrapped tabstops after resizing the window #6559

Closed
opened 2026-01-31 00:41:39 +00:00 by claunia · 7 comments
Owner

Originally created by @ethanherbertson on GitHub (Feb 20, 2020).

Environment

Windows build number: 10.0.18362.0
Windows Terminal version (if applicable): 0.9.433.0

Steps to reproduce

  1. From WSL, echo a line of text containing a literal tab character, long enough to cause the tab character to render AFTER Terminal line-wraps the line (e.g. on a second line).
  2. Resize Terminal, increasing its width enough so that the whole line of text now fits on a single line
  3. Print the same line of text again.

Expected behavior

The second printing of the text is printed in a single line, with the tab producing the expected amount of horizontal whitespace.

Actual behavior

The line of text is corrupted, with the tab consuming too much horizontal whitespace (= the full remaining width of the window - 1), causing the line to sill be wrapped across multiple lines as well.

I would assume this is related to the various problems listed in #4200, but I don't see this specifically mentioned (though some of the issues listed there are beyond my ability to grok).

Fully fleshed-out example:

Assuming an initial window width of approximately 80 characters, here's an example command that will print a suitable line:

echo -e "123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 Hardtab:\t123456789 123456789 123456789 123456789"

On a smallish window, that renders something like this:

image

If you then resize the window wide enough that the output line is reflowed onto a single line...

image

... and then re-run the echo you get something clearly quite wrong:

image

Originally created by @ethanherbertson on GitHub (Feb 20, 2020). <!-- 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨 I ACKNOWLEDGE THE FOLLOWING BEFORE PROCEEDING: 1. If I delete this entire template and go my own path, the core team may close my issue without further explanation or engagement. 2. If I list multiple bugs/concerns in this one issue, the core team may close my issue without further explanation or engagement. 3. If I write an issue that has many duplicates, the core team may close my issue without further explanation or engagement (and without necessarily spending time to find the exact duplicate ID number). 4. If I leave the title incomplete when filing the issue, the core team may close my issue without further explanation or engagement. 5. If I file something completely blank in the body, the core team may close my issue without further explanation or engagement. All good? Then proceed! --> <!-- This bug tracker is monitored by Windows Terminal development team and other technical folks. **Important: When reporting BSODs or security issues, DO NOT attach memory dumps, logs, or traces to Github issues**. Instead, send dumps/traces to secure@microsoft.com, referencing this GitHub issue. If this is an application crash, please also provide a Feedback Hub submission link so we can find your diagnostic data on the backend. Use the category "Apps > Windows Terminal (Preview)" and choose "Share My Feedback" after submission to get the link. Please use this form and describe your issue, concisely but precisely, with as much detail as possible. --> # Environment ```none Windows build number: 10.0.18362.0 Windows Terminal version (if applicable): 0.9.433.0 ``` # Steps to reproduce 1. From WSL, echo a line of text containing a literal tab character, long enough to cause the tab character to render AFTER Terminal line-wraps the line (e.g. on a second line). 2. Resize Terminal, increasing its width enough so that the whole line of text now fits on a single line 3. Print the same line of text again. # Expected behavior The second printing of the text is printed in a single line, with the tab producing the expected amount of horizontal whitespace. # Actual behavior The line of text is corrupted, with the tab consuming too much horizontal whitespace (= the full remaining width of the window - 1), causing the line to sill be wrapped across multiple lines as well. I would assume this is related to the various problems listed in #4200, but I don't see this specifically mentioned (though some of the issues listed there are beyond my ability to grok). Fully fleshed-out example: Assuming an initial window width of approximately 80 characters, here's an example command that will print a suitable line: ```bash echo -e "123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 Hardtab:\t123456789 123456789 123456789 123456789" ``` On a smallish window, that renders something like this: ![image](https://user-images.githubusercontent.com/6392396/74988047-5f137580-5402-11ea-86d5-289e54c78b07.png) If you then resize the window wide enough that the output line is reflowed onto a single line... ![image](https://user-images.githubusercontent.com/6392396/74988084-7b171700-5402-11ea-80cb-f74f1522f87b.png) ... and then re-run the echo you get something clearly quite wrong: ![image](https://user-images.githubusercontent.com/6392396/74988134-a6016b00-5402-11ea-8c48-5c6d431b6a09.png)
Author
Owner

@j4james commented on GitHub (Feb 21, 2020):

If this is what I think it is, it's a bug in conhost. The problem is that the VT tab stops are initialized at startup (more or less) in just enough positions to fill the width of the buffer. If you make the screen wider, there won't be any tab stops in the newly revealed area.

Now it's not just a matter of reinitializing the tab stops after a resize, because we need to preserve the state of any tab stops which have been added and removed by VT escape sequences. And when the screen is made narrower, we even need to remember the state of tab stops that have gone off screen in case the screen is made wider again (at which point they will need to be reapplied).

The bottom line is it's probably not a simple fix. I have an item on my TODO list to put together a proposal for the tab management code that would address this, but I just haven't gotten around to it yet. Part of that was also moving the tab management out of the SCREEN_INFORMATION class and into the AdaptDispatch (or at least a property of that class), so that functionality could more easily be shared with the Terminal VT implementation one day.

If this considered a priority, though, you may want to consider a simpler patch of the existing code, even if it doesn't perfectly address all the edge cases.

@j4james commented on GitHub (Feb 21, 2020): If this is what I think it is, it's a bug in conhost. The problem is that the VT tab stops are initialized at startup (more or less) in just enough positions to fill the width of the buffer. If you make the screen wider, there won't be any tab stops in the newly revealed area. Now it's not just a matter of reinitializing the tab stops after a resize, because we need to preserve the state of any tab stops which have been added and removed by VT escape sequences. And when the screen is made narrower, we even need to remember the state of tab stops that have gone off screen in case the screen is made wider again (at which point they will need to be reapplied). The bottom line is it's probably not a simple fix. I have an item on my TODO list to put together a proposal for the tab management code that would address this, but I just haven't gotten around to it yet. Part of that was also moving the tab management out of the `SCREEN_INFORMATION` class and into the `AdaptDispatch` (or at least a property of that class), so that functionality could more easily be shared with the Terminal VT implementation one day. If this considered a priority, though, you may want to consider a simpler patch of the existing code, even if it doesn't perfectly address all the edge cases.
Author
Owner

@ethanherbertson commented on GitHub (Feb 21, 2020):

The problem is that the VT tab stops are initialized at startup (more or less) in just enough positions to fill the width of the buffer. If you make the screen wider, there won't be any tab stops in the newly revealed area.

Yeah I just ran a quick test and this looks like a good explanation. I was able to reproduce my issue with just (a) a small initial window size, (b) a resize to make the window larger, and (c) printing a line with a literal tab that falls beyond the original width of the window. I thought the issue only appeared if you first caused a tab to appear on the second+ line of a wrapped line first, before resizing... but that's not the case after all.

As to priorities: This is a real pain in the neck when you have a CLI program that uses tabs in its output, as if your window started too small for your output there's no way to resize it to make it work. (The workaround is to start a new Terminal tab after resizing—which is at best inconvenient—or to pipe the output through a formatter which converts tabs to spaces.)

@ethanherbertson commented on GitHub (Feb 21, 2020): >The problem is that the VT tab stops are initialized at startup (more or less) in just enough positions to fill the width of the buffer. If you make the screen wider, there won't be any tab stops in the newly revealed area. Yeah I just ran a quick test and this looks like a good explanation. I was able to reproduce my issue with just (a) a small initial window size, (b) a resize to make the window larger, and (c) printing a line with a literal tab that falls beyond the original width of the window. I thought the issue only appeared if you first caused a tab to appear on the second+ line of a wrapped line first, *before* resizing... but that's not the case after all. As to priorities: This is a real pain in the neck when you have a CLI program that uses tabs in its output, as if your window *started* too small for your output there's no way to resize it to make it work. (The workaround is to start a new Terminal tab after resizing—which is at best inconvenient—or to pipe the output through a formatter which converts tabs to spaces.)
Author
Owner

@DHowett-MSFT commented on GitHub (Feb 21, 2020):

I'm curious, actually. This is a big of an annoying ask, so feel free to shoot me down. I can't reproduce it over here, so:

If you grab the latest .msixbundle from our releases page and unzip it (it's just a zip file), then further unzip the "x64" .msix inside it (also just a zip file) and run OpenConsole.exe... do you still see this behavior?

OpenConsole is the console host (conhost.exe), but built out of this repository. That'll help us narrow down whether it's conhost or the terminal that's doing something wrong here.

@DHowett-MSFT commented on GitHub (Feb 21, 2020): I'm curious, actually. This is a big of an annoying ask, so feel free to shoot me down. I can't reproduce it over here, so: If you grab the latest .msixbundle from our releases page and unzip it (it's just a zip file), then further unzip the "x64" .msix inside it (also just a zip file) and _run OpenConsole.exe_... do you still see this behavior? OpenConsole is the console host (conhost.exe), but built out of this repository. That'll help us narrow down whether it's conhost or the terminal that's doing something wrong here.
Author
Owner

@ethanherbertson commented on GitHub (Feb 24, 2020):

If you grab the latest .msixbundle from our releases page and unzip it (it's just a zip file), then further unzip the "x64" .msix inside it (also just a zip file) and run OpenConsole.exe... do you still see this behavior?

Yes, I've just replicated it using CascadiaPackage_0.9.433.0_x64.msix/OpenConsole.exe:

image

The space between square brackets is a tab.

@ethanherbertson commented on GitHub (Feb 24, 2020): > If you grab the latest .msixbundle from our releases page and unzip it (it's just a zip file), then further unzip the "x64" .msix inside it (also just a zip file) and _run OpenConsole.exe_... do you still see this behavior? Yes, I've just replicated it using `CascadiaPackage_0.9.433.0_x64.msix/OpenConsole.exe`: ![image](https://user-images.githubusercontent.com/6392396/75168249-32a27680-56ec-11ea-824a-c34f38526713.png) The space between square brackets is a tab.
Author
Owner

@ethanherbertson commented on GitHub (Feb 24, 2020):

And, because why not, here's the file I tested with.

tabtest.txt

@ethanherbertson commented on GitHub (Feb 24, 2020): And, because why not, here's the file I tested with. [tabtest.txt](https://github.com/microsoft/terminal/files/4245451/tabtest.txt)
Author
Owner

@ethanherbertson commented on GitHub (Feb 24, 2020):

The problem is that the VT tab stops are initialized at startup (more or less)

IANAEITE (I Am Not An Expert In Terminal Emulation)... but that seems like a strange choice in and of itself. I'd have thought the only stateful tab stops would be the user-specified ones. Is there a benefit to pre-calculating the rest?

(Also, I'd just like to say: I am constantly and profoundly impressed with this project, this team, and this community. You guys rock! This project is keeping Windows my preferred development environment.)

@ethanherbertson commented on GitHub (Feb 24, 2020): > The problem is that the VT tab stops are initialized at startup (more or less) IANAEITE (I Am Not An Expert In Terminal Emulation)... but that seems like a strange choice in and of itself. I'd have thought the only stateful tab stops would be the user-specified ones. Is there a benefit to pre-calculating the rest? (Also, I'd just like to say: I am constantly and profoundly impressed with this project, this team, and this community. You guys rock! This project is keeping Windows my preferred development environment.)
Author
Owner

@ghost commented on GitHub (Apr 22, 2020):

:tada:This issue was addressed in #5173, which has now been successfully released as Windows Terminal Preview v0.11.1121.0.🎉

Handy links:

@ghost commented on GitHub (Apr 22, 2020): :tada:This issue was addressed in #5173, which has now been successfully released as `Windows Terminal Preview v0.11.1121.0`.:tada: Handy links: * [Release Notes](https://github.com/microsoft/terminal/releases/tag/v0.11.1121.0) * [Store Download](https://www.microsoft.com/store/apps/9n0dx20hk701?cid=storebadge&ocid=badge)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#6559