'Windows Console (conhost) discards newline when output matches witdth of the window

I have a C++ application on Windows, that logs to stdout (via the Win32 api using WriteConsole). Each logline consists of some text and a trailing newline character. The problem is:

When the width of the log-text (not including the newline character) matches the width of the console window, the newline character gets discarded.

See this example:

enter image description here

There are 3 log-messages:

  • the first one is smaller than the console-width
  • the second one matches the console-width exactly
  • the third one is longer than the console width, and thus wraps.

If I resize the window, the following happens:

enter image description here

The second and third line got merged into a single line, despite a newline character being printed between them. I suspect that windows, in an attempt to be smart, discarded the newline after the second message, since it would have visually led to a gap between the second and third message (new line from word wrapping + my newline charater). This is all well and good for that console-width, but when I resize, everything breaks.

Strive Sun - MSFT pointed out in their answer, that this behavior seems to happen due to the ENABLE_VIRTUAL_TERMINAL_PROCESSING flag being set. Disabling it fixes the issue. I use this flag to enable outputs of different colors, so would like to find some way to fix the newlines without losing colored output.

Is there some way to tell Windows not to do that (without disabling ENABLE_VIRTUAL_TERMINAL_PROCESSING to not lose colors)?



Solution 1:[1]

Is there some way to tell Windows not to do that?

After some debugging, I found that this problem will not occur after removing the ENABLE_VIRTUAL_TERMINAL_PROCESSING style in the console.

Like this,

DWORD lp;
HANDLE std_out = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleMode(std_out, &lp);
SetConsoleMode(std_out, lp &~ENABLE_VIRTUAL_TERMINAL_PROCESSING );
...

Updated:

int main()
{
    DWORD lp;
    HANDLE std_out = GetStdHandle(STD_OUTPUT_HANDLE);
    GetConsoleMode(std_out, &lp);
    SetConsoleMode(std_out, lp & ~ENABLE_VIRTUAL_TERMINAL_PROCESSING);

    SetConsoleTextAttribute(std_out, FOREGROUND_RED);
    DWORD written;
    char str1[] = "aaaaaa\n";
    char str2[] = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\r\ndddddd";
    //    char str2[] = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n";
    char str3[] = "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc\n";
    int len = strlen(str2);
    WriteConsoleA(std_out, str1, strlen(str1), &written, NULL);
    SetConsoleTextAttribute(std_out, FOREGROUND_INTENSITY);
    WriteConsoleA(std_out, str2, strlen(str2), &written, NULL);
    SetConsoleTextAttribute(std_out, FOREGROUND_INTENSITY | FOREGROUND_GREEN); 
    WriteConsoleA(std_out, str3, strlen(str3), &written, NULL);
    system("pause");
    return 0;
}

enter image description here

More colors, please refer: C++ Win32 Console Color

Solution 2:[2]

I found that, if one wants to keep using ANSI escape codes and not getting strange errors with linebreaks, passing this to ConsoleMode should suffice:

auto h = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleMode(h, ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Neervana