Repository: microsoft/terminal (language: cpp)

Issue:
Reset disables the ability to pass through C1 control characters
### Windows Terminal version

1.15.1862.0

### Windows build number

10.0.19044.1889

### Other Software

_No response_

### Steps to reproduce

1. Open a WSL bash shell in Windows Terminal.
2. Execute the following statement: `printf "\e 7\u009B?5h"`
3. Note that the screen attributes have reversed.
4. Execute `reset` to get the screen back to normal.
5. Execute `printf "\e 7\u009B?5h"` again.



### Expected Behavior

Both step 2 and step 5 should cause the screen attributes to be reversed.

### Actual Behavior

Only the first attempt works. The second attempt appears to output `?5h` instead.

What's happening is we've got a `DECAC1` sequence (`ESC SP 7`) which is supposed to enable `C1` support, followed by `DECSCNM` (reverse screen mode), using a `C1` control sequence (`CSI ? 5 h`).

That works the first time, but after the reset, the `C1` support is permanently disabled on the conpty client side, so `C1` control sequences can no longer be passed through.


Discussion / hints:
I think this may be another regression from #13024.

When we first added support for `DECAC1` in #11690, the assumption was that it would be enabled permanently on the conpty client side, and there was nothing in the terminal code that could turn that off. However, when `TerminalDispatch` was replaced with `AdaptDispatch`, it inherited the conhost `SoftReset` implementation, and that included turning off `DECAC1`.

I haven't tried this yet, but one simple fix could be to add another parser mode - something like `AlwaysAcceptC1` - which is set at startup in the terminal, and never reset anywhere. Then the test in the state machine just becomes:

```
_parserMode.any(Mode::AcceptC1, Mode::AlwaysAcceptC1)
```

It's a bit hacky, but that should add no significant overhead, and we won't then have to care what `AcceptC1` might be set to.

Fix patch:
diff --git a/src/cascadia/TerminalCore/Terminal.cpp b/src/cascadia/TerminalCore/Terminal.cpp
index 1cf4528a569..6e9a3be7b19 100644
--- a/src/cascadia/TerminalCore/Terminal.cpp
+++ b/src/cascadia/TerminalCore/Terminal.cpp
@@ -91,7 +91,7 @@ void Terminal::Create(til::size viewportSize, til::CoordType scrollbackLines, Re
     // But if they are being accepted by conhost, there's a chance they may get
     // passed through in some situations, so it's important that our state
     // machine is always prepared to accept them.
-    _stateMachine->SetParserMode(StateMachine::Mode::AcceptC1, true);
+    _stateMachine->SetParserMode(StateMachine::Mode::AlwaysAcceptC1, true);
 }
 
 // Method Description:
diff --git a/src/terminal/parser/stateMachine.cpp b/src/terminal/parser/stateMachine.cpp
index 21ee4a88efb..36848694f32 100644
--- a/src/terminal/parser/stateMachine.cpp
+++ b/src/terminal/parser/stateMachine.cpp
@@ -1716,7 +1716,7 @@ void StateMachine::ProcessCharacter(const wchar_t wch)
         // code points that get translated as C1 controls when that is not their
         // intended use. In order to avoid them triggering unintentional escape
         // sequences, we ignore these characters by default.
-        if (_parserMode.test(Mode::AcceptC1))
+        if (_parserMode.any(Mode::AcceptC1, Mode::AlwaysAcceptC1))
         {
             ProcessCharacter(AsciiChars::ESC);
             ProcessCharacter(_c1To7Bit(wch));
diff --git a/src/terminal/parser/stateMachine.hpp b/src/terminal/parser/stateMachine.hpp
index c3c3936693b..41bce50f97e 100644
--- a/src/terminal/parser/stateMachine.hpp
+++ b/src/terminal/parser/stateMachine.hpp
@@ -50,6 +50,7 @@ namespace Microsoft::Console::VirtualTerminal
         enum class Mode : size_t
         {
             AcceptC1,
+            AlwaysAcceptC1,
             Ansi,
         };
 


Test patch: