About ncurses Colors

Why does ncurses support only eight colors?

If you've looked into the color palette available in curses, you may wonder why curses supports only eight colors. The curses.h include file defines these color macros:


COLOR_BLACK
COLOR_RED
COLOR_GREEN
COLOR_YELLOW
COLOR_BLUE
COLOR_MAGENTA
COLOR_CYAN
COLOR_WHITE

But why only eight colors, and why these particular colors? At least with the Linux console, if you're running on a PC, the color range's origins are with the PC hardware.

A Brief History of Color

Linux started as a PC operating system, so the first Linux console was a PC running in text mode. And to understand the color palette on the PC console, you need to go all the way back to the old CGA days. In text mode, the PC terminal had a color palette of 16 colors, enumerated 0 (black) to 15 (white). Backgrounds were limited to the first eight colors:

  • 0. Black
  • 1. Blue
  • 2. Green
  • 3. Cyan
  • 4. Red
  • 5. Magenta
  • 6. Brown
  • 7. White ("Light Gray")
  • 8. Bright Black ("Gray")
  • 9. Bright Blue
  • 10. Bright Green
  • 11. Bright Cyan
  • 12. Bright Red
  • 13. Bright Magenta
  • 14. Yellow
  • 15. Bright White

These colors go back to CGA, IBM's Color/Graphics Adapter from the earlier PC-compatible computers. This was a step up from the plain monochrome displays; as the name implies, monochrome could display only black or white. CGA could display a limited range of colors.

CGA supports mixing red (R), green (G) and blue (B) colors. In its simplest form, RGB is either "on" or "off". In this case, you can mix the RGB colors in 2x2x2=8 ways. Table 1 shows the binary and decimal representations of RGB.

Table 1. Binary and Decimal Representations of RGB

000 (0) Black
001 (1) Blue
010 (2) Green
011 (3) Cyan
100 (4) Red
101 (5) Magenta
110 (6) Yellow
111 (7) White

To double the number of colors, CGA added an extra bit called the "intensifier" bit. With the intensifier bit set, the red, green and blue colors would be set to their maximum values. Without the intensifier bit, each RGB value would be set to a "midrange" intensity. Let's represent that intensifier bit as an extra 1 or 0 in the binary color representation, as iRGB (Table 2).