DECCOLM Column Mode
Switch the screen between 80 and 132 columns, clearing it.
CSI ? 3 h/l
?40 Allow 80/132 Column Mode
CSI ? 40 h/l
- Defaults
- reset, 80 columns
- DEC STD 070
- §5.4.6 Set/Reset Column Mode, p. 5-71
- VT220
- §4.6.10 Column Mode (DECCOLM)
- VT510
- DECCOLM—Select 80 or 132 Columns per Page
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 too. DEC STD 070 makes column mode an optional extension at every level, marked 1X to 4X.
xterm decides what to do in three steps, in this order (srm_DECCOLM, set_column_mode):
flowchart TD
start(["CSI ? 3 h or l"]) --> m40{"Mode 40?"}
m40 -- reset --> ignored(["Ignored"])
m40 -- set --> ncsm{"DECNCSM?"}
ncsm -- reset --> clear["Clear the screen"]
ncsm -- set --> resize
clear --> resize{"ColumnMode?"}
resize -- "allowed, and the width changes" --> ask["Ask for 80 or 132 columns"]
resize -- otherwise --> rest
ask --> rest(["Set or reset column mode<br>Lines back to single width<br>Margins removed<br>Cursor home"])
- Mode 40, xterm’s allow 80/132 column mode, is off by default: the
c132resource isFalse. Without it DECCOLM is ignored. - Mode 95, DECNCSM, keeps a VT510 from clearing the screen. xterm honors it only at VT510 level or above, and a default xterm is a VT420, so it always clears.
ColumnModeis a window operation, a switch apart from mode 40. Put in thedisallowedWindowOpsresource, it keeps the width as it was while the rest of DECCOLM still happens, DECRQM included. A default xterm allows it (DEF_DISALLOWED_WINDOW), so the cases expect the resize unless they say otherwise. It suits a host that owns the terminal’s size, such as a multiplexer laying out panes.
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 reports both modes.
libghostty-vt implements DECCOLM and mode 40 as xterm does, but has no setting like ColumnMode: with mode 40 set it always resizes, so DECCOLM-8, which keeps the width, is a known difference. It does clear the screen and home the cursor as xterm does, so DECCOLM-7 passes.
Support
| Terminal | Version | Support | Notes |
|---|---|---|---|
| VT220 | manual, 2nd ed., 1984 | Yes | §4.6.10 Column Mode (DECCOLM) |
| VT510 | manual, 1st ed., 1993 | Yes | DECCOLM |
| xterm | patch 412, xterm-411a | Partly | ignored unless mode 40 allows it; off by default (c132) |
| libghostty-vt | 0f171f6 | Yes | with mode 40, as xterm; no setting like xterm’s ColumnMode to keep the width (DECCOLM-8) |
| kitty | 0.49.1, run in a VM | Partly | fails DECCOLM-4, DECCOLM-5, DECCOLM-6 of the 4 cases that show it working |
| foot | 1.28.0, run in a VM | No | fails the 4 cases that show it working |
| pyte | 0.8.2, run as a library | Partly | fails DECCOLM-5 of the 3 cases that show it working |
| xterm.js headless | 6.0.0, run as a library | No | fails the 4 cases that show it working |
| alacritty_terminal | 0.26.0, run as a library | Partly | fails DECCOLM-4, DECCOLM-5 of the 4 cases that show it working |
| ConEmu | build 230724, its documentation | No | not in ConEmu’s list, ANSI escape codes |
| rxvt-unicode | 9.31, run in a VM | Partly | fails DECCOLM-3, DECCOLM-6 of the 4 cases that show it working |
| VTE | 0.84.1, run as a library | Partly | fails DECCOLM-4, DECCOLM-5 of the 4 cases that show it working |
Validation
DECCOLM-1: Ignored unless allowed
ABC
\e[2;3H
\e[?3h # 132 columns, not allowed
\e[?3$p # ask about column mode
|ABC___|
|______|
cursor 2,3
reply \e[?3;2$y
DECCOLM-2: Mode 40 is off by default
\e[?40$p
\e[?40h
\e[?40$p
|______|
reply \e[?40;2$y\e[?40;1$y
DECCOLM-3: 132 columns, cleared, cursor home
\e[?40h # allow 80/132
ABC
\e[2;3H
\e[?3h # 132 columns
|______|
|______|
cursor 1,1
DECCOLM-4: The new width
\e[?40h # allow 80/132
\e[?3h # 132 columns
\e[1;999H
\e[?3$p
|______|
cursor 1,132
reply \e[?3;1$y
DECCOLM-5: Back to 80
\e[?40h # allow 80/132
\e[?3h # 132 columns
\e[?3l # 80 columns
\e[1;999H
|______|
cursor 1,80
DECCOLM-6: The margins are removed
\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
|______|
|Hello_|
|World_|
|______|
DECCOLM-7: Cleared and homed without a resize
\e[?40h # allow 80/132
ABC
\e[2;3H
\e[?3h # 132 columns, but the width is kept
|______|
|______|
cursor 1,1
DECCOLM-8: The width is kept, the mode is set
\e[?40h # allow 80/132
\e[?3h # 132 columns, but the width is kept
\e[1;999H
\e[?3$p
|______|
cursor 1,6
reply \e[?3;1$y