CBT Cursor Backward Tabulation
Move the cursor back to the previous tab stop, n times.
CSI Pn Z
- Defaults
- Pn = 1
- ECMA-48
- §8.3.7 CBT – Cursor Backward Tabulation, p. 34
- VT510
- CBT—Cursor Backward Tabulation
Move the cursor left to the previous tab stop, and repeat that Pn times. A parameter of 0 is treated as 1.
The cursor never moves left of the first column, and if origin mode and left and right margins are both enabled, never left of the left margin. When that limit is reached the cursor stays there, however many tab stops remained.
Unlike the cursor movements, CBT does not cancel a pending wrap. DEC STD 070 lists the controls that should reset the pending wrap, which it calls the Last Column Flag (§D.6.1, p. D-13); HT is on the list, but CBT is not, and DEC STD 070 adds that “existing products vary widely” in how they handle it. xterm moves the cursor in TabToPrevStop without clearing the flag, and its dotext wraps whenever the flag is set, wherever the cursor now is. So after CBT from the last column, the next character printed still starts a new line. libghostty-vt does the same. Ghostty’s own VT reference expects the opposite in its second validation case, so there Ghostty’s documentation and its implementation disagree.
Tab stops are set with HTS and cleared with TBC. Most terminals, libghostty-vt included, start with one every eight columns, and CSI ? 5 W puts them back to that.
Validation
CBT-1: Stops at the first column
\e[?5W # reset tab stops
\e[10Z
A
|A_________|
cursor 1,2
CBT-2: A pending wrap survives
\e[?5W # reset tab stops
\e[1;10H # last column
X # wrap is now pending
\e[Z # back to the tab stop at column 9; still pending
A # so this starts the next line
|_________X|
|A_________|
cursor 2,2
CBT-3: From exactly on a tab stop
\e[?5W # reset tab stops
\e[1;9H # the tab stop at column 9
X
\e[1;9H
\e[Z
A
|A_______X_|
CBT-4: Inside a left margin, with origin mode
\e[?5W # reset tab stops
\e[?6h # origin mode
\e[?69h # allow left and right margins
\e[3;6s # margins at columns 3 and 6
\e[1;2H # column 2 of the margins, column 4 of the screen
X
\e[Z
A
|__AX______|