^[control-codes live in libghostty-vt

Control sequences

DECRQPSR Request Presentation State Report

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

CSI Ps $ w
DEC STD 070
§5.13.2 Request Presentation State Report, p. 5-198
VT510
DECRQPSR—Request Presentation State Report

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:

PsReportAnswer
1DECCIR, the cursor information reportDCS 1 $ u D…D ST
2DECTABSR, the tab stop reportDCS 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:

Field1248
renditionboldunderlineblinkinginverse
protectionselectively erasable (DECSCA)
flagsorigin modesingle shift 2 pendingsingle shift 3 pendingwrap pending
sizesG0 has 96 charactersG1G2G3

DEC STD 070 defines DECCIR at p. 5-200 and DECTABSR at p. 5-204; the VT510 manual has DECCIR and DECTABSR. 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, DECRSPS).

xterm, a VT420 by default, implements both reports in CASE_DECRQPSR and DECRSPS in misc.c. Its reports put no ; between a character field and a number that follows it (unparseseq), and its GR is G2 to start with (resetCharsets). 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

\e(B\e)B\e*B\e+B # designate ASCII into G0 to G3
\e[2;3H
\e[1$w
|__________|
|__________|
reply \eP1$u2;3;1;@;@;@;0;2;@;BBBB\e\\

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

\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
|__________|
reply \eP1$u1;1;1;C;A;A;1;2;@;B0BB\e\\

DECRQPSR-3: Tab stops

\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
|__________|
reply \eP2$u3/7\e\\

DECRQPSR-4: No tab stops

\e[3g     # clear every tab stop
\e[2$w
|__________|
reply \eP2$u\e\\

DECRQPSR-5: DECRSPS puts tab stops back

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

DECRQPSR-6: Any other report is not answered

\e[3$w
|__________|
reply none
Every example on these pages runs in your browser, in libghostty-vt compiled to WebAssembly.