From 165b0b0a69b7c772003dd9d5a1b8f17fd4a047e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 24 Jul 2024 09:28:52 +0800 Subject: [PATCH] TerminalFont (Linux): remove Windows Terminal support for WSL Fix #1113 --- src/detection/terminalfont/terminalfont.c | 194 ------------------ .../terminalfont/terminalfont_windows.c | 183 ++++++++++++++++- 2 files changed, 180 insertions(+), 197 deletions(-) diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index 088411925..eb176b180 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -72,193 +72,6 @@ FF_MAYBE_UNUSED static void detectTTY(FFTerminalFontResult* terminalFont) ffStrbufAppendS(&terminalFont->error, "Couldn't find Font in "FASTFETCH_TARGET_DIR_ETC"/vconsole.conf"); } -#if defined(_WIN32) || defined(__linux__) - -#include "common/library.h" -#include - -static const char* detectWTProfile(yyjson_val* profile, FFstrbuf* name, double* size) -{ - yyjson_val* font = yyjson_obj_get(profile, "font"); - if (!font) - return "yyjson_obj_get(profile, \"font\"); failed"; - - if (!yyjson_is_obj(font)) - return "yyjson_is_obj(font) returns false"; - - if (name->length == 0) - { - yyjson_val* pface = yyjson_obj_get(font, "face"); - if(yyjson_is_str(pface)) - ffStrbufAppendS(name, unsafe_yyjson_get_str(pface)); - } - - if (*size < 0) - { - yyjson_val* psize = yyjson_obj_get(font, "size"); - if (yyjson_is_num(psize)) - *size = yyjson_get_num(psize); - } - return NULL; -} - -static inline void wrapYyjsonFree(yyjson_doc** doc) -{ - assert(doc); - if (*doc) - yyjson_doc_free(*doc); -} - -static const char* detectFromWTImpl(FFstrbuf* content, FFstrbuf* name, double* size) -{ - yyjson_doc* __attribute__((__cleanup__(wrapYyjsonFree))) doc = yyjson_read_opts(content->chars, content->length, YYJSON_READ_ALLOW_COMMENTS | YYJSON_READ_ALLOW_TRAILING_COMMAS | YYJSON_READ_ALLOW_INF_AND_NAN, NULL, NULL); - if (!doc) - return "Failed to parse WT JSON config file"; - - yyjson_val* const root = yyjson_doc_get_root(doc); - assert(root); - - yyjson_val* profiles = yyjson_obj_get(root, "profiles"); - if (!profiles) - return "yyjson_obj_get(root, \"profiles\") failed"; - - FF_STRBUF_AUTO_DESTROY wtProfileId = ffStrbufCreateS(getenv("WT_PROFILE_ID")); - ffStrbufTrim(&wtProfileId, '\''); - if (wtProfileId.length > 0) - { - yyjson_val* list = yyjson_obj_get(profiles, "list"); - if (yyjson_is_arr(list)) - { - yyjson_val* profile; - size_t idx, max; - yyjson_arr_foreach(list, idx, max, profile) - { - yyjson_val* guid = yyjson_obj_get(profile, "guid"); - - if(ffStrbufEqualS(&wtProfileId, yyjson_get_str(guid))) - { - detectWTProfile(profile, name, size); - break; - } - } - } - } - - yyjson_val* defaults = yyjson_obj_get(profiles, "defaults"); - if (defaults) - detectWTProfile(defaults, name, size); - - if(name->length == 0) - ffStrbufSetS(name, "Cascadia Mono"); - if(*size < 0) - *size = 12; - return NULL; -} - -#ifdef _WIN32 - #include "common/io/io.h" - - #include -#endif - -static void detectFromWindowsTerminal(const FFstrbuf* terminalExe, FFTerminalFontResult* terminalFont) -{ - //https://learn.microsoft.com/en-us/windows/terminal/install#settings-json-file - FF_STRBUF_AUTO_DESTROY json = ffStrbufCreate(); - const char* error = NULL; - - #ifdef _WIN32 - if(terminalExe && terminalExe->length > 0 && !ffStrbufEqualS(terminalExe, "Windows Terminal")) - { - char jsonPath[MAX_PATH + 1]; - strncpy(jsonPath, terminalExe->chars, ffStrbufLastIndexC(terminalExe, '\\') + 1); - char* pathEnd = jsonPath + strlen(jsonPath); - strncpy(pathEnd, ".portable", sizeof(jsonPath) - (size_t) (pathEnd - jsonPath) - 1); - - if(ffPathExists(jsonPath, FF_PATHTYPE_ANY)) - { - strncpy(pathEnd, "settings\\settings.json", sizeof(jsonPath) - (size_t) (pathEnd - jsonPath) - 1); - if(!ffAppendFileBuffer(jsonPath, &json)) - error = "Error reading Windows Terminal portable settings JSON file"; - } - else if(SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, jsonPath))) - { - size_t remaining = sizeof(jsonPath) - strlen(jsonPath) - 1; - if(ffStrbufContainIgnCaseS(terminalExe, "_8wekyb3d8bbwe\\")) - { - // Microsoft Store version - if(ffStrbufContainIgnCaseS(terminalExe, ".WindowsTerminalPreview_")) - { - // Preview version - strncat(jsonPath, "\\Packages\\Microsoft.WindowsTerminalPreview_8wekyb3d8bbwe\\LocalState\\settings.json", remaining); - if(!ffAppendFileBuffer(jsonPath, &json)) - error = "Error reading Windows Terminal Preview settings JSON file"; - } - else - { - // Stable version - strncat(jsonPath, "\\Packages\\Microsoft.WindowsTerminal_8wekyb3d8bbwe\\LocalState\\settings.json", remaining); - if(!ffAppendFileBuffer(jsonPath, &json)) - error = "Error reading Windows Terminal settings JSON file"; - } - } - else - { - strncat(jsonPath, "\\Microsoft\\Windows Terminal\\settings.json", remaining); - if(!ffAppendFileBuffer(jsonPath, &json)) - error = "Error reading Windows Terminal settings JSON file"; - } - } - } - #else - FF_UNUSED(terminalExe); - #endif - - if(!error && json.length == 0) - { - 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); - return; - } - ffStrbufTrimRight(&json, '\n'); - if(json.length == 0) - { - ffStrbufAppendS(&terminalFont->error, "Cannot find file \"settings.json\""); - return; - } - - FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate(); - double size = -1; - error = detectFromWTImpl(&json, &name, &size); - - if(error) - ffStrbufAppendS(&terminalFont->error, error); - else - { - char sizeStr[16]; - snprintf(sizeStr, sizeof(sizeStr), "%g", size); - ffFontInitValues(&terminalFont->font, name.chars, sizeStr); - } -} - -#endif //defined(_WIN32) || defined(__linux__) - static bool queryKittyTerm(const char* query, FFstrbuf* res) { // https://github.com/fastfetch-cli/fastfetch/discussions/1030#discussioncomment-9845233 @@ -430,13 +243,6 @@ static bool detectTerminalFontCommon(const FFTerminalResult* terminal, FFTermina detectTTY(terminalFont); #endif - #if defined(_WIN32) || defined(__linux__) - //Used by both Linux (WSL) and Windows - else if(ffStrbufIgnCaseEqualS(&terminal->processName, "Windows Terminal") || - ffStrbufIgnCaseEqualS(&terminal->processName, "WindowsTerminal.exe")) - detectFromWindowsTerminal(&terminal->exe, terminalFont); - #endif - else return false; diff --git a/src/detection/terminalfont/terminalfont_windows.c b/src/detection/terminalfont/terminalfont_windows.c index 633781ad7..cf82da291 100644 --- a/src/detection/terminalfont/terminalfont_windows.c +++ b/src/detection/terminalfont/terminalfont_windows.c @@ -1,10 +1,184 @@ -#include "common/properties.h" +#include "common/library.h" #include "common/io/io.h" +#include "common/processing.h" +#include "common/properties.h" #include "detection/terminalshell/terminalshell.h" -#include "terminalfont.h" #include "util/windows/unicode.h" +#include "terminalfont.h" +#include #include +#include + +static const char* detectWTProfile(yyjson_val* profile, FFstrbuf* name, double* size) +{ + yyjson_val* font = yyjson_obj_get(profile, "font"); + if (!font) + return "yyjson_obj_get(profile, \"font\"); failed"; + + if (!yyjson_is_obj(font)) + return "yyjson_is_obj(font) returns false"; + + if (name->length == 0) + { + yyjson_val* pface = yyjson_obj_get(font, "face"); + if(yyjson_is_str(pface)) + ffStrbufAppendS(name, unsafe_yyjson_get_str(pface)); + } + + if (*size < 0) + { + yyjson_val* psize = yyjson_obj_get(font, "size"); + if (yyjson_is_num(psize)) + *size = yyjson_get_num(psize); + } + return NULL; +} + +static inline void wrapYyjsonFree(yyjson_doc** doc) +{ + assert(doc); + if (*doc) + yyjson_doc_free(*doc); +} + +static const char* detectFromWTImpl(FFstrbuf* content, FFstrbuf* name, double* size) +{ + yyjson_doc* __attribute__((__cleanup__(wrapYyjsonFree))) doc = yyjson_read_opts(content->chars, content->length, YYJSON_READ_ALLOW_COMMENTS | YYJSON_READ_ALLOW_TRAILING_COMMAS | YYJSON_READ_ALLOW_INF_AND_NAN, NULL, NULL); + if (!doc) + return "Failed to parse WT JSON config file"; + + yyjson_val* const root = yyjson_doc_get_root(doc); + assert(root); + + yyjson_val* profiles = yyjson_obj_get(root, "profiles"); + if (!profiles) + return "yyjson_obj_get(root, \"profiles\") failed"; + + FF_STRBUF_AUTO_DESTROY wtProfileId = ffStrbufCreateS(getenv("WT_PROFILE_ID")); + ffStrbufTrim(&wtProfileId, '\''); + if (wtProfileId.length > 0) + { + yyjson_val* list = yyjson_obj_get(profiles, "list"); + if (yyjson_is_arr(list)) + { + yyjson_val* profile; + size_t idx, max; + yyjson_arr_foreach(list, idx, max, profile) + { + yyjson_val* guid = yyjson_obj_get(profile, "guid"); + + if(ffStrbufEqualS(&wtProfileId, yyjson_get_str(guid))) + { + detectWTProfile(profile, name, size); + break; + } + } + } + } + + yyjson_val* defaults = yyjson_obj_get(profiles, "defaults"); + if (defaults) + detectWTProfile(defaults, name, size); + + if(name->length == 0) + ffStrbufSetS(name, "Cascadia Mono"); + if(*size < 0) + *size = 12; + return NULL; +} + +static void detectFromWindowsTerminal(const FFstrbuf* terminalExe, FFTerminalFontResult* terminalFont) +{ + //https://learn.microsoft.com/en-us/windows/terminal/install#settings-json-file + FF_STRBUF_AUTO_DESTROY json = ffStrbufCreate(); + const char* error = NULL; + + if(terminalExe && terminalExe->length > 0 && !ffStrbufEqualS(terminalExe, "Windows Terminal")) + { + char jsonPath[MAX_PATH + 1]; + strncpy(jsonPath, terminalExe->chars, ffStrbufLastIndexC(terminalExe, '\\') + 1); + char* pathEnd = jsonPath + strlen(jsonPath); + strncpy(pathEnd, ".portable", sizeof(jsonPath) - (size_t) (pathEnd - jsonPath) - 1); + + if(ffPathExists(jsonPath, FF_PATHTYPE_ANY)) + { + strncpy(pathEnd, "settings\\settings.json", sizeof(jsonPath) - (size_t) (pathEnd - jsonPath) - 1); + if(!ffAppendFileBuffer(jsonPath, &json)) + error = "Error reading Windows Terminal portable settings JSON file"; + } + else if(SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, jsonPath))) + { + size_t remaining = sizeof(jsonPath) - strlen(jsonPath) - 1; + if(ffStrbufContainIgnCaseS(terminalExe, "_8wekyb3d8bbwe\\")) + { + // Microsoft Store version + if(ffStrbufContainIgnCaseS(terminalExe, ".WindowsTerminalPreview_")) + { + // Preview version + strncat(jsonPath, "\\Packages\\Microsoft.WindowsTerminalPreview_8wekyb3d8bbwe\\LocalState\\settings.json", remaining); + if(!ffAppendFileBuffer(jsonPath, &json)) + error = "Error reading Windows Terminal Preview settings JSON file"; + } + else + { + // Stable version + strncat(jsonPath, "\\Packages\\Microsoft.WindowsTerminal_8wekyb3d8bbwe\\LocalState\\settings.json", remaining); + if(!ffAppendFileBuffer(jsonPath, &json)) + error = "Error reading Windows Terminal settings JSON file"; + } + } + else + { + strncat(jsonPath, "\\Microsoft\\Windows Terminal\\settings.json", remaining); + if(!ffAppendFileBuffer(jsonPath, &json)) + error = "Error reading Windows Terminal settings JSON file"; + } + } + } + + if(!error && json.length == 0) + { + 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); + return; + } + ffStrbufTrimRight(&json, '\n'); + if(json.length == 0) + { + ffStrbufAppendS(&terminalFont->error, "Cannot find file \"settings.json\""); + return; + } + + FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate(); + double size = -1; + error = detectFromWTImpl(&json, &name, &size); + + if(error) + ffStrbufAppendS(&terminalFont->error, error); + else + { + char sizeStr[16]; + snprintf(sizeStr, sizeof(sizeStr), "%g", size); + ffFontInitValues(&terminalFont->font, name.chars, sizeStr); + } +} static void detectMintty(FFTerminalFontResult* terminalFont) { @@ -87,7 +261,10 @@ static void detectConEmu(FFTerminalFontResult* terminalFont) void ffDetectTerminalFontPlatform(const FFTerminalResult* terminal, FFTerminalFontResult* terminalFont) { - if(ffStrbufIgnCaseEqualS(&terminal->processName, "mintty")) + if(ffStrbufIgnCaseEqualS(&terminal->processName, "Windows Terminal") || + ffStrbufIgnCaseEqualS(&terminal->processName, "WindowsTerminal.exe")) + detectFromWindowsTerminal(&terminal->exe, terminalFont); + else if(ffStrbufIgnCaseEqualS(&terminal->processName, "mintty")) detectMintty(terminalFont); else if(ffStrbufIgnCaseEqualS(&terminal->processName, "conhost.exe")) detectConhost(terminalFont);