# Request Presentation State Report (DECRQPSR)

> Ask for the cursor's state or the tab stops, as a report that can be sent back later to restore them.

- **Sequence:** `CSI Ps $ w`
- **DEC STD 070:** [§5.13.2 Request Presentation State Report, p. 5-198](https://archive.org/details/bitsavers_decstandar0VideoSystemsReferenceManualDec91_74264381/page/n452/mode/1up)
- **VT510:** [DECRQPSR—Request Presentation State Report](https://vt100.net/docs/vt510-rm/DECRQPSR.html)

Ask the terminal for part of its *presentation state*, the state that
decides how the next character will look and where it will go. `Ps` says
which part, and the terminal answers with a control string:

| `Ps` | Report | Answer |
| --- | --- | --- |
| `1` | DECCIR, the cursor information report | `DCS 1 $ u D…D ST` |
| `2` | DECTABSR, the tab stop report | `DCS 2 $ u D…D ST` |

DECCIR's data is ten fields, separated by `;`: the cursor's line, column
and page; the rendition of what will be written next; its protection
attribute; a set of flags; the sets invoked into GL and GR; the sizes of
the four designated character sets; and their designations. The rendition,
protection, flags and sizes are each one character, `@` (`40`) plus a bit
for each thing that is on:

| Field | `1` | `2` | `4` | `8` |
| --- | --- | --- | --- | --- |
| rendition | bold | underline | blinking | inverse |
| protection | selectively erasable ([DECSCA](https://control-codes.page/csi/decsca/index.html.md)) | | | |
| flags | [origin mode](https://control-codes.page/modes/decom/index.html.md) | single shift 2 pending | single shift 3 pending | wrap pending |
| sizes | G0 has 96 characters | G1 | G2 | G3 |

DEC STD 070 defines DECCIR at
[p. 5-200](https://archive.org/details/bitsavers_decstandar0VideoSystemsReferenceManualDec91_74264381/page/n454/mode/1up) and DECTABSR at
[p. 5-204](https://archive.org/details/bitsavers_decstandar0VideoSystemsReferenceManualDec91_74264381/page/n458/mode/1up); the VT510 manual has
[DECCIR](https://vt100.net/docs/vt510-rm/DECCIR.html) and
[DECTABSR](https://vt100.net/docs/vt510-rm/DECTABSR.html). DECTABSR's data
is the columns that have tab stops, separated by `/`.

The point of both reports is that the host can keep them and send them back
later as DECRSPS, `DCS Ps $ t D…D ST`, to put that state back
([p. 5-205](https://archive.org/details/bitsavers_decstandar0VideoSystemsReferenceManualDec91_74264381/page/n459/mode/1up),
[DECRSPS](https://vt100.net/docs/vt510-rm/DECRSPS.html)).

xterm, a VT420 by default, implements both reports in
[`CASE_DECRQPSR`](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/charproc.c#L5775-L5852) and DECRSPS in
[`misc.c`](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/misc.c#L5333-L5345). Its reports put no `;` between
a character field and a number that follows it
([`unparseseq`](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/charproc.c#L9368-L9433)), and its GR is G2 to
start with ([`resetCharsets`](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/charproc.c#L1278)). The cases here
designate all four character sets first, because what xterm starts with in
G2 and G3 depends on whether it runs in UTF-8.

libghostty-vt implements none of this: its CSI dispatch in `stream.zig` has
no case for the final byte `w`, so DECRQPSR gets no answer, and its DCS
handling has no `$ t`, so DECRSPS changes nothing. That is a known
difference from xterm in every case below but the last.

## Validation

### DECRQPSR-1: Cursor information

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

Input, one step per line:

```text
\e(B\e)B\e*B\e+B # designate ASCII into G0 to G3
\e[2;3H
\e[1$w
```

Expected screen:

```text
|__________|
|__________|
reply \eP1$u2;3;1;@;@;@;0;2;@;BBBB\e\\
```

### DECRQPSR-2: With a rendition, protection, origin mode and SO

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

Input, one step per line:

```text
\e(B\e)0\e*B\e+B # DEC Special Graphics into G1
\e[1;4m   # bold, underline
\e[1"q    # selectively erasable
\e[?6h    # origin mode; homes the cursor
\x0e      # SO: G1 into GL
\e[1$w
```

Expected screen:

```text
|__________|
reply \eP1$u1;1;1;C;A;A;1;2;@;B0BB\e\\
```

### DECRQPSR-3: Tab stops

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

Input, one step per line:

```text
\e[3g     # clear every tab stop
\e[1;3H\eH # set one at column 3
\e[1;7H\eH # and at column 7
\e[2$w
```

Expected screen:

```text
|__________|
reply \eP2$u3/7\e\\
```

### DECRQPSR-4: No tab stops

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

Input, one step per line:

```text
\e[3g     # clear every tab stop
\e[2$w
```

Expected screen:

```text
|__________|
reply \eP2$u\e\\
```

### DECRQPSR-5: DECRSPS puts tab stops back

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

Input, one step per line:

```text
\e[3g     # clear every tab stop
\eP2$t3/7\e\\ # DECRSPS: stops at 3 and 7
\r\tX
```

Expected screen:

```text
|__X_______|
```

### DECRQPSR-6: Any other report is not answered

Input, one step per line:

```text
\e[3$w
```

Expected screen:

```text
|__________|
reply none
```

---

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