[PR #15084] [MERGED] Add support for horizontal margin sequences #30393

Open
opened 2026-01-31 09:40:34 +00:00 by claunia · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/microsoft/terminal/pull/15084
Author: @j4james
Created: 4/3/2023
Status: Merged
Merged: 5/15/2023
Merged by: @DHowett

Base: mainHead: feature-lrmargins


📝 Commits (10+)

  • c4d5f4e Add helper methods for horizontal margins.
  • c375245 Hook up the DECSLRM sequence.
  • a062ab3 Add support for DECLRMM.
  • af83796 Update scroll operations to use left/right margins.
  • 9deb4c4 Clamp cursor ops within left/right margins.
  • e7d2246 Support querying margins with DECRQSS.
  • 37647ad Clamp PrintString within left/right margins.
  • 8842efd Clamp rect area ops within left/right margins.
  • 6821577 Account for left margin in DECOM cursor reports.
  • 7df5171 Only home cursor if margins are valid.

📊 Changes

13 files changed (+1025 additions, -351 deletions)

View changed files

📝 .github/actions/spelling/expect/alphabet.txt (+4 -0)
📝 src/host/ut_host/ScreenBufferTests.cpp (+646 -259)
📝 src/terminal/adapter/DispatchTypes.hpp (+1 -0)
📝 src/terminal/adapter/ITermDispatch.hpp (+1 -0)
📝 src/terminal/adapter/adaptDispatch.cpp (+329 -74)
📝 src/terminal/adapter/adaptDispatch.hpp (+11 -1)
📝 src/terminal/adapter/termDispatch.hpp (+1 -0)
📝 src/terminal/adapter/ut_adapter/adapterTest.cpp (+17 -1)
📝 src/terminal/parser/OutputStateMachineEngine.cpp (+7 -6)
📝 src/terminal/parser/OutputStateMachineEngine.hpp (+2 -2)
📝 src/terminal/parser/telemetry.cpp (+1 -1)
📝 src/terminal/parser/telemetry.hpp (+1 -1)
📝 src/terminal/parser/ut_parser/OutputEngineTest.cpp (+4 -6)

📄 Description

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


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/microsoft/terminal/pull/15084 **Author:** [@j4james](https://github.com/j4james) **Created:** 4/3/2023 **Status:** ✅ Merged **Merged:** 5/15/2023 **Merged by:** [@DHowett](https://github.com/DHowett) **Base:** `main` ← **Head:** `feature-lrmargins` --- ### 📝 Commits (10+) - [`c4d5f4e`](https://github.com/microsoft/terminal/commit/c4d5f4ee0182e63422bfab12e85c5218d1fd43e4) Add helper methods for horizontal margins. - [`c375245`](https://github.com/microsoft/terminal/commit/c375245bde02a151bfd4cdf627f6a8716b269bf2) Hook up the DECSLRM sequence. - [`a062ab3`](https://github.com/microsoft/terminal/commit/a062ab3dfa5fde37877c861019f01096da01213d) Add support for DECLRMM. - [`af83796`](https://github.com/microsoft/terminal/commit/af8379610a31ff2a8f2f86dcaba846b9fc3c8757) Update scroll operations to use left/right margins. - [`9deb4c4`](https://github.com/microsoft/terminal/commit/9deb4c4d459b586c00e7ec9cd21e814539e618f1) Clamp cursor ops within left/right margins. - [`e7d2246`](https://github.com/microsoft/terminal/commit/e7d22462933659414b7590e3116d3f7422cbed10) Support querying margins with DECRQSS. - [`37647ad`](https://github.com/microsoft/terminal/commit/37647adc6c50245834821b81d7e5f75aa91f64d9) Clamp PrintString within left/right margins. - [`8842efd`](https://github.com/microsoft/terminal/commit/8842efd47a24652514d6e4bedc97eaa3d8aca992) Clamp rect area ops within left/right margins. - [`6821577`](https://github.com/microsoft/terminal/commit/6821577ad3c3386a0671206ddf74ee6f71e276e4) Account for left margin in DECOM cursor reports. - [`7df5171`](https://github.com/microsoft/terminal/commit/7df517110bb7dd928ffbff1d28fe0e2f088e4632) Only home cursor if margins are valid. ### 📊 Changes **13 files changed** (+1025 additions, -351 deletions) <details> <summary>View changed files</summary> 📝 `.github/actions/spelling/expect/alphabet.txt` (+4 -0) 📝 `src/host/ut_host/ScreenBufferTests.cpp` (+646 -259) 📝 `src/terminal/adapter/DispatchTypes.hpp` (+1 -0) 📝 `src/terminal/adapter/ITermDispatch.hpp` (+1 -0) 📝 `src/terminal/adapter/adaptDispatch.cpp` (+329 -74) 📝 `src/terminal/adapter/adaptDispatch.hpp` (+11 -1) 📝 `src/terminal/adapter/termDispatch.hpp` (+1 -0) 📝 `src/terminal/adapter/ut_adapter/adapterTest.cpp` (+17 -1) 📝 `src/terminal/parser/OutputStateMachineEngine.cpp` (+7 -6) 📝 `src/terminal/parser/OutputStateMachineEngine.hpp` (+2 -2) 📝 `src/terminal/parser/telemetry.cpp` (+1 -1) 📝 `src/terminal/parser/telemetry.hpp` (+1 -1) 📝 `src/terminal/parser/ut_parser/OutputEngineTest.cpp` (+4 -6) </details> ### 📄 Description 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 --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
claunia added the pull-request label 2026-01-31 09:40:34 +00:00
Sign in to join this conversation.
No Label pull-request
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#30393