Download Pelles C here: http://www.pellesc.se
BOOL SetConsoleFontToConsolas(void)
{
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
if (hConsole == INVALID_HANDLE_VALUE) return FALSE;
CONSOLE_FONT_INFOEX cfi;
cfi.cbSize = sizeof(CONSOLE_FONT_INFOEX);
// Get the current font info first to preserve defaults
if (!GetCurrentConsoleFontEx(hConsole, FALSE, &cfi))
{
return FALSE;
}
// Set font properties
cfi.dwFontSize.X = 0; // Width (0 lets Windows calculate based on height)
cfi.dwFontSize.Y = 16; // Height (Font size in points/pixels)
cfi.FontFamily = FF_DONTCARE;
cfi.FontWeight = FW_NORMAL;
// Specify a TrueType font that supports UTF-8 Unicode characters
// Common choices: L"Cascadia Code", L"Consolas", L"Lucida Console"
wcscpy_s(cfi.FaceName, LF_FACESIZE, L"Consolas");
// Apply the new font
return SetCurrentConsoleFontEx(hConsole, FALSE, &cfi);
}QuoteThe functions SetConsoleOutputCP and SetConsoleCP along with the CP_UTF8 code page constant (code page 65001) have been supported since Windows 2000.
However, the minimal OS version depends on what you are trying to achieve:
Basic Function Support (API availability): Windows 2000 or later. Calling SetConsoleOutputCP(65001) is supported on all Windows NT-based OS versions starting from 2000, as well as Windows XP, Vista, 7, 8, and 10.
Functional UTF-8 Console Rendering: Windows 10 Version 1903 (Build 18362) or later.
Why the distinction matters:
While the functions exist on older OS versions, UTF-8 support inside cmd.exe on legacy releases (Windows 7/8/early Win 10) was notoriously buggy:
Legacy Bugs: On older versions like Windows 7, setting the console to code page 65001 frequently broke C runtime output routines (printf), caused character truncation, or crashed batch scripts.
Font Rendering: Legacy consoles couldn't render multi-byte UTF-8 sequences properly unless using specific TrueType fonts.
Full ConPTY Overhaul: Microsoft fully overhauled the Windows Console infrastructure in Windows 10 version 1903 (Build 18362)—the exact same release that introduced manifest-based UTF-8 ACP support—making UTF-8 output reliable and stable in the terminal.
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<activeCodePage xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">UTF-8</activeCodePage>
</windowsSettings>
</application>
The attached sample demonstrate how it works. You can test it in both versions ANSI and WIDECHAR, just change the '#if 1' to '#if 0' to compile in ANSI mode.#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
// 1. UTF-8 (multibyte char*) -> UTF-16 (wchar_t*)
wchar_t* Utf8ToUtf16(const char* utf8_str) {
if (!utf8_str) return NULL;
// Get required buffer size in wchar_t elements (including null-terminator)
int size_needed = MultiByteToWideChar(CP_UTF8, 0, utf8_str, -1, NULL, 0);
if (size_needed == 0) return NULL;
wchar_t* wstr = (wchar_t*)malloc(size_needed * sizeof(wchar_t));
if (!wstr) return NULL;
// Perform conversion
MultiByteToWideChar(CP_UTF8, 0, utf8_str, -1, wstr, size_needed);
return wstr; // Caller must free()
}
// 2. UTF-16 (wchar_t*) -> UTF-8 (multibyte char*)
char* Utf16ToUtf8(const wchar_t* wstr) {
if (!wstr) return NULL;
// Get required buffer size in bytes (including null-terminator)
int size_needed = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
if (size_needed == 0) return NULL;
char* utf8_str = (char*)malloc(size_needed);
if (!utf8_str) return NULL;
// Perform conversion
WideCharToMultiByte(CP_UTF8, 0, wstr, -1, utf8_str, size_needed, NULL, NULL);
return utf8_str; // Caller must free()
}
typedef unsigned char u8;
void pack_a(const u8 *in, u8 *out)
{
out[0] = (u8)(((in[1] & 0x0f) << 8) | in[2]);
}
void pack_b(const u8 *in, u8 *out)
{
out[0] = (u8)((((int)in[1]) & 0x0f) * 256 | in[2]);
}
pocc -Tx64-coff -std:C17 -Ze -Zx -Go -Ot -W1 -c d006_minimal.c
warning #2131: Shifting an 'unsigned char' by 8 bits is undefined.
warning #2131: Shifting an 'char' by 8 bits is undefined.
Page created in 0.041 seconds with 15 queries.