# Request Termcap/Terminfo String (XTGETTCAP)

> Ask the terminal what a key sends, or for one of a few of its capabilities, by its terminfo or termcap name.

- **Sequence:** `DCS + q Pt ST`
- **xterm:** [Device-Control functions](https://invisible-island.net/xterm/ctlseqs/ctlseqs.html)

`DCS + q Pt ST` asks for one or more capabilities by name, so that a program
can learn about the terminal it is actually talking to rather than trusting
`$TERM`'s terminfo entry, which may be wrong or on another machine. `Pt` is
the names, each in hexadecimal and separated by `;`: `kcuu1` is
`6B63757531`. The answer is `DCS 1 + r name=value ST`, with the name as it
was sent and the value in hexadecimal too, or `DCS 0 + r ST` if the first
name is not one the terminal knows.

It is xterm's, and what a default xterm knows is a fixed table, not a
terminfo entry
([`xtermcap.c`](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/xtermcap.c#L70-L244)):

- the keys: arrows, editing keys, function keys and the keypad, each by its
  terminfo name (`kcuu1`, `khome`, `kf1`) or its termcap name (`ku`, `kh`,
  `k1`), and shifted ones such as `kRIT`;
- `Co` or `colors`, the number of colors, `256`;
- `RGB`, the bits per color it can show directly, `8` on a 24-bit display;
- `TN` or `name`, the terminal name it set `$TERM` to, `xterm` unless the
  `termName` resource says otherwise.

A key is answered by pretending to press it, so the answer is what the key
sends *now*: `kcuu1` is `CSI A`, until [DECCKM](https://control-codes.page/modes/decckm/index.html.md) makes it
`SS3 A`
([`XTGETTCAP`](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/misc.c#L5171-L5248),
[`xtermcapKeycode`](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/xtermcap.c#L386-L456),
[cursor keys](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/input.c#L1401-L1412)).
Several names in one request get one answer, with the `name=value` pairs
separated by `;`; it stops at the first name it does not know, after
writing the `;`.

libghostty-vt answers from Ghostty's own terminfo entry instead. Its key
strings are fixed, the ones that entry gives, which assume DECCKM is set; it
knows terminfo names only; it answers many capabilities xterm does not, such
as `Smulx` and `setrgbf`, giving those as their terminfo source text; it
gives each name its own `DCS … ST`, writes the names back in upper case, and
says nothing about a name it does not know. It does not answer `TN`. The
cases follow a default xterm, and the cases that touch those differences are
known differences.

The names in the cases are sent in upper-case hexadecimal, which both write
back unchanged, so that a case shows one difference at a time.

## Validation

### XTGETTCAP-1: Number of colors

Input, one step per line:

```text
\eP+q436F\e\\  # Co
\eP+q636F6C6F7273\e\\  # colors
```

Expected screen:

```text
|______|
reply \eP1+r436F=323536\e\\\eP1+r636F6C6F7273=323536\e\\
```

### XTGETTCAP-2: Direct color

Input, one step per line:

```text
\eP+q524742\e\\  # RGB
```

Expected screen:

```text
|______|
reply \eP1+r524742=38\e\\
```

### XTGETTCAP-3: F1

Input, one step per line:

```text
\eP+q6B6631\e\\  # kf1
```

Expected screen:

```text
|______|
reply \eP1+r6B6631=1B4F50\e\\
```

### XTGETTCAP-4: Up arrow, as it is now

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

Input, one step per line:

```text
\eP+q6B63757531\e\\  # kcuu1: CSI A
```

Expected screen:

```text
|______|
reply \eP1+r6B63757531=1B5B41\e\\
```

### XTGETTCAP-5: Up arrow, after DECCKM

Input, one step per line:

```text
\e[?1h
\eP+q6B63757531\e\\  # kcuu1: SS3 A
```

Expected screen:

```text
|______|
reply \eP1+r6B63757531=1B4F41\e\\
```

### XTGETTCAP-6: Home

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

Input, one step per line:

```text
\eP+q6B686F6D65\e\\  # khome: CSI H
\e[?1h
\eP+q6B686F6D65\e\\  # khome: SS3 H
```

Expected screen:

```text
|______|
reply \eP1+r6B686F6D65=1B5B48\e\\\eP1+r6B686F6D65=1B4F48\e\\
```

### XTGETTCAP-7: Shift and right arrow

Input, one step per line:

```text
\eP+q6B524954\e\\  # kRIT: CSI 1 ; 2 C
```

Expected screen:

```text
|______|
reply \eP1+r6B524954=1B5B313B3243\e\\
```

### XTGETTCAP-8: By termcap name

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

Input, one step per line:

```text
\eP+q6B75\e\\  # ku
```

Expected screen:

```text
|______|
reply \eP1+r6B75=1B5B41\e\\
```

### XTGETTCAP-9: The terminal's name

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

Input, one step per line:

```text
\eP+q544E\e\\  # TN
```

Expected screen:

```text
|______|
reply \eP1+r544E=787465726D\e\\
```

### XTGETTCAP-10: Two at once

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

Input, one step per line:

```text
\eP+q436F;524742\e\\  # Co;RGB
```

Expected screen:

```text
|______|
reply \eP1+r436F=323536;524742=38\e\\
```

### XTGETTCAP-11: A name it does not know

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

Input, one step per line:

```text
\eP+q536D756C78\e\\  # Smulx
```

Expected screen:

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

### XTGETTCAP-12: The name comes back as it was sent

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

Input, one step per line:

```text
\eP+q436f\e\\  # Co, in lower case
```

Expected screen:

```text
|______|
reply \eP1+r436f=323536\e\\
```

---

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