From 06262c078dad07e2640bd7217ad6995f02e35a3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 12 Oct 2022 20:40:38 +0800 Subject: [PATCH] TerminaFont: move windows specific code into its own file --- CMakeLists.txt | 2 +- src/common/properties.h | 2 +- src/detection/terminalfont/terminalfont.c | 187 +++++++++++++ .../terminalfont/terminalfont_linux.c | 263 ------------------ .../terminalfont/terminalfont_windows.c | 82 ++++++ 5 files changed, 271 insertions(+), 265 deletions(-) create mode 100644 src/detection/terminalfont/terminalfont_windows.c diff --git a/CMakeLists.txt b/CMakeLists.txt index ea760f60c..1eac66074 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -365,8 +365,8 @@ if(MSYS) src/detection/font/font_windows.cpp src/detection/terminalshell/terminalshell_linux.c src/detection/terminalshell/terminalshell_windows.cpp - src/detection/terminalfont/terminalfont_linux.c src/detection/packages/packages_linux.c + src/detection/terminalfont/terminalfont_windows.c src/detection/packages/packages_windows.c src/detection/kernel/kernel_windows.cpp src/detection/localip/localip_windows.c diff --git a/src/common/properties.h b/src/common/properties.h index 38d79c2ec..dfdcad96e 100644 --- a/src/common/properties.h +++ b/src/common/properties.h @@ -3,7 +3,7 @@ #ifndef FF_INCLUDED_common_properties #define FF_INCLUDED_common_properties -#include "util/FFstrbuf.h" +#include "fastfetch.h" typedef struct FFpropquery { diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index 297301f2f..c79ed7827 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -64,6 +64,185 @@ static void detectTTY(FFTerminalFontResult* terminalFont) ffStrbufDestroy(&fontName); } +#if defined(_WIN32) || defined(__MSYS__) || defined(__linux__) +#ifdef FF_HAVE_LIBCJSON + +#include "common/library.h" +#include "common/processing.h" + +#include +#include + +typedef struct CJSONData +{ + FF_LIBRARY_SYMBOL(cJSON_Parse) + FF_LIBRARY_SYMBOL(cJSON_IsObject) + FF_LIBRARY_SYMBOL(cJSON_GetObjectItemCaseSensitive) + FF_LIBRARY_SYMBOL(cJSON_IsString) + FF_LIBRARY_SYMBOL(cJSON_GetStringValue) + FF_LIBRARY_SYMBOL(cJSON_IsNumber) + FF_LIBRARY_SYMBOL(cJSON_GetNumberValue) + FF_LIBRARY_SYMBOL(cJSON_IsArray) + FF_LIBRARY_SYMBOL(cJSON_Delete) +} CJSONData; + +static const char* detectWTProfile(CJSONData* cjsonData, cJSON* profile, FFstrbuf* name, int* size) +{ + if(!cjsonData->ffcJSON_IsObject(profile)) + return "cJSON_IsObject(profile) returns false"; + + cJSON* font = cjsonData->ffcJSON_GetObjectItemCaseSensitive(profile, "font"); + if(!cjsonData->ffcJSON_IsObject(font)) + return "cJSON_IsObject(font) returns false"; + + if(name->length == 0) + { + cJSON* pface = cjsonData->ffcJSON_GetObjectItemCaseSensitive(font, "face"); + if(cjsonData->ffcJSON_IsString(pface)) + ffStrbufAppendS(name, cjsonData->ffcJSON_GetStringValue(pface)); + } + if(*size < 0) + { + cJSON* psize = cjsonData->ffcJSON_GetObjectItemCaseSensitive(font, "size"); + if(cjsonData->ffcJSON_IsNumber(psize)) + *size = (int)cjsonData->ffcJSON_GetNumberValue(psize); + } + return NULL; +} + +static const char* detectFromWTImpl(const FFinstance* instance, FFstrbuf* content, FFstrbuf* name, int* size) +{ + CJSONData cjsonData; + + FF_LIBRARY_LOAD(libcjson, &instance->config.libcJSON, "dlopen libcjson"FF_LIBRARY_EXTENSION" failed", "libcjson"FF_LIBRARY_EXTENSION, 1) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_Parse) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_IsObject) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_GetObjectItemCaseSensitive) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_IsString) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_GetStringValue) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_IsNumber) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_GetNumberValue) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_IsArray) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_Delete) + + const char* error = NULL; + + cJSON* root = cjsonData.ffcJSON_Parse(content->chars); + if(!cjsonData.ffcJSON_IsObject(root)) + { + error = "cJSON_Parse() failed"; + goto exit; + } + + cJSON* profiles = cjsonData.ffcJSON_GetObjectItemCaseSensitive(root, "profiles"); + if(!cjsonData.ffcJSON_IsObject(profiles)) + { + error = "cJSON_GetObjectItemCaseSensitive(root, \"profiles\") failed"; + goto exit; + } + + FFstrbuf wtProfileId; + ffStrbufInitS(&wtProfileId, getenv("WT_PROFILE_ID")); + ffStrbufTrim(&wtProfileId, '\''); + if(wtProfileId.length > 0) + { + cJSON* list = cjsonData.ffcJSON_GetObjectItemCaseSensitive(profiles, "list"); + if(cjsonData.ffcJSON_IsArray(list)) + { + cJSON* profile; + cJSON_ArrayForEach(profile, list) + { + if(!cjsonData.ffcJSON_IsObject(profile)) + continue; + cJSON* guid = cjsonData.ffcJSON_GetObjectItemCaseSensitive(profile, "guid"); + if(!cjsonData.ffcJSON_IsString(guid)) + continue; + if(ffStrbufCompS(&wtProfileId, cjsonData.ffcJSON_GetStringValue(guid)) == 0) + { + detectWTProfile(&cjsonData, profile, name, size); + break; + } + } + } + } + ffStrbufDestroy(&wtProfileId); + + cJSON* defaults = cjsonData.ffcJSON_GetObjectItemCaseSensitive(profiles, "defaults"); + detectWTProfile(&cjsonData, defaults, name, size); + + if(name->length == 0) + ffStrbufSetS(name, "Cascadia Mono"); + if(*size < 0) + *size = 12; + +exit: + cjsonData.ffcJSON_Delete(root); + dlclose(libcjson); + return error; +} + +static void detectFromWindowsTeriminal(const FFinstance* instance, FFTerminalFontResult* terminalFont) +{ + //https://learn.microsoft.com/en-us/windows/terminal/install#settings-json-file + FFstrbuf json; + ffStrbufInit(&json); + const char* error; + error = ffProcessAppendStdOut(&json, (char* const[]) { + "cmd.exe", + "/c", + //print the file content directly, so we don't need to handle the difference of Windows and POSIX path + "if exist %LOCALAPPDATA%\\Packages\\Microsoft.WindowsTerminal_8wekyb3d8bbwe\\LocalState\\settings.json " + "( type %LOCALAPPDATA%\\Packages\\Microsoft.WindowsTerminal_8wekyb3d8bbwe\\LocalState\\settings.json ) " + "else if exist %LOCALAPPDATA%\\Packages\\Microsoft.WindowsTerminalPreview_8wekyb3d8bbwe\\LocalState\\settings.json " + "( type %LOCALAPPDATA%\\Packages\\Microsoft.WindowsTerminalPreview_8wekyb3d8bbwe\\LocalState\\settings.json ) " + "else if exist \"%LOCALAPPDATA%\\Microsoft\\Windows Terminal\\settings.json\" " + "( type %LOCALAPPDATA%\\Microsoft\\Windows Terminal\\settings.json ) " + "else ( call )", + NULL + }); + if(error) + { + ffStrbufAppendS(&terminalFont->error, error); + ffStrbufDestroy(&json); + return; + } + ffStrbufTrimRight(&json, '\n'); + if(json.length == 0) + { + ffStrbufAppendS(&terminalFont->error, "Cannot find file \"settings.json\""); + ffStrbufDestroy(&json); + return; + } + + FFstrbuf name; + ffStrbufInit(&name); + int size = -1; + error = detectFromWTImpl(instance, &json, &name, &size); + ffStrbufDestroy(&json); + + if(error) + ffStrbufAppendS(&terminalFont->error, error); + else + { + char sizeStr[16]; + snprintf(sizeStr, sizeof(sizeStr), "%d", size); + ffFontInitValues(&terminalFont->font, name.chars, sizeStr); + } + + ffStrbufDestroy(&name); +} + +#else + +static void detectFromWindowsTeriminal(const FFinstance* instance, FFTerminalFontResult* terminalFont) +{ + FF_UNUSED(instance, terminalFont); + ffStrbufAppendS(&terminalFont->error, "fastfetch is built without libcjson support"); +} + +#endif +#endif //defined(_WIN32) || defined(__MSYS__) || defined(__linux__) + void ffDetectTerminalFontPlatform(const FFinstance* instance, const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont); const FFTerminalFontResult* ffDetectTerminalFont(const FFinstance* instance) @@ -79,6 +258,14 @@ const FFTerminalFontResult* ffDetectTerminalFont(const FFinstance* instance) detectAlacritty(instance, &result); else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalExe, "/dev/tty")) detectTTY(&result); + + #if defined(_WIN32) || defined(__MSYS__) || defined(__linux__) + //Used by both Linux (WSL) and Windows + else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "Windows Terminal") == 0 || + ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "WindowsTerminal.exe") == 0) + detectFromWindowsTeriminal(instance, &result); + #endif + else ffDetectTerminalFontPlatform(instance, terminalShell, &result); diff --git a/src/detection/terminalfont/terminalfont_linux.c b/src/detection/terminalfont/terminalfont_linux.c index 06a71da50..e63ccd815 100644 --- a/src/detection/terminalfont/terminalfont_linux.c +++ b/src/detection/terminalfont/terminalfont_linux.c @@ -140,259 +140,6 @@ static void detectXFCETerminal(const FFinstance* instance, FFTerminalFontResult* ffStrbufDestroy(&useSysFont); } -#ifdef FF_HAVE_LIBCJSON - -#include "common/library.h" -#include "common/processing.h" - -#include -#include - -typedef struct CJSONData -{ - FF_LIBRARY_SYMBOL(cJSON_Parse) - FF_LIBRARY_SYMBOL(cJSON_IsObject) - FF_LIBRARY_SYMBOL(cJSON_GetObjectItemCaseSensitive) - FF_LIBRARY_SYMBOL(cJSON_IsString) - FF_LIBRARY_SYMBOL(cJSON_GetStringValue) - FF_LIBRARY_SYMBOL(cJSON_IsNumber) - FF_LIBRARY_SYMBOL(cJSON_GetNumberValue) - FF_LIBRARY_SYMBOL(cJSON_IsArray) - FF_LIBRARY_SYMBOL(cJSON_Delete) -} CJSONData; - -static const char* detectWTProfile(CJSONData* cjsonData, cJSON* profile, FFstrbuf* name, int* size) -{ - if(!cjsonData->ffcJSON_IsObject(profile)) - return "cJSON_IsObject(profile) returns false"; - - cJSON* font = cjsonData->ffcJSON_GetObjectItemCaseSensitive(profile, "font"); - if(!cjsonData->ffcJSON_IsObject(font)) - return "cJSON_IsObject(font) returns false"; - - if(name->length == 0) - { - cJSON* pface = cjsonData->ffcJSON_GetObjectItemCaseSensitive(font, "face"); - if(cjsonData->ffcJSON_IsString(pface)) - ffStrbufAppendS(name, cjsonData->ffcJSON_GetStringValue(pface)); - } - if(*size < 0) - { - cJSON* psize = cjsonData->ffcJSON_GetObjectItemCaseSensitive(font, "size"); - if(cjsonData->ffcJSON_IsNumber(psize)) - *size = (int)cjsonData->ffcJSON_GetNumberValue(psize); - } - return NULL; -} - -static const char* detectFromWTImpl(const FFinstance* instance, FFstrbuf* content, FFstrbuf* name, int* size) -{ - CJSONData cjsonData; - - FF_LIBRARY_LOAD(libcjson, &instance->config.libcJSON, "dlopen libcjson"FF_LIBRARY_EXTENSION" failed", "libcjson"FF_LIBRARY_EXTENSION, 1) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_Parse) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_IsObject) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_GetObjectItemCaseSensitive) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_IsString) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_GetStringValue) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_IsNumber) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_GetNumberValue) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_IsArray) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_Delete) - - const char* error = NULL; - - cJSON* root = cjsonData.ffcJSON_Parse(content->chars); - if(!cjsonData.ffcJSON_IsObject(root)) - { - error = "cJSON_Parse() failed"; - goto exit; - } - - cJSON* profiles = cjsonData.ffcJSON_GetObjectItemCaseSensitive(root, "profiles"); - if(!cjsonData.ffcJSON_IsObject(profiles)) - { - error = "cJSON_GetObjectItemCaseSensitive(root, \"profiles\") failed"; - goto exit; - } - - FFstrbuf wtProfileId; - ffStrbufInitS(&wtProfileId, getenv("WT_PROFILE_ID")); - ffStrbufTrim(&wtProfileId, '\''); - if(wtProfileId.length > 0) - { - cJSON* list = cjsonData.ffcJSON_GetObjectItemCaseSensitive(profiles, "list"); - if(cjsonData.ffcJSON_IsArray(list)) - { - cJSON* profile; - cJSON_ArrayForEach(profile, list) - { - if(!cjsonData.ffcJSON_IsObject(profile)) - continue; - cJSON* guid = cjsonData.ffcJSON_GetObjectItemCaseSensitive(profile, "guid"); - if(!cjsonData.ffcJSON_IsString(guid)) - continue; - if(ffStrbufCompS(&wtProfileId, cjsonData.ffcJSON_GetStringValue(guid)) == 0) - { - detectWTProfile(&cjsonData, profile, name, size); - break; - } - } - } - } - ffStrbufDestroy(&wtProfileId); - - cJSON* defaults = cjsonData.ffcJSON_GetObjectItemCaseSensitive(profiles, "defaults"); - detectWTProfile(&cjsonData, defaults, name, size); - - if(name->length == 0) - ffStrbufSetS(name, "Cascadia Mono"); - if(*size < 0) - *size = 12; - -exit: - cjsonData.ffcJSON_Delete(root); - dlclose(libcjson); - return error; -} - -static void detectFromWindowsTeriminal(const FFinstance* instance, FFTerminalFontResult* terminalFont) -{ - //https://learn.microsoft.com/en-us/windows/terminal/install#settings-json-file - FFstrbuf json; - ffStrbufInit(&json); - const char* error; - error = ffProcessAppendStdOut(&json, (char* const[]) { - "cmd.exe", - "/c", - //print the file content directly, so we don't need to handle the difference of Windows and POSIX path - "if exist %LOCALAPPDATA%\\Packages\\Microsoft.WindowsTerminal_8wekyb3d8bbwe\\LocalState\\settings.json " - "( type %LOCALAPPDATA%\\Packages\\Microsoft.WindowsTerminal_8wekyb3d8bbwe\\LocalState\\settings.json ) " - "else if exist %LOCALAPPDATA%\\Packages\\Microsoft.WindowsTerminalPreview_8wekyb3d8bbwe\\LocalState\\settings.json " - "( type %LOCALAPPDATA%\\Packages\\Microsoft.WindowsTerminalPreview_8wekyb3d8bbwe\\LocalState\\settings.json ) " - "else if exist \"%LOCALAPPDATA%\\Microsoft\\Windows Terminal\\settings.json\" " - "( type %LOCALAPPDATA%\\Microsoft\\Windows Terminal\\settings.json ) " - "else ( call )", - NULL - }); - if(error) - { - ffStrbufAppendS(&terminalFont->error, error); - ffStrbufDestroy(&json); - return; - } - ffStrbufTrimRight(&json, '\n'); - if(json.length == 0) - { - ffStrbufAppendS(&terminalFont->error, "Cannot find file \"settings.json\""); - ffStrbufDestroy(&json); - return; - } - - FFstrbuf name; - ffStrbufInit(&name); - int size = -1; - error = detectFromWTImpl(instance, &json, &name, &size); - ffStrbufDestroy(&json); - - if(error) - ffStrbufAppendS(&terminalFont->error, error); - else - { - char sizeStr[16]; - snprintf(sizeStr, sizeof(sizeStr), "%d", size); - ffFontInitValues(&terminalFont->font, name.chars, sizeStr); - } - - ffStrbufDestroy(&name); -} - -#else - -static void detectFromWindowsTeriminal(const FFinstance* instance, FFTerminalFontResult* terminalFont) -{ - FF_UNUSED(instance, terminalFont); - ffStrbufAppendS(&terminalFont->error, "fastfetch is built without libcjson support"); -} - -#endif - -#if defined(_WIN32) || defined(__MSYS__) -// TODO: move to a separate file - -static void detectMintty(const FFinstance* instance, FFTerminalFontResult* terminalFont) -{ - FFstrbuf fontName; - ffStrbufInit(&fontName); - - FFstrbuf fontSize; - ffStrbufInit(&fontSize); - - ffParsePropFileHomeValues(instance, ".minttyrc", 2, (FFpropquery[]) { - {"Font=", &fontName}, - {"FontHeight=", &fontSize} - }); - if(fontName.length == 0) - ffStrbufAppendS(&fontName, "Lucida Console"); - if(fontSize.length == 0) - ffStrbufAppendC(&fontSize, '9'); - - ffFontInitValues(&terminalFont->font, fontName.chars, fontSize.chars); - - ffStrbufDestroy(&fontName); - ffStrbufDestroy(&fontSize); -} - -#define WIN32_LEAN_AND_MEAN 1 -#include - -static void detectConhost(const FFinstance* instance, FFTerminalFontResult* terminalFont) -{ - FF_UNUSED(instance); - - //Current font of conhost doesn't seem to be detectable, we detect default font instead - - HKEY hKey; - if(RegOpenKeyExW(HKEY_CURRENT_USER, L"Console", 0, KEY_READ, &hKey) != ERROR_SUCCESS) - { - ffStrbufAppendS(&terminalFont->error, "RegOpenKeyExW() failed"); - return; - } - - DWORD bufSize; - - wchar_t fontNameW[64]; - bufSize = sizeof(fontNameW); - if(RegQueryValueExW(hKey, L"FaceName", NULL, NULL, (LPBYTE)fontNameW, &bufSize) != ERROR_SUCCESS) - { - ffStrbufAppendS(&terminalFont->error, "RegOpenKeyExW(FaceName) failed"); - goto exit; - } - fontNameW[bufSize] = '\0'; - - char fontNameA[128]; - int fontNameALen = WideCharToMultiByte(CP_UTF8, 0, fontNameW, (int)(bufSize / 2), fontNameA, sizeof(fontNameA), NULL, NULL); - fontNameA[fontNameALen] = '\0'; - - uint32_t fontSizeNum = 0; - bufSize = sizeof(fontSizeNum); - if(RegQueryValueExW(hKey, L"fontSize", NULL, NULL, (LPBYTE)&fontSizeNum, &bufSize) != ERROR_SUCCESS) - { - ffStrbufAppendS(&terminalFont->error, "RegOpenKeyExW(fontSize) failed"); - goto exit; - } - - char fontSize[16]; - snprintf(fontSize, sizeof(fontSize), "%u", (fontSizeNum >> 16)); - - ffFontInitValues(&terminalFont->font, fontNameA, fontSize); - -exit: - RegCloseKey(hKey); -} - -#endif //defined(_WIN32) || defined(__MSYS__) - void ffDetectTerminalFontPlatform(const FFinstance* instance, const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont) { if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "konsole") == 0) @@ -405,14 +152,4 @@ void ffDetectTerminalFontPlatform(const FFinstance* instance, const FFTerminalSh detectFromGSettings(instance, "/com/gexperts/Tilix/profiles/", "com.gexperts.Tilix.ProfilesList", "com.gexperts.Tilix.Profile", terminalFont); else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "gnome-terminal-") == 0) detectFromGSettings(instance, "/org/gnome/terminal/legacy/profiles:/:", "org.gnome.Terminal.ProfilesList", "org.gnome.Terminal.Legacy.Profile", terminalFont); - else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "Windows Terminal") == 0 || - ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "WindowsTerminal.exe") == 0) - detectFromWindowsTeriminal(instance, terminalFont); - - #if defined(_WIN32) || defined(__MSYS__) - else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "mintty") == 0) - detectMintty(instance, terminalFont); - else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "conhost.exe") == 0) - detectConhost(instance, terminalFont); - #endif } diff --git a/src/detection/terminalfont/terminalfont_windows.c b/src/detection/terminalfont/terminalfont_windows.c new file mode 100644 index 000000000..6a68bb6a5 --- /dev/null +++ b/src/detection/terminalfont/terminalfont_windows.c @@ -0,0 +1,82 @@ +#include "common/properties.h" +#include "detection/terminalshell/terminalshell.h" +#include "terminalfont.h" + +#define WIN32_LEAN_AND_MEAN 1 +#include + +static void detectMintty(const FFinstance* instance, FFTerminalFontResult* terminalFont) +{ + FFstrbuf fontName; + ffStrbufInit(&fontName); + + FFstrbuf fontSize; + ffStrbufInit(&fontSize); + + ffParsePropFileHomeValues(instance, ".minttyrc", 2, (FFpropquery[]) { + {"Font=", &fontName}, + {"FontHeight=", &fontSize} + }); + if(fontName.length == 0) + ffStrbufAppendS(&fontName, "Lucida Console"); + if(fontSize.length == 0) + ffStrbufAppendC(&fontSize, '9'); + + ffFontInitValues(&terminalFont->font, fontName.chars, fontSize.chars); + + ffStrbufDestroy(&fontName); + ffStrbufDestroy(&fontSize); +} + +static void detectConhost(const FFinstance* instance, FFTerminalFontResult* terminalFont) +{ + FF_UNUSED(instance); + + //Current font of conhost doesn't seem to be detectable, we detect default font instead + + HKEY hKey; + if(RegOpenKeyExW(HKEY_CURRENT_USER, L"Console", 0, KEY_READ, &hKey) != ERROR_SUCCESS) + { + ffStrbufAppendS(&terminalFont->error, "RegOpenKeyExW() failed"); + return; + } + + DWORD bufSize; + + wchar_t fontNameW[64]; + bufSize = sizeof(fontNameW); + if(RegQueryValueExW(hKey, L"FaceName", NULL, NULL, (LPBYTE)fontNameW, &bufSize) != ERROR_SUCCESS) + { + ffStrbufAppendS(&terminalFont->error, "RegOpenKeyExW(FaceName) failed"); + goto exit; + } + fontNameW[bufSize] = '\0'; + + char fontNameA[128]; + int fontNameALen = WideCharToMultiByte(CP_UTF8, 0, fontNameW, (int)(bufSize / 2), fontNameA, sizeof(fontNameA), NULL, NULL); + fontNameA[fontNameALen] = '\0'; + + uint32_t fontSizeNum = 0; + bufSize = sizeof(fontSizeNum); + if(RegQueryValueExW(hKey, L"fontSize", NULL, NULL, (LPBYTE)&fontSizeNum, &bufSize) != ERROR_SUCCESS) + { + ffStrbufAppendS(&terminalFont->error, "RegOpenKeyExW(fontSize) failed"); + goto exit; + } + + char fontSize[16]; + snprintf(fontSize, sizeof(fontSize), "%u", (fontSizeNum >> 16)); + + ffFontInitValues(&terminalFont->font, fontNameA, fontSize); + +exit: + RegCloseKey(hKey); +} + +void ffDetectTerminalFontPlatform(const FFinstance* instance, const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont) +{ + if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "mintty") == 0) + detectMintty(instance, terminalFont); + else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "conhost.exe") == 0) + detectConhost(instance, terminalFont); +}