# Set Mode (SM)

> Turn one or more ANSI modes on.

- **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)
- **VT220:** [§4.6.1 Set Mode (SM)](https://vt100.net/docs/vt220-rm/chapter4.html#S4.6.1)
- **VT510:** [SM—Set Mode](https://vt100.net/docs/vt510-rm/SM.html)

`CSI Pm h` sets one or more modes. Each parameter names one mode, the modes
are set in order, and ECMA-48 gives no default. [RM](https://control-codes.page/csi/rm/index.html.md), `CSI Pm l`,
resets them again.

ECMA-48 numbers 22 modes, most of them for block-mode terminals, editing
devices and bidirectional text, and each has a page under
[ANSI modes](https://control-codes.page/ansi/index.html.md). DEC STD 070 lists only four a DEC terminal accepts,
KAM, IRM, SRM and LNM, and says that a `0` is an error and is ignored; the
VT220 manual's table of ANSI modes is the same. xterm and libghostty-vt
accept the same four ([`ansi_modes`](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/charproc.c#L7399-L7424)) and ignore every other number. They differ only
in what [DECRQM](https://control-codes.page/csi/decrqm/index.html.md) says about the rest:

| `Pm` | Mode | Name | In xterm | In libghostty-vt |
| --- | --- | --- | --- | --- |
| `1` | [GATM](https://control-codes.page/ansi/gatm/index.html.md) | Guarded Area Transfer Mode | permanently reset | not recognized |
| `2` | [KAM](https://control-codes.page/ansi/kam/index.html.md) | Keyboard Action Mode | yes | yes |
| `3` | [CRM](https://control-codes.page/ansi/crm/index.html.md) | Control Representation Mode | reported as reset | not recognized |
| `4` | [IRM](https://control-codes.page/ansi/irm/index.html.md) | Insertion Replacement Mode | yes | yes |
| `5` | [SRTM](https://control-codes.page/ansi/srtm/index.html.md) | Status Report Transfer Mode | permanently reset | not recognized |
| `6` | [ERM](https://control-codes.page/ansi/erm/index.html.md) | Erasure Mode | not recognized | not recognized |
| `7` | [VEM](https://control-codes.page/ansi/vem/index.html.md) | Line Editing Mode | permanently reset | not recognized |
| `8` | [BDSM](https://control-codes.page/ansi/bdsm/index.html.md) | Bi-directional Support Mode | not recognized | not recognized |
| `9` | [DCSM](https://control-codes.page/ansi/dcsm/index.html.md) | Device Component Select Mode | not recognized | not recognized |
| `10` | [HEM](https://control-codes.page/ansi/hem/index.html.md) | Character Editing Mode | permanently reset | not recognized |
| `11` | [PUM](https://control-codes.page/ansi/pum/index.html.md) | Positioning Unit Mode | permanently reset | not recognized |
| `12` | [SRM](https://control-codes.page/ansi/srm/index.html.md) | Send/Receive Mode | yes | yes |
| `13` | [FEAM](https://control-codes.page/ansi/feam/index.html.md) | Format Effector Action Mode | permanently reset | not recognized |
| `14` | [FETM](https://control-codes.page/ansi/fetm/index.html.md) | Format Effector Transfer Mode | permanently reset | not recognized |
| `15` | [MATM](https://control-codes.page/ansi/matm/index.html.md) | Multiple Area Transfer Mode | permanently reset | not recognized |
| `16` | [TTM](https://control-codes.page/ansi/ttm/index.html.md) | Transfer Termination Mode | permanently reset | not recognized |
| `17` | [SATM](https://control-codes.page/ansi/satm/index.html.md) | Selected Area Transfer Mode | permanently reset | not recognized |
| `18` | [TSM](https://control-codes.page/ansi/tsm/index.html.md) | Tabulation Stop Mode | permanently reset | not recognized |
| `19` | [EBM](https://control-codes.page/ansi/ebm/index.html.md) | Editing Boundary Mode | permanently reset | not recognized |
| `20` | [LNM](https://control-codes.page/ansi/lnm/index.html.md) | Line Feed/New Line Mode | yes | yes |
| `21` | [GRCM](https://control-codes.page/ansi/grcm/index.html.md) | Graphic Rendition Combination Mode | not recognized | not recognized |
| `22` | [ZDM](https://control-codes.page/ansi/zdm/index.html.md) | Zero Default Mode | not recognized | not recognized |

Only IRM and LNM change what appears on the screen, so they are the ones
the cases here use.

ANSI modes and DEC private modes cannot be mixed in one sequence. The DEC
private form, `CSI ? Pm h`, is [DECSET](https://control-codes.page/csi/decset/index.html.md), and its numbers name
the [private modes](https://control-codes.page/modes/index.html.md).

## Support

| Terminal | Version | Support | Notes |
| --- | --- | --- | --- |
| VT220 | [manual](https://vt100.net/docs/vt220-rm/), 2nd ed., 1984 | Yes | [§4.6.1 Set Mode (SM)](https://vt100.net/docs/vt220-rm/chapter4.html#S4.6.1) |
| VT510 | [manual](https://vt100.net/docs/vt510-rm/), 1st ed., 1993 | Yes | [SM](https://vt100.net/docs/vt510-rm/SM.html) |
| xterm | patch 412, [xterm-411a](https://github.com/ThomasDickey/xterm-snapshots/tree/xterm-411a) | Yes | KAM, IRM, SRM and LNM |
| libghostty-vt | [0f171f6](https://github.com/ghostty-org/ghostty/tree/0f171f650a1cbbd6df4a2573b6b0c7de57cc6d90) | Yes | KAM, IRM, SRM and LNM |
| 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 2 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) | No | fails the 2 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) | Yes | passes the 2 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 2 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 SM-1 of the 2 cases that show it working |
| ConEmu | build 230724, its [documentation](https://conemu.github.io/en/AnsiEscapeCodes.html) | Partly | lists only `20` (LNM) and its own `7`, line wrapping at a column; [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) | No | fails the 2 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 SM-1 of the 2 cases that show it working |

## Validation

### SM-1: Two modes in one sequence

Input, one step per line:

```text
abc
\e[1;1H
\e[4;20h  # IRM and LNM
X
\n
Y
```

Expected screen:

```text
|Xabc_|
|Y____|
cursor 2,2
```

### SM-2: A mode that is not known does not stop the others

Input, one step per line:

```text
abc
\e[1;1H
\e[0;99;4h # 0 is an error, 99 is no mode
X
```

Expected screen:

```text
|Xabc_|
cursor 1,2
```

### SM-3: A question mark makes it a different mode

Input, one step per line:

```text
abc
\e[1;1H
\e[?4h    # DECSCLM, smooth scrolling, not IRM
X
```

Expected screen:

```text
|Xbc__|
cursor 1,2
```

---

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