# Sixel Display Mode (DECSDM)

> Choose whether a sixel image scrolls with the text from the cursor, or is drawn from the top left corner.

- **Sequence:** `CSI ? 80 h`
- **Defaults:** reset
- **VT330/VT340:** [§14.4 Sixel Scrolling Mode](https://vt100.net/docs/vt3xx-gp/chapter14.html#S14.4)
- **xterm:** [Sixel Display Mode (DECSDM)](https://invisible-island.net/xterm/ctlseqs/ctlseqs.html)

Mode 80 decides where a [sixel image](https://control-codes.page/dcs/sixel/index.html.md) is drawn. With *sixel
scrolling*, the image starts at the text cursor, the screen scrolls when it
reaches the bottom margin, and when the image ends the text cursor is left
where the sixels stopped. Without it, in *sixel display mode*, the image
starts at the top left corner of the screen, cannot scroll, and the text
cursor stays where it was.

Which of the two *set* means is a contradiction in DEC's own documents. The
VT330/VT340 manual says that "when sixel display mode is set, the Sixel
Scrolling feature is enabled"
([§14.4.3](https://vt100.net/docs/vt3xx-gp/chapter14.html#S14.4.3)), the
opposite of the mode's name. The VT382 manuals have it the other way round:
set is display mode, with no scrolling. xterm followed the VT330/VT340
manual until patch 369, which inverted it "to correspond with VT382 manuals"
([`xterm.log.html`](https://invisible-island.net/xterm/xterm.log.html#xterm_369)),
so in xterm today `CSI ? 80 l` turns sixel scrolling on, and a program that
sends an image to be scrolled with the text sends that first.

In xterm, the mode is reset to begin with, because its `sixelScrolling`
resource is true by default
([`charproc.c`](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/charproc.c#L11743-L11753)),
and [RIS](https://control-codes.page/esc/ris/index.html.md) puts it back to that. It can be set or reset only when
sixel graphics are on
([`charproc.c`](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/charproc.c#L7791-L7800)),
which in a default xterm, a VT420, they are not. [DECRQM](https://control-codes.page/csi/decrqm/index.html.md)
reports the mode all the same
([`misc.c`](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/misc.c#L5632-L5636)),
so a default xterm answers that it is reset, whatever was sent. The cases
follow it, as the [sources](https://control-codes.page/sources/index.html.md) page explains.

xterm has two more modes for sixels, each its own: `1070` gives each image
its own color registers, and `8452` leaves the cursor to the right of an
image rather than below it.

## Not in libghostty-vt

libghostty-vt has no sixel graphics and no mode 80: it is not in the table in
`modes.zig`, so DECRQM reports it as not recognized (`0`). Both cases are
known differences.

## Support

| Terminal | Version | Support | Notes |
| --- | --- | --- | --- |
| VT220 | [manual](https://vt100.net/docs/vt220-rm/), 2nd ed., 1984 | No | the VT220 has no graphics |
| VT340 | [manual](https://vt100.net/docs/vt3xx-gp/), vol. 2, 2nd ed., 1988 | Yes | [§14.4 Sixel Scrolling Mode](https://vt100.net/docs/vt3xx-gp/chapter14.html#S14.4); set enables sixel scrolling, the reverse of xterm |
| VT510 | [manual](https://vt100.net/docs/vt510-rm/), 1st ed., 1993 | No | the VT510 manual has no sixel graphics |
| xterm | patch 412, [xterm-411a](https://github.com/ThomasDickey/xterm-snapshots/tree/xterm-411a) | Partly | reported, reset, but set or reset only when sixel graphics are on, which in a default xterm they are not |
| libghostty-vt | [83edd49](https://github.com/ghostty-org/ghostty/tree/83edd491e3024ae5e50393d62877b8897da1cccd) | No | no mode 80 (DECSDM-1, DECSDM-2) |
| Konsole | 26.11.70, [a24c3d71](https://invent.kde.org/utilities/konsole/-/tree/a24c3d71be3684f24d030aa2dbe9bd723d985233) | Yes | set turns sixel scrolling off, as in xterm; no DECRQM ([`Vt102Emulation.cpp`](https://invent.kde.org/utilities/konsole/-/blob/a24c3d71be3684f24d030aa2dbe9bd723d985233/src/Vt102Emulation.cpp#L2263-L2264)) |
| ConEmu | build 230724, its [documentation](https://conemu.github.io/en/AnsiEscapeCodes.html) | No | not in ConEmu's list, [ANSI escape codes](https://conemu.github.io/en/AnsiEscapeCodes.html) |

## Validation

### DECSDM-1: Reset by default

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

Input, one step per line:

```text
\e[?80$p
```

Expected screen:

```text
|_____|
reply \e[?80;2$y
```

### DECSDM-2: Setting it is ignored without sixel graphics

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

Input, one step per line:

```text
\e[?80h
\e[?80$p
```

Expected screen:

```text
|_____|
reply \e[?80;2$y
```

---

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