4.1 Attributes and Colour

Characters can be displayed in different ways. Status lines in a text-based application are commonly shown in reverse video; a text viewer may need to highlight certain words. curses supports this by allowing you to specify an attribute for each cell on the screen.

An attribute is a integer, each bit representing a different attribute. You can try to display text with multiple attribute bits set, but curses doesn't guarantee that all the possible combinations are available, or that they're all visually distinct. That depends on the ability of the terminal being used, so it's safest to stick to the most commonly available attributes, listed here.

Attribute Description
A_BLINK Blinking text
A_BOLD Extra bright or bold text
A_DIM Half bright text
A_REVERSE Reverse-video text
A_STANDOUT The best highlighting mode available
A_UNDERLINE Underlined text

So, to display a reverse-video status line on the top line of the screen, you could code:

stdscr.addstr(0, 0, "Current mode: Typing mode",
	      curses.A_REVERSE)
stdscr.refresh()

SVr4 curses also supports colour on those terminals that provide it, and Oliver Andrich's extended Python curses allows you to use the relevant functions. The most common such terminal is probably the Linux console, followed by colour xterms.

To use colour, you must call the start_color() function soon after calling initscr(), to initialize the default colour set. Once that's done, the has_colors() function returns TRUE if the terminal in use can actually display colour. (Note that curses uses the American spelling 'color', instead of the Canadian/British spelling 'colour'; if you're like me, you'll have to resign yourself to misspelling it for the sake of these functions.)

curses maintains a finite number of colour pairs, containing a foreground (or text) colour and a background colour. You can get the attribute value corresponding to a colour pair with the COLOR_PAIR() function; this can be bitwise-OR'ed with other attributes such as A_REVERSE, but again, such combinations are not guaranteed to work on all terminals.

An example, which displays a line of text using colour pair 1:

stdscr.addstr( "Pretty text", curses.COLOR_PAIR(1) )
stdscr.refresh()

As I said before, a colour pair consists of a foreground and background colour. start_color() initializes 8 basic colours when it activates colour mode. They are: 0:black, 1:red, 2:green, 3:yellow, 4:blue, 5:magenta, 6:cyan, and 7:white. The curses module defines named constants for each of these colours: curses.COLOR_BLACK, curses.COLOR_RED, and so forth.

The init_pair(n, f, b) function changes the definition of colour pair n, to foreground colour f and background colour b. Colour pair 0 is hard-wired to white on black, and cannot be changed.

Let's put all this together. To change colour 1 to red text on a white background, you would call:

curses.init_pair(1, curses.COLOR_RED, curses.COLOR_WHITE)

When you change a colour pair, any text already displayed using that colour pair will change to the new colours. You can also display new text in this colour with:

stdscr.addstr(0,0, "RED ALERT!", curses.COLOR_PAIR(1) )

Very fancy terminals can change the definitions of the actual colours to a given RGB value. This lets you change colour 1, which is usually red, to purple or blue or any other colour you like. Unfortunately, the Linux console doesn't support this, so I'm unable to try it out, and can't provide any examples. You can check if your terminal can do this by calling can_change_color(), which returns TRUE if the capability is there. If you're lucky enough to have such a talented terminal, consult your system's man pages for more information.