Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for horizontal margin sequences #14876

Closed
j4james opened this issue Feb 19, 2023 · 14 comments · Fixed by #15084
Closed

Add support for horizontal margin sequences #14876

j4james opened this issue Feb 19, 2023 · 14 comments · Fixed by #15084
Labels
Area-VT Virtual Terminal sequence support Help Wanted We encourage anyone to jump in on these. In-PR This issue has a related PR Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. Needs-Tag-Fix Doesn't match tag requirements Product-Terminal The new Windows Terminal.
Milestone

Comments

@j4james
Copy link
Collaborator

j4james commented Feb 19, 2023

Description of the new feature/enhancement

The DECSLRM escape sequence lets you set left and right margins, so you can wrap your output within a given horizontal range, and also limit the scrolling within those boundaries. This is useful for apps like multiplexers, where you can have two panes side by side, and you need to be able to scroll the one side independently of the other.

Proposed technical implementation details (optional)

There are actually two sequences we need to implement for this. The first is DECLRMM (Left Right Margin Mode), without which the margin functionality won't be active. It's disabled by default because you can't use horizontal margins at the same time as double-width line attributes.

The main sequence is DECSLRM (Set Left Right Margins), which works similarly to the DECSTBM sequence (Set Top Bottom Margins) which we already support. But there a bunch of operations we then need to update to take those margins into account - cursor movement, insert and delete ops, text output, etc.

I should also note that the DECSLRM sequence clashes with the ANSISYSSC sequence which we already support. But the way most modern terminals deal with that is to disable ANSISYSSC when the DECLRMM mode is enabled. So by default CSI s is ANSISYSSC (as we have it now), but with DECLRMM enabled it's interpreted as DECSLRM.

@j4james j4james added the Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. label Feb 19, 2023
@microsoft-github-policy-service microsoft-github-policy-service bot added Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting Needs-Tag-Fix Doesn't match tag requirements labels Feb 19, 2023
@j4james
Copy link
Collaborator Author

j4james commented Feb 19, 2023

This is another one of those sequences which has lots of edge cases that aren't always clearly specified, and which everyone handles differently. So before I submit a PR for this, it would be ideal if we could get some of those aspects clarified by testing on a real DEC terminal.

To that end I've created a Python script with a series of test cases here:
https://gist.github.com/j4james/2eae626e461175cfcc29a304e066ae87

@KalleOlaviNiemitalo and @jerch, I'd be very grateful if either of you would be willing to give that a run on your VT420 or VT525. It's setup as an automated test, so you shouldn't need to do anything other than run it, and the results will be logged in a file named margins.log.

Note that it could take a while, because it uses DECRQCRA queries to read the screen content when checking the output. But it outputs the results of each test as they're executed, so you should be able to tell whether it's frozen for some reason.

I should also mention that it highlights the results with reverse video if they've "failed", but that's just based on my best guess of how things should work. I wouldn't be surprised if the real terminals behave differently from my expectations.

Also note that some of the operations were only supported on the VT510 and above, so you can definitely expect to see failures for those if testing on a VT420. I think that includes HPA, HPR, VPA, VPR, CNL, CPL, CHT, and CBT.

So @KalleOlaviNiemitalo, if the test is running really slowly, and you want to save some time, feel free to comment those ones out. You'll find all the test groups listed at the bottom of the script, so for example, you can comment out the test_hpa() call to skip that particular group.

@zadjii-msft zadjii-msft added Help Wanted We encourage anyone to jump in on these. Area-VT Virtual Terminal sequence support Product-Terminal The new Windows Terminal. and removed Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting Needs-Tag-Fix Doesn't match tag requirements labels Feb 20, 2023
@zadjii-msft zadjii-msft added this to the Backlog milestone Feb 20, 2023
@j4james
Copy link
Collaborator Author

j4james commented Mar 6, 2023

I had some spare time this weekend and was able to make a serial cable to connect VT520 to Linux (RPi). Then I downloaded your .py script and ran it. It runs pretty long, so I had to cancel it at some point (esp. when it was filling up the screen with letters and doing some text cutting), but I did notice output in reverse meaning (according to the opening comments in the source code) that some assumptions were not met. Anyways, I'm not exactly sure how to share the results with you. I can take a video on my phone and then send you a link.

@al20878: Thanks for giving it try. I probably should have explained that it switches to a second page for some of the tests, where it fills the screen with characters and then performs various operations on that content. When each test is finished, it switches back to the initial page to output the results. On a slow connection it's probably going to seem like you're on the second test page for most of the time, and you may not even notice the results page until the very end.

