How to use ESC sequences to set foreground colors?

2019-08-19 00:25发布

问题:

I'm writing a dynamic color palette for console terminal. The thing is to get ANSI ESC sequences to work within a default wincon terminal is enough to set those flags to the handles of the console:

    DWORD dwRequestedOutModes = ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN;
    DWORD dwRequestedInModes = ENABLE_VIRTUAL_TERMINAL_INPUT;

but using them is another thing. Right now my console engine outputs screen buffer made with CHAR_INFO with WriteConsoleOutputW(), but CHAR_INFO itself supports only 16 default scheme colors.

Using CONSOLE_SCREEN_BUFFER_INFOEX is again limited by 16 colors, but this time custom.

Using console ESC sequences is a good point, but the problem is I've found only examples of using printf(). For my project printf is too slow and unreliable, is there any other way to assign ESC sequence to each symbol in buffer.

Here is an example of my code:

WriteConsoleOutputW(this->m_hConsole, this->localFrame, (COORD){ (short)this->m_nScreenWidth, (short)this->m_nScreenHeight }, (COORD){ 0,0 }, &this->m_rectWindow);

Drawing routine: localFrame is CHAR_INFO pointer

void PrintFrameW(void* self, int x, int y, wchar_t character, short color)
{
    struct c_class* this = self;
    if (x >= 0 && x < this->nFrameLength&&y >= 0 && y < this->nFrameHeight)
    {
        this->localFrame[y*this->nFrameLength + x].Char.UnicodeChar = character;
        this->localFrame[y*this->nFrameLength + x].Attributes = color;
    }
}

It looks like C++ code, but this one is my self made C with classes, so it is ANSI-C wrap-up made for educational purposes.

The question is: How to colorize the output of the console with Escape sequences, and where to put them, with it being able to print something like this:

using ' ' char(space) and setting background color to ESC [48 ; 2 ; r ; g ; b or ESC [48 ; 5 ; s

回答1:

Turns out the low-level function can be done to write something in console without any checks. For this it's required only two things: char buffer and WriteFile().

char lfbuf[5120U] = { '\x1b','[','3','8',';','2',';','1','0','0',';','0',';','0','m','w','\0' };



        DWORD const lfbuf_length = (DWORD)(17);

        DWORD written;
        WriteFile(hOut, lfbuf, lfbuf_length, &written, NULL);

where hOut is a console handle. Turns out this one is being processed by the terminal and is fast, as it lasts only for couple thousands of ticks. I had to reverse the entire printf() to find this one out. Maybe there is something faster, but WriteFile is irreversible, it stops the execution when I reach out for assembly.