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.
Support
| Terminal | Version | Support | Notes |
|---|---|---|---|
| VT220 | manual, 2nd ed., 1984 | No | not in the manual; DECSCUSR came with the VT520 |
| VT510 | manual, 1st ed., 1993 | Yes | DECSCUSR; styles 0 to 4; the bars, 5 and 6, are xterm’s |
| xterm | patch 412, xterm-411a | Yes | |
| libghostty-vt | 0f171f6 | Yes | 0 is the host’s default style, a steady block unless set (DECSCUSR-5) |
| kitty | 0.49.1, run in a VM | Partly | fails DECSCUSR-4 of the 5 cases that show it working |
| foot | 1.28.0, run in a VM | Partly | fails DECSCUSR-5 of the 5 cases that show it working |
| pyte | 0.8.2, run as a library | No | fails the 5 cases that show it working |
| xterm.js headless | 6.0.0, run as a library | Partly | fails DECSCUSR-2, DECSCUSR-3, DECSCUSR-4, DECSCUSR-5 of the 5 cases that show it working |
| ConEmu | build 230724, its documentation | Yes | 0 is ConEmu’s default rather than a blinking block; ANSI escape codes |
| VTE | 0.84.1, run as a library | Partly | fails DECSCUSR-5 of the 5 cases that show it working |
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.