# Device Control String (DCS)

> Open a control string carrying commands for the terminal itself.

- **Sequence:** `DCS Pm Pi Pf Pt ST`
- **ECMA-48:** [§8.3.27 DCS – Device Control String, p. 38](https://archive.org/details/ecma-48-5th-edition-june-1991/page/n51/mode/1up)
- **DEC STD 070:** [§3.5.4.1 Device Control Strings, p. 3-28](https://archive.org/details/bitsavers_decstandar0VideoSystemsReferenceManualDec91_74264381/page/n132/mode/1up)
- **VT510:** [4.3.4 Device Control Strings](https://vt100.net/docs/vt510-rm/chapter4.html#S4.3.4)

DCS opens a control string of commands for the terminal, closed by
[ST](https://control-codes.page/esc/st/index.html.md). ECMA-48 leaves the format of the commands to the devices
involved. DEC STD 070 gives the one DEC terminals use: a parameter string,
intermediates and a final byte, exactly like a [control sequence](https://control-codes.page/esc/csi/index.html.md)'s,
followed by the data, `D…D`, and ST. The final byte is always one of the
private ones, `p` to `~`. DEC uses device control strings for loading
character sets, user-defined keys and sixel graphics, and for asking about
settings.

Nothing in a device control string is displayed. One the terminal does not
implement is thrown away whole, from DCS to ST, "without being displayed"
([DEC STD 070 §3.5.4.6, p. 3-30](https://archive.org/details/bitsavers_decstandar0VideoSystemsReferenceManualDec91_74264381/page/n134/mode/1up)).

**Ending early.** On the same page, DEC STD 070 lets CAN, SUB, ESC or any C1
control end a control string too, "to minimize the effect of a lost String
Terminator", though software should not rely on it. The format effectors
`BS` to `CR` may appear in the data, and it recommends that any other
control be ignored. So [BEL](https://control-codes.page/c0/bel/index.html.md) neither ends a device control string
nor rings in one in libghostty-vt. xterm, which only lets BEL end an
[OSC](https://control-codes.page/osc/title/index.html.md), rings the bell for one inside a DCS and carries on
([`CASE_BELL`](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/charproc.c#L3691-L3705)).

**Request Status String.** One device control string libghostty-vt does
answer is [DECRQSS](https://control-codes.page/dcs/decrqss/index.html.md), `DCS $ q Pt ST`, which asks for the current setting of
the function `Pt` names: `m` for [SGR](https://control-codes.page/csi/sgr/index.html.md), `r` for the top and
bottom margins, and others. The answer, DECRPSS, is `DCS Ps $ r D…D ST`,
where `D…D` is the setting written as the sequence that would set it. The
VT510 manual's [DECRPSS](https://vt100.net/docs/vt510-rm/DECRPSS.html) page
gives `Ps` as `0` for a valid request and `1` for an invalid one, but xterm
answers `1` for valid and `0` for invalid, its
[Control Sequences](https://invisible-island.net/xterm/ctlseqs/ctlseqs.html)
document says so, and esctest2's `decrqss.py` expects it. libghostty-vt
answers as xterm does.

xterm adds three more of its own, which libghostty-vt answers only in part:
[XTGETTCAP](https://control-codes.page/dcs/xtgettcap/index.html.md), `DCS + q`, which asks what a key sends;
[XTSETTCAP](https://control-codes.page/dcs/xtsettcap/index.html.md), `DCS + p`; and
[XTGETXRES](https://control-codes.page/dcs/xtgetxres/index.html.md), `DCS + Q`, which asks for its settings.

DCS is a C1 control. ECMA-48 also defines it as the single byte `90`, which
libghostty-vt, decoding its input as UTF-8, does not accept.

## Validation

### DCS-1: Not displayed

Input, one step per line:

```text
A
\eP1;2zhello\e\\   # a DCS libghostty-vt does not implement
B
```

Expected screen:

```text
|AB____|
cursor 1,3
reply none
```

### DCS-2: Asking for the rendition

Input, one step per line:

```text
\e[1;31m  # bold, red
\eP$qm\e\\
```

Expected screen:

```text
|______|
reply \eP1$r0;1;31m\e\\
```

### DCS-3: Asking for the margins

Input, one step per line:

```text
\e[2;3r
\eP$qr\e\\
```

Expected screen:

```text
|______|
|______|
|______|
reply \eP1$r2;3r\e\\
```

### DCS-4: A request it does not understand

Input, one step per line:

```text
\eP$qz\e\\
```

Expected screen:

```text
|______|
reply \eP0$r\e\\
```

### DCS-5: ESC or CAN ends it early

Input, one step per line:

```text
A
\ePzhi    # never terminated
\e[2;2H   # the ESC ends the string, and this is a CUP
B
\ePzhi\x18   # CAN ends it too
C
```

Expected screen:

```text
|A_____|
|_BC___|
```

### DCS-6: BEL does not end it

Input, one step per line:

```text
A
\ePzhi\a  # BEL is part of the string
B         # and so is this
\e\\
C
```

Expected screen:

```text
|AC____|
bell 0
```

---

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