Background colour sometimes ignored in Windows Terminal #12113

Open
opened 2026-01-31 03:06:36 +00:00 by claunia · 0 comments
Owner

Originally created by @clinton-r on GitHub (Jan 19, 2021).

Environment

Microsoft Windows [Version 10.0.19041.746]
Windows Terminal Version: 1.4.3243.0
Microsoft Visual Studio Community 2019 Version 16.8.4

Steps to reproduce

Compile the test program below.
Open Windows Terminal cmd or Powershell tab. Run the program. (Might have to run it several times to see the problem.)

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

static HANDLE hStdin = NULL;
static HANDLE hStdout = NULL;

typedef struct
{
    int fgCode;
    int bgCode;
    char* colourName;

} VT_COLOUR_INFO;

void writeString(char* str)
{
#if 1
    WriteConsoleA(hStdout, str, strlen(str), NULL, NULL);
#else
    printf(str);
#endif
}

int main(void)
{
    char buf[1000];
    DWORD mode;

    // Get handles for stdin and stdout
    hStdin = GetStdHandle(STD_INPUT_HANDLE);
    if (hStdin == INVALID_HANDLE_VALUE || hStdin == NULL)
        return 1;
    hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
    if (hStdout == INVALID_HANDLE_VALUE || hStdout == NULL)
        return 1;

    // Enable escape sequences
    if (!GetConsoleMode(hStdout, &mode))
        return 1;
    if (!SetConsoleMode(hStdout, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING))
        return 1;

    if (!GetConsoleMode(hStdin, &mode))
        return 1;
    if (!SetConsoleMode(hStdin, mode | ENABLE_VIRTUAL_TERMINAL_INPUT))
        return 1;

    // TEST OUTPUT

    // SGR colour codes
    VT_COLOUR_INFO colourLookup[] =
    {
        { 30, 40, "black" },
        { 31, 41, "red" },
        { 32, 42, "green" },
        { 33, 43, "yellow" },
        { 34, 44, "blue" },
        { 35, 45, "magenta" },
        { 36, 46, "cyan" },
        { 37, 47, "white" },

        { 90, 100, "bright black" },
        { 91, 101, "bright red" },
        { 92, 102, "bright green" },
        { 93, 103, "bright yellow" },
        { 94, 104, "bright blue" },
        { 95, 105, "bright magenta" },
        { 96, 106, "bright cyan" },
        { 97, 107, "bright white" },
    };

    writeString("normal text\r\n");

    for (int bg = 0; bg < (sizeof(colourLookup) / sizeof(colourLookup[0])); bg += 1)
    {
        sprintf_s(buf, sizeof(buf), "\x1b[%dm", colourLookup[bg].bgCode); // set background colour
        writeString(buf);
        for (int fg = 0; fg < (sizeof(colourLookup) / sizeof(colourLookup[0])); fg += 1)
        {
            writeString("\x1b[2K"); // erase line (set line to background colour)
            sprintf_s(buf, sizeof(buf), "\x1b[%dm", colourLookup[fg].fgCode); // set foreground colour
            writeString(buf);
            sprintf_s(buf, sizeof(buf), "%16s on %16s ",
                colourLookup[fg].colourName, colourLookup[bg].colourName);
            writeString(buf);
            writeString("\x1b[7mnegative ");    // SGR negative on
            writeString("\x1b[27m");            // SGR negative off
            writeString("\x1b[4munderline ");   // SGR underline on
            writeString("\x1b[24m\r\n");        // SGR underline off
        }
    }

    writeString("\x1b[0m"); // SGR defaults
    writeString("\x1b[2K"); // erase line
    writeString("\r\nnormal text\r\n");

    if (!SetConsoleMode(hStdin, mode))
        return 1;

    return 0;
}

Expected behavior

The test program uses SGR VT sequences to show all the different foreground and background colours, as well as negative and underlined text.

Actual behavior

For each line, the program first erases the line before printing text on it, to set the entire line to the background colour. It appears that sometimes black is used instead of the background colour. Also, spaces are sometimes printed as black instead of the background colour as well. Here is an example with both line and a space:
bgcolour

Notes

Doesn't happen in conhost.

Something similar happens when the terminal scrolls down - usually the new blank line gets the background colour as it should, but occasionally it gets black instead. (Try commenting out the first line in the for loop.)

Thanks

