CSI K at end of line behaves wrongly #23633

Closed
opened 2026-01-31 08:47:45 +00:00 by claunia · 4 comments
Owner

Originally created by @chrisant996 on GitHub (Sep 21, 2025).

Windows Terminal version

1.24.2372.0

Windows build number

10.0.26100.6584

Other Software

The following linked zip file contains a cpp file that reproduces the issue, and sln and vcxproj files for compiling it with VS2022.

wt_csi_k.zip

Running the program shows first what the output is supposed to look like, and next what the output actually looks like in Windows Terminal.

Please refer to comments in the cpp file for details. There's also a comment with a command line to copy/paste into git-bash running in mintty to demonstrate that mintty behaves as expected.

Steps to reproduce

The issue repros in WT v1.22 through 1.24 (and in several older versions of WT as well).

Repro Steps in Windows Terminal:

  1. Download the linked wt_csi_k.zip file.
  2. Extract the files into a wt_csi_k directory somewhere.
  3. Important: Review the wt_csi_k.cpp file for details about the issue, and what the program does.
  4. Use VS2022 to build the project.
  5. In a Windows Terminal window, run the produced wt_csi_k.exe file.

Compare to git-bash in mintty:

  1. Run git-bash, which shows up in mintty.
  2. Make sure the terminal is 80 columns wide (or replace the 77 with the terminal width minus 3 and replace the 78 with the terminal width minus 2).
  3. Paste and execute either of the following commands:
    • echo -e '\e[77Gx中a\e[Kb\b文\e[A\e[78G'
    • echo -e '\e[77GxYYa\e[Kb\bZZ\e[A\e[78G'
  4. Compare the output within git-bash and mintty to the wt_csi_k program's output within Windows Terminal.

Expected Behavior

The program first prints what the output should look like -- that's what it should look like.

Actual Behavior

The program next prints the actual text sequences, and the CSI K changes the cursor position (incorrect) and clears the last column (incorrect), causing the output to become garbled and the final cursor position to be incorrect (wrong column and wrong row).

Originally created by @chrisant996 on GitHub (Sep 21, 2025). ### Windows Terminal version 1.24.2372.0 ### Windows build number 10.0.26100.6584 ### Other Software The following linked zip file contains a cpp file that reproduces the issue, and sln and vcxproj files for compiling it with VS2022. [wt_csi_k.zip](https://github.com/user-attachments/files/22450242/wt_csi_k.zip) Running the program shows first what the output is supposed to look like, and next what the output actually looks like in Windows Terminal. Please refer to comments in the cpp file for details. There's also a comment with a command line to copy/paste into `git-bash` running in `mintty` to demonstrate that `mintty` behaves as expected. ### Steps to reproduce The issue repros in WT v1.22 through 1.24 (and in several older versions of WT as well). **Repro Steps in Windows Terminal:** 1. Download the linked [wt_csi_k.zip](https://github.com/user-attachments/files/22450262/wt_csi_k.zip) file. 2. Extract the files into a `wt_csi_k` directory somewhere. 3. **Important:** Review the `wt_csi_k.cpp` file for details about the issue, and what the program does. 4. Use VS2022 to build the project. 5. In a Windows Terminal window, run the produced `wt_csi_k.exe` file. **Compare to git-bash in mintty:** 1. Run `git-bash`, which shows up in mintty. 2. Make sure the terminal is 80 columns wide (or replace the `77` with the terminal width minus 3 and replace the `78` with the terminal width minus 2). 3. Paste and execute either of the following commands: - `echo -e '\e[77Gx中a\e[Kb\b文\e[A\e[78G'` - `echo -e '\e[77GxYYa\e[Kb\bZZ\e[A\e[78G'` 4. Compare the output within git-bash and mintty to the `wt_csi_k` program's output within Windows Terminal. ### Expected Behavior The program first prints what the output should look like -- that's what it should look like. ### Actual Behavior The program next prints the actual text sequences, and the CSI K changes the cursor position (incorrect) and clears the last column (incorrect), causing the output to become garbled and the final cursor position to be incorrect (wrong column and wrong row).
claunia added the Needs-TriageIssue-Bug labels 2026-01-31 08:47:46 +00:00
Author
Owner

@chrisant996 commented on GitHub (Sep 21, 2025):

Image
@chrisant996 commented on GitHub (Sep 21, 2025): <img width="1092" height="171" alt="Image" src="https://github.com/user-attachments/assets/3808e3b7-71a3-402e-9654-847538d2c089" />
Author
Owner

