# Soft Terminal Reset (DECSTR)

> Put the modes and settings a program may have changed back to their defaults, leaving the screen alone.

- **Sequence:** `CSI ! p`
- **DEC STD 070:** [§4, ch. 5 Soft Terminal Reset, p. 31](https://archive.org/details/bitsavers_decstandar0VideoSystemsReferenceManualDec91_74264381/page/n234/mode/1up)
- **VT220:** [§4.18.1 Soft Terminal Reset (DECSTR)](https://vt100.net/docs/vt220-rm/chapter4.html#S4.18.1)
- **VT510:** [DECSTR—Soft Terminal Reset](https://vt100.net/docs/vt510-rm/DECSTR.html)

DECSTR is the reset a program sends: it puts back the state a program may
have changed, and leaves what is on the screen and where the cursor is.
[RIS](https://control-codes.page/esc/ris/index.html.md), the full reset, also erases the screen and restores the
user's own settings, and both DEC STD 070 and the VT510 manual recommend
DECSTR instead.

DEC STD 070 lists what DECSTR resets, and the VT510 manual's table agrees:

- the top and bottom margins, to the whole screen, and the left and right
  margins likewise;
- the current rendition, to normal, and the selective erase attribute
  ([DECSCA](https://control-codes.page/csi/decsca/index.html.md)), to erasable;
- the character sets and which are in use, to their defaults;
- the saved cursor ([DECSC](https://control-codes.page/esc/decsc/index.html.md)), to its default, the home
  position;
- insert mode ([IRM](https://control-codes.page/ansi/irm/index.html.md)), to replace;
- origin mode ([DECOM](https://control-codes.page/modes/decom/index.html.md)), to absolute;
- the cursor ([DECTCEM](https://control-codes.page/modes/dectcem/index.html.md)), to shown;
- the keyboard: cursor key mode, keypad mode, keyboard action mode.

It also lists what DECSTR leaves alone: the data on the screen, the cursor
position ("DECSTR has no affect on the Active Position"), the tab stops,
column mode, screen mode, new line mode and line attributes.

Auto wrap mode is where the sources part. DEC STD 070 sets it to "Auto Wrap
Off (NVM if present)", the user's stored setting when there is one, and the
VT510 manual's table says "No autowrap". xterm leaves it on, and esctest2's
`test_DECSTR_DECAWM` checks that autowrap is still on afterwards.
libghostty-vt sets it back to its default, which is on. There is no case for
it here.

libghostty-vt's DECSTR (`softReset` in `Terminal.zig`) resets everything in
DEC STD 070's list, and, as xterm's does, the cursor style, the color
palette ([OSC 4](https://control-codes.page/osc/palette/index.html.md)), `modifyOtherKeys` and which display
[DECSASD](https://control-codes.page/csi/decsasd/index.html.md) has selected.

## Support

| Terminal | Version | Support | Notes |
| --- | --- | --- | --- |
| VT220 | [manual](https://vt100.net/docs/vt220-rm/), 2nd ed., 1984 | Yes | [§4.18.1 Soft Terminal Reset (DECSTR)](https://vt100.net/docs/vt220-rm/chapter4.html#S4.18.1) |
| VT510 | [manual](https://vt100.net/docs/vt510-rm/), 1st ed., 1993 | Yes | [DECSTR](https://vt100.net/docs/vt510-rm/DECSTR.html) |
| xterm | patch 412, [xterm-411a](https://github.com/ThomasDickey/xterm-snapshots/tree/xterm-411a) | Yes | leaves autowrap on |
| libghostty-vt | [919dca5](https://github.com/ghostty-org/ghostty/tree/919dca5c848d43a489a4cb2e1feade016f0fa2db) | Yes | leaves autowrap on |
| kitty | 0.49.1, [run in a VM](https://git.jcollie.dev/jeff/control-codes/src/branch/main/emulators/results/kitty.json) | Yes | passes the 7 cases that show it working |
| foot | 1.28.0, [run in a VM](https://git.jcollie.dev/jeff/control-codes/src/branch/main/emulators/results/foot.json) | Partly | fails DECSTR-7 of the 6 cases that show it working |
| pyte | 0.8.2, [run as a library](https://git.jcollie.dev/jeff/control-codes/src/branch/main/emulators/results/pyte.json) | No | fails the 7 cases that show it working |
| xterm.js headless | 6.0.0, [run as a library](https://git.jcollie.dev/jeff/control-codes/src/branch/main/emulators/results/xtermjs.json) | Yes | passes the 7 cases that show it working |
| alacritty_terminal | 0.26.0, [run as a library](https://git.jcollie.dev/jeff/control-codes/src/branch/main/emulators/results/alacritty.json) | Partly | fails DECSTR-2, DECSTR-3, DECSTR-4, DECSTR-5 and 2 more of the 7 cases that show it working |
| ConEmu | build 230724, its [documentation](https://conemu.github.io/en/AnsiEscapeCodes.html) | No | not in [ANSI escape codes](https://conemu.github.io/en/AnsiEscapeCodes.html) |
| rxvt-unicode | 9.31, [run in a VM](https://git.jcollie.dev/jeff/control-codes/src/branch/main/emulators/results/urxvt.json) | Partly | fails DECSTR-1, DECSTR-7 of the 7 cases that show it working |
| VTE | 0.84.1, [run as a library](https://git.jcollie.dev/jeff/control-codes/src/branch/main/emulators/results/vte.json) | Partly | fails DECSTR-7 of the 6 cases that show it working |

## Validation

### DECSTR-1: The screen and the cursor stay

Input, one step per line:

```text
AB
\e[2;3H
\e[!p
```

Expected screen:

```text
|AB___|
|_____|
cursor 2,3
```

### DECSTR-2: Insert mode is reset

Input, one step per line:

```text
ABC
\e[4h     # insert mode
\e[!p
\e[1;1H
X         # replaces A
```

Expected screen:

```text
|XBC__|
```

DEC STD 070, the VT510 manual and esctest2's `test_DECSTR_IRM` all reset IRM
to replace, so the `X` replaces `A` rather than being inserted before it.

### DECSTR-3: Origin mode is reset

Input, one step per line:

```text
\e[2;3r   # region is lines 2 and 3
\e[?6h    # origin mode
\e[!p
\e[1;1H   # the corner of the screen again
X
```

Expected screen:

```text
|X____|
|_____|
|_____|
```

DEC STD 070, the VT510 manual and esctest2's `test_DECSTR_DECOM` reset
origin mode to absolute, so `CSI 1 ; 1 H` goes to the corner of the screen
rather than the top of the region, line 2.

### DECSTR-4: The rendition is reset

Input, one step per line:

```text
\e[1;31m  # bold red
\e[!p
A
```

Expected screen:

```text
|A____|
attr 1,1 plain
```

Both manuals reset the rendition to normal, so the `A` is neither bold nor
red.

### DECSTR-5: The margins are reset

Input, one step per line:

```text
1\r\n2\r\n3\r\n4
\e[2;3r   # region is lines 2 and 3
\e[!p
\e[3;1H
\n        # would scroll lines 2 and 3 if the region were still set
X
```

Expected screen:

```text
|1____|
|2____|
|3____|
|X____|
```

DEC STD 070, the VT510 manual and esctest2's `test_DECSTR_STBM` reset the
margins to the whole screen, so the line feed moves the cursor to line 4
rather than scrolling lines 2 and 3.

### DECSTR-6: The cursor is shown again

Input, one step per line:

```text
\e[?25l   # hide the cursor
\e[!p
```

Expected screen:

```text
|_____|
cursor-visible yes
```

DEC STD 070 turns the cursor on, "ignore NVM", and the VT510 manual's table
says "Cursor enabled".

### DECSTR-7: The saved cursor goes back to its default

Input, one step per line:

```text
\e[2;3H
\e7       # save the cursor at 2,3
\e[!p
\e8       # restore it
X
```

Expected screen:

```text
|X____|
|_____|
```

The VT510 manual's table resets the saved cursor state to the home position,
and esctest2's `test_DECSTR_DECSC` checks that a restore afterwards goes
there, rather than to 2,3.

---

This is the Markdown version of <https://control-codes.page/csi/decstr/>. On that page every validation case runs live in libghostty-vt, the terminal emulation core of Ghostty, compiled to WebAssembly.

The validation cases are written in the notation described in <https://control-codes.page/notation/index.html.md>.
