Repository: microsoft/terminal (language: cpp)

Issue:
CSI 18t "Report Size In Characters" not working.
### Windows Terminal version

1.15.2282.0

### Windows build number

10.0.19044.1889

### Other Software

Own project.

### Steps to reproduce

Start CMD or PS within Terminal.
Run app which activates VT-Modes for IN and OUT.
Send **CSI 18 t** to stdout.
Read (wait for) response on stdin.

### Expected Behavior

A response from the Terminal a la:
**CSI** 'Decimal-Rows' **;** 'Decimal-Columns' **t**

### Actual Behavior

No response from the Terminal.
But i.e. sending **CSI 6 n** (Report Actual Cursor Position) results as expected in a response a la:
**CSI** 'Decimal-Row' **;** 'Decimal-Column' **R**


Discussion / hints:
We just don't support any of the `CSI t` queries. I actually thought we already had an open issue for this, but I can't find it right now.

I should also say I'd recommend against relying on `CSI t` for querying the terminal dimensions if you're expecting your application to be widely used. There are quite a few terminals that don't support it, and `DSR-CPR` can serve the same purpose more reliably.
So, you mean that way:

1. Save Actual CursorPos
2. Place Cursor Outside Limits
3. Read Resulted CursorPos ( `CSI 6 n` )
4. Place Cursor Back To 1.

??

I couldn't find a Linux Terminal not supporting `CSI t`. On Monterey-Mac I only tested the "on board" terminal - working fine too.
Yes, the 4-steps method seems actually more cross-compatible - but just because of the MS-Terminal refuses `CSI t` - not because of one of the 10 most used Linix-Terminals or the OnBoard Mac-Terminal would struggle with `CSI t`.

> So, you mean that way:
> 
>     1. Save Actual CursorPos
> 
>     2. Place Cursor Outside Limits
> 
>     3. Read Resulted CursorPos ( `CSI 6 n` )
> 
>     4. Place Cursor Back To 1.

You make it sound like it's a complicated serious of operations, but it's essentially just a longer escape sequence. Something like `\e7\e[999;999H\e[6n\e8`.

> I couldn't find a Linux Terminal not supporting `CSI t`.

Admittedly I don't always have the latest version of every terminal, and it's been a while since I last tested these sequences, so maybe things have improved a lot since then. At the time I think there were a half dozen or so that didn't support `CSI t`, or produced invalid results. But if you're happy to rely on `CSI t` based on your own research, that's fine. I was just offering my opinion.
Uh, please do not misunderstand me.
I am really thankful for what MS is doing with the Terminal/VS-Code/WSL etc. I'm also impressed getting that fast an answer - and will follow your advice.
I'm on a MicroChip 2560... serial connected to Terminals. The whole TUI-Logic is running on the µC. Terminal is just a screen and a keyboard. In best case I do not even need a binary on the Terminal side to get serial redirected to stdio of a VT-Mode terminal.
So yes, on the µC I'm glad about every byte I can save... in code and on the serial line.
On the other side... there are some more issues where very small OS-specific binaries would make life much easier...


I'll toss this on the backlog. No arguments that we should support it, even if there is a viable (albeit, verbose) alternative.
> No arguments that we should support it

For me it looks much more logical to call a GetScreenSize-Function if I want to know the ScreenSize, than to call some functions to be able to use GetCursorPos as a substitute for GetScreenSize.

I have to set a flag NextCurserPosIsAScreenSize and have to check on each incoming CursorPos if it's not a ScreenSize...

That's in coding really not a thing - but on a 2560 it's 1 byte global RAM, ~8 additional cpu cycles per incoming CursorPos, and ~30 Bytes program memory.
I have to waste resources of the µC - cause 34% of Users want to administrate them with Windows.

`CSI t` commands do not conflict with anything - I also can't see why it wouldn't make sense to get the MS-Terminal (without cnflicting riscs) again one step closer to Xterm-compatibility...




Fix patch:
diff --git a/src/terminal/adapter/DispatchTypes.hpp b/src/terminal/adapter/DispatchTypes.hpp
index b1af645cc4b..6acd6f3651a 100644
--- a/src/terminal/adapter/DispatchTypes.hpp
+++ b/src/terminal/adapter/DispatchTypes.hpp
@@ -467,6 +467,7 @@ namespace Microsoft::Console::VirtualTerminal::DispatchTypes
         IconifyWindow = 2,
         RefreshWindow = 7,
         ResizeWindowInCharacters = 8,
+        ReportTextSizeInCharacters = 18
     };
 
     enum class CursorStyle : VTInt
diff --git a/src/terminal/adapter/adaptDispatch.cpp b/src/terminal/adapter/adaptDispatch.cpp
index 7c2c04705fd..fee96626f63 100644
--- a/src/terminal/adapter/adaptDispatch.cpp
+++ b/src/terminal/adapter/adaptDispatch.cpp
@@ -3058,6 +3058,9 @@ bool AdaptDispatch::WindowManipulation(const DispatchTypes::WindowManipulationTy
     case DispatchTypes::WindowManipulationType::ResizeWindowInCharacters:
         _api.ResizeWindow(parameter2.value_or(0), parameter1.value_or(0));
         return true;
+    case DispatchTypes::WindowManipulationType::ReportTextSizeInCharacters:
+        _api.ReturnResponse(fmt::format(FMT_COMPILE(L"\033[8;{};{}t"), _api.GetViewport().height(), _api.GetTextBuffer().GetSize().Width()));
+        return true;
     default:
         return false;
     }
diff --git a/src/terminal/adapter/ut_adapter/adapterTest.cpp b/src/terminal/adapter/ut_adapter/adapterTest.cpp
index dcb917750d6..5065703426c 100644
--- a/src/terminal/adapter/ut_adapter/adapterTest.cpp
+++ b/src/terminal/adapter/ut_adapter/adapterTest.cpp
@@ -2852,6 +2852,14 @@ class AdapterTest
         _pDispatch->_macroBuffer = nullptr;
     }
 
+    TEST_METHOD(WindowManipulationTypeTests)
+    {
+        _testGetSet->PrepData();
+        _pDispatch->WindowManipulation(DispatchTypes::WindowManipulationType::ReportTextSizeInCharacters, NULL, NULL);
+        const std::wstring expectedResponse = fmt::format(L"\033[8;{};{}t", _testGetSet->GetViewport().height(), _testGetSet->GetTextBuffer().GetSize().Width());
+        _testGetSet->ValidateInputEvent(expectedResponse.c_str());
+    }
+
 private:
     TerminalInput _terminalInput{ nullptr };
     std::unique_ptr<TestGetSet> _testGetSet;


Test patch: