^[control-codes
live in libghostty-vt

Private modes

DECCOLM Column Mode

View as Markdown

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 c132 resource is False. 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.
  • ColumnMode is a window operation, a switch apart from mode 40. Put in the disallowedWindowOps resource, 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

TerminalVersionSupportNotes
VT220manual, 2nd ed., 1984Yes§4.6.10 Column Mode (DECCOLM)
VT510manual, 1st ed., 1993YesDECCOLM
xtermpatch 412, xterm-411aPartlyignored unless mode 40 allows it; off by default (c132)
libghostty-vt0f171f6Yeswith mode 40, as xterm; no setting like xterm’s ColumnMode to keep the width (DECCOLM-8)
kitty0.49.1, run in a VMPartlyfails DECCOLM-4, DECCOLM-5, DECCOLM-6 of the 4 cases that show it working
foot1.28.0, run in a VMNofails the 4 cases that show it working
pyte0.8.2, run as a libraryPartlyfails DECCOLM-5 of the 3 cases that show it working
xterm.js headless6.0.0, run as a libraryNofails the 4 cases that show it working
alacritty_terminal0.26.0, run as a libraryPartlyfails DECCOLM-4, DECCOLM-5 of the 4 cases that show it working
ConEmubuild 230724, its documentationNonot in ConEmu’s list, ANSI escape codes
rxvt-unicode9.31, run in a VMPartlyfails DECCOLM-3, DECCOLM-6 of the 4 cases that show it working
VTE0.84.1, run as a libraryPartlyfails 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
Every example on these pages runs in your browser, in libghostty-vt compiled to WebAssembly.