# Set Mode and Reset Mode (SM, RM)

> Turn terminal modes on and off.

- **Sequence:** `CSI Pm h`
- **ECMA-48:** [§8.3.125 SM – Set Mode, p. 65](https://archive.org/details/ecma-48-5th-edition-june-1991/page/n78/mode/1up)
- **DEC STD 070:** [§5.10.1 SM/RM – Set Mode, Reset Mode, p. 5-133](https://archive.org/details/bitsavers_decstandar0VideoSystemsReferenceManualDec91_74264381/page/n387/mode/1up)
- **VT510:** [SM—Set Mode](https://vt100.net/docs/vt510-rm/SM.html)

`CSI Pm h` (SM) sets one or more modes, and `CSI Pm l` (RM) resets them.
Each parameter names one mode, and ECMA-48 gives no default. RM is
[ECMA-48 §8.3.106, p. 56](https://archive.org/details/ecma-48-5th-edition-june-1991/page/n69/mode/1up)
and [RM—Reset Mode](https://vt100.net/docs/vt510-rm/RM.html) in the VT510
manual.

ECMA-48 numbers 22 modes, most of them for data transmission, editing
devices and bidirectional text. DEC STD 070 lists the four a DEC terminal
accepts, and libghostty-vt accepts the same four. The defaults are
libghostty-vt's:

| `Pm` | Mode | Set | Reset |
| --- | --- | --- | --- |
| `2` | KAM, keyboard action | keyboard locked | keyboard unlocked (default) |
| `4` | IRM, insertion/replacement | insert | replace (default) |
| `12` | SRM, send/receive | no local echo (default) | local echo |
| `20` | LNM, line feed/new line | LF, VT and FF also return | LF, VT and FF only move down (default) |

KAM and SRM concern the keyboard, so they have no effect on the screen and
no cases here.

**IRM.** In replace mode, which is the default, a printed character takes the
place of the one under the cursor. In insert mode, the character under the
cursor and everything right of it move one column right to make room, and
whatever is pushed past the right margin is lost. DEC STD 070 defines it at
[§5.11, p. 5-138](https://archive.org/details/bitsavers_decstandar0VideoSystemsReferenceManualDec91_74264381/page/n392/mode/1up),
and the VT510 manual as [IRM](https://vt100.net/docs/vt510-rm/IRM.html).

**LNM.** With LNM set, a [line feed](https://control-codes.page/c0/lf/index.html.md), [vertical tab](https://control-codes.page/c0/vt/index.html.md) or
[form feed](https://control-codes.page/c0/ff/index.html.md) also moves the cursor to the first column, as `CR LF`
would. DEC STD 070 defines it at
[§5.4.4, p. 5-57](https://archive.org/details/bitsavers_decstandar0VideoSystemsReferenceManualDec91_74264381/page/n311/mode/1up),
and says that conforming software should not set it; the VT510 manual
describes it as [LNM](https://vt100.net/docs/vt510-rm/LNM.html). ECMA-48
removed it in this fifth edition, having deprecated it in the fourth, and
mode 20 is now "shall not be used", but DEC terminals, and libghostty-vt,
still have it.

ANSI modes and DEC private modes cannot be mixed in one sequence. The DEC
private form, `CSI ? Pm h` and `CSI ? Pm l` (DECSET and DECRST), takes a
different set of mode numbers and is not covered on this page.

## Validation

### SM-1: Insert mode

Input, one step per line:

```text
abc
\e[1;1H
\e[4h     # IRM
X
```

Expected screen:

```text
|Xabc__|
cursor 1,2
```

### SM-2: What is pushed off the line is lost

Input, one step per line:

```text
ABCDEF    # fills the line
\e[1;2H
\e[4h     # IRM
X
```

Expected screen:

```text
|AXBCDE|
|______|
cursor 1,3
```

### SM-3: Back to replace mode

Input, one step per line:

```text
abc
\e[1;1H
\e[4h     # IRM: insert
X
\e[4l     # replace
Y         # over the a
```

Expected screen:

```text
|XYbc__|
```

### SM-4: Insert stops at the right margin

Input, one step per line:

```text
\e[1;5H
abcdef            # columns 5 to 10
\e[?69h           # allow left and right margins
\e[5;10s          # margins at columns 5 and 10
\e[1;7H
\e[4h             # IRM
X                 # the f is pushed past column 10
```

Expected screen:

```text
|____abXcde__|
```

### SM-5: Line feed/new line mode

Input, one step per line:

```text
\e[20h    # LNM
AB
\n
C
\e[20l
\n
D
```

Expected screen:

```text
|AB___|
|C____|
|_D___|
```

---

This is the Markdown version of <https://control-codes.page/csi/sm/>. 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>.