Originally created by @clinton-r on GitHub (Jan 19, 2021). <!-- 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨 I ACKNOWLEDGE THE FOLLOWING BEFORE PROCEEDING: 1. If I delete this entire template and go my own path, the core team may close my issue without further explanation or engagement. 2. If I list multiple bugs/concerns in this one issue, the core team may close my issue without further explanation or engagement. 3. If I write an issue that has many duplicates, the core team may close my issue without further explanation or engagement (and without necessarily spending time to find the exact duplicate ID number). 4. If I leave the title incomplete when filing the issue, the core team may close my issue without further explanation or engagement. 5. If I file something completely blank in the body, the core team may close my issue without further explanation or engagement. All good? Then proceed! --> <!-- This bug tracker is monitored by Windows Terminal development team and other technical folks. **Important: When reporting BSODs or security issues, DO NOT attach memory dumps, logs, or traces to Github issues**. Instead, send dumps/traces to secure@microsoft.com, referencing this GitHub issue. If this is an application crash, please also provide a Feedback Hub submission link so we can find your diagnostic data on the backend. Use the category "Apps > Windows Terminal (Preview)" and choose "Share My Feedback" after submission to get the link. Please use this form and describe your issue, concisely but precisely, with as much detail as possible. --> # Environment Microsoft Windows [Version 10.0.19041.746] Windows Terminal Version: 1.4.3243.0 Microsoft Visual Studio Community 2019 Version 16.8.4 # Steps to reproduce <!-- A description of how to trigger this bug. --> Compile the test program below. Open Windows Terminal cmd or Powershell tab. Run the program. (Might have to run it several times to see the problem.) ```C #include <stdio.h> #include <stdlib.h> #include <windows.h> static HANDLE hStdin = NULL; static HANDLE hStdout = NULL; typedef struct { int fgCode; int bgCode; char* colourName; } VT_COLOUR_INFO; void writeString(char* str) { #if 1 WriteConsoleA(hStdout, str, strlen(str), NULL, NULL); #else printf(str); #endif } int main(void) { char buf[1000]; DWORD mode; // Get handles for stdin and stdout hStdin = GetStdHandle(STD_INPUT_HANDLE); if (hStdin == INVALID_HANDLE_VALUE || hStdin == NULL) return 1; hStdout = GetStdHandle(STD_OUTPUT_HANDLE); if (hStdout == INVALID_HANDLE_VALUE || hStdout == NULL) return 1; // Enable escape sequences if (!GetConsoleMode(hStdout, &mode)) return 1; if (!SetConsoleMode(hStdout, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) return 1; if (!GetConsoleMode(hStdin, &mode)) return 1; if (!SetConsoleMode(hStdin, mode | ENABLE_VIRTUAL_TERMINAL_INPUT)) return 1; // TEST OUTPUT // SGR colour codes VT_COLOUR_INFO colourLookup[] = { { 30, 40, "black" }, { 31, 41, "red" }, { 32, 42, "green" }, { 33, 43, "yellow" }, { 34, 44, "blue" }, { 35, 45, "magenta" }, { 36, 46, "cyan" }, { 37, 47, "white" }, { 90, 100, "bright black" }, { 91, 101, "bright red" }, { 92, 102, "bright green" }, { 93, 103, "bright yellow" }, { 94, 104, "bright blue" }, { 95, 105, "bright magenta" }, { 96, 106, "bright cyan" }, { 97, 107, "bright white" }, }; writeString("normal text\r\n"); for (int bg = 0; bg < (sizeof(colourLookup) / sizeof(colourLookup[0])); bg += 1) { sprintf_s(buf, sizeof(buf), "\x1b[%dm", colourLookup[bg].bgCode); // set background colour writeString(buf); for (int fg = 0; fg < (sizeof(colourLookup) / sizeof(colourLookup[0])); fg += 1) { writeString("\x1b[2K"); // erase line (set line to background colour) sprintf_s(buf, sizeof(buf), "\x1b[%dm", colourLookup[fg].fgCode); // set foreground colour writeString(buf); sprintf_s(buf, sizeof(buf), "%16s on %16s ", colourLookup[fg].colourName, colourLookup[bg].colourName); writeString(buf); writeString("\x1b[7mnegative "); // SGR negative on writeString("\x1b[27m"); // SGR negative off writeString("\x1b[4munderline "); // SGR underline on writeString("\x1b[24m\r\n"); // SGR underline off } } writeString("\x1b[0m"); // SGR defaults writeString("\x1b[2K"); // erase line writeString("\r\nnormal text\r\n"); if (!SetConsoleMode(hStdin, mode)) return 1; return 0; } ``` # Expected behavior <!-- A description of what you're expecting, possibly containing screenshots or reference material. --> The test program uses SGR VT sequences to show all the different foreground and background colours, as well as negative and underlined text. # Actual behavior <!-- What's actually happening? --> For each line, the program first erases the line before printing text on it, to set the entire line to the background colour. It appears that sometimes black is used instead of the background colour. Also, spaces are sometimes printed as black instead of the background colour as well. Here is an example with both line and a space: ![bgcolour](https://user-images.githubusercontent.com/50687925/104981429-d44a4a80-59c5-11eb-8f95-4bc92fc34152.png) # Notes Doesn't happen in conhost. Something similar happens when the terminal scrolls down - usually the new blank line gets the background colour as it should, but occasionally it gets black instead. (Try commenting out the first line in the for loop.) Thanks
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#12113