Introduction
At this point, there are hundreds of graphical terminal emulators out there. Every single one that I have run into pretends like it is some varient of a hardware terminal made by Digital Equipment Corporation (DEC) from their Video Terminal (VT) line of products, from 1978’s VT100 through 1993’s VT525.
A reader might chime in here and say, no MY TERMINAL thinks it is an xterm
,
but alas xterm
pretends to be a VT420 (xterm
can actually pretend it is
many different terminals, so even if you DO use THE xterm
software I doubt
your computer is actually set up to most efficiently talk to it, I’ll talk
about that later ).
First, the language a computer uses to access a terminal’s capabilities like, clear the screen, move the cursor, start printing inverse color, etc., are called Control Codes. Second, is that there was a standard created for control codes: ANSI X3.64-1979 The first product to market to mostly follow these standards was the DEC VT100 (several months before they were published).
About X3.64-1979
This document, which I’ll refer to as The Standard, isn’t easy to read
because it refers to characters not by the common GLYPHS and Abbreviations
we are used to seeing in a common ASCII chart, but instead a 4/4 bit split,
using decimal.
That is ?
is referenced as 5/15
which these days would be talked
about in HEX x5F
, and this notation is true throughout The Standard.
The Standard also makes it clear that NO single product is expected to implement every code but should be aware of the paramters for codes so that a product can know to ignore the codes it doesn’t implement. With the exception of iTerm2, every Terminal I’ve used mostly follows The Standard.
The Standard’s Non-Standard Carve-out
The Standard specifies that there are four entries to special controls; SS2, SS3, ESC and CSI. The SS (Single Shift) entries aren’t relevant here, but the ESC and Control Sequence Introducer are relevant.
ESC is character 1/11
or x1B
. The standard only assigns four functions
that exist past an ESC without the [
(5/11
/ x58
) which turns it into
CSI.
- 8-bit ASCII: CSI is a standalone character,
CSI
8/11
orx8B
. - 7-bit ASCII: CSI is two characters:
ESC [
1/11 5/11
orx1B x5B
.
Unicode only preserved the 7-bit ASCII table, and CSI being in the 8 bit range, moved the CSI into a different place, so unless a terminal emulator still uses a retro-8bit ASCII code-page mode, it is easier to use the 7-bit control varient given that Unicode CSI doesn’t save any transmitted bits.
After the CSI, The Standard suggests that parameters can start. The first
position of the first parameter, though, is restricted.
ASCII 0
through ;
/ x30
- x3B
indicates something that is either
defined by The Standard or reserved for future standards. However,
ASCII <
, =
, >
and ?
( x3C
- x3F
) are reserved for
“Private Parameter”. This means that this indicates something that will
never be defined by the standard, and is a safe place to indicate feature
parameters that are not covered by The Standard.
DEC Video Terminals and the Device Capability Feature
Before the standard, The DEC VT50 had a control initiated by ESC Z
which
DEC named DECID
. DECID
is NOT one of the four “ESC Fn” codes in
The Standard. The DEC VT100 would also respond to this, but it was
not part of The Standard, and the manuals begged users to stop relying
on its existence (VT400 and later terminals ignore it).
Instead of DECID
, DEC instead did something more weird.
They created a control called Device Attributes
(DA) which was accessed
with CSI c
(ESC [ c
). This gets a bit complicated but c
is inside the
range of characters reserved for future standards, so it should not have
been grabbed by DEC for this function.
That is I’m starting out to say that DEC itself doesn’t fully follow The Standard. I would guess they figured if they sold enough terminals, nobody would assign something else to that function, and, well, they were right in taking that gamble.
Later, with the VT220, they kept Device Attributes
but also added what
they called a Secondary DA
. That DID follow The Standard: CSI < c
,
which uses the <
character to designate that this is, at least, a
“Private Parameter”. Though the final function still shouldn’t be c
, by
setting a Private Parameter, is at least makes other ANSI compliant terminal
know to not try to figure out the meaning, even were c
to be given a
standardized function meaning later. Good job on the bare minimum.
Secondary DA would return the sub-model within a range, a firmware version
of the terminal, and an indicator of hardware feature (special keyboard or
internal modem). Outside of xterm
itself, all Terminal Emulators I have
tested pick some numbers, and never change it no matter how much the
software itself changes.
Most currently maintained Terminal Emulators respond to Device Attributes
and Secondary DA
, even if the Device Attributes
response indicates a
VT100 model that didn’t support the secondary feature. Note that the VT400
line also introduced Tertiary DA
.
Broken Terminal Emulators
Claiming to Be, But Not Actually
Several terminal emulators take a safe
route by claiming to be a
VT100 or VT102. Since this is the first ANSI Escape sequence terminal,
they have less features than subsequent Video Terminal models.
\033[?1;0c
VT100 without Advanced Video Option (AVO)\033[?1;2c
VT100 with AVO (underline, blink, bold, reverse video)\033[?6c
VT102 zero option version of the VT100
Terminal emulators that claim to be a VT102 or VT100 without options are claiming that they cannot even do underline, bold, blink or reverse video. Yet, all of them can do these things (or, at least they’ll use brighter colors to emulate Bold, which a VT100 couldn’t do).
VT200 and higher terminals have controls to protect an area of the screen from overwrite or overrun. Few terminal emulators can do this correctly. That requires programs to be extra careful to wrap their own text to stay out of protected areas (that aren’t actually protected).
Mislabeled Device Attributes
DEC terminal products from VT200 included a DA response that listed out
features numerically. Has printer, has alternate code-page, has graphics,
etc. Again, xterm
does a good job emulating these correctly, but many
terminal emulators seem to just put something else’s answer in as the return.
\033[?62;4c
VT200 ONLY 80 columns supporting sixel graphics.
Does it Really support Sixel? xterm
does in the right emulation mode,
iTerm2
does. If not, don’t do this.
\033[?65;1;9c
VT540 supporting 132 character width and 7bit National Replacement Character sets.
For those that talk Unicode, option 9; 7bit National Replacement Character Sets, doesn’t really make sense anymore.
Color
The DEC VT340 and VT525 products did color. If your terminal emulator does
support color, maybe try emulating one of those models? But no,
“I’m a VT100” respose probably also means “I can do color”.
Nothing indicates color depth either. xterm
DA will include a 22 to
indicate color support, but is that 8, 16, 88, 256 or even Direct Color?
“Direct Color” can theoretically support 48 bit color. Nothing is
available to tell the software which is available. Sigh.
Unicode
Unicode was first published before the last DEC terminal was designed, but it was hard-coded 16-bit (two byte) at the time, and had far more code points that most Terminal buyers would need anyway. That is, the VT500 series was still 7 or 8bit ASCII with swappable code-pages.
Since 1994 and the last DEC Video Terminal debut, UTF-8 has slowly
become the defacto standard, and terminal emulators have been quietly adding
support for UTF-8, led (as was the typicaly case) by xterm
.
Since xterm
didn’t add a response number to indicate UTF8, nobody else did
either. That means there’s no way for a program to ask a terminal if it
is expecting ASCII or UTF-8. After 2010, most programs just assume that
UTF-8 will be accepted but that’s a weird expectation.
This ALSO means that even terminals that claim to be an 8bit capable
DEC terminal just no longer support the CSI
character (under Unicode,
it is no longer a single byte, but was moved into a two byte range, yet
that isn’t a valid reason to drop this support entirely).
Glyph support
This didn’t matter much in the days of 7bit ASCII, but in the Unicode era it would be super helpful for a program to be able to ask the terminal if a certain codepoint can actually be printed or not. If my program wants to drop a beer emoji (like homebrew), I have to do a lot of guess-work to figure out if that is possible. Worse, if my terminal program wants to print traditional Chinese characters as still used on the island of Taiwan, I no longer have a way of checking if such a thing is available.
iTerm2 abusing The Standard
iTerm2 does this weird thing of introducing new controls in reserved space,
with several new controls that start with ESC ] 1
which doesn’t start with the CSI (that terminals were taught to ignore if
they don’t understand them), and ends with The Standard’s 7bit ST
(ESC \\
).
It makes the Zeroth Parameter into a Sub Function designator and the Oneth
Parameter into a Sub Function selector.
Terminal capabilities and Terminfo
There’s this great bit of software and sets of libraries that are able to map a terminal’s capabilities into the Control Codes that that terminal ACTUALLY uses. There’s even a very extensive file that includes those definitions for a huge number of terminals and terminal emulators.
Do you use the new Windows Terminal
on Win 10 or 11? That one’s
entry is ms-terminal. Do you use the default Terminal.app
on macOS?
That is nsterm. What about Konsole
(konsole) or Gnome Terminal
(vte)
on Linux. How about xterm
… uh… Well… That’s a problem.
If you actually use xterm (it’s ugly and few people can tolerate it these
days), then you actually DON’T want to use the xterm
entry at all.
The xterm
and xterm-256color
entries are purosely hobbled because
most modern terminal emulators ask for the xterm
entry, claiming
compatability, when they just aren’t fully there. That means, the
xterm
entry is a pared down entry of VT102 basic controls that
everyone generally has, forcing software to do things with padding
or extra cursor moves because actual features are reported as
missing … for the lowest common denominator.
Being Awkwardly Good: KiTTY
I won’t use it because it forces bash
into POSIX mode
on purpose, but as far as a terminal emulator, the KiTTY terminal
emulator is awkwardly good. It does NOT ask to be treated like an
xterm like everything else. Instead it installs it’s own terminfo
(it’s called xterm-kitty
, awkward name, but unique), and with ssh
integration it will even forward its own entry to any computer you
log into. It’s a rare case where even if KiTTY does everything else
wrong, it doesn’t matter because a program can trust that it has the
best terminal definitions avaible already.
Writing a Terminal Program?
Stop Pretending to be Something Else
Please do support the Device Attributes
, Secondary DA
and Tertiary DA
entries, but don’t reply with stock answers. Let it be the different thing
that it is.
\033[?13;...c
There was never a VT that answered between 13 and 61.\033[?66;...c
There was never a six series VT, it’s there and open.
New Feature Flags
The highest feature number I’ve seen is 46
.
Go ahead a reserve a feature number for explicit UTF-8 support. The first one to do it and document it is likely to become the standard maker.
Go ahead and make a scheme for color supports. 8, 16, 88, 256, and Direct are all out there, but don’t have option numbers.
Will this be the first one to add a feature for telling a program if a Glyph is printable? Will this be the first one to have a way to explicitly say how wide a glyph actually will print?
Learn from KiTTY, supply a terminfo entry.
Even if a terminal emulator is designed to be compatible with the stripped
down xterm
terminfo, if it has ANY features beyond that, it should start
shipping a terminfo source file with all of its features.