# 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. There is
no case for it here.

libghostty-vt does not implement DECSTR. Its dispatch for `CSI … p` in
`stream.zig` handles only DECRQM, and logs any other intermediate byte as
unimplemented, so `CSI ! p` changes nothing. The cases below show what it
should reset; each fails for that one reason. The two that pass are about
what DECSTR keeps.

## 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

*A known difference: libghostty-vt does not pass this case.*

Input, one step per line:

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

Expected screen:

```text
|XBC__|
```

libghostty-vt ignores the DECSTR, so insert mode stays on and the `X` is
inserted before `A`. DEC STD 070, the VT510 manual and esctest2's
`test_DECSTR_IRM` all reset IRM to replace.

### DECSTR-3: Origin mode is reset

*A known difference: libghostty-vt does not pass this case.*

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____|
|_____|
|_____|
```

Origin mode stays on, so `CSI 1 ; 1 H` goes to the top of the region, line 2.
DEC STD 070, the VT510 manual and esctest2's `test_DECSTR_DECOM` reset it to
absolute.

### DECSTR-4: The rendition is reset

*A known difference: libghostty-vt does not pass this case.*

Input, one step per line:

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

Expected screen:

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

The `A` is still bold and red. Both manuals reset the rendition to normal.

### DECSTR-5: The margins are reset

*A known difference: libghostty-vt does not pass this case.*

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____|
```

The region stays at lines 2 and 3, so the line feed scrolls them and the `X`
lands on line 3. DEC STD 070, the VT510 manual and esctest2's
`test_DECSTR_STBM` reset the margins to the whole screen.

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

*A known difference: libghostty-vt does not pass this case.*

Input, one step per line:

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

Expected screen:

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

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

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

*A known difference: libghostty-vt does not pass this case.*

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 saved position survives, so the `X` is written at 2,3. 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.

---

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>.
