DECSCUSR Set Cursor Style
Choose the cursor's shape, and whether it blinks.
CSI Ps SP q
- Defaults
- Ps = 1
- VT510
- DECSCUSR—Set Cursor Style
- xterm
- Functions using CSI
Set the shape of the cursor, and whether it blinks. SP is a space, 20, used here as an intermediate byte.
Ps | Cursor |
|---|---|
0, 1, or left out | blinking block |
2 | steady block |
3 | blinking underline |
4 | steady underline |
5 | blinking bar |
6 | steady bar |
The VT510 manual defines 0 to 4, and calls the blinking block the default. The bar, 5 and 6, is xterm’s addition. DECSCUSR came with the VT520, so DEC STD 070 does not have it. It changes only how the cursor looks: whether it is shown at all is DECTCEM’s job.
Nothing about the cursor’s style is in the cell grid, so the cases ask the terminal for it with DECRQSS, DCS $ q SP q ST, which both the VT510 manual and xterm list for DECSCUSR (see DCS). The answer is DCS 1 $ r Ps SP q ST, with the style as Ps.
0, or no parameter, is where libghostty-vt departs from the manuals. It reads it as “go back to the host’s default style”, and the host chooses that default with libghostty-vt’s DEFAULT_CURSOR_STYLE and DEFAULT_CURSOR_BLINK options. Left unset, as the cases here leave them, the default is a steady block, so CSI 0 SP q reports 2. Before any DECSCUSR at all, the cursor is the same steady block.
Validation
DECSCUSR-1: Steady block
\e[2\sq
\eP$q\sq\e\\ # ask for the style
|_____|
reply \eP1$r2 q\e\\
DECSCUSR-2: Blinking underline
\e[3\sq
\eP$q\sq\e\\
|_____|
reply \eP1$r3 q\e\\
DECSCUSR-3: Steady bar
\e[6\sq
\eP$q\sq\e\\
|_____|
reply \eP1$r6 q\e\\
DECSCUSR-4: Blinking block
\e[1\sq
\eP$q\sq\e\\
|_____|
reply \eP1$r1 q\e\\
DECSCUSR-5: Zero is a blinking block
\e[2\sq # steady block
\e[0\sq # back to the default
\eP$q\sq\e\\
|_____|
reply \eP1$r1 q\e\\
libghostty-vt answers \eP1$r2 q\e\\, a steady block. Its DECSCUSR handler in stream.zig turns 0 and an omitted parameter into .default, and setCursorStyle in Terminal.zig takes the host’s default shape and blink, which unless the host sets them are a block that does not blink. The VT510 manual makes 0 a blinking block, the default, and xterm’s ctlseqs says “Ps = 0 ⇒ blinking block”, which its CASE_DECSCUSR does. A host can make libghostty-vt agree by setting DEFAULT_CURSOR_BLINK.