Reverse video is fun.
The terminfo model is simplistic and wrong. It does not match how terminal emulators and real terminals actually operate. You really won't get very far with terminfo here.
The model of real terminals is at first blush quite simple:
- There is a current set of colours and attributes, one of which is an inverse video attribute. Inverse video causes the pixels in a character glyph to be inverted: an on pixel is the background colour and an off pixel is the foreground colour.
- There is a whole screen inverse video setting, which inverts the sense of the inverse video attribute across all cells. Set it on, and all inverted character cells are displayed non-inverted and vice versa.
For a monochrome video terminal, this is just some XOR logic in hardware.
The inverse video attribute is of course SGR 7 and SGR 27, with almost no-one doing anything other than ECMA-48 in decades. The whole screen inverse video setting is controlled by control sequences that originate with DEC VTs, named DECSCNM (DEC Screen Mode). This is a vendor-private mode, which ECMA-48 provides the mechanism for. The sequences are just the ECMA-48 SM and RM of DEC private mode #5.
If you really do want to invert the whole screen, rather than just the next line(s) of output, DECSCNM is the way to go. Many terminal emulators recognize and respond to DECSCNM, including Unicode rxvt, terminal emulators based upon the VTE library, Konsole, kitty, KiTTY, PuTTY, XTerm, the Linux built-in terminal emulator, and my console-terminal-emulator
in the nosh toolset.
You can print the DECSCNM control sequences with printf
. There's no terminfo capability for it. This is outside of the limited terminfo model. For those that don't want to remember control sequences, my portable setterm
provides a handy convenience way of doing this:
% setterm -7 --invertscreen on
% setterm -7 --invertscreen off
This is where things get nasty.
In reality, there are two sets of colours and attributes. There is the set used to draw printed characters, and there is the set used to erase characters and to draw the blank rows and columns that are introduced by scrolling. A setting named erase colour mode (DECECM) controls how disjoint these two sets are. On actual late model DEC VTs, the default was that they were largely the same, erasure/scrolling colours matching printing colours. However, too many terminal emulators initialize their DECECM settings to the old convention that erasure/scrolling colour was different to printing colour, and was always SGR 39/SGR 49.
The initial state is selectable via a checkbox in PuTTY, where it is called background colour erase. The terminfo model calls it that, too, but gets it backwards. On the terminals that have it in the first place, it is a settable mode, not a fixed aspect of the terminal. It's switchable by the host emitting the control sequences. terminfo doesn't provide a capability for setting it, however, only a fixed-value flag that says whether it is off or on, which may not match the current state of the terminal. Again, for those that don't want to remember control sequences:
% setterm -7 --bce on
% setterm -7 --bce off
But DECECM strictly speaking controls just the (background) colour. It does not, strictly speaking, connect the attributes. Erased/scrolled character cells need not be given the reverse video attribute that is assigned for printed characters (or indeed any of the other attributes such as underline). Some terminals (such as mine and the FreeBSD kernel built-in terminal emulator) do, and many do not.
Moreover, it only applies when erasure/scrolling is happening in the first place. Not erasing/scrolling but not printing up to the full length of the line will also leave a differently coloured/attribute portion.
This is why one sees the rest of the line not in reverse video on many such terminal emulators. (If one uses my terminal emulator, or a FreeBSD KVT, the whole line comes out as reverse video when it is scrolled, or erased with EL. See the result of printf '\e[7m\e[117hwibble\e[K\n'
on either.)
If this were not enough, there are a bunch of bizarre behaviours:
One might think to give up on reverse video and erasure/scrolling and just use whole screen reverse video. But the fun does not stop:
- PuTTY interprets quickly turning DECSNM on and off as an attempt to sound a bell.
- Several terminal emulators swap light and dark. Request a dark background with DECSCNM low, and you'll get a light background, and vice versa.
- Windows Terminal changes several palette entries in response to DECSCNM, in particular indexed colour #232. XTerm makes palette changes too.
So, yes, that full screen application that is printing full-width reverse video bars is either having to do some work with DECECM and EL sequences (which are tricky to use with deferred wrap, which I haven't even mentioned) … or is just printing a lot of spaces, explicitly swapping foreground/background colours, and side-stepping reverse video entirely.
Further reading