Anyway, it's not important that you see the results, and you don't need to take a video, since it writes everything to a margins.log file. Even if you stop the test early, there should at least be a partial log. If you could upload that here I can see if it's doing something meaningful.

@al20878
Copy link

al20878 commented Mar 6, 2023

No problem, @j4james , I'll just leave it run on VT420 and then submit the logfile (the connection speed is 9600 baud, not too bad, but it'll take some time to finish).

@al20878
Copy link

al20878 commented Mar 6, 2023

It finished in 7 and a half minutes
margins.vt420.log

@al20878
Copy link

al20878 commented Mar 6, 2023

VT520 finished the same script in 8:56 (same 9600 baud), the results are here:
margins.vt520.log

@al20878
Copy link

al20878 commented Mar 6, 2023

VT525 has done it in 5:56, but I noticed it wasn't getting any characters back from the terminal, unlike previously, as everything was coming in as asterisks ('*'). All three terminals are real H/W and were reset to factory (default) settings.
margins.vt525.log

@al20878
Copy link

al20878 commented Mar 6, 2023

Let me know if you need anything else!

@j4james
Copy link
Collaborator Author

j4james commented Mar 6, 2023

@al20878 This is brilliant! Thank you so much! There are quite a lot of operations where the results weren't what I expected, but that's exactly why I wanted to run these tests. It's great to have these details confirmed.

VT525 has done it in 5:56, but I noticed it wasn't getting any characters back from the terminal

That's interesting. I'm using the DECRQCRA checksum operation to "read" the screen, but the details of the checksum algorithm aren't actually documented anywhere. I've been assuming it was one of two commonly used formats I've seen in other terminal emulators, one of which I know was derived from a real VT520. But I'm guessing the VT525 algorithm is different (possibly because it covers things like color attributes), so that would be an interesting subject for a future investigation.

@j4james
Copy link
Collaborator Author

j4james commented Mar 8, 2023

@al20878 Now that I've had a chance to look at all the results in detail, the only thing I'm unsure about is the handling of DECOM (origin mode). And I think the problem is with the way my test script is evaluating the results. I'm relying on certain behavior of the DECRC (restore cursor) operation, which I suspect might have changed in later DEC terminals.

So when you have a chance, I've got another little script (linked here) that I'm hoping you'll test for me. All it does is write 4 digits to the screen, while altering the margins and saving and restoring the cursor position with DECSC and DECRC. There's a short pause after each digit, so you can see what's happening (just on the off chance they end up overwriting each other).

On a VT100 and VT240 (tested on MAME), the output looks like this:

3







1

                                       24

My theory is that the later DEC terminals do something different, though. My guess is the 4 will be output several rows up (line 3 to be exact).

@al20878
Copy link

al20878 commented Mar 8, 2023

Sure, I'll run the script on the real terminals. So far I ran it in PuTTY, and I saw this:

3







1

                                       24








pi@raspberrypi:~$





@al20878
Copy link

al20878 commented Mar 8, 2023

Obviously, I would not be able to copy-paste the same from the terminals, but I can compare what would they show. I need to do a little cable reconf to reattach them in the proper order (now that I have the right cable adapter, it won't be a problem at all, and I'll do it shortly). Stay tuned

@al20878
Copy link

al20878 commented Mar 8, 2023

@j4james as the saying goes, a picture is worth a thousand words, I'm attaching the "screenshots" of your script's output on 5 DEC terminals (VT320, VT330, VT420, VT520, and VT525, in order):
vt320
vt330
vt420
vt520
vt525
Let me know if you need anything else!

@j4james
Copy link
Collaborator Author

j4james commented Mar 8, 2023

@al20878 This is great, thanks! I'm so glad you tested on the VT320 and VT330 as well, so now we know exactly when the new behavior was introduced. I'm now inclined to update the Windows Terminal implementation to match the VT420/VT5xx devices by default, because that's seems to be the more "correct" behavior. In the long term we can always have an option for more strict compatibility with the lower level devices for edge cases like this.

Let me know if you need anything else!

There are a number of other operations I'd like to get a better understanding of, so if you don't mind doing this sort of thing, I'd love to ping you from time to time when I've got something ready to test. But feel free to ignore me if you're busy or if you lose interest.

@al20878
Copy link

al20878 commented Mar 9, 2023

@j4james I'm happy to help!

to ping you from time to time when I've got something ready to test

Sure, reach out any time!

DHowett pushed a commit that referenced this issue May 15, 2023
This PR introduces two new escapes sequences: `DECLRMM` (Left Right
Margin Mode), which enables the horizontal margin support, and `DECSLRM`
(Set Left and Right Margins), which does exactly what the name suggests.

A whole lot of existing operations have then been updated to take those
horizontal margins into account.

