diff --git a/CMakeLists.txt b/CMakeLists.txt index 91649c043e..1edbb9bc1c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,8 @@ project(fastfetch HOMEPAGE_URL "https://github.com/LinusDierheimer/fastfetch" ) +set(PROJECT_LICENSE "MIT license") + ################### # Target Platform # ################### @@ -578,6 +580,26 @@ target_link_libraries(flashfetch PRIVATE libfastfetch ) +if(WIN32) + if(PROJECT_VERSION_TWEAK) + string(REGEX MATCH "[0-9]+" PROJECT_VERSION_TWEAK_NUM "${PROJECT_VERSION_TWEAK}") + else() + set(PROJECT_VERSION_TWEAK_NUM "0") + endif() + + set(TARGET_NAME fastfetch) + configure_file(src/util/windows/version.rc.in version.fastfetch.rc) + target_sources(fastfetch + PRIVATE version.fastfetch.rc + ) + + set(TARGET_NAME flashfetch) + configure_file(src/util/windows/version.rc.in version.flashfetch.rc) + target_sources(flashfetch + PRIVATE version.flashfetch.rc + ) +endif() + ################### # Testing targets # ################### diff --git a/README.md b/README.md index 646e4277ea..6a5f0b7703 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Fastfetch -Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying them in a pretty way. It is written in pure c, with performance and customizability in mind. Currently Linux, Android, FreeBSD, MacOS and Windows are supported. +Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying them in a pretty way. It is written in pure c, with performance and customizability in mind. Currently Linux, Android, FreeBSD, MacOS and Windows 7+ are supported. @@ -61,6 +61,8 @@ The following libraries are used if present at runtime: * [`libvulkan`](https://www.vulkan.org/): Vulkan module. Usually has been provided by GPU drivers. * [`libOpenCL`](https://www.khronos.org/opencl/): OpenCL module +Note: On Windows 10-, [ConEmu](https://conemu.github.io/en/AnsiEscapeCodes.html) is required to run fastfetch due to [the lack of ASCII escape code native support](https://en.wikipedia.org/wiki/ANSI_escape_code#DOS,_OS/2,_and_Windows). Also make sure to [use `chcp 65001` to enable UTF-8 support](https://conemu.github.io/en/UnicodeSupport.html#utf-8) if you run Windows locale other than English. + ### Android * [`freetype`](https://www.freetype.org/): Used for Termux font detection. @@ -101,7 +103,7 @@ KDE Plasma, Gnome, Cinnamon, Mate, XFCE4, LXQt ##### Terminal fonts ``` -Konsole, Gnome Terminal, Tilix, XFCE4 Terminal, Alacritty, LXTerminal, iTerm2, Apple Terminal, TTY, Windows Terminal, Termux, mintty +Konsole, Gnome Terminal, Tilix, XFCE4 Terminal, Alacritty, LXTerminal, iTerm2, Apple Terminal, Warp, TTY, Windows Terminal, Termux, mintty, ConEmu ``` ## Building diff --git a/src/common/init.c b/src/common/init.c index 962bde9fee..e8dc449401 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -334,12 +334,9 @@ static void resetConsole() #ifdef _WIN32 BOOL WINAPI consoleHandler(DWORD signal) { - if(signal == CTRL_C_EVENT) - { + FF_UNUSED(signal); resetConsole(); - return TRUE; - } - return false; + exit(0); } #else static void exitSignalHandler(int signal) @@ -360,6 +357,11 @@ void ffStart(FFinstance* instance) #ifdef _WIN32 SetConsoleCtrlHandler(consoleHandler, TRUE); + HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + DWORD mode = 0; + GetConsoleMode(hStdout, &mode); + SetConsoleMode(hStdout, mode | ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING); + // SetConsoleOutputCP(CP_UTF8); #else struct sigaction action = { .sa_handler = exitSignalHandler }; sigaction(SIGINT, &action, NULL); diff --git a/src/common/networking_linux.c b/src/common/networking_linux.c index 5d656fddd7..7fb6fade55 100644 --- a/src/common/networking_linux.c +++ b/src/common/networking_linux.c @@ -67,7 +67,7 @@ bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, con #ifdef FF_HAVE_THREADS state->thread = ffThreadCreate(connectAndSendThreadMain, state); - return state->thread != NULL; + return !!state->thread; #else connectAndSend(state); return state->sockfd != -1; diff --git a/src/common/networking_windows.c b/src/common/networking_windows.c index dd32fac164..5814acc165 100644 --- a/src/common/networking_windows.c +++ b/src/common/networking_windows.c @@ -75,7 +75,7 @@ bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, con } } - FFstrbuf command; + FF_STRBUF_AUTO_DESTROY command; ffStrbufInitA(&command, 64); ffStrbufAppendS(&command, "GET "); ffStrbufAppendS(&command, path); @@ -87,7 +87,6 @@ bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, con BOOL result = ConnectEx(state->sockfd, addr->ai_addr, (int)addr->ai_addrlen, command.chars, command.length, NULL, &state->overlapped); freeaddrinfo(addr); - ffStrbufDestroy(&command); if(!result && WSAGetLastError() != WSA_IO_PENDING) { @@ -95,7 +94,6 @@ bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, con return false; } - ffStrbufDestroy(&command); return true; } diff --git a/src/common/processing_windows.c b/src/common/processing_windows.c index cd091ac6c3..30e5157343 100644 --- a/src/common/processing_windows.c +++ b/src/common/processing_windows.c @@ -27,27 +27,30 @@ const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[]) .hStdOutput = hChildStdoutWrite, }; - FFstrbuf cmdline; - ffStrbufInitF(&cmdline, "\"%s\"", argv[0]); - for(char* const* parg = &argv[1]; *parg; ++parg) - { - ffStrbufAppendC(&cmdline, ' '); - ffStrbufAppendS(&cmdline, *parg); - } + BOOL success; - BOOL success = CreateProcessA( - NULL, // application name - cmdline.chars, // command line - NULL, // process security attributes - NULL, // primary thread security attributes - TRUE, // handles are inherited - 0, // creation flags - NULL, // use parent's environment - NULL, // use parent's current directory - &siStartInfo, // STARTUPINFO pointer - &piProcInfo); // receives PROCESS_INFORMATION + { + FF_STRBUF_AUTO_DESTROY cmdline; + ffStrbufInitF(&cmdline, "\"%s\"", argv[0]); + for(char* const* parg = &argv[1]; *parg; ++parg) + { + ffStrbufAppendC(&cmdline, ' '); + ffStrbufAppendS(&cmdline, *parg); + } - ffStrbufDestroy(&cmdline); + success = CreateProcessA( + NULL, // application name + cmdline.chars, // command line + NULL, // process security attributes + NULL, // primary thread security attributes + TRUE, // handles are inherited + 0, // creation flags + NULL, // use parent's environment + NULL, // use parent's current directory + &siStartInfo, // STARTUPINFO pointer + &piProcInfo // receives PROCESS_INFORMATION + ); + } CloseHandle(hChildStdoutWrite); if(!success) diff --git a/src/common/thread.h b/src/common/thread.h index 74c536cf2b..c4d2230842 100644 --- a/src/common/thread.h +++ b/src/common/thread.h @@ -29,7 +29,7 @@ static inline void ffThreadMutexLock(FFThreadMutex* mutex) { pthread_mutex_lock(mutex); } static inline void ffThreadMutexUnlock(FFThreadMutex* mutex) { pthread_mutex_unlock(mutex); } static inline FFThreadType ffThreadCreate(void* (* func)(void*), void* data) { - FFThreadType newThread = NULL; + FFThreadType newThread = 0; pthread_create(&newThread, NULL, func, data); return newThread; } diff --git a/src/detection/battery/battery_apple.c b/src/detection/battery/battery_apple.c index 88499aaa70..7244a89a15 100644 --- a/src/detection/battery/battery_apple.c +++ b/src/detection/battery/battery_apple.c @@ -7,7 +7,7 @@ static double detectBatteryTemp() { - FFlist temps; + FF_LIST_AUTO_DESTROY temps; ffListInit(&temps, sizeof(FFTempValue)); ffDetectCoreTemps(FF_TEMP_BATTERY, &temps); @@ -25,7 +25,6 @@ static double detectBatteryTemp() ffStrbufDestroy(&tempValue->deviceClass); } result /= temps.length; - ffListDestroy(&temps); return result; } diff --git a/src/detection/cpu/cpu.c b/src/detection/cpu/cpu.c index 3a304606e5..3bfe92e872 100644 --- a/src/detection/cpu/cpu.c +++ b/src/detection/cpu/cpu.c @@ -31,7 +31,6 @@ static void detectCPU(const FFinstance* instance, FFCPUResult* cpu) return; const char* removeStrings[] = { - "(R)", "(r)", "(TM)", "(tm)", " CPU", " FPU", " APU", " Processor", " Dual-Core", " Quad-Core", " Six-Core", " Eight-Core", " Ten-Core", " 2-Core", " 4-Core", " 6-Core", " 8-Core", " 10-Core", " 12-Core", " 14-Core", " 16-Core", diff --git a/src/detection/cpu/cpu_apple.c b/src/detection/cpu/cpu_apple.c index dc0c1a3ebe..5f1b354948 100644 --- a/src/detection/cpu/cpu_apple.c +++ b/src/detection/cpu/cpu_apple.c @@ -15,7 +15,7 @@ static double getFrequency(const char* propName) static double detectCpuTemp(const FFstrbuf* cpuName) { - FFlist temps; + FF_LIST_AUTO_DESTROY temps; ffListInit(&temps, sizeof(FFTempValue)); if(ffStrbufStartsWithS(cpuName, "Apple M1")) @@ -38,7 +38,6 @@ static double detectCpuTemp(const FFstrbuf* cpuName) ffStrbufDestroy(&tempValue->deviceClass); } result /= temps.length; - ffListDestroy(&temps); return result; } diff --git a/src/detection/cpu/cpu_windows.cpp b/src/detection/cpu/cpu_windows.cpp index 8740fa4b96..e5939cd604 100644 --- a/src/detection/cpu/cpu_windows.cpp +++ b/src/detection/cpu/cpu_windows.cpp @@ -17,11 +17,21 @@ void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu, bool cached) ffStrbufInit(&cpu->name); ffStrbufInit(&cpu->vendor); - FFWmiQuery query(L"SELECT Name, Manufacturer, NumberOfCores, NumberOfLogicalProcessors, ThreadCount, CurrentClockSpeed, MaxClockSpeed FROM Win32_Processor WHERE ProcessorType = 3"); + FFWmiQuery query(L"SELECT Name, Manufacturer, NumberOfCores, NumberOfLogicalProcessors, NumberOfEnabledCore, CurrentClockSpeed, MaxClockSpeed FROM Win32_Processor WHERE ProcessorType = 3"); if(!query) return; - if(FFWmiRecord record = query.next()) + FFWmiRecord record = query.next(); + if(!record) + { + //NumberOfEnabledCore is not supported on Windows 10- + query = FFWmiQuery(L"SELECT Name, Manufacturer, NumberOfCores, NumberOfLogicalProcessors, CurrentClockSpeed, MaxClockSpeed FROM Win32_Processor WHERE ProcessorType = 3"); + if(!query) + return; + record = query.next(); + } + + if(record) { record.getString(L"Name", &cpu->name); record.getString(L"Manufacturer", &cpu->vendor); @@ -32,8 +42,7 @@ void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu, bool cached) cpu->coresPhysical = (uint16_t)value; record.getUnsigned(L"NumberOfLogicalProcessors", &value); cpu->coresLogical = (uint16_t)value; - record.getUnsigned(L"ThreadCount", &value); - cpu->coresOnline = (uint16_t)value; + cpu->coresOnline = record.getUnsigned(L"NumberOfEnabledCore", &value) ? (uint16_t)value : cpu->coresPhysical; record.getUnsigned(L"CurrentClockSpeed", &value); //There's no MinClockSpeed in Win32_Processor cpu->frequencyMin = (double)value / 1000.0; record.getUnsigned(L"MaxClockSpeed", &value); diff --git a/src/detection/cpuUsage/cpuUsage.c b/src/detection/cpuUsage/cpuUsage.c index 7470236dc3..82bf1f7d43 100644 --- a/src/detection/cpuUsage/cpuUsage.c +++ b/src/detection/cpuUsage/cpuUsage.c @@ -36,23 +36,30 @@ const char* ffGetCpuUsageResult(double* result) error = ffGetCpuUsageInfo(&inUseAll1, &totalAll1); if(error) return error; - ffTimeSleep(1000); + ffTimeSleep(250); } else { uint64_t duration = ffTimeGetTick() - startTime; - if(duration < 1000) - ffTimeSleep(1000 - (uint32_t) duration); + if(duration < 250) + ffTimeSleep(250 - (uint32_t) duration); } - uint64_t inUseAll2, totalAll2; - error = ffGetCpuUsageInfo(&inUseAll2, &totalAll2); - if(error) - return error; - - *result = (double)(inUseAll2 - inUseAll1) / (double)(totalAll2 - totalAll1) * 100; + while(true) + { + uint64_t inUseAll2, totalAll2; + error = ffGetCpuUsageInfo(&inUseAll2, &totalAll2); + if(error) + return error; - return NULL; + if(inUseAll2 != inUseAll1) + { + *result = (double)(inUseAll2 - inUseAll1) / (double)(totalAll2 - totalAll1) * 100; + return NULL; + } + else + ffTimeSleep(250); + } } #endif //FF_DETECTION_CPUUSAGE_NOWAIT diff --git a/src/detection/cpuUsage/cpuUsage_windows.c b/src/detection/cpuUsage/cpuUsage_windows.c index 1aa9ba3f64..bf4cc7644e 100644 --- a/src/detection/cpuUsage/cpuUsage_windows.c +++ b/src/detection/cpuUsage/cpuUsage_windows.c @@ -1,8 +1,7 @@ #include "fastfetch.h" #include "cpuUsage.h" -#define WIN32_LEAN_AND_MEAN 1 -#include +#include static inline uint64_t fileTimeToUint64(const FILETIME* ft) { return (((uint64_t)ft->dwHighDateTime) << 32) | ((uint64_t)ft->dwLowDateTime); @@ -11,10 +10,12 @@ static inline uint64_t fileTimeToUint64(const FILETIME* ft) { const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll) { FILETIME idleTime, kernelTime, userTime; - if(GetSystemTimes(&idleTime, &kernelTime, &userTime) == 0) + if(!GetSystemTimes(&idleTime, &kernelTime, &userTime)) return "GetSystemTimes() failed"; - *inUseAll = fileTimeToUint64(&userTime) + fileTimeToUint64(&kernelTime); - *totalAll = *inUseAll + fileTimeToUint64(&idleTime); + // https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getsystemtimes + // `kernelTime` also includes the amount of time the system has been idle. + *totalAll = fileTimeToUint64(&userTime) + fileTimeToUint64(&kernelTime); + *inUseAll = *totalAll - fileTimeToUint64(&idleTime); return NULL; } diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index 93dee0f7d3..8abfbdf20e 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -73,9 +73,15 @@ void ffDetectDisksImpl(FFDiskResult* disks) #endif //Detects stats - struct statvfs fs; - if(statvfs(disk->mountpoint.chars, &fs) != 0) - memset(&fs, 0, sizeof(struct statvfs)); //Set all values to 0, so our values get initialized to 0 too + #ifdef __USE_LARGEFILE64 + struct statvfs64 fs; + if(statvfs64(disk->mountpoint.chars, &fs) != 0) + memset(&fs, 0, sizeof(struct statvfs64)); //Set all values to 0, so our values get initialized to 0 too + #else + struct statvfs fs; + if(statvfs(disk->mountpoint.chars, &fs) != 0) + memset(&fs, 0, sizeof(struct statvfs)); //Set all values to 0, so our values get initialized to 0 too + #endif disk->bytesTotal = fs.f_blocks * fs.f_frsize; disk->bytesUsed = disk->bytesTotal - (fs.f_bavail * fs.f_frsize); diff --git a/src/detection/displayserver/displayserver_apple.c b/src/detection/displayserver/displayserver_apple.c index 80211fb38b..96bdf3d2ea 100644 --- a/src/detection/displayserver/displayserver_apple.c +++ b/src/detection/displayserver/displayserver_apple.c @@ -4,53 +4,31 @@ #include #include #include -#include - -//Resolution code heavily inspired by displayplacer <3 - -typedef union -{ - uint8_t rawData[0xDC]; - struct - { - uint32_t mode; - uint32_t flags; // 0x4 - uint32_t width; // 0x8 - uint32_t height; // 0xC - uint32_t depth; // 0x10 - uint32_t dc2[42]; - uint16_t dc3; - uint16_t freq; // 0xBC - uint32_t dc4[4]; - float density; // 0xD0 - } derived; -} modes_D4; - -void CGSGetCurrentDisplayMode(CGDirectDisplayID display, int* modeNum); -void CGSGetDisplayModeDescriptionOfLength(CGDirectDisplayID display, int idx, modes_D4* mode, int length); +#include +#include static void detectResolution(FFDisplayServerResult* ds) { - CGDisplayCount screenCount; - CGGetOnlineDisplayList(INT_MAX, NULL, &screenCount); - if(screenCount == 0) + CGDirectDisplayID screens[128]; + uint32_t screenCount; + if(CGGetOnlineDisplayList(sizeof(screens) / sizeof(screens[0]), screens, &screenCount) != kCGErrorSuccess) return; - CGDirectDisplayID* screens = malloc(screenCount * sizeof(CGDirectDisplayID)); - CGGetOnlineDisplayList(INT_MAX, screens, &screenCount); - for(uint32_t i = 0; i < screenCount; i++) { - int modeID; - CGSGetCurrentDisplayMode(screens[i], &modeID); - modes_D4 mode; - CGSGetDisplayModeDescriptionOfLength(screens[i], modeID, &mode, 0xD4); - - uint32_t refreshRate = ffdsParseRefreshRate(mode.derived.freq); - ffdsAppendResolution(ds, mode.derived.width, mode.derived.height, refreshRate); + CGDirectDisplayID screen = screens[i]; + CGDisplayModeRef mode = CGDisplayCopyDisplayMode(screen); + if(mode) + { + ffdsAppendResolution(ds, + (uint32_t)CGDisplayModeGetWidth(mode), + (uint32_t)CGDisplayModeGetHeight(mode), + (uint32_t)CGDisplayModeGetRefreshRate(mode) + ); + CGDisplayModeRelease(mode); + } + CGDisplayRelease(screen); } - - free(screens); } static void detectWM(FFDisplayServerResult* ds) diff --git a/src/detection/font/font.h b/src/detection/font/font.h index 63d19e2ee6..80bed7a395 100644 --- a/src/detection/font/font.h +++ b/src/detection/font/font.h @@ -12,10 +12,10 @@ typedef struct FFFontResult FFstrbuf error; /** - * Linux / BSD: QT, GTK2, GTK3, GTK4 - * MacOS: System, User, Monospace, Application - * Windows: Desktop, Unset, Unset, Unset - * Other: Unset, Unset, Unset, Unset + * Linux / BSD: QT, GTK2, GTK3, GTK4 + * MacOS: System, User, System Mono, User Mono + * Windows: Desktop, Unset, Unset, Unset + * Other: Unset, Unset, Unset, Unset */ FFstrbuf fonts[FF_DETECT_FONT_NUM_FONTS]; } FFFontResult; diff --git a/src/detection/font/font_apple.m b/src/detection/font/font_apple.m index 91689f6e93..773c7705b5 100644 --- a/src/detection/font/font_apple.m +++ b/src/detection/font/font_apple.m @@ -1,23 +1,14 @@ #include "common/font.h" #include "common/io.h" -#include "util/apple/cf_helpers.h" #include "font.h" -#import - -static void detectFontForType(CTFontUIFontType uiType, FFstrbuf* font) -{ - CTFontRef ctFont = CTFontCreateUIFontForLanguage(uiType, 12, NULL); - ffCfStrGetString(CTFontCopyFamilyName(ctFont), font); -} +#import void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result) { FF_UNUSED(instance); - ffSuppressIO(true); - detectFontForType(kCTFontUIFontSystem, &result->fonts[0]); - detectFontForType(kCTFontUIFontUser, &result->fonts[1]); - detectFontForType(kCTFontUIFontUserFixedPitch, &result->fonts[2]); - detectFontForType(kCTFontUIFontApplication, &result->fonts[3]); - ffSuppressIO(false); + ffStrbufAppendS(&result->fonts[0], [NSFont systemFontOfSize:12].familyName.UTF8String); + ffStrbufAppendS(&result->fonts[1], [NSFont userFontOfSize:12].familyName.UTF8String); + ffStrbufAppendS(&result->fonts[2], [NSFont monospacedSystemFontOfSize:12 weight:400].familyName.UTF8String); + ffStrbufAppendS(&result->fonts[3], [NSFont userFixedPitchFontOfSize:12].familyName.UTF8String); } diff --git a/src/detection/font/font_windows.cpp b/src/detection/font/font_windows.cpp index 3d883bd586..fd400fb715 100644 --- a/src/detection/font/font_windows.cpp +++ b/src/detection/font/font_windows.cpp @@ -18,7 +18,7 @@ void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result) if(FFWmiRecord record = query.next()) { - FFstrbuf fontName; + FF_STRBUF_AUTO_DESTROY fontName; ffStrbufInit(&fontName); record.getString(L"IconTitleFaceName", &fontName); @@ -26,8 +26,6 @@ void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result) record.getUnsigned(L"IconTitleSize", &fontSize); ffStrbufAppendF(&result->fonts[0], "%*s (%upt)", fontName.length, fontName.chars, (unsigned)fontSize); - - ffStrbufDestroy(&fontName); } else ffStrbufInitS(&result->error, "No WMI result returned"); diff --git a/src/detection/gpu/gpu_apple.c b/src/detection/gpu/gpu_apple.c index bad6747d3a..52292d83e8 100644 --- a/src/detection/gpu/gpu_apple.c +++ b/src/detection/gpu/gpu_apple.c @@ -8,7 +8,7 @@ static double detectGpuTemp(const FFstrbuf* gpuName) { - FFlist temps; + FF_LIST_AUTO_DESTROY temps; ffListInit(&temps, sizeof(FFTempValue)); if(ffStrbufStartsWithS(gpuName, "Apple M1")) @@ -35,7 +35,6 @@ static double detectGpuTemp(const FFstrbuf* gpuName) ffStrbufDestroy(&tempValue->deviceClass); } result /= temps.length; - ffListDestroy(&temps); return result; } diff --git a/src/detection/host/host.h b/src/detection/host/host.h index e66af41fb6..e49e8faadc 100644 --- a/src/detection/host/host.h +++ b/src/detection/host/host.h @@ -5,9 +5,6 @@ #include "fastfetch.h" -#define FF_HOST_PRODUCT_NAME_WSL "Windows Subsystem for Linux" -#define FF_HOST_PRODUCT_NAME_MSYS "Windows on MSYS" - typedef struct FFHostResult { FFstrbuf productFamily; diff --git a/src/detection/host/host_linux.c b/src/detection/host/host_linux.c index ef9cfbf5e3..4833131036 100644 --- a/src/detection/host/host_linux.c +++ b/src/detection/host/host_linux.c @@ -1,5 +1,6 @@ #include "host.h" #include "common/io.h" +#include "common/processing.h" #include @@ -94,6 +95,27 @@ void ffDetectHostImpl(FFHostResult* host) { //On WSL, the real host can't be detected. Instead use WSL as host. if(getenv("WSL_DISTRO") != NULL || getenv("WSL_INTEROP") != NULL) - ffStrbufAppendS(&host->productName, FF_HOST_PRODUCT_NAME_WSL); + { + ffStrbufAppendS(&host->productName, "Windows Subsystem for Linux"); + + FFstrbuf wslVer; //Wide charactors + ffStrbufInit(&wslVer); + if(!ffProcessAppendStdOut(&wslVer, (char* const[]){ + "wsl.exe", + "--version", + NULL + }) && wslVer.length > 0) + { + ffStrbufSubstrBeforeFirstC(&wslVer, '\r'); //CRLF + ffStrbufSubstrAfterLastC(&wslVer, ' '); + ffStrbufAppendS(&host->productName, " ("); + for(uint32_t i = 0; i < wslVer.length; ++i) { + if(wslVer.chars[i]) //don't append \0 + ffStrbufAppendC(&host->productName, wslVer.chars[i]); + } + ffStrbufAppendC(&host->productName, ')'); + } + ffStrbufDestroy(&wslVer); + } } } diff --git a/src/detection/host/host_windows.cpp b/src/detection/host/host_windows.cpp index 5d0333db85..cbdd440ad1 100644 --- a/src/detection/host/host_windows.cpp +++ b/src/detection/host/host_windows.cpp @@ -28,5 +28,5 @@ extern "C" void ffDetectHostImpl(FFHostResult* host) record.getString(L"Vendor", &host->sysVendor); } else - ffStrbufInitS(&host->error, "No Wmi result returned"); + ffStrbufAppendS(&host->error, "No Wmi result returned"); } diff --git a/src/detection/os/os_android.c b/src/detection/os/os_android.c index bb3b6c9daf..eb4bf97d55 100644 --- a/src/detection/os/os_android.c +++ b/src/detection/os/os_android.c @@ -5,14 +5,11 @@ void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance) { FF_UNUSED(instance); - ffStrbufInit(&os->name); - ffStrbufSetS(&os->name, "Android"); + ffStrbufInitS(&os->name, "Android"); - ffStrbufInit(&os->prettyName); - ffStrbufSetS(&os->prettyName, "Android"); + ffStrbufInitS(&os->prettyName, "Android"); - ffStrbufInit(&os->id); - ffStrbufSetS(&os->id, "android"); + ffStrbufInitS(&os->id, "android"); ffStrbufInit(&os->version); ffSettingsGetAndroidProperty("ro.build.version.release", &os->version); @@ -26,13 +23,11 @@ void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance) ffStrbufInit(&os->buildID); ffSettingsGetAndroidProperty("ro.build.id", &os->buildID); - ffStrbufInit(&os->systemName); - ffStrbufSetS(&os->systemName, instance->state.utsname.sysname); + ffStrbufInitS(&os->systemName, instance->state.utsname.sysname); - ffStrbufInit(&os->architecture); - ffStrbufSetS(&os->architecture, instance->state.utsname.machine); + ffStrbufInitS(&os->architecture, instance->state.utsname.machine); - ffStrbufInitA(&os->idLike, 0); - ffStrbufInitA(&os->variant, 0); - ffStrbufInitA(&os->variantID, 0); + ffStrbufInit(&os->idLike); + ffStrbufInit(&os->variant); + ffStrbufInit(&os->variantID); } diff --git a/src/detection/os/os_windows.cpp b/src/detection/os/os_windows.cpp index e28607c9c1..5bd9d11c53 100644 --- a/src/detection/os/os_windows.cpp +++ b/src/detection/os/os_windows.cpp @@ -26,6 +26,7 @@ void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance) if(FFWmiRecord record = query.next()) { record.getString(L"Caption", &os->variant); + ffStrbufTrimRight(&os->variant, ' '); if(ffStrbufStartsWithS(&os->variant, "Microsoft Windows ")) { ffStrbufAppendS(&os->name, "Microsoft Windows"); diff --git a/src/detection/packages/packages_apple.c b/src/detection/packages/packages_apple.c index 3966240fdc..e1323e1e55 100644 --- a/src/detection/packages/packages_apple.c +++ b/src/detection/packages/packages_apple.c @@ -27,7 +27,7 @@ static uint32_t getNumElements(const char* dirname, unsigned char type) static uint32_t countBrewPackages(const char* dirname) { - FFstrbuf baseDir; + FF_STRBUF_AUTO_DESTROY baseDir; ffStrbufInitS(&baseDir, dirname); uint32_t result = 0; @@ -41,7 +41,6 @@ static uint32_t countBrewPackages(const char* dirname) result += getNumElements(baseDir.chars, DT_DIR); ffStrbufSubstrBefore(&baseDir, baseDirLength); - ffStrbufDestroy(&baseDir); return result; } @@ -59,14 +58,11 @@ static uint32_t getBrewPackages() static uint32_t countMacPortsPackages(const char* dirname) { - FFstrbuf baseDir; + FF_STRBUF_AUTO_DESTROY baseDir; ffStrbufInitS(&baseDir, dirname); ffStrbufAppendS(&baseDir, "/var/macports/software"); - uint32_t result = getNumElements(baseDir.chars, DT_DIR); - - ffStrbufDestroy(&baseDir); - return result; + return getNumElements(baseDir.chars, DT_DIR); } static uint32_t getMacPortsPackages() diff --git a/src/detection/temps/temps_apple.c b/src/detection/temps/temps_apple.c index 015546ecf0..9daee1c917 100644 --- a/src/detection/temps/temps_apple.c +++ b/src/detection/temps/temps_apple.c @@ -104,12 +104,11 @@ static uint32_t smcStrtoul(const char *str, int size, int base) static void smcUltostr(char *str, uint32_t val) { - str[0] = '\0'; - sprintf(str, "%c%c%c%c", - (unsigned int)val >> 24, - (unsigned int)val >> 16, - (unsigned int)val >> 8, - (unsigned int)val); + str[0] = (char)(val >> 24); + str[1] = (char)(val >> 16); + str[2] = (char)(val >> 8); + str[3] = (char)val; + str[4] = '\0'; } static const char *smcCall(io_connect_t conn, uint32_t selector, SmcKeyData_t *inputStructure, SmcKeyData_t *outputStructure) diff --git a/src/detection/terminalfont/terminalfont_android.c b/src/detection/terminalfont/terminalfont_android.c index 8dd1ff2fe3..eaa4fa52d8 100644 --- a/src/detection/terminalfont/terminalfont_android.c +++ b/src/detection/terminalfont/terminalfont_android.c @@ -31,7 +31,7 @@ const char* detectTermux(const FFinstance* instance, FFTerminalFontResult* termi goto exit; } - if(ffFT_New_Face(library, FF_TERMUX_FONT_PATH, 0, &face )) + if(ffFT_New_Face(library, FF_TERMUX_FONT_PATH, 0, &face)) { error = "FT_NEW_Face(" FF_TERMUX_FONT_PATH ") failed"; goto exit; @@ -49,7 +49,7 @@ const char* detectTermux(const FFinstance* instance, FFTerminalFontResult* termi #else FF_UNUSED(terminalFont); - ffStrbufSetS(&terminalFont->error, "fastfetch is built without freetype2 support"); + return "fastfetch is built without freetype2 support"; #endif } diff --git a/src/detection/terminalfont/terminalfont_apple.m b/src/detection/terminalfont/terminalfont_apple.m index fb8c2769b3..1ee387aa27 100644 --- a/src/detection/terminalfont/terminalfont_apple.m +++ b/src/detection/terminalfont/terminalfont_apple.m @@ -22,7 +22,7 @@ static void detectIterm2(const FFinstance* instance, FFTerminalFontResult* termi error:&error]; if(error) { - ffStrbufAppendS(&terminalFont->error, [error localizedDescription].UTF8String); + ffStrbufAppendS(&terminalFont->error, error.localizedDescription.UTF8String); return; } @@ -46,25 +46,42 @@ static void detectIterm2(const FFinstance* instance, FFTerminalFontResult* termi static void detectAppleTerminal(FFTerminalFontResult* terminalFont) { - FFstrbuf fontName; - ffStrbufInit(&fontName); - ffOsascript("tell application \"Terminal\" to font name of window frontmost", &fontName); + FF_STRBUF_AUTO_DESTROY font; + ffStrbufInit(&font); + ffOsascript("tell application \"Terminal\" to font name of window frontmost & \" \" & font size of window frontmost", &font); - if(fontName.length == 0) + if(font.length == 0) { ffStrbufAppendS(&terminalFont->error, "executing osascript failed"); - ffStrbufDestroy(&fontName); return; } - FFstrbuf fontSize; - ffStrbufInit(&fontSize); - ffOsascript("tell application \"Terminal\" to font size of window frontmost", &fontSize); + ffFontInitWithSpace(&terminalFont->font, font.chars); +} + +static void detectWarpTerminal(const FFinstance* instance, FFTerminalFontResult* terminalFont) +{ + NSError* error; + NSString* fileName = [NSString stringWithFormat:@"file://%s/Library/Preferences/dev.warp.Warp-Stable.plist", instance->state.passwd->pw_dir]; + NSDictionary* dict = [NSDictionary dictionaryWithContentsOfURL:[NSURL URLWithString:fileName] + error:&error]; + if(error) + { + ffStrbufAppendS(&terminalFont->error, error.localizedDescription.UTF8String); + return; + } + + NSString* fontName = [dict valueForKey:@"FontName"]; + if(!fontName) + fontName = @"Hack"; + else + fontName = [fontName stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"\""]]; - ffFontInitValues(&terminalFont->font, fontName.chars, fontSize.chars); + NSString* fontSize = [dict valueForKey:@"FontSize"]; + if(!fontSize) + fontSize = @"13"; - ffStrbufDestroy(&fontName); - ffStrbufDestroy(&fontSize); + ffFontInitValues(&terminalFont->font, fontName.UTF8String, fontSize.UTF8String); } void ffDetectTerminalFontPlatform(const FFinstance* instance, const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont) @@ -73,4 +90,6 @@ void ffDetectTerminalFontPlatform(const FFinstance* instance, const FFTerminalSh detectIterm2(instance, terminalFont); else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "Apple_Terminal") == 0) detectAppleTerminal(terminalFont); + else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "WarpTerminal") == 0) + detectWarpTerminal(instance, terminalFont); } diff --git a/src/detection/terminalfont/terminalfont_windows.c b/src/detection/terminalfont/terminalfont_windows.c index 6a68bb6a5f..e6ea456be2 100644 --- a/src/detection/terminalfont/terminalfont_windows.c +++ b/src/detection/terminalfont/terminalfont_windows.c @@ -1,4 +1,5 @@ #include "common/properties.h" +#include "common/io.h" #include "detection/terminalshell/terminalshell.h" #include "terminalfont.h" @@ -7,10 +8,10 @@ static void detectMintty(const FFinstance* instance, FFTerminalFontResult* terminalFont) { - FFstrbuf fontName; + FF_STRBUF_AUTO_DESTROY fontName; ffStrbufInit(&fontName); - FFstrbuf fontSize; + FF_STRBUF_AUTO_DESTROY fontSize; ffStrbufInit(&fontSize); ffParsePropFileHomeValues(instance, ".minttyrc", 2, (FFpropquery[]) { @@ -23,9 +24,12 @@ static void detectMintty(const FFinstance* instance, FFTerminalFontResult* termi ffStrbufAppendC(&fontSize, '9'); ffFontInitValues(&terminalFont->font, fontName.chars, fontSize.chars); +} - ffStrbufDestroy(&fontName); - ffStrbufDestroy(&fontSize); +static inline void wrapRegCloseKey(HKEY* phKey) +{ + if(*phKey) + RegCloseKey(*phKey); } static void detectConhost(const FFinstance* instance, FFTerminalFontResult* terminalFont) @@ -34,7 +38,7 @@ static void detectConhost(const FFinstance* instance, FFTerminalFontResult* term //Current font of conhost doesn't seem to be detectable, we detect default font instead - HKEY hKey; + HKEY __attribute__((__cleanup__(wrapRegCloseKey))) hKey = NULL; if(RegOpenKeyExW(HKEY_CURRENT_USER, L"Console", 0, KEY_READ, &hKey) != ERROR_SUCCESS) { ffStrbufAppendS(&terminalFont->error, "RegOpenKeyExW() failed"); @@ -43,34 +47,78 @@ static void detectConhost(const FFinstance* instance, FFTerminalFontResult* term DWORD bufSize; - wchar_t fontNameW[64]; - bufSize = sizeof(fontNameW); - if(RegQueryValueExW(hKey, L"FaceName", NULL, NULL, (LPBYTE)fontNameW, &bufSize) != ERROR_SUCCESS) + char fontName[128]; + bufSize = sizeof(fontName); + if(RegGetValueA(hKey, NULL, "FaceName", RRF_RT_REG_SZ, NULL, fontName, &bufSize) != ERROR_SUCCESS) { - ffStrbufAppendS(&terminalFont->error, "RegOpenKeyExW(FaceName) failed"); - goto exit; + ffStrbufAppendS(&terminalFont->error, "RegGetValueA(FaceName) failed"); + return; } - 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) + if(RegGetValueW(hKey, NULL, L"FontSize", RRF_RT_DWORD, NULL, &fontSizeNum, &bufSize) != ERROR_SUCCESS) { - ffStrbufAppendS(&terminalFont->error, "RegOpenKeyExW(fontSize) failed"); - goto exit; + ffStrbufAppendS(&terminalFont->error, "RegGetValueW(FontSize) failed"); + return; } char fontSize[16]; - snprintf(fontSize, sizeof(fontSize), "%u", (fontSizeNum >> 16)); + _ultoa((unsigned long)(fontSizeNum >> 16), fontSize, 10); + + ffFontInitValues(&terminalFont->font, fontName, fontSize); +} + +static void detectConEmu(const FFinstance* instance, FFTerminalFontResult* terminalFont) +{ + FF_UNUSED(instance) + + //https://conemu.github.io/en/ConEmuXml.html#search-sequence + FFstrbuf path; + ffStrbufInit(&path); + + FFstrbuf fontName; + ffStrbufInit(&fontName); + + FFstrbuf fontSize; + ffStrbufInit(&fontSize); + + const char* paths[] = { "ConEmuDir", "ConEmuBaseDir", "APPDATA" }; + for (uint32_t i = 0; i < sizeof(paths) / sizeof(paths[0]); ++i) + { + ffStrbufSetS(&path, getenv(paths[i])); + if(path.length > 0) + { + ffStrbufAppendS(&path, "/ConEmu.xml"); + if(ffParsePropFileValues(path.chars, 2, (FFpropquery[]){ + {"error, "Failed to parse ConEmu.xml"); + return; + } + + if(fontName.length > 0) + ffStrbufSubstrBeforeLastC(&fontName, '"'); + else + ffStrbufAppendS(&fontName, "Consola"); - ffFontInitValues(&terminalFont->font, fontNameA, fontSize); + if(fontSize.length > 0) + ffStrbufSubstrBeforeLastC(&fontSize, '"'); + else + ffStrbufAppendS(&fontSize, "14"); -exit: - RegCloseKey(hKey); + ffFontInitValues(&terminalFont->font, fontName.chars, fontSize.chars); + + ffStrbufDestroy(&fontName); + ffStrbufDestroy(&fontSize); } void ffDetectTerminalFontPlatform(const FFinstance* instance, const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont) @@ -79,4 +127,6 @@ void ffDetectTerminalFontPlatform(const FFinstance* instance, const FFTerminalSh detectMintty(instance, terminalFont); else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "conhost.exe") == 0) detectConhost(instance, terminalFont); + else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalProcessName, "ConEmuC")) + detectConEmu(instance, terminalFont); } diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index 57867fdb60..2c3e7319de 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -1,5 +1,4 @@ #include "fastfetch.h" -#include "detection/host/host.h" #include "common/io.h" #include "common/parsing.h" #include "common/processing.h" @@ -180,10 +179,17 @@ static void getTerminalFromEnv(FFTerminalShellResult* result) if( result->terminalProcessName.length > 0 && !ffStrbufStartsWithIgnCaseS(&result->terminalProcessName, "login") && - ffStrbufIgnCaseCompS(&result->terminalProcessName, "(login)") != 0 && - ffStrbufIgnCaseCompS(&result->terminalProcessName, "systemd") != 0 && - ffStrbufIgnCaseCompS(&result->terminalProcessName, "init") != 0 && - ffStrbufIgnCaseCompS(&result->terminalProcessName, "(init)") != 0 && + !ffStrbufIgnCaseEqualS(&result->terminalProcessName, "(login)") && + + #ifdef __APPLE__ + !ffStrbufIgnCaseEqualS(&result->terminalProcessName, "launchd") && + !ffStrbufIgnCaseEqualS(&result->terminalProcessName, "stable") && //for WarpTerminal + #else + !ffStrbufIgnCaseEqualS(&result->terminalProcessName, "systemd") && + !ffStrbufIgnCaseEqualS(&result->terminalProcessName, "init") && + !ffStrbufIgnCaseEqualS(&result->terminalProcessName, "(init)") && + #endif + ffStrbufIgnCaseCompS(&result->terminalProcessName, "0") != 0 ) return; @@ -193,11 +199,13 @@ static void getTerminalFromEnv(FFTerminalShellResult* result) if(getenv("SSH_CONNECTION") != NULL) term = getenv("SSH_TTY"); + #ifdef __linux__ //Windows Terminal if(!ffStrSet(term) && ( getenv("WT_SESSION") != NULL || getenv("WT_PROFILE_ID") != NULL )) term = "Windows Terminal"; + #endif //Alacritty if(!ffStrSet(term) && ( @@ -230,10 +238,8 @@ static void getTerminalFromEnv(FFTerminalShellResult* result) if(!ffStrSet(term)) { //We are in WSL but not in Windows Terminal - const FFHostResult* host = ffDetectHost(); - if(ffStrbufCompS(&host->productName, FF_HOST_PRODUCT_NAME_WSL) == 0 || - ffStrbufCompS(&host->productName, FF_HOST_PRODUCT_NAME_MSYS) == 0) //TODO better WSL or MSYS detection - term = "conhost"; + if(getenv("WSL_DISTRO") != NULL || getenv("WSL_INTEROP") != NULL) + term = "conhost"; } #endif @@ -365,6 +371,8 @@ const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance) ffStrbufInitS(&result.terminalPrettyName, "iTerm"); else if(ffStrbufEqualS(&result.terminalProcessName, "Apple_Terminal")) ffStrbufInitS(&result.terminalPrettyName, "Apple Terminal"); + else if(ffStrbufEqualS(&result.terminalProcessName, "WarpTerminal")) + ffStrbufInitS(&result.terminalPrettyName, "Warp"); else if(strncmp(result.terminalExeName, result.terminalProcessName.chars, result.terminalProcessName.length) == 0) // if exeName starts with processName, print it. Otherwise print processName ffStrbufInitS(&result.terminalPrettyName, result.terminalExeName); else diff --git a/src/detection/terminalshell/terminalshell_windows.cpp b/src/detection/terminalshell/terminalshell_windows.cpp index 770e043eb5..6f0139a2ee 100644 --- a/src/detection/terminalshell/terminalshell_windows.cpp +++ b/src/detection/terminalshell/terminalshell_windows.cpp @@ -189,6 +189,8 @@ static uint32_t getTerminalInfo(FFTerminalShellResult* result, uint32_t pid) ffStrbufSetS(&result->terminalPrettyName, "Visual Studio Code"); else if(ffStrbufIgnCaseEqualS(&result->terminalPrettyName, "explorer")) ffStrbufSetS(&result->terminalPrettyName, "Windows Explorer"); + else if(ffStrbufStartsWithIgnCaseS(&result->terminalPrettyName, "ConEmuC")) + ffStrbufSetS(&result->terminalPrettyName, "ConEmu"); return ppid; } diff --git a/src/detection/wmtheme/wmtheme_windows.c b/src/detection/wmtheme/wmtheme_windows.c index 7611f05dae..00303300d4 100644 --- a/src/detection/wmtheme/wmtheme_windows.c +++ b/src/detection/wmtheme/wmtheme_windows.c @@ -4,38 +4,67 @@ #define WIN32_LEAN_AND_MEAN 1 #include +static inline void wrapRegCloseKey(HKEY* phKey) +{ + if(*phKey) + RegCloseKey(*phKey); +} + bool ffDetectWmTheme(FFinstance* instance, FFstrbuf* themeOrError) { FF_UNUSED(instance); - HKEY hKey; - if(RegOpenKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", 0, KEY_READ, &hKey) != ERROR_SUCCESS) + HKEY __attribute__((__cleanup__(wrapRegCloseKey))) hKey = NULL; + if(RegOpenKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", 0, KEY_READ, &hKey) == ERROR_SUCCESS) { - ffStrbufAppendS(themeOrError, "RegOpenKeyExW() failed"); - return false; - } + int SystemUsesLightTheme = 1; + DWORD bufSize = sizeof(SystemUsesLightTheme); - bool result = true; - int SystemUsesLightTheme = 1; - DWORD bufSize = sizeof(SystemUsesLightTheme); + if(RegGetValueW(hKey, NULL, L"SystemUsesLightTheme", RRF_RT_DWORD, NULL, &SystemUsesLightTheme, &bufSize) != ERROR_SUCCESS) + { + ffStrbufAppendS(themeOrError, "RegGetValueW(SystemUsesLightTheme) failed"); + return false; + } - if(RegQueryValueExW(hKey, L"SystemUsesLightTheme", NULL, NULL, (LPBYTE)&SystemUsesLightTheme, &bufSize) != ERROR_SUCCESS) - { - ffStrbufAppendS(themeOrError, "RegOpenKeyExW(SystemUsesLightTheme) failed"); - goto exit; - } + int AppsUsesLightTheme = 1; + bufSize = sizeof(AppsUsesLightTheme); + if(RegGetValueW(hKey, NULL, L"AppsUseLightTheme", RRF_RT_DWORD, NULL, &AppsUsesLightTheme, &bufSize) != ERROR_SUCCESS) + { + ffStrbufAppendS(themeOrError, "RegGetValueW(AppsUseLightTheme) failed"); + return false; + } - int AppsUsesLightTheme = 1; - bufSize = sizeof(AppsUsesLightTheme); - if(RegQueryValueExW(hKey, L"AppsUseLightTheme", NULL, NULL, (LPBYTE)&AppsUsesLightTheme, &bufSize) != ERROR_SUCCESS) - { - ffStrbufAppendS(themeOrError, "RegOpenKeyExW(AppsUseLightTheme) failed"); - goto exit; + ffStrbufAppendF(themeOrError, "System - %s, Apps - %s", SystemUsesLightTheme ? "Light" : "Dark", AppsUsesLightTheme ? "Light" : "Dark"); + + return true; } + else if(RegOpenKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes", 0, KEY_READ, &hKey) == ERROR_SUCCESS) + { + DWORD length = 0; + if(RegGetValueA(hKey, NULL, "CurrentTheme", RRF_RT_REG_SZ, NULL, NULL, &length) != ERROR_SUCCESS) + { + ffStrbufAppendS(themeOrError, "RegGetValueA(CurrentTheme, NULL) failed"); + return false; + } - ffStrbufAppendF(themeOrError, "System - %s, Apps - %s", SystemUsesLightTheme ? "Light" : "Dark", AppsUsesLightTheme ? "Light" : "Dark"); + ffStrbufEnsureFree(themeOrError, length); + if(RegGetValueA(hKey, NULL, "CurrentTheme", RRF_RT_REG_SZ, NULL, themeOrError->chars, &length) != ERROR_SUCCESS) + { + ffStrbufAppendS(themeOrError, "RegGetValueA(CurrentTheme) failed"); + return false; + } -exit: - RegCloseKey(hKey); - return result; + themeOrError->length = length; + ffStrbufSubstrBeforeLastC(themeOrError, '.'); + ffStrbufSubstrAfterLastC(themeOrError, '\\'); + if (isalpha(themeOrError->chars[0])) + themeOrError->chars[0] = (char)toupper(themeOrError->chars[0]); + + return true; + } + else + { + ffStrbufAppendS(themeOrError, "Failed to find current theme"); + return false; + } } diff --git a/src/modules/gpu.c b/src/modules/gpu.c index 11507191a4..905fd9774a 100644 --- a/src/modules/gpu.c +++ b/src/modules/gpu.c @@ -44,12 +44,6 @@ void ffPrintGPU(FFinstance* instance) if(ffPrintFromCache(instance, FF_GPU_MODULE_NAME, &instance->config.gpu, FF_GPU_NUM_FORMAT_ARGS)) return; - if(ffStrbufCompS(&ffDetectHost()->productName, FF_HOST_PRODUCT_NAME_WSL) == 0) - { - ffPrintError(instance, FF_GPU_MODULE_NAME, 0, &instance->config.gpu, "WSL doesn't expose senseful GPU names"); - return; - } - const FFlist* gpus = ffDetectGPU(instance); if(gpus->length == 0) diff --git a/src/util/FFlist.h b/src/util/FFlist.h index d9d5167922..fd7a0f5ca6 100644 --- a/src/util/FFlist.h +++ b/src/util/FFlist.h @@ -45,4 +45,8 @@ static inline void ffListSort(FFlist* list, int(*compar)(const void*, const void qsort(list->data, list->length, list->elementSize, compar); } +#if defined(_WIN32) || defined(__APPLE__) + #define FF_LIST_AUTO_DESTROY FFlist __attribute__((__cleanup__(ffListDestroy))) +#endif + #endif diff --git a/src/util/FFstrbuf.h b/src/util/FFstrbuf.h index 736e1d26da..80503e55d3 100644 --- a/src/util/FFstrbuf.h +++ b/src/util/FFstrbuf.h @@ -301,4 +301,9 @@ static inline FF_C_NODISCARD bool ffStrbufEndsWithIgnCase(const FFstrbuf* strbuf { return ffStrbufEndsWithIgnCaseNS(strbuf, end->length, end->chars); } + +#if defined(_WIN32) || defined(__APPLE__) + #define FF_STRBUF_AUTO_DESTROY FFstrbuf __attribute__((__cleanup__(ffStrbufDestroy))) +#endif + #endif diff --git a/src/util/apple/osascript.m b/src/util/apple/osascript.m index 363a50d12d..8b01ba0697 100644 --- a/src/util/apple/osascript.m +++ b/src/util/apple/osascript.m @@ -4,14 +4,14 @@ #import #import -bool ffOsascript(const char* input, FFstrbuf* result) { - NSString* appleScript = [NSString stringWithUTF8String: input]; - NSAppleScript* script = [[NSAppleScript alloc] initWithSource:appleScript]; +bool ffOsascript(const char* input, FFstrbuf* result) +{ + NSAppleScript* script = [NSAppleScript.alloc initWithSource:@(input)]; NSDictionary* errInfo = nil; NSAppleEventDescriptor* descriptor = [script executeAndReturnError:&errInfo]; if (errInfo) return false; - ffStrbufSetS(result, [[descriptor stringValue] cStringUsingEncoding:NSUTF8StringEncoding]); + ffStrbufSetS(result, descriptor.stringValue.UTF8String); return true; } diff --git a/src/util/windows/utsname.c b/src/util/windows/utsname.c index 07f6e52e81..a1f68021df 100644 --- a/src/util/windows/utsname.c +++ b/src/util/windows/utsname.c @@ -27,20 +27,22 @@ static int detectVersion(struct utsname *name) DWORD bufSize; - DWORD currentMajorVersionNumber; - bufSize = sizeof(currentMajorVersionNumber); - if(RegGetValueA(hKey, NULL, "CurrentMajorVersionNumber", RRF_RT_REG_DWORD, NULL, ¤tMajorVersionNumber, &bufSize) != ERROR_SUCCESS) - { - RegCloseKey(hKey); - return 1; - } + char currentVersion[32]; - DWORD currentMinorVersionNumber; - bufSize = sizeof(currentMinorVersionNumber); - if(RegGetValueA(hKey, NULL, "CurrentMinorVersionNumber", RRF_RT_REG_DWORD, NULL, ¤tMinorVersionNumber, &bufSize) != ERROR_SUCCESS) { - RegCloseKey(hKey); - return 1; + DWORD currentMajorVersionNumber; + DWORD currentMinorVersionNumber; + bufSize = sizeof(currentMajorVersionNumber); + if(RegGetValueW(hKey, NULL, L"CurrentMajorVersionNumber", RRF_RT_REG_DWORD, NULL, ¤tMajorVersionNumber, &bufSize) == ERROR_SUCCESS && + RegGetValueW(hKey, NULL, L"CurrentMinorVersionNumber", RRF_RT_REG_DWORD, NULL, ¤tMinorVersionNumber, &bufSize) == ERROR_SUCCESS + ) + snprintf(currentVersion, sizeof(currentVersion), "%u.%u", (unsigned)currentMajorVersionNumber, (unsigned)currentMinorVersionNumber); + else + { + bufSize = sizeof(currentVersion); + if(RegGetValueA(hKey, NULL, "CurrentVersion", RRF_RT_REG_SZ, NULL, currentVersion, &bufSize) != ERROR_SUCCESS) + strcpy(currentVersion, "0.0"); + } } char currentBuildNumber[32]; @@ -53,7 +55,7 @@ static int detectVersion(struct utsname *name) if(RegGetValueA(hKey, NULL, "UBR", RRF_RT_REG_DWORD, NULL, &ubr, &bufSize) != ERROR_SUCCESS || bufSize != sizeof(ubr)) ubr = 0; - snprintf(name->release, sizeof(name->release), "%u.%u.%s.%u", (unsigned)currentMajorVersionNumber, (unsigned)currentMinorVersionNumber, currentBuildNumber, (unsigned)ubr); + snprintf(name->release, sizeof(name->release), "%s.%s.%u", currentVersion, currentBuildNumber, (unsigned)ubr); bufSize = sizeof(name->version); RegGetValueA(hKey, NULL, "DisplayVersion", RRF_RT_REG_SZ, NULL, name->version, &bufSize); diff --git a/src/util/windows/version.rc.in b/src/util/windows/version.rc.in new file mode 100644 index 0000000000..3e1833eec4 --- /dev/null +++ b/src/util/windows/version.rc.in @@ -0,0 +1,47 @@ +// +// Include the necessary resources +// +#include +#include + +#ifdef RC_INVOKED + +// +// Set up debug information +// +#if DEBUG +#define VER_DEBUG VS_FF_DEBUG +#else +#define VER_DEBUG 0 +#endif + +// ------- version info ------------------------------------------------------- + +VS_VERSION_INFO VERSIONINFO +FILEVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,@PROJECT_VERSION_TWEAK_NUM@ +PRODUCTVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,@PROJECT_VERSION_TWEAK_NUM@ +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +FILEFLAGS (VER_DEBUG|VS_FF_PRERELEASE) +FILEOS VOS_NT +FILETYPE VFT_APP +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "@PROJECT_HOMEPAGE_URL@" + VALUE "FileDescription", "@PROJECT_DESCRIPTION@" + VALUE "FileVersion", "@PROJECT_VERSION@@PROJECT_VERSION_TWEAK@" + VALUE "InternalName", "@TARGET_NAME@.exe" + VALUE "LegalCopyright", "@PROJECT_LICENSE@" + VALUE "OriginalFilename", "@TARGET_NAME@.exe" + VALUE "ProductName", "@PROJECT_NAME@" + VALUE "ProductVersion", "@PROJECT_VERSION@@PROJECT_VERSION_TWEAK@" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409,1252 + END +END +#endif diff --git a/src/util/windows/wmi.cpp b/src/util/windows/wmi.cpp index 6a273f86a4..cba0c07c55 100644 --- a/src/util/windows/wmi.cpp +++ b/src/util/windows/wmi.cpp @@ -128,7 +128,7 @@ FFWmiQuery::FFWmiQuery(const wchar_t* queryStr, FFstrbuf* error) if (InitOnceExecuteOnce(&s_InitOnce, &InitHandleFunction, nullptr, (void**)&context) == FALSE) { if(error) - ffStrbufInitS(error, context); + ffStrbufAppendS(error, context); return; } diff --git a/src/util/windows/wmi.hpp b/src/util/windows/wmi.hpp index 7b27c75904..6f7d214cb9 100644 --- a/src/util/windows/wmi.hpp +++ b/src/util/windows/wmi.hpp @@ -23,12 +23,15 @@ struct FFWmiRecord if(!ok) obj = nullptr; } FFWmiRecord(const FFWmiRecord&) = delete; - FFWmiRecord(FFWmiRecord&& other) { + FFWmiRecord(FFWmiRecord&& other) { *this = (FFWmiRecord&&)other; } + ~FFWmiRecord() { if(obj) obj->Release(); } + explicit operator bool() { return !!obj; } + FFWmiRecord& operator =(FFWmiRecord&& other) { + if(obj) obj->Release(); obj = other.obj; other.obj = nullptr; + return *this; } - ~FFWmiRecord() { if(obj) obj->Release(); } - explicit operator bool() { return !!obj; } bool getString(const wchar_t* key, FFstrbuf* strbuf); bool getSigned(const wchar_t* key, int64_t* integer); @@ -43,13 +46,16 @@ struct FFWmiQuery FFWmiQuery(const wchar_t* queryStr, FFstrbuf* error = nullptr); explicit FFWmiQuery(IEnumWbemClassObject* pEnumerator): pEnumerator(pEnumerator) {} FFWmiQuery(const FFWmiQuery& other) = delete; - FFWmiQuery(FFWmiQuery&& other) { - pEnumerator = other.pEnumerator; - other.pEnumerator = nullptr; - } + FFWmiQuery(FFWmiQuery&& other) { *this = (FFWmiQuery&&)other; } ~FFWmiQuery() { if(pEnumerator) pEnumerator->Release(); } explicit operator bool() { return !!pEnumerator; } + FFWmiQuery& operator =(FFWmiQuery&& other) { + if(pEnumerator) pEnumerator->Release(); + pEnumerator = other.pEnumerator; + other.pEnumerator = nullptr; + return *this; + } FFWmiRecord next() { FFWmiRecord result(pEnumerator);