Those who used curses at least once to draw something in color had to notice that setting colors happens in pairs (foreground and background) and number of such pairs is limited. These limitations and some basics about upgrading code to lift one of the limits will be described in this short post.
The 256 color pairs limit
The first issue is that while 256 color pairs are enough to hold all color configurations of 16-colors (16 foreground * 16 background = 256), they become scarce resource that requires managing on part of your application when number of available colors is greater (usually 256 these days).
The second issue is that original color API (
COLOR_PAIR() macro) didn't
account for possibility of having more than 256 color pairs and your application
needs changes to be able to handle this case or it might work incorrectly
COLOR_PAIR() just can't handle large color pair numbers, yet you'll feed them
The third and last piece is that most of curses examples you'll find are using old API and there seems to be no (at least easy to find) documentation on how to transition to the new one. There are applications which use new API, it's just documentation that didn't really caught up.
ncurses FAQ provides extensive details on the subject in this entry.
I guess someone else might also have them.
What's limiting color pairs
I used to think that color pairs limit exists only at the level of the library
implementation, however it's not that hard to find documentation referencing
max_pairs entry of terminfo database, which is fetched by
curses on call to
max_pairs variable in
man terminfo will give you its capability
name making it easy to check how much color pairs you can get with current
$ tput pairs 32767
You can't just switch to new API
Apparently, you can. Replacing all uses of
COLOR_PAIR() with equivalents
should be fine and everything should continue to work as before. However,
that's not enough to get more than 256 color pairs working, library itself
should be built for that (see below). It's also available for many years at
least in ncurses, which has it since 2005.
If new API is there, all color pairs are available
No, even if it's there, you might be limited to 256 color pairs at most. Supporting more pairs requires changes in types, which means API/ABI breakage. In ncurses new ABI has version 6, yet this doesn't mean version 6 of the library. ncurses 6 with wide support can be built to support large color pair numbers, see this comment from Thomas Dickey (its maintainer).
Elements of new API
Original API operates on
int, which might include the following components
ORed together by the client:
- color pair number
- attributes (
New API accepts these things separately (internal representation might be
whatever works) and uses constants for flags that start with
A_. And from the client's perspective there is a new type called
cchar_t (for "complex character") and two functions that convert to and from
There are various calls that accept color pair and attributes separately or
cchar_t. Names lack consistency, so to say:
bkgrndset()is an equivalent of older
wattr_set()is an equivalent of older
- etc., see
curses.hfor interesting functions with
cchar_tand then call
manon them or
apropos 'complex character'(is there a better way?)
Functions of new API also take
void *options parameter along with attributes
and color pair number, which should be
NULL unless you're using ncurses 6.1
or newer which uses it as an extension for using
int as color pair number (for
true RGB colors; see functions with "extended" in their names).
wbkgdset(win, COLOR_PAIR(pair) | attrs);
cchar_t cch; setcchar(&cch, L" ", attrs, pair, NULL); wbkgrndset(win, &cch);
wattrset(win, COLOR_PAIR(pair) | attrs);
wattr_set(win, attrs, pair, NULL);