## Detailed Description of the Pull Request / Additional comments

The main complication was in figuring out in what way each operation is
affected, since there's a fair amount of variation.

* When writing text to the buffer, we need to wrap within the horizontal
margins, but only when the cursor is also within the vertical margins,
otherwise we just wrap within the boundaries of the screen.

* Not all cursor movement operations are constrained by the margins, but
for those that are, we clamp within both the vertical and horizontal
margins. But if the cursor is already outside the margins, it is just
clamped at the edges of the screen.

* The `ICH` and `DCH` operations are constrained by the horizontal
margins, but only when inside the vertical margins. And if the cursor is
outside the horizontal margins, these operations have no effect at all.

* The rectangular area operations are clamped within the horizontal
margins when in the origin mode, the same way they're clamped within the
vertical margins.

* The scrolling operations only scroll the area inside both horizontal
and vertical margins. This includes the `IL` and `DL` operations, but
they also won't have any effect at all unless the cursor is already
inside the margin area.

* `CR` returns to the left margin rather than the start of the line,
unless the cursor is already left of that margin, or outside the
vertical margins.

* `LF`, `VT`, `FF`, and `IND` only trigger a scroll at the bottom margin
if the cursor is already inside both vertical and horizontal margins.
The same rules apply to `RI` when triggering a scroll at the top margin.

Another thing worth noting is the change to the `ANSISYSSC` operation.
Since that shares the same escape sequence as `DECSLRM`, they can't both
be active at the same time. However, the latter is only meant to be
active when `DECLRMM` is set, so by default `ANSISYSC` will still work,
but it'll no longer apply once the `DECLRMM` mode is enabled.

## Validation Steps Performed

Thanks to @al20878, these operations have been extensively tested on a
number of DEC terminals and I've manually confirmed our implementation
matches their behavior.

I've also extended some of our existing unit tests to cover at least the
basic margin handling, although not all of the edge cases.

Closes #14876
@microsoft-github-policy-service microsoft-github-policy-service bot added the Needs-Tag-Fix Doesn't match tag requirements label May 15, 2023
DHowett pushed a commit that referenced this issue May 15, 2023
This PR introduces two new escapes sequences: `DECLRMM` (Left Right
Margin Mode), which enables the horizontal margin support, and `DECSLRM`
(Set Left and Right Margins), which does exactly what the name suggests.

A whole lot of existing operations have then been updated to take those
horizontal margins into account.

## Detailed Description of the Pull Request / Additional comments

The main complication was in figuring out in what way each operation is
affected, since there's a fair amount of variation.

* When writing text to the buffer, we need to wrap within the horizontal
margins, but only when the cursor is also within the vertical margins,
otherwise we just wrap within the boundaries of the screen.

* Not all cursor movement operations are constrained by the margins, but
for those that are, we clamp within both the vertical and horizontal
margins. But if the cursor is already outside the margins, it is just
clamped at the edges of the screen.

* The `ICH` and `DCH` operations are constrained by the horizontal
margins, but only when inside the vertical margins. And if the cursor is
outside the horizontal margins, these operations have no effect at all.

* The rectangular area operations are clamped within the horizontal
margins when in the origin mode, the same way they're clamped within the
vertical margins.

* The scrolling operations only scroll the area inside both horizontal
and vertical margins. This includes the `IL` and `DL` operations, but
they also won't have any effect at all unless the cursor is already
inside the margin area.

* `CR` returns to the left margin rather than the start of the line,
unless the cursor is already left of that margin, or outside the
vertical margins.

* `LF`, `VT`, `FF`, and `IND` only trigger a scroll at the bottom margin
if the cursor is already inside both vertical and horizontal margins.
The same rules apply to `RI` when triggering a scroll at the top margin.

Another thing worth noting is the change to the `ANSISYSSC` operation.
Since that shares the same escape sequence as `DECSLRM`, they can't both
be active at the same time. However, the latter is only meant to be
active when `DECLRMM` is set, so by default `ANSISYSC` will still work,
but it'll no longer apply once the `DECLRMM` mode is enabled.

## Validation Steps Performed

Thanks to @al20878, these operations have been extensively tested on a
number of DEC terminals and I've manually confirmed our implementation
matches their behavior.

I've also extended some of our existing unit tests to cover at least the
basic margin handling, although not all of the edge cases.

Closes #14876

(cherry picked from commit b00b77a)
Service-Card-Id: 89180228
Service-Version: 1.18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-VT Virtual Terminal sequence support Help Wanted We encourage anyone to jump in on these. In-PR This issue has a related PR Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. Needs-Tag-Fix Doesn't match tag requirements Product-Terminal The new Windows Terminal.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants