[PR #3160] Improve the DECSC/DECRC implementation #25265

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

Original Pull Request: https://github.com/microsoft/terminal/pull/3160

State: closed
Merged: Yes


Summary of the Pull Request

The current DECSC implementation only saves the cursor position and origin mode. This PR improves that functionality with additional support for saving the SGR attributes, as well as the active character set.

It also fixes the way the saved state interacts with the alt buffer (private mode 1049), triggering a save when switching to the alt buffer, and a restore when switching back, and tracking the alt buffer state independently from the main state.

PR Checklist

  • Closes Inconsistent Color in Bash on Ubuntu on Windows (#148)
  • CLA signed. If not, go over here and sign the CLA
  • Tests added/passed
  • Requires documentation to be updated
  • I've not discussed this with core contributors already. I'm ready to accept this work might be rejected in favor of a different grand plan.

Detailed Description of the Pull Request / Additional comments

In order to properly save and restore the SGR attributes, we first needed to add a pair of APIs in the ConGetSet interface which could round-trip the attributes with full 32-bit colors (the existing methods only work with legacy attributes).

I then added a struct in the AdaptDispatch implementation to make it easier to manage all of the parameters that needed to be saved. This includes the cursor position and origin mode that we were already tracking, and now also the SGR text attributes and the active character set (via the TermOutput class).

Two instances of this structure are required, since changes made to the saved state in the alt buffer need to be tracked separately from changes in the main buffer. I've added a boolean property that specifies whether we're in the alt buffer or not, and use that to decide which of the two instances we're working with.

I also needed to explicitly trigger a save when switching to the alt buffer, and a restore when switching back, since we weren't already doing that (the existing implementation gave the impression that the state was saved, because each buffer has its own cursor position, but that doesn't properly match the XTerm behaviour).

For the state tracking itself, we've now got two additional properties - the SGR attributes, which we obtain via the new private API, and the active character set, which we get from a local AdaptDispatch field. I'm saving the whole TermOutput class for the character set, since I'm hoping that will make it automatically supports future enhancements.

When restoring the cursor position, there is also now a fix to handle the relative origin mode correctly. If the margins are changed between the position being saved and restored, it's possible for the cursor to end up outside of the new margins, which would be illegal. So there is now an additional step that clamps the Y coordinate within the margin boundaries if the origin mode is relative.

Validation Steps Performed

I've added a couple of screen buffer tests which check that the various parameters are saved and restored as expected, as well as checking that the Y coordinate is clamped appropriately when the relative origin mode is set.

I've also tested manually with Vttest and confirmed that the SAVE/RESTORE CURSOR test (the last page of the Test of screen features)) is now working a lot better than it used to.

**Original Pull Request:** https://github.com/microsoft/terminal/pull/3160 **State:** closed **Merged:** Yes --- ## Summary of the Pull Request The current [DECSC](https://www.vt100.net/docs/vt510-rm/DECSC.html) implementation only saves the cursor position and origin mode. This PR improves that functionality with additional support for saving the SGR attributes, as well as the active character set. It also fixes the way the saved state interacts with the alt buffer (private mode 1049), triggering a save when switching to the alt buffer, and a restore when switching back, and tracking the alt buffer state independently from the main state. ## PR Checklist * [x] Closes #148 * [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA * [x] Tests added/passed * [ ] Requires documentation to be updated * [ ] I've not discussed this with core contributors already. I'm ready to accept this work might be rejected in favor of a different grand plan. ## Detailed Description of the Pull Request / Additional comments In order to properly save and restore the SGR attributes, we first needed to add a pair of APIs in the `ConGetSet` interface which could round-trip the attributes with full 32-bit colors (the existing methods only work with legacy attributes). I then added a struct in the `AdaptDispatch` implementation to make it easier to manage all of the parameters that needed to be saved. This includes the cursor position and origin mode that we were already tracking, and now also the SGR text attributes and the active character set (via the `TermOutput` class). Two instances of this structure are required, since changes made to the saved state in the alt buffer need to be tracked separately from changes in the main buffer. I've added a boolean property that specifies whether we're in the alt buffer or not, and use that to decide which of the two instances we're working with. I also needed to explicitly trigger a save when switching to the alt buffer, and a restore when switching back, since we weren't already doing that (the existing implementation gave the impression that the state was saved, because each buffer has its own cursor position, but that doesn't properly match the XTerm behaviour). For the state tracking itself, we've now got two additional properties - the SGR attributes, which we obtain via the new private API, and the active character set, which we get from a local `AdaptDispatch` field. I'm saving the whole `TermOutput` class for the character set, since I'm hoping that will make it automatically supports future enhancements. When restoring the cursor position, there is also now a fix to handle the relative origin mode correctly. If the margins are changed between the position being saved and restored, it's possible for the cursor to end up outside of the new margins, which would be illegal. So there is now an additional step that clamps the Y coordinate within the margin boundaries if the origin mode is relative. ## Validation Steps Performed I've added a couple of screen buffer tests which check that the various parameters are saved and restored as expected, as well as checking that the Y coordinate is clamped appropriately when the relative origin mode is set. I've also tested manually with [Vttest](https://invisible-island.net/vttest/) and confirmed that the _SAVE/RESTORE CURSOR_ test (the last page of the _Test of screen features_)) is now working a lot better than it used to.
claunia added the pull-request label 2026-01-31 09:08:23 +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#25265