This is a tale of two scripts and is related to a previous question.
The two scripts are at http://gist.github.com/50692. The ansi.rb script displays all 256 colors on all 256 background colors. The ncurses.rb script displays all 256 foreground colors but the background displays the basic 16 and then seems to cycle through various attributes like blinking and reverse video.
So what gives? Is this the bug in ncurses that it uses a signed integer for color pairs? (ie 'tput colors' says 256 but 'tput pairs' says 32767 instead 65536) It seems like if that were the case the first half of the colors pairs would display properly but the second half would repeat or get into the attributes as the int wraps.
The reason is because ncurses pre ABI 6, which includes the current version that most distributions including Debian and Amazon AMI use, COLOR_PAIR(n)
cannot reference any defined pairs above 256. This is because the argument to COLOR_PAIR(n)
is of type chtype
. The lower 8 bits choose the color pair, and the rest are treated as bitflags OR
ed in for specific terminal attributes. This is why you see blink, inverse, underline, etc. when you attempt to go beyond pair number 255 in your sample code.
This is pretty unfortunate, and I plan to use a queue in my program to define colors on the fly using init_pair()
and just overwrite the least recently used pairs as a compromise. I wrote the ncurses maintainer Thomas Dickey asking if there is a way to step outside of ncurses temporarily to write raw terminal codes and then return to ncurses. This was his reply:
Essentially you'd have to forget about screen-optimization and just do your own drawing using the functions listed in terminfo(3), e.g., tigetstr, mvcur, tputs.
You can exit temporarily from ncurses, but then have to repaint the screen. Otherwise ncurses will be confused about what is on the screen and where the cursor is.
This solution seems to present too many pitfalls, but if you absolutely need more than 256 simultaneous pairs in an ncurses program (not counting pairs you could fake with the inverse attribute), then this is what you'll have to do.