^[control-codes live in libghostty-vt

Control sequences

DECSCPP Set Columns Per Page

Make the page 80 or 132 columns wide, without clearing it.

CSI Pn $ |
Defaults
Pn = 80
DEC STD 070
§5.4.6 Set Columns Per Page, p. 5-73
VT510
DECSCPP—Select 80 or 132 Columns per Page

Set the width of the page: Pn is 80 or 132, and left out or 0 means 80. It does what DECCOLM does to the width, but DEC STD 070 says it “does not clear page memory”: what is in columns 1 to 80 is kept. The cursor does not move, unless it is beyond the new width, in which case it goes to the last column.

DEC STD 070 makes DECSCPP a level 4 function, or level 3 with the windowing extension. It also says a value it does not support picks the next larger width it does, that the right margin moves in to the new edge if it was beyond it, and that going from 132 columns to 80 clears columns 81 to 132.

xterm, a VT420 by default, implements it at level 3 and up (CASE_DECSCPP). It accepts only 80 and 132 and ignores any other value, where DEC STD 070 would round up. If the cursor is beyond the new width it moves it to the last column straight away, then asks the window system to resize the window (RequestResize). The screen only changes size when the window does, which depends on the window manager, so the cases here check only what xterm does at once: where the cursor goes.

libghostty-vt has no handler for CSI Pn $ |. Its control sequence dispatch in stream.zig has no case for the final byte |, so DECSCPP is ignored and the cursor stays where it was.

Validation

DECSCPP-1: The cursor moves in to column 80

\e[1;82H  # column 82 of 82
\e[80$|   # 80 columns per page
|__________________________________________________________________________________|
cursor 1,80

libghostty-vt ignores DECSCPP, so the cursor stays in column 82. xterm moves it to column 80 before it asks for the narrower window.

DECSCPP-2: Left out means 80

\e[1;82H
\e[$|
|__________________________________________________________________________________|
cursor 1,80

DECSCPP-3: A cursor inside the new width does not move

\e[1;5H
\e[80$|
|__________________________________________________________________________________|
cursor 1,5

DECSCPP-4: Any width but 80 or 132 is ignored

\e[1;82H
\e[100$|  # neither 80 nor 132
|__________________________________________________________________________________|
cursor 1,82
Every example on these pages runs in your browser, in libghostty-vt compiled to WebAssembly.