0

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)?

pulp_user
  • 2,454
  • 3
  • 14
  • 18
  • 2
    cmd has nothing to do with this. It's a shell which has to be attached to some console (like conhost.exe or Windows terminal). It's the console that prints the texts out – phuclv Feb 17 '21 at 15:36
  • Ok, I guess conhost.exe is the issue then. I am still going to leave the title the way it is, since I would not have searched for conhost. So if there are other people in my situation I doubt they would find this post. – pulp_user Feb 17 '21 at 15:55
  • @pulp_user Add both console and conhost, remove cmd.exe since it’s irrelevant. And actually try starting the application without using cmd.exe - the latter may be changing console state and making it behave “weirdly”. – Kuba hasn't forgotten Monica Feb 17 '21 at 16:39
  • I am not starting my application using cmd.exe, I just double click. I guess cmd.exe is not at involved then, its just my application and conhost (I thought cmd and conhost were the same thing) – pulp_user Feb 17 '21 at 16:50

2 Answers2

2

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

Strive Sun
  • 5,988
  • 1
  • 9
  • 26
  • This does indeed work, however I have ENABLE_VIRTUAL_TERMINAL_PROCESSING active to enable colored text output and would like to keep that. I edited the question to make that clear. Seems for now like those two things are mutually exclusive. (I tried out other flags that might interfere with newlines, but I didn't find a combination that fixes the newlines and lets me keep colored output). – pulp_user Feb 22 '21 at 12:32
  • @pulp_user In fact, you canceled accepting my answer, I was a little frustrated. Because it explains your original problem. For your new question, I suggest you can use [SetConsoleTextAttribute](https://learn.microsoft.com/en-us/windows/console/setconsoletextattribute) instead. – Strive Sun Mar 02 '21 at 07:35
  • 1
    Thank you! I'll test that as soon as I have the possibility. I didn't mean to upset anybody, but just realized that its kind of counterproductive to leave an answer as accepted, if there is still a (newly added) part of the question that I'd like to have an answer to. So no ill will. – pulp_user Mar 02 '21 at 07:45
  • 1
    It does. Its still not 100% what I wanted, since I have way fewer colours now, but I guess the ideal solution I want just doesn't exist, and at this point I'd be a monster not to let you leave this question behind you in peace :D. Thanks for investing so much time into it! – pulp_user Mar 02 '21 at 17:41
  • @pulp_user There seems to be no better way to get more colors. Maybe someone knows a better answer. You can post a new question to ask about this. – Strive Sun Mar 03 '21 at 08:56
0

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);
Neervana
  • 318
  • 1
  • 10