- rewrote Windows console code for Windows 10's new terminal.

This allows dumping a lot of shit code using deprecated Windows functionality and bringing the code in line with Microsoft's roadmap for terminal/console functionality.
Note that this will cause garbled output of non-ASCII characters on Windows 7 and 8.1, but proper handling on these declining systems is of far lesser importance than future-proofing the feature.
This commit is contained in:
Christoph Oelckers 2022-07-15 13:04:02 +02:00
parent 595975fcc7
commit 0e90098de8
2 changed files with 30 additions and 92 deletions

View file

@ -43,6 +43,7 @@
#include <processenv.h> #include <processenv.h>
#include <shellapi.h> #include <shellapi.h>
#include <VersionHelpers.h>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(disable:4244) #pragma warning(disable:4244)
@ -179,7 +180,7 @@ int DoMain (HINSTANCE hInstance)
StdOut = NULL; StdOut = NULL;
} }
} }
if (StdOut == NULL) if (StdOut == nullptr)
{ {
if (AttachConsole(ATTACH_PARENT_PROCESS)) if (AttachConsole(ATTACH_PARENT_PROCESS))
{ {
@ -187,25 +188,21 @@ int DoMain (HINSTANCE hInstance)
DWORD foo; WriteFile(StdOut, "\n", 1, &foo, NULL); DWORD foo; WriteFile(StdOut, "\n", 1, &foo, NULL);
AttachedStdOut = true; AttachedStdOut = true;
} }
if (StdOut == NULL && AllocConsole()) if (StdOut == nullptr && AllocConsole())
{ {
StdOut = GetStdHandle(STD_OUTPUT_HANDLE); StdOut = GetStdHandle(STD_OUTPUT_HANDLE);
} }
if (StdOut != nullptr)
// Deprecated stuff for legacy consoles. As of now this is still relevant, but this code can be removed once Windows 7 is no longer relevant.
CONSOLE_FONT_INFOEX cfi;
cfi.cbSize = sizeof(cfi);
if (GetCurrentConsoleFontEx(StdOut, false, &cfi))
{ {
if (*cfi.FaceName == 0) // If the face name is empty, the default (useless) raster font is actoive. SetConsoleCP(CP_UTF8);
SetConsoleOutputCP(CP_UTF8);
DWORD mode;
if (GetConsoleMode(StdOut, &mode))
{ {
//cfi.dwFontSize = { 8, 14 }; if (SetConsoleMode(StdOut, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING))
wcscpy(cfi.FaceName, L"Lucida Console"); FancyStdOut = IsWindows10OrGreater(); // Windows 8.1 and lower do not understand ANSI formatting.
cfi.FontFamily = FF_DONTCARE;
SetCurrentConsoleFontEx(StdOut, false, &cfi);
} }
} }
FancyStdOut = true;
} }
} }

View file

@ -278,97 +278,38 @@ void CalculateCPUSpeed()
static void PrintToStdOut(const char *cpt, HANDLE StdOut) static void PrintToStdOut(const char *cpt, HANDLE StdOut)
{ {
if (StdOut == nullptr && !con_debugoutput) const char* srcp = cpt;
return; FString printData = "";
bool terminal = FancyStdOut;
wchar_t wbuf[256]; while (*srcp != 0)
int bpos = 0;
const uint8_t *cptr = (const uint8_t*)cpt;
auto outputIt = [&]()
{ {
wbuf[bpos] = 0; if (*srcp == 0x1c && terminal)
if (con_debugoutput)
{ {
OutputDebugStringW(wbuf); srcp += 1;
} const uint8_t* scratch = (const uint8_t*)srcp; // GCC does not like direct casting of the parameter.
if (StdOut != nullptr) EColorRange range = V_ParseFontColor(scratch, CR_UNTRANSLATED, CR_YELLOW);
{ srcp = (char*)scratch;
// Convert back to UTF-8.
DWORD bytes_written;
if (!FancyStdOut)
{
FString conout(wbuf);
WriteFile(StdOut, conout.GetChars(), (DWORD)conout.Len(), &bytes_written, NULL);
}
else
{
WriteConsoleW(StdOut, wbuf, bpos, &bytes_written, nullptr);
}
}
bpos = 0;
};
while (int chr = GetCharFromString(cptr))
{
if ((chr == TEXTCOLOR_ESCAPE && bpos != 0) || bpos == 255)
{
outputIt();
}
if (chr != TEXTCOLOR_ESCAPE)
{
if (chr >= 0x1D && chr <= 0x1F)
{ // The bar characters, most commonly used to indicate map changes
chr = 0x2550; // Box Drawings Double Horizontal
}
wbuf[bpos++] = chr;
}
else
{
EColorRange range = V_ParseFontColor(cptr, CR_UNTRANSLATED, CR_YELLOW);
if (range != CR_UNDEFINED) if (range != CR_UNDEFINED)
{ {
// Change the color of future text added to the control.
PalEntry color = V_LogColorFromColorRange(range); PalEntry color = V_LogColorFromColorRange(range);
if (StdOut != NULL && FancyStdOut) printData.AppendFormat("\033[38;2;%u;%u;%um", color.r, color.g, color.b);
}
}
else if (*srcp != 0x1c && *srcp != 0x1d && *srcp != 0x1e && *srcp != 0x1f)
{ {
// Unfortunately, we are pretty limited here: There are only printData += *srcp++;
// eight basic colors, and each comes in a dark and a bright
// variety.
float h, s, v, r, g, b;
int attrib = 0;
RGBtoHSV(color.r / 255.f, color.g / 255.f, color.b / 255.f, &h, &s, &v);
if (s != 0)
{ // color
HSVtoRGB(&r, &g, &b, h, 1, 1);
if (r == 1) attrib = FOREGROUND_RED;
if (g == 1) attrib |= FOREGROUND_GREEN;
if (b == 1) attrib |= FOREGROUND_BLUE;
if (v > 0.6) attrib |= FOREGROUND_INTENSITY;
} }
else else
{ // gray
if (v < 0.33) attrib = FOREGROUND_INTENSITY;
else if (v < 0.90) attrib = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
else attrib = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
}
SetConsoleTextAttribute(StdOut, (WORD)attrib);
}
}
}
}
if (bpos != 0)
{ {
outputIt(); if (srcp[1] != 0) srcp += 2;
else break;
} }
if (StdOut != NULL && FancyStdOut)
{ // Set text back to gray, in case it was changed.
SetConsoleTextAttribute(StdOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
} }
DWORD bytes_written;
WriteFile(StdOut, printData.GetChars(), (DWORD)printData.Len(), &bytes_written, NULL);
if (terminal)
WriteFile(StdOut, "\033[0m", 4, &bytes_written, NULL);
} }
void I_PrintStr(const char *cp) void I_PrintStr(const char *cp)