@chrisant996 commented on GitHub (Sep 21, 2025):

Note: the repro program by default uses Chinese characters because that was the original repro that was reported to me. But the same problem happens with purely ASCII characters as well: run wt_csi_k --ascii to see the problem occur with ASCII characters.

@chrisant996 commented on GitHub (Sep 21, 2025): Note: the repro program by default uses Chinese characters because that was the original repro that was reported to me. But the same problem happens with purely ASCII characters as well: run `wt_csi_k --ascii` to see the problem occur with ASCII characters.
Author
Owner

@j4james commented on GitHub (Sep 21, 2025):

This is working as intended, and I think you'll find that Xterm works in exactly the same way as Windows Terminal. The expected behavior is documented in section D.6 of the DEC STD 070 manual. This is a partial quote from that section:

Normally the Active Position is advanced immediately after a character is entered into the display. The only exception to this is when a character is entered into the last column position of a line. Writing a character into the last position in a line causes a special flag (referred to as the Last Column Flag) to be set. This flag is checked each time a character is entered into the display, and will cause the Active position to advance to the first column of the next line PRIOR to entering that character. The flag is then reset.

The Last Column Flag should also be reset by executing any control which potentially changes the Active Position from the end-of-line position. These controls include the following...

It then goes on to list a bunch of controls, including ERASE IN LINE.

So when you write x中a or xYYa starting at column 77, the a is written to column 80, but the Active Position remains in column 80 and sets the Last Column Flag.

And when you then execute \e[K (i.e. ERASE IN LINE), that a is erased, because column 80 is the starting point of the erase operation (this is mintty's first bug).

As explained above, the ERASE IN LINE control also resets the Last Column Flag, so when you output the b, that's also written into column 80, instead of wrapping onto the next line (this is mintty's second bug).

And again the Active Position remains in column 80 (although the Last Column Flag is now set), so the \b control moves the Active Position back to column 79, and the 文 or ZZ is written into columns 79 and 80.

So the end result is expected to be x 文 (the 文 ends up deleting the 中 because they overlap), or xYZZ for the plain ASCII version. At this point the Active Position has never moved from the original line, so when you execute CUU, that's going to move you onto the line above.

@j4james commented on GitHub (Sep 21, 2025): This is working as intended, and I think you'll find that Xterm works in exactly the same way as Windows Terminal. The expected behavior is documented in section D.6 of the DEC STD 070 manual. This is a partial quote from that section: > Normally the Active Position is advanced immediately after a character is entered into the display. The only exception to this is when a character is entered into the last column position of a line. Writing a character into the last position in a line causes a special flag (referred to as the Last Column Flag) to be set. This flag is checked each time a character is entered into the display, and will cause the Active position to advance to the first column of the next line PRIOR to entering that character. The flag is then reset. > > The Last Column Flag should also be reset by executing any control which potentially changes the Active Position from the end-of-line position. These controls include the following... It then goes on to list a bunch of controls, including `ERASE IN LINE`. So when you write `x中a` or `xYYa` starting at column 77, the `a` is written to column 80, but the Active Position remains in column 80 and sets the Last Column Flag. And when you then execute `\e[K` (i.e. `ERASE IN LINE`), that `a` is erased, because column 80 is the starting point of the erase operation (this is mintty's first bug). As explained above, the `ERASE IN LINE` control also resets the Last Column Flag, so when you output the `b`, that's also written into column 80, instead of wrapping onto the next line (this is mintty's second bug). And again the Active Position remains in column 80 (although the Last Column Flag is now set), so the `\b` control moves the Active Position back to column 79, and the `文` or `ZZ` is written into columns 79 and 80. So the end result is expected to be `x 文` (the `文` ends up deleting the `中` because they overlap), or `xYZZ` for the plain ASCII version. At this point the Active Position has never moved from the original line, so when you execute `CUU`, that's going to move you onto the line above.
Author
Owner

@chrisant996 commented on GitHub (Sep 21, 2025):

Wow. Ok so mintty is non-compliant, then.

Thanks for sharing the spec. Seems like a strange choice to have made EIL reset the flag, but it's moot at this late date.

@chrisant996 commented on GitHub (Sep 21, 2025): Wow. Ok so mintty is non-compliant, then. Thanks for sharing the spec. Seems like a strange choice to have made EIL reset the flag, but it's moot at this late date.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#23633