DECAWM escape sequence doesn't work correctly in non-active buffer #16433

Open
opened 2026-01-31 05:10:50 +00:00 by claunia · 0 comments
Owner

Originally created by @j4james on GitHub (Jan 18, 2022).

Windows Terminal version

1.12.3472.0

Windows build number

10.0.19041.1415

Other Software

No response

Steps to reproduce

Run the following C++ test case in Windows Terminal or conhost.

#include <windows.h>
#include <conio.h>
#include <string>

int main() {
  // Get the handle of the main buffer, and also create a second buffer.
  HANDLE buff1 = GetStdHandle(STD_OUTPUT_HANDLE);
  HANDLE buff2 = CreateConsoleScreenBuffer(GENERIC_READ|GENERIC_WRITE, 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);

  // Enable VT processing.
  DWORD dwMode = 0;
  GetConsoleMode(buff1, &dwMode);
  dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
  SetConsoleMode(buff1, dwMode);

  DWORD written;
  std::wstring s;

  // Switch to the second buffer, but disable DECAWM in the main buffer.
  SetConsoleActiveScreenBuffer(buff2);
  s = L"\033[?7l";
  WriteConsoleW(buff1, s.data(), s.length(), &written, NULL);

  // Write some content starting at the end of the line in the second buffer.
  s = L"\033[2J\033[H\033[999C Second Buffer";
  WriteConsoleW(buff2, s.data(), s.length(), &written, NULL);
  getch();

  // Close the second buffer so the main buffer is active again.
  CloseHandle(buff2);

  // Write some content starting at the end of the line in the main buffer.
  s = L"\033[2J\033[H\033[999C Main Buffer";
  WriteConsoleW(buff1, s.data(), s.length(), &written, NULL);

  return 0;
}

Expected Behavior

The sample above opens two screen buffers, and while the second one is active, sends an DECAWM escape sequence (disabling auto-wrap) to the handle of the first buffer. It then writes some text at the end of the line in the second buffer, which should still wrap. After a keypress, it switches back to the main buffer, and again writes some text at the end of the line, which now shouldn't wrap.

Actual Behavior

The text written to the second buffer doesn't wrap, while the text written to the main buffer does wrap.

This is a similar in cause to issue #12193. The DoSrvPrivateSetAutoWrapMode function is updating the output mode in the active screen buffer, when it should be obtaining the target buffer from the handle that initiated the operation.

62c95b5017/src/host/getset.cpp (L1258-L1262)

Again I'm hoping this will be fixed by the conhost refactoring I'm working on.

Originally created by @j4james on GitHub (Jan 18, 2022). ### Windows Terminal version 1.12.3472.0 ### Windows build number 10.0.19041.1415 ### Other Software _No response_ ### Steps to reproduce Run the following C++ test case in Windows Terminal or conhost. ```cpp #include <windows.h> #include <conio.h> #include <string> int main() { // Get the handle of the main buffer, and also create a second buffer. HANDLE buff1 = GetStdHandle(STD_OUTPUT_HANDLE); HANDLE buff2 = CreateConsoleScreenBuffer(GENERIC_READ|GENERIC_WRITE, 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL); // Enable VT processing. DWORD dwMode = 0; GetConsoleMode(buff1, &dwMode); dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; SetConsoleMode(buff1, dwMode); DWORD written; std::wstring s; // Switch to the second buffer, but disable DECAWM in the main buffer. SetConsoleActiveScreenBuffer(buff2); s = L"\033[?7l"; WriteConsoleW(buff1, s.data(), s.length(), &written, NULL); // Write some content starting at the end of the line in the second buffer. s = L"\033[2J\033[H\033[999C Second Buffer"; WriteConsoleW(buff2, s.data(), s.length(), &written, NULL); getch(); // Close the second buffer so the main buffer is active again. CloseHandle(buff2); // Write some content starting at the end of the line in the main buffer. s = L"\033[2J\033[H\033[999C Main Buffer"; WriteConsoleW(buff1, s.data(), s.length(), &written, NULL); return 0; } ``` ### Expected Behavior The sample above opens two screen buffers, and while the second one is active, sends an `DECAWM` escape sequence (disabling auto-wrap) to the handle of the first buffer. It then writes some text at the end of the line in the second buffer, which should still wrap. After a keypress, it switches back to the main buffer, and again writes some text at the end of the line, which now shouldn't wrap. ### Actual Behavior The text written to the second buffer doesn't wrap, while the text written to the main buffer does wrap. This is a similar in cause to issue #12193. The `DoSrvPrivateSetAutoWrapMode` function is updating the output mode in the active screen buffer, when it should be obtaining the target buffer from the handle that initiated the operation. https://github.com/microsoft/terminal/blob/62c95b5017e92a780cdc43008e30b4e43d2edc9b/src/host/getset.cpp#L1258-L1262 Again I'm hoping this will be fixed by the conhost refactoring I'm working on.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#16433