Color Text, Part I

Your C programs’ text output need not be so dull. Aside from adding wide characters, you can spice things up with color text. The terminal flavor is what determines the color palette. All you need to know are the secret codes that activate and deactivate the attributes.

The secret is ANSI, which uses escape sequences to encode various text attributes, among them colors. I wrote about ANSI in an blog post from 2020 regarding inverse text. The same type of sequences are used to generate color.

Don’t get too excited.

Be aware that not every terminal program recognizes ANSI sequences. Most do, so you should be in luck. If not, you can find alternative terminal apps available, some of which boast about their ANSI color capabilities.

ANSI defines eight color codes representing basic text colors: black, red, green, yellow, blue, magenta, cyan, and white. These can be foreground or background colors.

The escape sequence to generate colors starts with the escape character (get it?), followed by a left bracket, the color code value and a lowercase M. Here is the escape sequence as encoded in C:

\x1b[nnm

The nn is replaced by the color code values as listed in the following table.

  Color Foreground code Background code
0 Black 30 \x1b[30m 40 \x1b[40m
1 Red 31 \x1b[31m 41 \x1b[41m
2 Green 32 \x1b[32m 42 \x1b[42m
3 Yellow 33 \x1b[33m 43 \x1b[43m
4 Blue 34 \x1b[34m 44 \x1b[44m
5 Magenta 35 \x1b[35m 45 \x1b[45m
6 Cyan 36 \x1b[36m 46 \x1b[46m
7 White 37 \x1b[37m 47 \x1b[47m

The color codes can be combined in a single sequence if separated by a semicolon. So blue text on a red background has this sequence: \0x1b[34;41m These codes can also be combined with other attributes, such as blinking and underline, if you really want to induce nausea in your users.

Another good code to know is \x1b[m, which is the “normal” escape sequence. It disables all other attributes. I use this normal sequence after outputting any color text, which halts further color output. This trick avoids the color “bleed” that happens when you end a line of text.

To use these colors attributes in my code, I’ve wrote a series of defined constants to assist me. These values are declared as strings, as shown in this sample code:

2022_04_02-Lesson-a.c

#include <stdio.h>

#define AC_BLACK "\x1b[30m"
#define AC_RED "\x1b[31m"
#define AC_GREEN "\x1b[32m"
#define AC_YELLOW "\x1b[33m"
#define AC_BLUE "\x1b[34m"
#define AC_MAGENTA "\x1b[35m"
#define AC_CYAN "\x1b[36m"
#define AC_WHITE "\x1b[37m"
#define AC_NORMAL "\x1b[m"

int main()
{
    printf("Color test:\n");
    printf("%sThis is red text\n",AC_RED);
    printf("End test\n");

    return(0);
}

The code uses only the AC_RED (ANSI Code red) literal to color all following text red. Figure 1 illustrates the output on my terminal, where the background color is preset to black and foreground to orange.

color text output

Figure 1. The text is colored red, but it bleeds over into the next line.

What you see in the output (Figure 1) is the color “bleed” to the following line. It looks worse when you set the background color. The solution is to output the AC_NORMAL code when you want to reset all attributes to zero. Here is the updated Line 16:

printf("%sThis is red text%s\n",AC_RED,AC_NORMAL);

The updated code is found here at GitHub. The updated output is shown in Figure 2.

color text output

Figure 2. The updated output, where the applied color is turned off at the end of the line.

In next week’s Lesson, I explore the background colors, plus a few more tips for outputting color text to the terminal when coding in the C language.

Leave a Reply