# DEC Private Mode Set (DECSET)

> Turn one or more DEC private modes on.

- **Sequence:** `CSI ? Pm h`
- **DEC STD 070:** [§5.10.1.2 DEC Private Modes, 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)
- **xterm:** [Functions using CSI](https://invisible-island.net/xterm/ctlseqs/ctlseqs.html)

`CSI ? Pm h` sets one or more DEC private modes, and
[DECRST](https://control-codes.page/csi/decrst/index.html.md), `CSI ? Pm l`, resets them. It is [SM](https://control-codes.page/csi/sm/index.html.md) with a
`?` in front of the parameters, which ECMA-48 leaves for private use, and the
`?` changes what every number means: `CSI 4 h` is insert mode, IRM, but
`CSI ? 4 h` is smooth scrolling, [DECSCLM](https://control-codes.page/modes/decsclm/index.html.md). Each mode has a
page under [private modes](https://control-codes.page/modes/index.html.md).

DEC's manuals do not call it DECSET. To them it is SM, Set Mode, with a `?`:
DEC STD 070 lists the private modes in its table of SM parameters, and the
VT220 and VT510 manuals describe both forms under SM, and DECRST under RM. The names DECSET and
DECRST are xterm's, from its list of control sequences, and are the ones
most documentation uses now.

Each parameter names one mode, and they are set in order. DEC STD 070 says
a `0` is an error and is ignored, as is any number the terminal does not
know, and that ANSI and private parameters cannot be mixed in one sequence.
xterm handles each mode in turn in [`dpmodes`](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/charproc.c#L7493-L8047), skipping those it does not know,
and so does libghostty-vt.

A host can ask about one mode with [DECRQM](https://control-codes.page/csi/decrqm/index.html.md), `CSI ? Pd $ p`.
xterm can also save the state of private modes with [XTSAVE](https://control-codes.page/csi/xtsave/index.html.md),
`CSI ? Pm s`, and put it back with [XTRESTORE](https://control-codes.page/csi/xtrestore/index.html.md),
`CSI ? Pm r`.

## Validation

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

Input, one step per line:

```text
\e[?7;25l
\e[?7;25h  # autowrap and the cursor
\e[?7$p
\e[?25$p
```

Expected screen:

```text
|_____|
reply \e[?7;1$y\e[?25;1$y
```

### DECSET-2: Autowrap on again

Input, one step per line:

```text
\e[?7l
\e[?7h
ABCDEFG
```

Expected screen:

```text
|ABCDE|
|FG___|
cursor 2,3
```

### DECSET-3: A mode that is not known does not stop the others

Input, one step per line:

```text
\e[?7l
\e[?0;9999;7h  # 0 is an error, 9999 is no mode
ABCDEFG
```

Expected screen:

```text
|ABCDE|
|FG___|
cursor 2,3
```

### DECSET-4: Without the question mark it is a different mode

Input, one step per line:

```text
\e[?7l
\e[7h      # VEM, not DECAWM
ABCDEFG
```

Expected screen:

```text
|ABCDG|
|_____|
cursor 1,5
```

---

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