Certain SGR attributes are not preserved after a resize sequence #3559

Open
opened 2026-01-30 23:24:23 +00:00 by claunia · 0 comments
Owner

Originally created by @j4james on GitHub (Aug 26, 2019).

Environment

Windows build number: Version 10.0.18362.239

Steps to reproduce

Open a WSL conhost shell, and execute the following two commands:

printf "\e[30;48;5;214m ORANGE \n\e[8;24;80t ORANGE \e[m\n"
printf "\e[7;38;5;15;48;5;4m REVERSE \n\e[8;24;80t REVERSE \e[m\n"

The first command uses an SGR escape sequence to set the background color to index 214 (a shade of orange), writes out the text "ORANGE", then uses the XTerm window manipulation sequence to resize the screen, and writes out "ORANGE" again.

The second command does the same sort of thing but with different attributes. It sets the colors to bright white (index 15) on blue (index 4), and also enable the reverse video attribute (making it blue on white).

Expected behavior

The screen resize should have no effect on the active SGR attributes, so in each case I'd expect to see two matching lines of text with identical colors.

Actual behavior

In the first test, the second "ORANGE" line is a shade of yellow rather than orange (the exact color will likely depend on your palette).

In the second test, the second "REVERSE" line is not actually reversed - it's white on blue instead of blue on white.

image

Cause

The resize escape sequence is handled by the DispatchCommon::s_ResizeWindow method, which does so by reading the screen buffer info with GetConsoleScreenBufferInfoEx, modifiying just the dwSize and srWindow fields (i.e the buffer and viewport sizes), and then writing the updated info back with SetConsoleScreenBufferInfoEx. The problem is that the CONSOLE_SCREEN_BUFFER_INFOEX structure can't reliable represent the text attributes in the wAttributes field, so they can become corrupted in the process.

The DECCOLM escape sequence, which is handled by the AdaptDispatch::SetColumns method, has essentially the same problem.

The reverse video case could probably be fixed with improvements to the GenerateLegacyAttributes method, but it's never going to be possible to accurately handle every attribute value with a legacy equivalent. I think the real solution is to avoid using the SetConsoleScreenBufferInfoEx method, and try and update the window and buffer size more directly, via SetConsoleWindowInfo and SetConsoleScreenBufferSize. I haven't actually tried that, though, so maybe it's not as simple as I think.

Originally created by @j4james on GitHub (Aug 26, 2019). # Environment ```none Windows build number: Version 10.0.18362.239 ``` # Steps to reproduce Open a WSL conhost shell, and execute the following two commands: printf "\e[30;48;5;214m ORANGE \n\e[8;24;80t ORANGE \e[m\n" printf "\e[7;38;5;15;48;5;4m REVERSE \n\e[8;24;80t REVERSE \e[m\n" The first command uses an SGR escape sequence to set the background color to index 214 (a shade of orange), writes out the text "ORANGE", then uses the XTerm window manipulation sequence to resize the screen, and writes out "ORANGE" again. The second command does the same sort of thing but with different attributes. It sets the colors to bright white (index 15) on blue (index 4), and also enable the reverse video attribute (making it blue on white). # Expected behavior The screen resize should have no effect on the active SGR attributes, so in each case I'd expect to see two matching lines of text with identical colors. # Actual behavior In the first test, the second "ORANGE" line is a shade of yellow rather than orange (the exact color will likely depend on your palette). In the second test, the second "REVERSE" line is not actually reversed - it's white on blue instead of blue on white. ![image](https://user-images.githubusercontent.com/4181424/63697684-4c363480-c815-11e9-87c8-d652a0ca6b89.png) # Cause The resize escape sequence is handled by the [`DispatchCommon::s_ResizeWindow`](https://github.com/microsoft/terminal/blob/9b92986b49bed8cc41fde4d6ef080921c41e6d9e/src/terminal/adapter/DispatchCommon.cpp#L20-L68) method, which does so by reading the screen buffer info with `GetConsoleScreenBufferInfoEx`, modifiying just the `dwSize` and `srWindow` fields (i.e the buffer and viewport sizes), and then writing the updated info back with `SetConsoleScreenBufferInfoEx`. The problem is that the `CONSOLE_SCREEN_BUFFER_INFOEX` structure can't reliable represent the text attributes in the `wAttributes` field, so they can become corrupted in the process. The DECCOLM escape sequence, which is handled by the [`AdaptDispatch::SetColumns`](https://github.com/microsoft/terminal/blob/594a7e4501d1108267388197ec187ca77f82756b/src/terminal/adapter/adaptDispatch.cpp#L1078-L1095) method, has essentially the same problem. The reverse video case could probably be fixed with improvements to the `GenerateLegacyAttributes` method, but it's never going to be possible to accurately handle every attribute value with a legacy equivalent. I think the real solution is to avoid using the `SetConsoleScreenBufferInfoEx` method, and try and update the window and buffer size more directly, via `SetConsoleWindowInfo` and `SetConsoleScreenBufferSize`. I haven't actually tried that, though, so maybe it's not as simple as I think.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#3559