DECSC, DECRC Save and Restore Cursor
Save the cursor and its attributes, and later put them back.
DECSC Save Cursor
ESC 7
- DEC STD 070
- §5.13.1 Save Cursor, p. 5-187
- VT220
- §4.7 Cursor Positioning
- VT510
- DECSC—Save Cursor
ESC 7 (DECSC) saves the state of the cursor, and ESC 8 (DECRC) puts it back. DEC STD 070 lists what is saved, and it is more than the position:
- the cursor position,
- the character attributes set by SGR,
- origin mode (DECOM),
- the character sets designated as G0 through G3, and which of them is invoked into GL (and, from level 2, GR),
- the selective erase attribute (DECSCA), where it is supported.
The VT510 manual’s list also has a “wrap flag (autowrap or no autowrap)”. DEC STD 070 leaves it out of DECSC’s own definition, but its appendix on autowrap says the pending wrap, which it calls the Last Column Flag, “should be saved when a Save Cursor operation is performed, and restored when a Restore Cursor operation is performed” (§D.6.1, p. D-14). xterm saves the pending wrap along with the rest, in CursorSave2, and puts it back last of all, in CursorRestoreFlags. It also keeps a saved cursor for each of the main and alternate screens, so a program on the alternate screen does not disturb what was saved on the main one.
There is only one saved cursor, so saving again replaces it. Restoring when nothing has been saved puts the cursor at the top-left with default attributes, because the save buffer starts out holding exactly that.
DECRC is defined in DEC STD 070 §5.13.1, p. 5-189 and in the VT510 manual as DECRC—Restore Cursor.
CSI s and CSI u are often used for the same thing, but CSI s means something else (DECSLRM) once left and right margins are enabled.
Support
| Terminal | Version | Support | Notes |
|---|---|---|---|
| VT220 | manual, 2nd ed., 1984 | Yes | §4.7 Cursor Positioning |
| VT510 | manual, 1st ed., 1993 | Yes | DECSC, DECRC |
| xterm | patch 412, xterm-411a | Yes | saves the pending wrap; one saved cursor for each screen |
| libghostty-vt | 0f171f6 | Yes | |
| kitty | 0.49.1, run in a VM | Partly | fails DECSC-3 of the 3 cases that show it working |
| foot | 1.28.0, run in a VM | Yes | passes the case that shows it working |
| pyte | 0.8.2, run as a library | Partly | fails DECSC-3 of the 3 cases that show it working |
| xterm.js headless | 6.0.0, run as a library | Yes | passes the 3 cases that show it working |
| alacritty_terminal | 0.26.0, run as a library | Yes | passes the 3 cases that show it working |
| ConEmu | build 230724, its documentation | Partly | ESC 7 and ESC 8 listed as saving and restoring the cursor position, in ANSI escape codes |
| rxvt-unicode | 9.31, run in a VM | Yes | passes the 3 cases that show it working |
| VTE | 0.84.1, run as a library | Yes | passes the 3 cases that show it working |
Validation
DECSC-1: Position
\e[2;3H
\e7 # save
\e[1;1H
A
\e8 # restore
B
|A____|
|__B__|
DECSC-2: Attributes
\e[1;91m # bold bright red
\e7 # save
\e[0m
A
\e8 # restore
B
|B____|
attr 1,1 bold fg=9
DECSC-3: Nothing saved
\e[1m
\e[2;4H
\e8 # restore, with nothing saved
A
|A____|
|_____|
attr 1,1 plain