Saving/restoring character attributes (and DECSCNM)? #12223

Open
opened 2026-01-31 03:09:27 +00:00 by claunia · 7 comments
Owner

Originally created by @vefatica on GitHub (Jan 27, 2021).

Microsoft Windows 10 Pro for Workstations
10.0.19042.746 (2009, 20H2)
WindowsTerminalPreview_1.5.3242.0_x64

I have a VBEEP command (visual beep, plugin for TCC.EXE from JPSoft). It saves the character attributes in the viewport like this.

dwSize = con.csbi.dwSize.X * con.csbi.dwSize.Y;	// terminal viewport
ReadConsoleOutputAttribute(con.h, attrs_original, dwSize, {0,0}, &dwRead); // get current attributes

Then it momentarily changes all attributes to the reverse of the default, like this.

attrs_reversed = ((con.csbi.wAttributes & 0x00F0) >> 4) | ((con.csbi.wAttributes & 0x000F) << 4);
FillConsoleOutputAttribute(con.h, attrs_reversed, dwSize, {0,0}, &dwWritten);

Then it restores the original attributes, like this.

WriteConsoleOutputAttribute(con.h, attrs_original, dwSize, {0,0}, &dwWritten); // back to original attributes

But, as I hope can be seen below, After executing VBEEP, the attributes of previously displayed text seem to have changed. Check out the display of the previous "echos ..." commands before/after the "vbeep" command; lines that were half yellow before the vbeep, are all yellow afterward.

https://user-images.githubusercontent.com/61856645/106033613-eef48180-609f-11eb-95d6-b508c3c01e62.mp4

Originally created by @vefatica on GitHub (Jan 27, 2021). Microsoft Windows 10 Pro for Workstations 10.0.19042.746 (2009, 20H2) WindowsTerminalPreview_1.5.3242.0_x64 I have a VBEEP command (visual beep, plugin for TCC.EXE from JPSoft). It saves the character attributes in the viewport like this. ``` dwSize = con.csbi.dwSize.X * con.csbi.dwSize.Y; // terminal viewport ReadConsoleOutputAttribute(con.h, attrs_original, dwSize, {0,0}, &dwRead); // get current attributes ``` Then it momentarily changes all attributes to the reverse of the default, like this. ``` attrs_reversed = ((con.csbi.wAttributes & 0x00F0) >> 4) | ((con.csbi.wAttributes & 0x000F) << 4); FillConsoleOutputAttribute(con.h, attrs_reversed, dwSize, {0,0}, &dwWritten); ``` Then it restores the original attributes, like this. `WriteConsoleOutputAttribute(con.h, attrs_original, dwSize, {0,0}, &dwWritten); // back to original attributes` But, as I hope can be seen below, After executing VBEEP, the attributes of previously displayed text seem to have changed. Check out the display of the previous "echos ..." commands before/after the "vbeep" command; lines that were half yellow before the vbeep, are all yellow afterward. https://user-images.githubusercontent.com/61856645/106033613-eef48180-609f-11eb-95d6-b508c3c01e62.mp4
claunia added the Product-ConhostArea-OutputIssue-BugPriority-3Impact-Visual labels 2026-01-31 03:09:27 +00:00
Author
Owner

@zadjii-msft commented on GitHub (Jan 27, 2021):

Huh. Could be two things:

  1. if you write to the attributes of the rightmost char in a row with FillConsoleOutputAttribute, then we extend that attribute to the end of the row, rather than leave it ending where it currently is.
  2. (perhaps more likely) when someone asks to ReadConsoleOutputAttribute for the entire row, we just fill in all the cells after the rightmost char with the attributes of the last cell. That ends up roundtripping, and filling the whole end of the row with those attrs.

I bet we could write a test for this fairly easily...

