Kied Llaentenn
Kied Llaentenn

Reputation: 145

Does ncurses support TrueColor?

I know that ncurses supports 16-bit colors with the init_pair function and friends. But is it possible to display characters in full RGB color (aka True Color)?

Upvotes: 3

Views: 2345

Answers (2)

Thomas Dickey
Thomas Dickey

Reputation: 54455

The ncurses FAQ Why only 16 (or 256) colors? goes into some detail, giving the history of this feature, pointing out that the proper term is direct color (since that is based on a standard, while true color is in other places said to be a special case of direct color). Likewise, the xterm FAQ Can I set a color by its number? provides corresponding detail on the history of this feature in xterm.

ncurses 6.1 (January 2018) introduced support for direct color, as illustrated in a recap of the ncurses versus slang history. That includes an example program picsmap which uses the RGB extension (documented in user_caps(5)).

Because the number of colors in 24-bit RGB is larger than the range of numbers supported in the original (signed!) 16-bit numbers (see term(5)), it was necessary to provide for larger numbers. ncurses 6.1 does this with minimal change to existing applications by adding to the opaque TERMINAL structure, and adding functions which can manipulate the extended numbers. It was not necessary to change the ABI (currently 6 since August 2015), because none of the documented features changed their binary interface.

To use the RGB feature in ncurses it is necessary to have the proper terminal description. xterm-direct is used for xterm. This example sets the RGB flag and overrides the color features (but reserves the first 8 ANSI colors, making it a workable hybrid):

xterm+direct|xterm with direct-color indexing,
        RGB,
        colors#0x1000000, pairs#0x10000, CO#8,
        initc@, op=\E[39;49m,
        setab=\E[%?%p1%{8}%<%t4%p1%d%e48\:2\:\:%p1%{65536}%/%d\:%p1
              %{256}%/%{255}%&%d\:%p1%{255}%&%d%;m,
        setaf=\E[%?%p1%{8}%<%t3%p1%d%e38\:2\:\:%p1%{65536}%/%d\:%p1
              %{256}%/%{255}%&%d\:%p1%{255}%&%d%;m,
        setb@, setf@,

Other terminals have their corresponding flavors. Because the feature is documented, with examples, it is possible for others to customize terminal descriptions as needed.

picsmap is one of the test-programs for ncurses, which is available separately as "ncurses-examples". Tutorials are off-topic; the source-code is readily available.

Upvotes: 7

Dietrich Epp
Dietrich Epp

Reputation: 213258

“True Color” is a bit of a misnomer—it does not exist.

Ncurses lets you redefine the values of the standard 16 colors, but does not support arbitrary RBG colors at arbitrary positions. Fortunately, many terminals do support 8-bit RGB (sometimes called “true color”) if you wish to do it yourself—to be clear, this means not using ncurses.

The sequences are:

  • ESC[ 38;2;⟨r⟩;⟨g⟩;⟨b⟩ m: Select RGB foreground color
  • ESC[ 48;2;⟨r⟩;⟨g⟩;⟨b⟩ m: Select RGB background color

(From ANSI Escape Code)

Here, “ESC” is just the character ‘\x1b’ and you replace r, g, and b with values from 0-255. Something like this:

printf("\x1b[38;2;%d,%d,%dm", r, g, b);

This does not work on all terminals but there are plenty that do support it.

Why Not Ncurses?

Why doesn’t Ncurses support this? It turns out that Ncurses is not just a library for styling text and placing it at different locations on the terminal, but it also tries to be clever and minimize the amount of data transmitted over stdout when the on-screen text changes. Ncurses does this by keeping its own text buffer internally, and transmitting deltas over stdout.

This is a really nice feature to have if you’re running over a 14.4 kbit/s modem or a slow serial connection back in 1993, back when Ncurses was originally made. However, Ncurses has made an implementation tradeoff of not supporting additional colors.

Upvotes: 2

Related Questions