^[control-codes
live in libghostty-vt

Escape sequences

DECSC, DECRC Save and Restore Cursor

View as Markdown

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

TerminalVersionSupportNotes
VT220manual, 2nd ed., 1984Yes§4.7 Cursor Positioning
VT510manual, 1st ed., 1993YesDECSC, DECRC
xtermpatch 412, xterm-411aYessaves the pending wrap; one saved cursor for each screen
libghostty-vt0f171f6Yes
kitty0.49.1, run in a VMPartlyfails DECSC-3 of the 3 cases that show it working
foot1.28.0, run in a VMYespasses the case that shows it working
pyte0.8.2, run as a libraryPartlyfails DECSC-3 of the 3 cases that show it working
xterm.js headless6.0.0, run as a libraryYespasses the 3 cases that show it working
alacritty_terminal0.26.0, run as a libraryYespasses the 3 cases that show it working
ConEmubuild 230724, its documentationPartlyESC 7 and ESC 8 listed as saving and restoring the cursor position, in ANSI escape codes
rxvt-unicode9.31, run in a VMYespasses the 3 cases that show it working
VTE0.84.1, run as a libraryYespasses 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
Every example on these pages runs in your browser, in libghostty-vt compiled to WebAssembly.