@zadjii-msft commented on GitHub (Jan 27, 2021): Huh. Could be two things: 1. if you write to the attributes of the rightmost char in a row with `FillConsoleOutputAttribute`, then we extend that attribute to the end of the row, rather than leave it ending where it currently is. 2. (perhaps more likely) when someone asks to `ReadConsoleOutputAttribute` for the entire row, we just fill in all the cells after the rightmost char with the attributes of the last cell. That ends up roundtripping, and filling the whole end of the row with those attrs. I bet we could write a test for this fairly easily...
Author
Owner

@vefatica commented on GitHub (Jan 27, 2021):

I'm using reading/filling attributes for the whole viewport, all at once (specifically reading/filling every cell, or so I thought). Are you saying that, even so, what you described is happening in each row?

@vefatica commented on GitHub (Jan 27, 2021): I'm using reading/filling attributes for the whole viewport, all at once (specifically reading/filling every cell, or so I thought). Are you saying that, even so, what you described is happening in each row?
Author
Owner

@j4james commented on GitHub (Jan 27, 2021):

I think I know what this is. When I added the DECSCNM functionality to Windows Terminal I noticed that it exposed a flaw in the way conpty optimized runs of spaces, and I think this is an example of that flaw. You can read more in the thread here: https://github.com/microsoft/terminal/pull/6809#issuecomment-654871619

At the time, @DHowett and I decided it was a fairly obscure edge case, so we thought we could leave it broken and probably nobody would notice. It seems we were wrong. 😄

@j4james commented on GitHub (Jan 27, 2021): I think I know what this is. When I added the `DECSCNM` functionality to Windows Terminal I noticed that it exposed a flaw in the way conpty optimized runs of spaces, and I think this is an example of that flaw. You can read more in the thread here: https://github.com/microsoft/terminal/pull/6809#issuecomment-654871619 At the time, @DHowett and I decided it was a fairly obscure edge case, so we thought we could leave it broken and probably nobody would notice. It seems we were wrong. 😄
Author
Owner

@DHowett commented on GitHub (Jan 28, 2021):

Oh gosh, you're totally right. I'm also willing to call this P3 and say "DECSCNM's most common use is visual belling, so if it happens to look funny for a small number of milliseconds it's okay." 😄

@DHowett commented on GitHub (Jan 28, 2021): Oh gosh, you're totally right. I'm also willing to call this P3 and say "DECSCNM's most common use is visual belling, so if it happens to look funny for a small number of milliseconds it's _okay_." :smile:
Author
Owner

@vefatica commented on GitHub (May 12, 2021):

"DECSCNM's most common use is visual belling, so if it happens to look funny for a small number of milliseconds it's okay."

Do you really think so?

I see there's a PR about flashing the pane on BEL. Will it use the same inversion as DECSCNM? That can get pretty hideous looking, especially if there's colored text (and those colors may be auto-extended to EOL on the inverted screen). Negative feedback wouldn't surprise me.

@vefatica commented on GitHub (May 12, 2021): > "DECSCNM's most common use is visual belling, so if it happens to look funny for a small number of milliseconds it's okay." Do you really think so? I see there's a PR about flashing the pane on BEL. Will it use the same inversion as DECSCNM? That can get pretty hideous looking, especially if there's colored text (and those colors may be auto-extended to EOL on the inverted screen). Negative feedback wouldn't surprise me.
Author
Owner

@DHowett commented on GitHub (May 12, 2021):

We've explicitly designed the visual bell implementation to do something only the Terminal UI can do-- nothing that looks like an application-controlled attribute :)

@DHowett commented on GitHub (May 12, 2021): We've explicitly designed the visual bell implementation to do something only the Terminal UI can do-- nothing that looks like an application-controlled attribute :)
Author
Owner

@vefatica commented on GitHub (May 12, 2021):

Are you saying that pane-flashing will not be the same as DECSCNM and that it's really nifty? If so, I can't wait to see it!

@vefatica commented on GitHub (May 12, 2021): Are you saying that pane-flashing will not be the same as DECSCNM and that it's really nifty? If so, I can't wait to see it!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#12223