# Select Presentation Directions (SPD)

> ECMA-48's choice of line orientation, line progression and character path for the whole presentation, which terminals that handle bidirectional text take as left to right or right to left.

- **Sequence:** `CSI Ps1 ; Ps2 SP S`
- **Defaults:** Ps1 = 0, Ps2 = 0
- **ECMA-48:** [§8.3.130 SPD – Select Presentation Directions, p. 66](https://archive.org/details/ecma-48-5th-edition-june-1991/page/n79/mode/1up)
- **Specification:** [BiDi in Terminal Emulators, v0.1, The escape sequences](https://gitlab.freedesktop.org/terminal-wg/bidi/-/blob/cc8686a93c8cc2f25a2f68f79c01b4822111509c/docs/30-recommendation/90-escape-sequences.md)

In ECMA-48, SPD sets three things at once for the whole presentation: the
*line orientation*, horizontal or vertical; the *line progression*, which
way successive lines follow one another; and the *character path*, which way
text runs along a line. `Ps1` picks one of eight combinations, and `Ps2`
says what happens to text already there, as it does for
[SCP](https://control-codes.page/csi/scp/index.html.md). Both default to `0`.

| `Ps1` | Lines | Line progression | Character path |
| --- | --- | --- | --- |
| `0` | horizontal | top to bottom | left to right |
| `1` | vertical | right to left | top to bottom |
| `2` | vertical | left to right | top to bottom |
| `3` | horizontal | top to bottom | right to left |
| `4` | vertical | left to right | bottom to top |
| `5` | horizontal | bottom to top | right to left |
| `6` | horizontal | bottom to top | left to right |
| `7` | vertical | right to left | bottom to top |

| `Ps2` | Effect on text already there |
| --- | --- |
| `0` | left to the implementation |
| `1` | the presentation is updated to match the data |
| `2` | the data is updated to match the presentation |

[*BiDi in Terminal Emulators*](https://terminal-wg.pages.freedesktop.org/bidi/recommendation/escape-sequences.html)
reads SPD and SCP as setting the same character path, the last one received
winning, and picks SCP for programs to use: the line orientation and
progression can only be global, while a character path can belong to a
paragraph, and SPD would also apply at once to everything on the screen.
Programs written to the recommendation do not send SPD. A terminal may still
take it from an older program, and the recommendation suggests SPD `0` and
`3`, the two horizontal, top-to-bottom layouts, as other ways of writing
SCP `1` and SCP `2`. It considers and rejects SPD as a way to set the
direction of a whole full-screen canvas, since BDSM and autodetection would
need a whole-screen form of their own too.

[VTE](https://gitlab.gnome.org/GNOME/vte/-/blob/0.84.1/src/vteseq.cc#L8625-L8672)
does just that: `0` or a missing parameter is left to right, `3` is right
to left, and every other value is ignored, as is `Ps2`. Like SCP, it
applies to the paragraph the cursor is in only if the cursor is at its
start. mintty documents the same two values, and calls SPD "a deprecated
fun feature"
([documentation](https://github.com/mintty/mintty/wiki/CtrlSeqs#bidirectional-rendering)).

A default xterm ignores `CSI SP S`: its table for a CSI with a space
intermediate has nothing for `S`
([`csi_sp_table`](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/VTPrsTbl.c#L1880)).
libghostty-vt ignores it too. The intermediate is the whole difference
between SPD and [SU](https://control-codes.page/csi/su/index.html.md), `CSI Pn S`, and neither terminal scrolls.
The cases follow xterm.

## Support

| Terminal | Version | Support | Notes |
| --- | --- | --- | --- |
| VT220 | [manual](https://vt100.net/docs/vt220-rm/), 2nd ed., 1984 | No | not in the manual |
| VT510 | [manual](https://vt100.net/docs/vt510-rm/), 1st ed., 1993 | No | not in the manual |
| xterm | patch 412, [xterm-411a](https://github.com/ThomasDickey/xterm-snapshots/tree/xterm-411a) | No | ignored; `CSI SP S` is not in its parser |
| libghostty-vt | [919dca5](https://github.com/ghostty-org/ghostty/tree/919dca5c848d43a489a4cb2e1feade016f0fa2db) | No | ignored |
| ConEmu | build 230724, its [documentation](https://conemu.github.io/en/AnsiEscapeCodes.html) | No | not in its [ANSI escape codes](https://conemu.github.io/en/AnsiEscapeCodes.html) |
| mintty | 3.8.3, its [documentation](https://github.com/mintty/mintty/wiki/CtrlSeqs) | Partly | `0` and `3` only, for left to right and right to left ([documentation](https://github.com/mintty/mintty/wiki/CtrlSeqs#bidirectional-rendering)) |
| VTE | 0.84.1, [source](https://gitlab.gnome.org/GNOME/vte/-/tree/0.84.1) | Partly | `0` and `3` only, as the BiDi recommendation suggests ([source](https://gitlab.gnome.org/GNOME/vte/-/blob/0.84.1/src/vteseq.cc#L8625-L8672)) |

## Validation

### SPD-1: Ignored, with nothing printed

Input, one step per line:

```text
AB
\e[3 S
C
```

Expected screen:

```text
|ABC___|
cursor 1,4
```

### SPD-2: It is not SU, and does not scroll

Input, one step per line:

```text
ABC\r\n
DEF
\e[ S
\e[3;0 S
```

Expected screen:

```text
|ABC___|
|DEF___|
|______|
cursor 2,4
```

### SPD-3: Nor does a vertical presentation turn the screen

Input, one step per line:

```text
AB\r\n
CD
\e[1 S
\e[7;1 S
```

Expected screen:

```text
|AB____|
|CD____|
cursor 2,3
```

---

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