# Column Mode (DECCOLM)

> Switch the screen between 80 and 132 columns, clearing it.

- **Sequence:** `CSI ? 3 h`
- **Defaults:** reset, 80 columns
- **DEC STD 070:** [§5.4.6 Set/Reset Column Mode, p. 5-71](https://archive.org/details/bitsavers_decstandar0VideoSystemsReferenceManualDec91_74264381/page/n325/mode/1up)
- **VT510:** [DECCOLM—Select 80 or 132 Columns per Page](https://vt100.net/docs/vt510-rm/DECCOLM.html)

`CSI ? 3 h` makes the screen 132 columns wide, and `CSI ? 3 l` makes it 80.
Either way, DEC STD 070 says it clears the screen, removes the scrolling
region, and moves the cursor to the top-left, "even if the terminal was
already in the selected state". Every line goes back to
[single-width](https://control-codes.page/esc/decdwl/index.html.md) too. DEC STD 070 makes column mode an optional
extension at every level, marked `1X` to `4X`.

xterm only does any of this when it has been allowed to, with
`CSI ? 40 h`, xterm's *allow 80/132 column mode*; without it, DECCOLM is
ignored. Mode 40 is off by default (the `c132` resource is
[`False`](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/charproc.c#L432)). With it on, xterm clears the screen,
asks for the new width, then resets the line sizes and margins and homes the
cursor ([`srm_DECCOLM`](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/charproc.c#L7559-L7580),
[`set_column_mode`](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/charproc.c#L7462-L7471)). Mode 95, DECNCSM, can stop
it clearing the screen; it is not covered here.

The case runner draws only as many columns as each expected
screen has, but a cursor sent to column 999 stops at the real last column,
which shows the width. [DECRQM](https://control-codes.page/csi/decrqm/index.html.md) reports both modes.

libghostty-vt implements DECCOLM and mode 40 as xterm does.

## Validation

### DECCOLM-1: Ignored unless allowed

Input, one step per line:

```text
ABC
\e[2;3H
\e[?3h    # 132 columns, not allowed
\e[?3$p   # ask about column mode
```

Expected screen:

```text
|ABC___|
|______|
cursor 2,3
reply \e[?3;2$y
```

### DECCOLM-2: Mode 40 is off by default

Input, one step per line:

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

Expected screen:

```text
|______|
reply \e[?40;2$y\e[?40;1$y
```

### DECCOLM-3: 132 columns, cleared, cursor home

Input, one step per line:

```text
\e[?40h   # allow 80/132
ABC
\e[2;3H
\e[?3h    # 132 columns
```

Expected screen:

```text
|______|
|______|
cursor 1,1
```

### DECCOLM-4: The new width

Input, one step per line:

```text
\e[?40h   # allow 80/132
\e[?3h    # 132 columns
\e[1;999H
\e[?3$p
```

Expected screen:

```text
|______|
cursor 1,132
reply \e[?3;1$y
```

### DECCOLM-5: Back to 80

Input, one step per line:

```text
\e[?40h   # allow 80/132
\e[?3h    # 132 columns
\e[?3l    # 80 columns
\e[1;999H
```

Expected screen:

```text
|______|
cursor 1,80
```

### DECCOLM-6: The margins are removed

Input, one step per line:

```text
\e[?40h   # allow 80/132
\e[1;2r   # region is lines 1 and 2
\e[?69h   # allow left and right margins
\e[1;2s   # margins at columns 1 and 2
\e[?3h    # 132 columns
\r\nHello # would wrap at column 2 and stay in lines 1 and 2
\r\nWorld
```

Expected screen:

```text
|______|
|Hello_|
|World_|
|______|
```

---

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