1

How to reverse console colours, to have black letters on white screen?

tput rev

kind of works, but only the background where some characters are is white, the rest of the screen remains black, which looks kinda strange. How to change the whole console background to white, even where there are no characters?

An extension of the question is how to make it some other colour, for example yellow background, black foreground?

tput setaf 0 && tput setab 3

Does it, but again - background without characters remains black.

I am talking about text console without using X, or the one you get when you press Cltr+Alt+F1 in X and get a full black screen console login, not in an x-terminal window.

This is Debian unstable/sid.

1 Answers1

8

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:

  • PuTTY and its derivatives (such as the confusingly named MobaXTerm) link the erasure colour to the background colour when DECECM is set on, but do not propagate reverse video similarly. Enjoy (on the last line of the screen) an effect where part of the line is reverse video and part not, but the colours are maintained:
    tput setaf 4 ; tput setab 3 ; tput rev ; echo wibble
    Windows Terminal appears to do this, too.
  • The Interix terminal emulator can turn reverse video on with SGR 7, but does not recognize SGR 27 to turn it off.
  • Some terminal emulators have crazy I-know-better-than-what-you-explicitly-requested ideas about reverse video, such as Unicode rxvt which switches to an entirely different colour pair if the background and foreground colours are set the same and reverse video is then switched on. Enjoy no blue at all with:
    tput setaf 4 ; tput setab 4 ; tput rev ; echo wibble

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

JdeBP
  • 68,745
  • Wow, thank you for this very long and throughout answer. Its very complex and I don't understand much of it. Before I spend a lot of time to understand it, what of this applies to a Linux console, such as you have without running X or any window environment? You write a lot about terminal emulators, XTerm, rxvt, PuTTY, but I specifically asked how to do it on a text console, i.e. without running X, so I am not sure what out of this applies. –  May 15 '20 at 01:02
  • Don't conflate the console with the kernel virtual terminals. And I did explicitly list the Linux built-in terminal emulator in paragraph 8. – JdeBP May 15 '20 at 01:13