Published in Articles on by Michiel van Oosterhout ~ 6 min read

As we've seen in the Windows command-line interface, part 1, all command-line programs on Windows are connected to Console Window Host. Even the new Windows Terminal app connects to a pseudo console that is provided by Console Window Host. Command-line programs can specify the forground and background color of their output via the Windows Console API or via terminal sequences. This article looks briefly at the history of color in Console Window Host and how the colors can be changed without changing the command-line programs themselves.

Colorful apartment buildings in İstanbul
Colorful apartment buildings in İstanbul Photo by Maurice Flesier, CC BY-SA

Color in the Windows Console API

The Windows Console API historically has allowed command-line programs to specify color by combining the following attribute flags defined in WinCon.h:

FOREGROUND_BLUE      0x0001
FOREGROUND_GREEN     0x0002
FOREGROUND_RED       0x0004
FOREGROUND_INTENSITY 0x0008

BACKGROUND_BLUE      0x0010
BACKGROUND_GREEN     0x0020
BACKGROUND_RED       0x0040
BACKGROUND_INTENSITY 0x0080

Effectively this provides 3 bits to specify a color and an additional bit to adjust that color (more 'intense', or 'brighter'). Perhaps in the initial version of Windows NT the 4-bit value was interpreted literally by Console Window Host, but later versions of Console Window Host, as well as the Windows Terminal app, interpret the value as an entry in a lookup table, and allow you to configure the actual color value for each entry.

The console color palette

The color palette used by Console Window Host is a lookup table with 16 numbered entries (#0 through #A, using base-16) each of which is associated with a 24-bit RGB color value. Although you are free to set any color value for each entry, the entries have predefined names based on the color you would get if you would interpret the attribute flags from WinCon.h literally:

0 = Black       8 = Gray
1 = Blue        9 = Light Blue
2 = Green       A = Light Green
3 = Aqua        B = Light Aqua
4 = Red         C = Light Red
5 = Purple      D = Light Purple
6 = Yellow      E = Light Yellow
7 = White       F = Bright White

Part of the help text for Windows Command Processor's built-in color command.

There are some notable differences to be aware of though.

.NET's System.ConsoleColor enumeration used by PowerShell has different names. ECMA-48's SGR terminal sequences to set the foreground and background color using a 3- or 4-bit color palette use different names as well, and also swap the (Light) Blue and (Light) Red, and the (Light) Aqua and (Light) Yellow entries.

The following table shows the differences for each entry in the color palette:

Entry Name .NET ECMA-48 R G B Color
#0 Black Black ^[[30m Black 12 12 12
#1 Blue DarkBlue ^[[34m Blue 0 55 218
#2 Green DarkGreen ^[[32m Green 19 161 14
#3 Aqua DarkCyan ^[[36m Cyan 58 150 221
#4 Red DarkRed ^[[31m Red 197 15 31
#5 Purple DarkMagenta ^[[35m Magenta 136 23 152
#6 Yellow DarkYellow ^[[33m Yellow 193 156 0
#7 White Gray ^[[37m White 204 204 204
#8 Gray DarkGray ^[[90m Bright Black 118 118 118
#9 Light Blue Blue ^[[94m Bright Blue 59 120 255
#A Light Green Green ^[[92m Bright Green 22 198 12
#B Light Aqua Cyan ^[[96m Bright Cyan 97 214 214
#C Light Red Red ^[[91m Bright Red 231 72 86
#D Light Purple Magenta ^[[95m Bright Magenta 180 0 158
#E Light Yellow Yellow ^[[93m Bright Yellow 249 241 165
#F Bright White White ^[[97m Bright White 242 242 242

(The terminal sequences shown here set the foreground color. To set the background color use ^[[40m through ^[[47m and ^[[100m through ^[[107m instead.)

Any particular combination of color values is called a color scheme or color theme 1, and the default color scheme (known as Campbell) has the color values shown in the table above.

The console screen buffer

The output of command-line programs is mapped onto a screen buffer, a 2-dimensional grid of cells. For each cell the screen buffer stores a record 2 containing the ASCII or Unicode character that should be rendered, along with the text attributes that should be applied to that character when it is rendered.

The screen buffer sets the text attributes of a cell to the current text attributes everytime that cell's character is set:

The current text attributes of [the] screen buffer are used for characters subsequently written or echoed by the high-level functions. Console Screen Buffers

Before writing text a command-line program can change the screen buffer's current text attributes using the Windows Console API's SetConsoleTextAttribute function, or using a terminal sequence.

Setting text attributes using terminal sequences before writing characters to output
Setting text attributes using terminal sequences before writing characters to output

The terminal sequence ^[[0m can be used to reset the text attributes to the defaults. To reset the text attributes using the Windows Console API, use GetConsoleScreenBufferInfo to get the current text attributes before changing them, and use the returned value to change them back after writing the text.

Default text attributes

When the screen buffer is first created its current text attributes are set to use #0 (Black) for the background color and #7 (White) for the foreground color (these are the defaults stored in the Window Registry). The color values for those entries are listed in the table above. Every cell's character is then set to space, ensuring every cell has text attributes. Then the cursor is positioned at the 0,0 coordinate and the command-line program is started.

Console Window Host's default text attributes
Console Window Host's default text attributes

Windows PowerShell, when started directly, is configured to use different color entries. When the screen buffer is first created its current text attributes are set to use #5 (Purple) for the background color and #6 (Yellow) for the foreground color. The color values for those entries are set to a blue and a very light gray respectively.

Console Window Host's default text attributes when starting Windows PowerShell directly
Console Window Host's default text attributes when starting Windows PowerShell directly

This particular configuration may have caused some confusion, as it sets color values that are incongruent with the color palette entry's predefined names.

The color command

Windows Command Processor has a built-in color command that can be used to set the text attributes of every cell in the screen buffer. Without arguments it will reset the default text attributes. With the attr argument it will set the text attributes specified. For example color 1B will set the background color to #1 (Blue) and the foreground color to #B (Light Aqua).

Using the `color` command to set the text atrributes for every cell of the screen buffer
Using the color command to set the text atrributes for every cell of the screen buffer

To use the color command in Windows PowerShell you can run cmd /c color 1B. This starts the Windows Command Processor, which then changes the screen buffer and exits back to Windows PowerShell. The changes to the screen buffer persist because the screen buffer is independent of the command-line program.

Summary

Colors in Console Window Host have historically been based on a 4-bit color palette. Although the palette only has 16 entries, each entry can be set to any 24-bit color value, and many color themes are available. Color changes via the Windows Console API or via terminal sequences change the screen buffer's current text attributes, and only apply to text written after the change.


  1. For a list of color themes see windowsterminalthemes.dev or iterm2colorschemes.com↩︎

  2. See CHAR_INFO structure↩︎