diff --git a/CHANGELOG.md b/CHANGELOG.md index 17c8047707..c81d8040bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,28 @@ +# 1.11.1 + +Features: +* Support xonsh detection (TerminalShell) +* Support Tabby version / terminal font detection (TerminalFont) + +Bugfixes: +* Fix name of Pro Controller (Gamepad, Windows) +* Fix compile error with imagemagick enabled (Windows) +* Fix copy-and-paste errors (Gamepad) +* Flatpak: Fix user package count +* Flatpak: Count runtime packages too (#441) +* Fix flatpak package count (#441) +* Don't print white color blocks with `--pipe` (#450) +* Fix iTerm being detected as iTermServer-* sometimes +* Fix sound device volume being incorrectly detected as muted sometimes (Sound) +* Fix memleaks reported by LeakSanitizer (Linux) +* Fix potential memory curruption bug in unicode.c (Windows) + +Logo: +* Update Windows 11 ASCII logo to look more visually consistent (#445) +* Add another font color index to arch icon (#446) +* Add SteamOS +* Add macOS small / small2 + # 1.11.0 Features: diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a115a63dd..6107b17b63 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url project(fastfetch - VERSION 1.11.0 + VERSION 1.11.1 LANGUAGES C DESCRIPTION "Fast system information tool" HOMEPAGE_URL "https://github.com/LinusDierheimer/fastfetch" @@ -73,7 +73,6 @@ cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR BSD" OFF) cmake_dependent_option(ENABLE_LIBCJSON "Enable libcjson" ON "LINUX OR WIN32" OFF) cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND" OFF) cmake_dependent_option(ENABLE_BUFFER "Enable stdout buffer" ON "LINUX OR APPLE OR BSD OR WIN32 OR ANDROID" OFF) -cmake_dependent_option(USE_WIN_NTAPI "Allow using internal NTAPI" ON "WIN32" OFF) option(BUILD_TESTS "Build tests" OFF) # Also create test executables option(SET_TWEAK "Add tweak to project version" ON) # This is set to off by github actions for release builds @@ -248,6 +247,7 @@ set(LIBFASTFETCH_SRC src/detection/host/host.c src/detection/locale/locale.c src/detection/media/media.c + src/detection/opencl/opencl.c src/detection/os/os.c src/detection/packages/packages.c src/detection/terminalfont/terminalfont.c @@ -296,6 +296,7 @@ set(LIBFASTFETCH_SRC src/modules/separator.c src/modules/shell.c src/modules/sound.c + src/modules/swap.c src/modules/media.c src/modules/terminal.c src/modules/terminalfont.c @@ -518,11 +519,11 @@ elseif(WIN32) src/detection/os/os_windows.cpp src/detection/packages/packages_windows.c src/detection/poweradapter/poweradapter_nosupport.c - src/detection/processes/processes_windows.cpp + src/detection/processes/processes_windows.c src/detection/sound/sound_windows.cpp - src/detection/swap/swap_windows.cpp + src/detection/swap/swap_windows.c src/detection/terminalfont/terminalfont_windows.c - src/detection/terminalshell/terminalshell_windows.cpp + src/detection/terminalshell/terminalshell_windows.c src/detection/temps/temps_windows.cpp src/detection/uptime/uptime_windows.c src/detection/users/users_windows.c @@ -710,6 +711,7 @@ if(APPLE) PRIVATE "-framework IOKit" PRIVATE "-framework OpenGL" PRIVATE "-framework OpenCL" + PRIVATE "-framework SystemConfiguration" PRIVATE "-weak_framework CoreDisplay" PRIVATE "-weak_framework DisplayServices -F /System/Library/PrivateFrameworks" PRIVATE "-weak_framework MediaRemote -F /System/Library/PrivateFrameworks" @@ -732,9 +734,6 @@ elseif(WIN32) PRIVATE "wtsapi32" PRIVATE "powrprof" ) - if(USE_WIN_NTAPI) - target_compile_definitions(libfastfetch PRIVATE FF_USE_WIN_NTAPI) - endif() endif() target_include_directories(libfastfetch diff --git a/README.md b/README.md index 9e79b14d05..ad5b335834 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ Battery, Bios, Bluetooth, Board, Break, Brightness, Colors, Command, CPU, CPUUsa ##### Builtin logos ``` -AlmaLinux, Alpine, Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, CRUX, Crystal, Debian, Deepin, Devuan, Endeavour, Enso, Fedora, FreeBSD, Garuda, Gentoo, KDE Neon, KISS, Kubuntu, LangitKetujuh, Linux, MacOS, Manjaro, Mint, MSYS2, NixOS, Nobara, OpenSUSE, OpenSUSE LEAP, OpenSUSE Tumbleweed, Parabola, Pop!_OS, Raspbian, RebornOS, RedstarOS, Rocky, Rosa, Slackware, Solus, Ubuntu, Vanilla, Void, Windows, Windows 11, Windows 8, Zorin +AlmaLinux, Alpine, Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, CRUX, Crystal, Debian, Deepin, Devuan, Endeavour, Enso, Fedora, FreeBSD, Garuda, Gentoo, KDE Neon, KISS, Kubuntu, LangitKetujuh, Linux, MacOS, Manjaro, Mint, MSYS2, NixOS, Nobara, OpenSUSE, OpenSUSE LEAP, OpenSUSE Tumbleweed, Parabola, Pop!_OS, Raspbian, RebornOS, RedstarOS, Rocky, Rosa, Slackware, Solus, SteamOS, Ubuntu, Vanilla, Void, Windows, Windows 11, Windows 8, Zorin ``` ##### Package managers @@ -114,7 +114,7 @@ Budgie, Cinnamon, Gnome, KDE Plasma, LXQt, Mate, XFCE4 ##### Terminal fonts ``` -Alacritty, Apple Terminal, ConEmu, Deepin Terminal, foot, Gnome Terminal, iTerm2, Kitty, Konsole, LXTerminal, mintty, Terminator, Termux, Tilix, TTY, Warp, WezTerm, Windows Terminal, XFCE4 Terminal +Alacritty, Apple Terminal, ConEmu, Deepin Terminal, foot, Gnome Terminal, iTerm2, Kitty, Konsole, LXTerminal, mintty, Tabby, Terminator, Termux, Tilix, TTY, Warp, WezTerm, Windows Terminal, XFCE4 Terminal ``` ## Building diff --git a/src/common/parsing.h b/src/common/parsing.h index 613e20bb5f..4f8a29c041 100644 --- a/src/common/parsing.h +++ b/src/common/parsing.h @@ -3,6 +3,8 @@ #ifndef FF_INCLUDED_parsing_h #define FF_INCLUDED_parsing_h +#include "fastfetch.h" + #include typedef struct FFVersion diff --git a/src/common/properties.c b/src/common/properties.c index 2e32465174..48b797599c 100644 --- a/src/common/properties.c +++ b/src/common/properties.c @@ -166,10 +166,10 @@ bool ffParsePropFileListValues(const FFlist* list, const char* relativeFile, uin FFstrbuf baseDir; ffStrbufInitA(&baseDir, 64); - for(uint32_t i = 0; i < list->length; i++) + FF_LIST_FOR_EACH(FFstrbuf, dirPrefix, *list) { //We need to copy the dir each time, because it used by multiple threads, so we can't directly write to it. - ffStrbufSet(&baseDir, ffListGet(list, i)); + ffStrbufSet(&baseDir, dirPrefix); ffStrbufAppendS(&baseDir, relativeFile); if(ffParsePropFileValues(baseDir.chars, numQueries, queries)) diff --git a/src/common/settings.c b/src/common/settings.c index 2805573588..8e05c3958e 100644 --- a/src/common/settings.c +++ b/src/common/settings.c @@ -57,23 +57,31 @@ typedef enum FFInitState typedef struct GVariantGetters { - FF_LIBRARY_SYMBOL(g_variant_get_string) + FF_LIBRARY_SYMBOL(g_variant_dup_string) FF_LIBRARY_SYMBOL(g_variant_get_boolean) FF_LIBRARY_SYMBOL(g_variant_get_int32) + FF_LIBRARY_SYMBOL(g_variant_unref) } GVariantGetters; static FFvariant getGVariantValue(GVariant* variant, FFvarianttype type, const GVariantGetters* variantGetters) { + FFvariant result; + if(variant == NULL) - return FF_VARIANT_NULL; + result = FF_VARIANT_NULL; else if(type == FF_VARIANT_TYPE_STRING) - return (FFvariant) {.strValue = variantGetters->ffg_variant_get_string(variant, NULL)}; + result = (FFvariant) {.strValue = variantGetters->ffg_variant_dup_string(variant, NULL)}; // Dup string, so that variant itself can be freed else if(type == FF_VARIANT_TYPE_BOOL) - return (FFvariant) {.boolValue = (bool) variantGetters->ffg_variant_get_boolean(variant), .boolValueSet = true}; + result = (FFvariant) {.boolValue = (bool) variantGetters->ffg_variant_get_boolean(variant), .boolValueSet = true}; else if(type == FF_VARIANT_TYPE_INT) - return (FFvariant) {.intValue = variantGetters->ffg_variant_get_int32(variant)}; + result = (FFvariant) {.intValue = variantGetters->ffg_variant_get_int32(variant)}; else - return FF_VARIANT_NULL; + result = FF_VARIANT_NULL; + + if(variant) + variantGetters->ffg_variant_unref(variant); + + return result; } typedef struct GSettingsData @@ -102,9 +110,10 @@ static const GSettingsData* getGSettingsData(const FFinstance* instance) FF_LIBRARY_DATA_LOAD_SYMBOL(g_settings_schema_source_get_default) #define data data.variantGetters - FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_get_string) + FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_dup_string) FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_get_boolean) FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_get_int32) + FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_unref); #undef data data.schemaSource = data.ffg_settings_schema_source_get_default(); @@ -169,7 +178,7 @@ static const DConfData* getDConfData(const FFinstance* instance) FF_LIBRARY_DATA_LOAD_SYMBOL(dconf_client_new) #define data data.variantGetters - FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_get_string) + FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_dup_string) FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_get_boolean) FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_get_int32) #undef data diff --git a/src/detection/battery/battery_windows.c b/src/detection/battery/battery_windows.c index af7afe8923..fc89a335ad 100644 --- a/src/detection/battery/battery_windows.c +++ b/src/detection/battery/battery_windows.c @@ -9,18 +9,15 @@ #include #include -#ifdef FF_USE_WIN_NTAPI - NTSYSCALLAPI - NTSTATUS - NTAPI - NtPowerInformation( - IN POWER_INFORMATION_LEVEL InformationLevel, - IN PVOID InputBuffer OPTIONAL, - IN ULONG InputBufferLength, - OUT PVOID OutputBuffer OPTIONAL, - IN ULONG OutputBufferLength); - #define CallNtPowerInformation NtPowerInformation -#endif +NTSYSCALLAPI +NTSTATUS +NTAPI +NtPowerInformation( + IN POWER_INFORMATION_LEVEL InformationLevel, + IN PVOID InputBuffer OPTIONAL, + IN ULONG InputBufferLength, + OUT PVOID OutputBuffer OPTIONAL, + IN ULONG OutputBufferLength); static inline void wrapCloseHandle(HANDLE* handle) { @@ -147,7 +144,7 @@ const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results) else { SYSTEM_BATTERY_STATE info; - if (NT_SUCCESS(CallNtPowerInformation(SystemBatteryState, NULL, 0, &info, sizeof(info))) && info.BatteryPresent) + if (NT_SUCCESS(NtPowerInformation(SystemBatteryState, NULL, 0, &info, sizeof(info))) && info.BatteryPresent) { BatteryResult* battery = (BatteryResult*)ffListAdd(results); ffStrbufInit(&battery->modelName); diff --git a/src/detection/cpuUsage/cpuUsage_windows.c b/src/detection/cpuUsage/cpuUsage_windows.c index d4ffbd2caa..60ebef4be9 100644 --- a/src/detection/cpuUsage/cpuUsage_windows.c +++ b/src/detection/cpuUsage/cpuUsage_windows.c @@ -1,8 +1,6 @@ #include "fastfetch.h" #include "cpuUsage.h" -#ifdef FF_USE_WIN_NTAPI - #include "util/mallocHelper.h" #include @@ -37,26 +35,3 @@ const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll) return NULL; } - -#else - -#include - -static inline uint64_t fileTimeToUint64(const FILETIME* ft) { - return (((uint64_t)ft->dwHighDateTime) << 32) | ((uint64_t)ft->dwLowDateTime); -} - -const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll) -{ - FILETIME idleTime, kernelTime, userTime; - if(!GetSystemTimes(&idleTime, &kernelTime, &userTime)) - return "GetSystemTimes() failed"; - - // 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; -} - -#endif diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index 7e6a1bc0b9..94b4c34883 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -25,9 +25,6 @@ static bool isPhysicalDevice(FFstrbuf* device) if(!S_ISBLK(deviceStat.st_mode)) return false; - //Ignore all devices that are not physical devices - - //DrvFs is a filesystem plugin to WSL that was designed to support interop between WSL and the Windows filesystem. if(ffStrbufEqualS(device, "drvfs")) return true; diff --git a/src/detection/disk/disk_windows.c b/src/detection/disk/disk_windows.c index 5f9cf82e6e..c5c881b574 100644 --- a/src/detection/disk/disk_windows.c +++ b/src/detection/disk/disk_windows.c @@ -1,35 +1,31 @@ #include "disk.h" +#include "util/windows/unicode.h" #include +#include void ffDetectDisksImpl(FFDiskResult* disks) { - uint32_t length = GetLogicalDriveStringsA(0, NULL); - if(length == 0) - { - ffStrbufAppendS(&disks->error, "GetLogicalDriveStringsA failed"); - return; - } - - char* buf = malloc(length + 1); - GetLogicalDriveStringsA(length, buf); + wchar_t buf[MAX_PATH + 1]; + uint32_t length = GetLogicalDriveStringsW(sizeof(buf) / sizeof(*buf), buf); + assert(length < sizeof(buf) / sizeof(*buf)); for(uint32_t i = 0; i < length; i++) { - const char* mountpoint = buf + i; + const wchar_t* mountpoint = buf + i; - UINT driveType = GetDriveTypeA(mountpoint); + UINT driveType = GetDriveTypeW(mountpoint); if(driveType == DRIVE_NO_ROOT_DIR) { - i += (uint32_t)strlen(mountpoint); + i += (uint32_t)wcslen(mountpoint); continue; } FFDisk* disk = ffListAdd(&disks->disks); - ffStrbufInitS(&disk->mountpoint, mountpoint); + ffStrbufInitWS(&disk->mountpoint, mountpoint); uint64_t bytesFree; - if(!GetDiskFreeSpaceExA(mountpoint, NULL, (PULARGE_INTEGER)&disk->bytesTotal, (PULARGE_INTEGER)&bytesFree)) + if(!GetDiskFreeSpaceExW(mountpoint, NULL, (PULARGE_INTEGER)&disk->bytesTotal, (PULARGE_INTEGER)&bytesFree)) { disk->bytesTotal = 0; bytesFree = 0; @@ -43,20 +39,27 @@ void ffDetectDisksImpl(FFDiskResult* disks) else disk->type = FF_DISK_TYPE_HIDDEN; - ffStrbufInitA(&disk->filesystem, MAX_PATH + 1); - ffStrbufInitA(&disk->name, MAX_PATH + 1); + ffStrbufInit(&disk->filesystem); + ffStrbufInit(&disk->name); + wchar_t diskName[MAX_PATH + 1], diskFileSystem[MAX_PATH + 1]; + //https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getvolumeinformationa#remarks UINT errorMode = SetErrorMode(SEM_FAILCRITICALERRORS); - GetVolumeInformationA(mountpoint, - disk->name.chars, disk->name.allocated, //Volume name + + BOOL result = GetVolumeInformationW(mountpoint, + diskName, sizeof(diskName) / sizeof(*diskName), //Volume name NULL, //Serial number NULL, //Max component length NULL, //File system flags - disk->filesystem.chars, disk->filesystem.allocated + diskFileSystem, sizeof(diskFileSystem) / sizeof(*diskFileSystem) ); SetErrorMode(errorMode); - ffStrbufRecalculateLength(&disk->name); - ffStrbufRecalculateLength(&disk->filesystem); + + if(result) + { + ffStrbufSetWS(&disk->filesystem, diskFileSystem); + ffStrbufSetWS(&disk->name, diskName); + } //TODO: implement disk->filesUsed = 0; @@ -64,6 +67,4 @@ void ffDetectDisksImpl(FFDiskResult* disks) i += disk->mountpoint.length; } - - free(buf); } diff --git a/src/detection/displayserver/displayserver_apple.c b/src/detection/displayserver/displayserver_apple.c index b3b8e78b40..ab8c224ac6 100644 --- a/src/detection/displayserver/displayserver_apple.c +++ b/src/detection/displayserver/displayserver_apple.c @@ -1,6 +1,7 @@ #include "displayserver.h" #include "common/sysctl.h" #include "util/apple/cf_helpers.h" +#include "util/mallocHelper.h" #include #include @@ -73,7 +74,7 @@ static void detectWMPlugin(FFstrbuf* name) u_int requestLength = sizeof(request) / sizeof(*request); size_t length = 0; - struct kinfo_proc* processes = ffSysctlGetData(request, requestLength, &length); + FF_AUTO_FREE struct kinfo_proc* processes = ffSysctlGetData(request, requestLength, &length); if(processes == NULL) return; @@ -94,8 +95,6 @@ static void detectWMPlugin(FFstrbuf* name) name->chars[0] = (char) toupper(name->chars[0]); break; } - - free(processes); } void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* instance) diff --git a/src/detection/displayserver/displayserver_windows.c b/src/detection/displayserver/displayserver_windows.c index 9c9f27984a..5d93746f5c 100644 --- a/src/detection/displayserver/displayserver_windows.c +++ b/src/detection/displayserver/displayserver_windows.c @@ -5,27 +5,6 @@ #include #include -typedef struct -{ - WCHAR* deviceName; - uint32_t width; - uint32_t height; -} DataBundle; - - -static CALLBACK WINBOOL enumMonitorProc(HMONITOR hMonitor, FF_MAYBE_UNUSED HDC hDC, FF_MAYBE_UNUSED LPRECT rc, LPARAM lparam) -{ - DataBundle* data = (DataBundle*) lparam; - MONITORINFOEXW mi = { .cbSize = sizeof(mi) }; - if(GetMonitorInfoW(hMonitor, (MONITORINFO *)&mi) && wcscmp(mi.szDevice, data->deviceName) == 0) - { - data->width = (uint32_t) (mi.rcMonitor.right - mi.rcMonitor.left); - data->height = (uint32_t) (mi.rcMonitor.bottom - mi.rcMonitor.top); - return FALSE; - } - return TRUE; -} - static void detectDisplays(FFDisplayServerResult* ds, bool detectName) { DISPLAYCONFIG_PATH_INFO paths[128]; @@ -45,8 +24,6 @@ static void detectDisplays(FFDisplayServerResult* ds, bool detectName) { DISPLAYCONFIG_PATH_INFO* path = &paths[i]; - DataBundle data = {}; - DISPLAYCONFIG_SOURCE_DEVICE_NAME sourceName = { .header = { .type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME, @@ -55,10 +32,14 @@ static void detectDisplays(FFDisplayServerResult* ds, bool detectName) .id = path->sourceInfo.id, }, }; + + uint32_t scaledWidth = 0, scaledHeight = 0; if (DisplayConfigGetDeviceInfo(&sourceName.header) == ERROR_SUCCESS) { - data.deviceName = sourceName.viewGdiDeviceName; - EnumDisplayMonitors(NULL, NULL, enumMonitorProc, (LPARAM) &data); + HDC hdc = CreateICW(sourceName.viewGdiDeviceName, NULL, NULL, NULL); + scaledWidth = (uint32_t) GetDeviceCaps(hdc, HORZRES); + scaledHeight = (uint32_t) GetDeviceCaps(hdc, VERTRES); + DeleteDC(hdc); } FF_STRBUF_AUTO_DESTROY name; @@ -101,8 +82,8 @@ static void detectDisplays(FFDisplayServerResult* ds, bool detectName) width, height, path->targetInfo.refreshRate.Numerator / (double) path->targetInfo.refreshRate.Denominator, - data.width, - data.height, + scaledWidth, + scaledHeight, &name, path->targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL || path->targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED || diff --git a/src/detection/displayserver/linux/xcb.c b/src/detection/displayserver/linux/xcb.c index 89fc1ae002..447c76bb27 100644 --- a/src/detection/displayserver/linux/xcb.c +++ b/src/detection/displayserver/linux/xcb.c @@ -175,7 +175,7 @@ typedef struct XcbRandrData static bool xcbRandrHandleModeInfo(XcbRandrData* data, xcb_randr_mode_info_t* modeInfo) { - double refreshRate = modeInfo->dot_clock / (double) (modeInfo->htotal * modeInfo->vtotal); + double refreshRate = (double) modeInfo->dot_clock / (double) (modeInfo->htotal * modeInfo->vtotal); return ffdsAppendDisplay( data->result, diff --git a/src/detection/displayserver/linux/xlib.c b/src/detection/displayserver/linux/xlib.c index f1dcbeabcd..13a08b2a5e 100644 --- a/src/detection/displayserver/linux/xlib.c +++ b/src/detection/displayserver/linux/xlib.c @@ -134,7 +134,7 @@ typedef struct XrandrData static bool xrandrHandleModeInfo(XrandrData* data, XRRModeInfo* modeInfo) { - double refreshRate = modeInfo->dotClock / (double) (modeInfo->hTotal * modeInfo->vTotal); + double refreshRate = (double) modeInfo->dotClock / (double) (modeInfo->hTotal * modeInfo->vTotal); return ffdsAppendDisplay( data->result, diff --git a/src/detection/font/font.c b/src/detection/font/font.c index 253e46242a..865c830d1a 100644 --- a/src/detection/font/font.c +++ b/src/detection/font/font.c @@ -9,6 +9,7 @@ static void detectFont(const FFinstance* instance, FFFontResult* font) for(uint32_t i = 0; i < FF_DETECT_FONT_NUM_FONTS; ++i) ffStrbufInit(&font->fonts[i]); + ffStrbufInit(&font->display); ffDetectFontImpl(instance, font); diff --git a/src/detection/font/font.h b/src/detection/font/font.h index 822815d2a9..5922375bba 100644 --- a/src/detection/font/font.h +++ b/src/detection/font/font.h @@ -18,6 +18,7 @@ typedef struct FFFontResult * Other: Unset, Unset, Unset, Unset */ FFstrbuf fonts[FF_DETECT_FONT_NUM_FONTS]; + FFstrbuf display; } FFFontResult; const FFFontResult* ffDetectFont(const FFinstance* instance); diff --git a/src/detection/font/font_apple.m b/src/detection/font/font_apple.m index 6f26803b02..471fad4307 100644 --- a/src/detection/font/font_apple.m +++ b/src/detection/font/font_apple.m @@ -4,6 +4,23 @@ #import +static void generateString(FFFontResult* font) +{ + if(font->fonts[0].length > 0) + { + ffStrbufAppend(&font->display, &font->fonts[0]); + ffStrbufAppendS(&font->display, " [System]"); + if(font->fonts[1].length > 0) + ffStrbufAppendS(&font->display, ", "); + } + + if(font->fonts[1].length > 0) + { + ffStrbufAppend(&font->display, &font->fonts[1]); + ffStrbufAppendS(&font->display, " [User]"); + } +} + void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result) { FF_UNUSED(instance); @@ -11,4 +28,5 @@ void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result) 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); + generateString(result); } diff --git a/src/detection/font/font_linux.c b/src/detection/font/font_linux.c index 1e51116f34..3e5fc5a9fb 100644 --- a/src/detection/font/font_linux.c +++ b/src/detection/font/font_linux.c @@ -1,8 +1,23 @@ #include "common/font.h" +#include "common/parsing.h" #include "detection/displayserver/displayserver.h" #include "detection/gtk_qt/gtk_qt.h" #include "font.h" +static void generateString(FFFontResult* font) +{ + ffParseGTK(&font->display, &font->fonts[1], &font->fonts[2], &font->fonts[3]); + + if(font->fonts[0].length > 0) + { + if(font->display.length > 0) + ffStrbufAppendS(&font->display, ", "); + + ffStrbufAppend(&font->display, &font->fonts[0]); + ffStrbufAppendS(&font->display, " [QT]"); + } +} + void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result) { const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance); @@ -32,4 +47,6 @@ void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result) ffFontInitPango(>k4, ffDetectGTK4(instance)->font.chars); ffStrbufAppend(&result->fonts[3], >k4.pretty); ffFontDestroy(>k4); + + generateString(result); } diff --git a/src/detection/font/font_windows.c b/src/detection/font/font_windows.c index 6427353297..6a31b07eb4 100644 --- a/src/detection/font/font_windows.c +++ b/src/detection/font/font_windows.c @@ -3,6 +3,26 @@ #include +static void generateString(FFFontResult* font) +{ + const char* types[] = { "Caption", "Menu", "Message", "Status" }; + for(uint32_t i = 0; i < sizeof(types) / sizeof(types[0]); ++i) + { + if(i == 0 || !ffStrbufEqual(&font->fonts[i - 1], &font->fonts[i])) + { + if(i > 0) + ffStrbufAppendS(&font->display, "], "); + ffStrbufAppendF(&font->display, "%s [%s", font->fonts[i].chars, types[i]); + } + else + { + ffStrbufAppendS(&font->display, " / "); + ffStrbufAppendS(&font->display, types[i]); + } + } + ffStrbufAppendC(&font->display, ']'); +} + void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result) { FF_UNUSED(instance); @@ -19,4 +39,6 @@ void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result) if(fonts[i]->lfHeight < 0) ffStrbufAppendF(&result->fonts[i], " (%dpt)", (int)-fonts[i]->lfHeight); } + + generateString(result); } diff --git a/src/detection/gamepad/gamepad_windows.c b/src/detection/gamepad/gamepad_windows.c index 63a6399902..216bde8e8a 100644 --- a/src/detection/gamepad/gamepad_windows.c +++ b/src/detection/gamepad/gamepad_windows.c @@ -17,7 +17,7 @@ static const char* detectKnownGamepad(uint32_t vendorId, uint32_t productId) { case 0x2006: return "Nintendo Switch Joycon L"; case 0x2007: return "Nintendo Switch Joycon R"; - case 0x2009: return "Nintendo Switch Pro"; + case 0x2009: return "Nintendo Switch Pro Controller"; case 0x200E: return "Nintendo Switch Charging Grip"; case 0x2017: return "Nintendo Switch SNES Controller"; @@ -117,8 +117,7 @@ const char* ffDetectGamepad(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* continue; FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices); - ffStrbufInit(&device->identifier); - ffStrbufSetWS(&device->identifier, devName); + ffStrbufInitWS(&device->identifier, devName); ffStrbufInit(&device->name); const char* knownGamepad = detectKnownGamepad(rdi.hid.dwVendorId, rdi.hid.dwProductId); diff --git a/src/detection/gpu/gpu.h b/src/detection/gpu/gpu.h index 17f34e68d9..1d34958bf4 100644 --- a/src/detection/gpu/gpu.h +++ b/src/detection/gpu/gpu.h @@ -37,6 +37,7 @@ typedef struct FFGPUResult int coreCount; FFGPUMemory dedicated; FFGPUMemory shared; + uint32_t vulkanDeviceId; // Only used for vulkan } FFGPUResult; const FFlist* ffDetectGPU(const FFinstance* instance); diff --git a/src/detection/gpu/gpu_windows.c b/src/detection/gpu/gpu_windows.c index fb0535b727..671328a1c1 100644 --- a/src/detection/gpu/gpu_windows.c +++ b/src/detection/gpu/gpu_windows.c @@ -20,15 +20,13 @@ const char* ffDetectGPUImpl(FFlist* gpus, FF_MAYBE_UNUSED const FFinstance* inst FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); ffStrbufInit(&gpu->vendor); - ffStrbufInit(&gpu->name); + ffStrbufInitWS(&gpu->name, displayDevice.DeviceString); ffStrbufInit(&gpu->driver); gpu->temperature = FF_GPU_TEMP_UNSET; gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->type = FF_GPU_TYPE_UNKNOWN; gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; - ffStrbufSetWS(&gpu->name, displayDevice.DeviceString); - if (deviceKeyLength == 100 && displayDevice.DeviceKey[deviceKeyPrefixLength - 1] == '{') { wmemcpy(regKey + regKeyPrefixLength, displayDevice.DeviceKey + deviceKeyPrefixLength, 100 - regKeyPrefixLength + 1); diff --git a/src/detection/localip/localip_linux.c b/src/detection/localip/localip_linux.c index b38958b19a..56a93190a9 100644 --- a/src/detection/localip/localip_linux.c +++ b/src/detection/localip/localip_linux.c @@ -2,14 +2,10 @@ #include #include +#include #include #include #include -#include - -#ifdef __FreeBSD__ - #include // FreeBSD needs this for AF_INET -#endif static void addNewIp(FFlist* list, const char* name, const char* addr, bool ipv6) { @@ -31,7 +27,7 @@ const char* ffDetectLocalIps(const FFinstance* instance, FFlist* results) continue; // loop back - if (strncmp(ifa->ifa_name, "lo", 2) == 0 && (ifa->ifa_name[2] == '\0' || isdigit(ifa->ifa_name[2])) && !instance->config.localIpShowLoop) + if ((ifa->ifa_flags & IFF_LOOPBACK) && !instance->config.localIpShowLoop) continue; if (instance->config.localIpNamePrefix.length && strncmp(ifa->ifa_name, instance->config.localIpNamePrefix.chars, instance->config.localIpNamePrefix.length) != 0) diff --git a/src/detection/memory/memory.h b/src/detection/memory/memory.h index ee34c8038a..bc140e6898 100644 --- a/src/detection/memory/memory.h +++ b/src/detection/memory/memory.h @@ -3,8 +3,14 @@ #ifndef FF_INCLUDED_detection_memory_memory #define FF_INCLUDED_detection_memory_memory -#include "detection/storage.h" +#include "fastfetch.h" -void ffDetectMemory(FFMemoryStorage* result); +typedef struct FFMemoryResult +{ + uint64_t bytesUsed; + uint64_t bytesTotal; +} FFMemoryResult; + +const char* ffDetectMemory(FFMemoryResult* result); #endif diff --git a/src/detection/memory/memory_apple.c b/src/detection/memory/memory_apple.c index 37b7addb7d..752c588c4b 100644 --- a/src/detection/memory/memory_apple.c +++ b/src/detection/memory/memory_apple.c @@ -3,31 +3,25 @@ #include #include #include +#include -void ffDetectMemory(FFMemoryStorage* ram) +const char* ffDetectMemory(FFMemoryResult* ram) { size_t length = sizeof(ram->bytesTotal); if (sysctl((int[]){ CTL_HW, HW_MEMSIZE }, 2, &ram->bytesTotal, &length, NULL, 0)) - { - ffStrbufAppendS(&ram->error, "Failed to read hw.memsize"); - return; - } + return "Failed to read hw.memsize"; uint32_t pagesize; length = sizeof(pagesize); if (sysctl((int[]){ CTL_HW, HW_PAGESIZE }, 2, &pagesize, &length, NULL, 0)) - { - ffStrbufAppendS(&ram->error, "Failed to read hw.pagesize"); - return; - } + return "Failed to read hw.pagesize"; mach_msg_type_number_t count = HOST_VM_INFO64_COUNT; vm_statistics64_data_t vmstat; if(host_statistics64(mach_host_self(), HOST_VM_INFO64, (host_info64_t) (&vmstat), &count) != KERN_SUCCESS) - { - ffStrbufAppendS(&ram->error, "Failed to read host_statistics64"); - return; - } + return "Failed to read host_statistics64"; ram->bytesUsed = ((uint64_t) vmstat.active_count + vmstat.wire_count) * pagesize; + + return NULL; } diff --git a/src/detection/memory/memory_bsd.c b/src/detection/memory/memory_bsd.c index 52d19a0c9b..05c74172fe 100644 --- a/src/detection/memory/memory_bsd.c +++ b/src/detection/memory/memory_bsd.c @@ -1,24 +1,21 @@ #include "memory.h" #include "common/sysctl.h" -void ffDetectMemory(FFMemoryStorage* ram) +const char* ffDetectMemory(FFMemoryResult* ram) { - uint32_t pageSize = (uint32_t) ffSysctlGetInt("hw.pagesize", 0); - if(pageSize == 0) - { - ffStrbufAppendS(&ram->error, "Failed to read hw.pagesize"); - return; - } + uint32_t pageSize; + uint64_t length = sizeof(pageSize); + if (sysctl((int[]){ CTL_HW, HW_PAGESIZE }, 2, &pageSize, &length, NULL, 0)) + return "Failed to read hw.pagesize"; ram->bytesTotal = (uint64_t) ffSysctlGetInt64("vm.stats.vm.v_page_count", 0) * pageSize; if(ram->bytesTotal == 0) - { - ffStrbufAppendS(&ram->error, "Failed to read vm.stats.vm.v_page_count"); - return; - } + return "Failed to read vm.stats.vm.v_page_count"; ram->bytesUsed = ram->bytesTotal - (uint64_t) ffSysctlGetInt64("vm.stats.vm.v_free_count", 0) * pageSize - (uint64_t) ffSysctlGetInt64("vm.stats.vm.v_inactive_count", 0) * pageSize ; + + return NULL; } diff --git a/src/detection/memory/memory_linux.c b/src/detection/memory/memory_linux.c index 339dda4fe8..60187185fb 100644 --- a/src/detection/memory/memory_linux.c +++ b/src/detection/memory/memory_linux.c @@ -1,18 +1,16 @@ #include "memory.h" +#include "util/mallocHelper.h" #include #include -void ffDetectMemory(FFMemoryStorage* ram) +const char* ffDetectMemory(FFMemoryResult* ram) { FILE* meminfo = fopen("/proc/meminfo", "r"); if(meminfo == NULL) - { - ffStrbufAppendS(&ram->error, "Failed to open /proc/meminfo"); - return; - } + return "Failed to open /proc/meminfo"; - char* line = NULL; + char* FF_AUTO_FREE line = NULL; size_t len = 0; uint32_t memTotal = 0, @@ -32,14 +30,13 @@ void ffDetectMemory(FFMemoryStorage* ram) sscanf(line, "SReclaimable: %u", &sReclaimable); } - if(line != NULL) - free(line); - fclose(meminfo); ram->bytesTotal = memTotal * (uint64_t) 1024; if(ram->bytesTotal == 0) - ffStrbufAppendS(&ram->error, "Failed to read MemTotal"); + return "Failed to read MemTotal"; else ram->bytesUsed = (memTotal + shmem - memFree - buffers - cached - sReclaimable) * (uint64_t) 1024; + + return NULL; } diff --git a/src/detection/memory/memory_windows.c b/src/detection/memory/memory_windows.c index 838b2534e0..666d797275 100644 --- a/src/detection/memory/memory_windows.c +++ b/src/detection/memory/memory_windows.c @@ -2,16 +2,15 @@ #include -void ffDetectMemory(FFMemoryStorage* ram) +const char* ffDetectMemory(FFMemoryResult* ram) { MEMORYSTATUSEX statex = { .dwLength = sizeof(statex), }; if (!GlobalMemoryStatusEx(&statex)) - { - ffStrbufAppendS(&ram->error, "GlobalMemoryStatusEx() failed"); - return; - } + return "GlobalMemoryStatusEx() failed"; + ram->bytesTotal = statex.ullTotalPhys; ram->bytesUsed = statex.ullTotalPhys - statex.ullAvailPhys; + return NULL; } diff --git a/src/detection/opencl/opencl.c b/src/detection/opencl/opencl.c new file mode 100644 index 0000000000..6eb2791d8e --- /dev/null +++ b/src/detection/opencl/opencl.c @@ -0,0 +1,102 @@ +#include "detection/opencl/opencl.h" + +#if defined(FF_HAVE_OPENCL) || defined(__APPLE__) + +#include "common/library.h" +#include "common/parsing.h" +#include "util/stringUtils.h" +#include + +#define CL_TARGET_OPENCL_VERSION 100 +#ifdef FF_HAVE_OPENCL + #include +#else + #include +#endif + +typedef struct OpenCLData +{ + FF_LIBRARY_SYMBOL(clGetPlatformIDs) + FF_LIBRARY_SYMBOL(clGetDeviceIDs) + FF_LIBRARY_SYMBOL(clGetDeviceInfo) +} OpenCLData; + +static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result) +{ + cl_platform_id platformID; + cl_uint numPlatforms; + data->ffclGetPlatformIDs(1, &platformID, &numPlatforms); + + if(numPlatforms == 0) + return "clGetPlatformIDs returned 0 platforms"; + + cl_device_id deviceID; + cl_uint numDevices; + data->ffclGetDeviceIDs(platformID, CL_DEVICE_TYPE_GPU, 1, &deviceID, &numDevices); + + if(numDevices == 0) + data->ffclGetDeviceIDs(platformID, CL_DEVICE_TYPE_ALL, 1, &deviceID, &numDevices); + + if(numDevices == 0) + return "clGetDeviceIDs returned 0 devices"; + + char version[64]; + data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VERSION, sizeof(version), version, NULL); + if(!ffStrSet(version)) + return "clGetDeviceInfo returned NULL or empty string"; + + const char* versionPretty = version; + const char* prefix = "OpenCL "; + if(strncasecmp(version, prefix, sizeof(prefix) - 1) == 0) + versionPretty = version + sizeof(prefix) - 1; + ffStrbufSetS(&result->version, versionPretty); + + ffStrbufEnsureFree(&result->device, 128); + data->ffclGetDeviceInfo(deviceID, CL_DEVICE_NAME, result->device.allocated, result->device.chars, NULL); + ffStrbufRecalculateLength(&result->device); + + ffStrbufEnsureFree(&result->vendor, 32); + data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VENDOR, result->vendor.allocated, result->vendor.chars, NULL); + ffStrbufRecalculateLength(&result->vendor); + + return NULL; +} + +#endif // defined(FF_HAVE_OPENCL) || defined(__APPLE__) + +const char* ffDetectOpenCL(FFinstance* instance, FFOpenCLResult* result) +{ + #ifdef FF_HAVE_OPENCL + + OpenCLData data; + + FF_LIBRARY_LOAD(opencl, &instance->config.libOpenCL, "dlopen libOpenCL"FF_LIBRARY_EXTENSION" failed", + #ifdef _WIN32 + "OpenCL"FF_LIBRARY_EXTENSION, -1, + #endif + "libOpenCL"FF_LIBRARY_EXTENSION, 1 + ); + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opencl, data, clGetPlatformIDs); + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opencl, data, clGetDeviceIDs); + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opencl, data, clGetDeviceInfo); + + return openCLHandleData(&data, result); + + #elif defined(__APPLE__) // FF_HAVE_OPENCL + + FF_UNUSED(instance); + + OpenCLData data; + data.ffclGetPlatformIDs = clGetPlatformIDs; + data.ffclGetDeviceIDs = clGetDeviceIDs; + data.ffclGetDeviceInfo = clGetDeviceInfo; + + return openCLHandleData(&data, result); + + #else + + FF_UNUSED(instance, result); + return "Fastfetch was build without OpenCL support"; + + #endif // FF_HAVE_OPENCL +} diff --git a/src/detection/opencl/opencl.h b/src/detection/opencl/opencl.h new file mode 100644 index 0000000000..93cceecc8c --- /dev/null +++ b/src/detection/opencl/opencl.h @@ -0,0 +1,17 @@ +#pragma once + +#ifndef FF_INCLUDED_detection_opencl_opencl +#define FF_INCLUDED_detection_opencl_opencl + +#include "fastfetch.h" + +typedef struct FFOpenCLResult +{ + FFstrbuf version; + FFstrbuf device; + FFstrbuf vendor; +} FFOpenCLResult; + +const char* ffDetectOpenCL(FFinstance* instance, FFOpenCLResult* result); + +#endif diff --git a/src/detection/packages/packages_linux.c b/src/detection/packages/packages_linux.c index 29b1ea2f21..b0b47f37c8 100644 --- a/src/detection/packages/packages_linux.c +++ b/src/detection/packages/packages_linux.c @@ -207,6 +207,19 @@ static uint32_t getSnap(FFstrbuf* baseDir) return result > 0 ? result - 1 : 0; } +static uint32_t getFlatpak(FFstrbuf* baseDir, const char* dirname) +{ + uint32_t baseDirLength = baseDir->length; + ffStrbufAppendS(baseDir, dirname); + + uint32_t result = + getNumElements(baseDir, "/app", DT_DIR) + + getNumElements(baseDir, "/runtime", DT_DIR); + + ffStrbufSubstrBefore(baseDir, baseDirLength); + return result; +} + #ifdef FF_HAVE_RPM #include "common/library.h" #include @@ -258,7 +271,7 @@ static void getPackageCounts(const FFinstance* instance, FFstrbuf* baseDir, FFPa packageCounts->dpkg += getNumStrings(baseDir, "/var/lib/dpkg/status", "Status: "); packageCounts->emerge += countFilesRecursive(baseDir, "/var/db/pkg", "SIZE"); packageCounts->eopkg += getNumElements(baseDir, "/var/lib/eopkg/package", DT_DIR); - packageCounts->flatpakSystem += getNumElements(baseDir, "/var/lib/flatpak/app", DT_DIR); + packageCounts->flatpakSystem += getFlatpak(baseDir, "/var/lib/flatpak"); packageCounts->nixDefault += getNixPackages(baseDir, "/nix/var/nix/profiles/default"); packageCounts->nixSystem += getNixPackages(baseDir, "/run/current-system"); packageCounts->pacman += getNumElements(baseDir, "/var/lib/pacman/local", DT_DIR); @@ -320,7 +333,7 @@ void ffDetectPackagesImpl(const FFinstance* instance, FFPackagesResult* result) ffStrbufInitA(&baseDir, 512); ffStrbufAppendS(&baseDir, FASTFETCH_TARGET_DIR_ROOT); - if(ffStrbufIgnCaseCompS(&(ffDetectOS(instance)->id), "bedrock") == 0) + if(ffStrbufIgnCaseEqualS(&ffDetectOS(instance)->id, "bedrock")) getPackageCountsBedrock(instance, &baseDir, result); else getPackageCountsRegular(instance, &baseDir, result); @@ -335,5 +348,5 @@ void ffDetectPackagesImpl(const FFinstance* instance, FFPackagesResult* result) ffStrbufSet(&baseDir, &instance->state.platform.homeDir); result->nixUser = getNixPackages(&baseDir, "/.nix-profile"); - result->flatpakUser += getNumElements(&baseDir, "/.var/app", DT_DIR); + result->flatpakUser = getFlatpak(&baseDir, "/.local/share/flatpak"); } diff --git a/src/detection/processes/processes.h b/src/detection/processes/processes.h index 74b29e1bbf..3feaaed873 100644 --- a/src/detection/processes/processes.h +++ b/src/detection/processes/processes.h @@ -5,6 +5,6 @@ #include "fastfetch.h" -uint32_t ffDetectProcesses(FFstrbuf* error); +const char* ffDetectProcesses(uint32_t* result); #endif diff --git a/src/detection/processes/processes_bsd.c b/src/detection/processes/processes_bsd.c index 36bb14773f..bc8cdaaeb7 100644 --- a/src/detection/processes/processes_bsd.c +++ b/src/detection/processes/processes_bsd.c @@ -6,15 +6,14 @@ #include #endif -uint32_t ffDetectProcesses(FFstrbuf* error) +const char* ffDetectProcesses(uint32_t* result) { int request[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL}; size_t length; if(sysctl(request, sizeof(request) / sizeof(*request), NULL, &length, NULL, 0) != 0) - { - ffStrbufAppendS(error, "sysctl() failed"); - return 0; - } - return (uint32_t)(length / sizeof(struct kinfo_proc)); + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed"; + + *result = (uint32_t)(length / sizeof(struct kinfo_proc)); + return NULL; } diff --git a/src/detection/processes/processes_linux.c b/src/detection/processes/processes_linux.c index 91871f8674..7e17fbc9a8 100644 --- a/src/detection/processes/processes_linux.c +++ b/src/detection/processes/processes_linux.c @@ -2,10 +2,12 @@ #include -uint32_t ffDetectProcesses(FFstrbuf* error) +const char* ffDetectProcesses(uint32_t* result) { struct sysinfo info; if(sysinfo(&info) != 0) - ffStrbufAppendS(error, "sysinfo() failed"); - return (uint32_t) info.procs; + return "sysinfo() failed"; + + *result = (uint32_t) info.procs; + return NULL; } diff --git a/src/detection/processes/processes_windows.c b/src/detection/processes/processes_windows.c new file mode 100644 index 0000000000..dc784c5db8 --- /dev/null +++ b/src/detection/processes/processes_windows.c @@ -0,0 +1,27 @@ +#include "processes.h" +#include "util/mallocHelper.h" + +#include +#include + +const char* ffDetectProcesses(uint32_t* result) +{ + ULONG size = 0; + if(NtQuerySystemInformation(SystemProcessInformation, NULL, 0, &size) != STATUS_INFO_LENGTH_MISMATCH) + return "NtQuerySystemInformation(SystemProcessInformation, NULL) failed"; + + size += sizeof(SystemProcessInformation) * 5; //What if new processes are created during two syscalls? + + SYSTEM_PROCESS_INFORMATION* FF_AUTO_FREE pstart = (SYSTEM_PROCESS_INFORMATION*)malloc(size); + if(!pstart) + return "malloc(size) failed"; + + if(!NT_SUCCESS(NtQuerySystemInformation(SystemProcessInformation, pstart, size, NULL))) + return "NtQuerySystemInformation(SystemProcessInformation, pstart) failed"; + + *result = 1; //Init with 1 because we test for ptr->NextEntryOffset + for (SYSTEM_PROCESS_INFORMATION* ptr = pstart; ptr->NextEntryOffset; ptr = (SYSTEM_PROCESS_INFORMATION*)((uint8_t*)ptr + ptr->NextEntryOffset)) + ++*result; + + return NULL; +} diff --git a/src/detection/processes/processes_windows.cpp b/src/detection/processes/processes_windows.cpp deleted file mode 100644 index 69a4946293..0000000000 --- a/src/detection/processes/processes_windows.cpp +++ /dev/null @@ -1,64 +0,0 @@ -extern "C" { -#include "processes.h" -#include "util/mallocHelper.h" -} - -#ifdef FF_USE_WIN_NTAPI - -#include -#include - -uint32_t ffDetectProcesses(FFstrbuf* error) -{ - ULONG size = 0; - if(NtQuerySystemInformation(SystemProcessInformation, nullptr, 0, &size) != STATUS_INFO_LENGTH_MISMATCH) - { - ffStrbufAppendS(error, "NtQuerySystemInformation(SystemProcessInformation, NULL) failed"); - return 0; - } - size += sizeof(SystemProcessInformation) * 5; //What if new processes are created during two syscalls? - - SYSTEM_PROCESS_INFORMATION* FF_AUTO_FREE pstart = (SYSTEM_PROCESS_INFORMATION*)malloc(size); - if(!pstart) - { - ffStrbufAppendF(error, "malloc(%u) failed", (unsigned)size); - return 0; - } - - if(!NT_SUCCESS(NtQuerySystemInformation(SystemProcessInformation, pstart, size, nullptr))) - { - ffStrbufAppendS(error, "NtQuerySystemInformation(SystemProcessInformation, pstart) failed"); - return 0; - } - - uint32_t result = 1; //Init with 1 because we test for ptr->NextEntryOffset - for (auto ptr = pstart; ptr->NextEntryOffset; ptr = (SYSTEM_PROCESS_INFORMATION*)((uint8_t*)ptr + ptr->NextEntryOffset)) - ++result; - - return result; -} - -#else - -#include "util/windows/wmi.hpp" - -uint32_t ffDetectProcesses(FFstrbuf* error) -{ - FFWmiQuery query(L"SELECT NumberOfProcesses FROM Win32_OperatingSystem", error); - if(!query) - return 0; - - if(FFWmiRecord record = query.next()) - { - uint64_t result = 0; - record.getUnsigned(L"NumberOfProcesses", &result); - return (uint32_t)result; - } - else - { - ffStrbufAppendS(error, "No Wmi result returned"); - return 0; - } -} - -#endif diff --git a/src/detection/sound/sound.h b/src/detection/sound/sound.h index 9a89ab6944..7603110f60 100644 --- a/src/detection/sound/sound.h +++ b/src/detection/sound/sound.h @@ -5,6 +5,8 @@ #include "fastfetch.h" +#define FF_SOUND_VOLUME_UNKNOWN 255 + typedef struct FFSoundDevice { FFstrbuf identifier; diff --git a/src/detection/sound/sound_apple.c b/src/detection/sound/sound_apple.c index e34920969d..862ee523a4 100644 --- a/src/detection/sound/sound_apple.c +++ b/src/detection/sound/sound_apple.c @@ -44,7 +44,7 @@ const char* ffDetectSound(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* de FFSoundDevice* device = (FFSoundDevice*) ffListAdd(devices); device->main = deviceId == mainDeviceId; device->active = false; - device->volume = 0; + device->volume = FF_SOUND_VOLUME_UNKNOWN; ffStrbufInitF(&device->identifier, "%u", (unsigned) deviceId); ffStrbufInit(&device->name); @@ -67,6 +67,34 @@ const char* ffDetectSound(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* de kAudioObjectPropertyElementMain }, 0, NULL, &dataSize, &volume) == kAudioHardwareNoError) device->volume = (uint8_t) (volume * 100 + 0.5); + else + { + // Try detecting volume from channels + uint32_t channels[2]; + dataSize = sizeof(channels); + if (AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress){ + kAudioDevicePropertyPreferredChannelsForStereo, + kAudioObjectPropertyScopeOutput, + kAudioObjectPropertyElementMain + }, 0, NULL, &dataSize, channels) == kAudioHardwareNoError) + { + dataSize = sizeof(volume); + if (AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress){ + kAudioDevicePropertyVolumeScalar, + kAudioObjectPropertyScopeOutput, + channels[0] + }, 0, NULL, &dataSize, &volume) == kAudioHardwareNoError) + { + float temp; + if (AudioObjectGetPropertyData(deviceId, &(AudioObjectPropertyAddress){ + kAudioDevicePropertyVolumeScalar, + kAudioObjectPropertyScopeOutput, + channels[1] + }, 0, NULL, &dataSize, &temp) == kAudioHardwareNoError) + device->volume = (uint8_t) ((volume + temp) / 2 * 100 + 0.5); + } + } + } } CFStringRef name; diff --git a/src/detection/sound/sound_windows.cpp b/src/detection/sound/sound_windows.cpp index 5221c8368c..faa7328f48 100644 --- a/src/detection/sound/sound_windows.cpp +++ b/src/detection/sound/sound_windows.cpp @@ -62,12 +62,10 @@ const char* ffDetectSound(FF_MAYBE_UNUSED const FFinstance* instance, FF_MAYBE_U FFSoundDevice* device = (FFSoundDevice*) ffListAdd(devices); device->main = wcscmp(mainDeviceId, immDeviceId) == 0; device->active = !!(immState & DEVICE_STATE_ACTIVE); - device->volume = 0; - ffStrbufInit(&device->identifier); + device->volume = FF_SOUND_VOLUME_UNKNOWN; + ffStrbufInitWS(&device->identifier, immDeviceId); ffStrbufInit(&device->name); - ffStrbufSetWS(&device->identifier, immDeviceId); - { PROPVARIANT __attribute__((__cleanup__(PropVariantClear))) friendlyName; PropVariantInit(&friendlyName); diff --git a/src/detection/storage.h b/src/detection/storage.h deleted file mode 100644 index c8cf7ed0d0..0000000000 --- a/src/detection/storage.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#ifndef FF_INCLUDED_detection_storage -#define FF_INCLUDED_detection_storage - -#include "fastfetch.h" - -typedef struct FFMemoryStorage -{ - FFstrbuf error; - uint64_t bytesUsed; - uint64_t bytesTotal; -} FFMemoryStorage; - -#endif diff --git a/src/detection/swap/swap.h b/src/detection/swap/swap.h index 246b2bfa3c..18e74c7bad 100644 --- a/src/detection/swap/swap.h +++ b/src/detection/swap/swap.h @@ -3,8 +3,14 @@ #ifndef FF_INCLUDED_detection_swap_swap #define FF_INCLUDED_detection_swap_swap -#include "detection/storage.h" +#include "fastfetch.h" -void ffDetectSwap(FFMemoryStorage* result); +typedef struct FFSwapResult +{ + uint64_t bytesUsed; + uint64_t bytesTotal; +} FFSwapResult; + +const char* ffDetectSwap(FFSwapResult* result); #endif diff --git a/src/detection/swap/swap_apple.c b/src/detection/swap/swap_apple.c index 15200da153..07bb477ee7 100644 --- a/src/detection/swap/swap_apple.c +++ b/src/detection/swap/swap_apple.c @@ -3,16 +3,14 @@ #include #include -void ffDetectSwap(FFMemoryStorage* swap) +const char* ffDetectSwap(FFSwapResult* swap) { struct xsw_usage xsw; size_t size = sizeof(xsw); if(sysctl((int[]){ CTL_VM, VM_SWAPUSAGE }, 2, &xsw, &size, NULL, 0) != 0) - { - ffStrbufAppendS(&swap->error, "Failed to read vm.swapusage"); - return; - } + return "Failed to read vm.swapusage"; swap->bytesTotal = xsw.xsu_total; swap->bytesUsed = xsw.xsu_used; + return NULL; } diff --git a/src/detection/swap/swap_bsd.c b/src/detection/swap/swap_bsd.c index b4c5fa7c70..82ec66779f 100644 --- a/src/detection/swap/swap_bsd.c +++ b/src/detection/swap/swap_bsd.c @@ -1,8 +1,9 @@ #include "swap.h" #include "common/sysctl.h" -void ffDetectSwap(FFMemoryStorage* swap) +const char* ffDetectSwap(FFSwapResult* swap) { swap->bytesTotal = (uint64_t)ffSysctlGetInt64("vm.swap_total", 0); swap->bytesUsed = (uint64_t)ffSysctlGetInt64("vm.swap_reserved", 0); + return NULL; } diff --git a/src/detection/swap/swap_linux.c b/src/detection/swap/swap_linux.c index ee623c0c45..4ed2e64753 100644 --- a/src/detection/swap/swap_linux.c +++ b/src/detection/swap/swap_linux.c @@ -2,12 +2,14 @@ #include -void ffDetectSwap(FFMemoryStorage* swap) +const char* ffDetectSwap(FFSwapResult* swap) { struct sysinfo info; if(sysinfo(&info) != 0) - ffStrbufAppendS(&swap->error, "sysinfo() failed"); + return "sysinfo() failed"; swap->bytesTotal = info.totalswap * (uint64_t) info.mem_unit; swap->bytesUsed = (info.totalswap - info.freeswap) * (uint64_t) info.mem_unit; + + return NULL; } diff --git a/src/detection/swap/swap_windows.c b/src/detection/swap/swap_windows.c new file mode 100644 index 0000000000..f541f1964f --- /dev/null +++ b/src/detection/swap/swap_windows.c @@ -0,0 +1,31 @@ +#include "swap.h" +#include "util/mallocHelper.h" + +#include +#include +#include + +const char* ffDetectSwap(FFSwapResult* swap) +{ + SYSTEM_INFO sysInfo; + GetNativeSystemInfo(&sysInfo); + + ULONG size = sizeof(SYSTEM_PAGEFILE_INFORMATION); + SYSTEM_PAGEFILE_INFORMATION* FF_AUTO_FREE pstart = (SYSTEM_PAGEFILE_INFORMATION*)malloc(size); + while(true) + { + NTSTATUS status = NtQuerySystemInformation(SystemPagefileInformation, pstart, size, &size); + if(status == STATUS_INFO_LENGTH_MISMATCH) + { + if(!(pstart = (SYSTEM_PAGEFILE_INFORMATION*)realloc(pstart, size))) + return "realloc(pstart, size) failed"; + } + else if(!NT_SUCCESS(status)) + return "NtQuerySystemInformation(SystemPagefileInformation, size) failed"; + break; + } + swap->bytesUsed = (uint64_t)pstart->TotalUsed * sysInfo.dwPageSize; + swap->bytesTotal = (uint64_t)pstart->CurrentSize * sysInfo.dwPageSize; + + return NULL; +} diff --git a/src/detection/swap/swap_windows.cpp b/src/detection/swap/swap_windows.cpp deleted file mode 100644 index 15d6336f4d..0000000000 --- a/src/detection/swap/swap_windows.cpp +++ /dev/null @@ -1,65 +0,0 @@ -extern "C" { -#include "swap.h" -#include "util/mallocHelper.h" -} - -#ifdef FF_USE_WIN_NTAPI - -#include -#include -#include - -extern "C" -void ffDetectSwap(FFMemoryStorage* swap) -{ - SYSTEM_INFO sysInfo; - GetNativeSystemInfo(&sysInfo); - - ULONG size = sizeof(SYSTEM_PAGEFILE_INFORMATION); - SYSTEM_PAGEFILE_INFORMATION* FF_AUTO_FREE pstart = (SYSTEM_PAGEFILE_INFORMATION*)malloc(size); - while(true) - { - NTSTATUS status = NtQuerySystemInformation(SystemPagefileInformation, pstart, size, &size); - if(status == STATUS_INFO_LENGTH_MISMATCH) - { - if(!(pstart = (SYSTEM_PAGEFILE_INFORMATION*)realloc(pstart, size))) - { - ffStrbufAppendF(&swap->error, "realloc(pstart, %lu) failed", size); - return; - } - } - else if(!NT_SUCCESS(status)) - { - ffStrbufAppendF(&swap->error, "NtQuerySystemInformation(SystemPagefileInformation, %lu) failed", size); - return; - } - break; - } - swap->bytesUsed = (uint64_t)pstart->TotalUsed * sysInfo.dwPageSize; - swap->bytesTotal = (uint64_t)pstart->CurrentSize * sysInfo.dwPageSize; -} - -#else - -#include "util/windows/wmi.hpp" - -extern "C" -void ffDetectSwapImpl(FFMemoryStorage* swap) -{ - FFWmiQuery query(L"SELECT AllocatedBaseSize, CurrentUsage FROM Win32_PageFileUsage", &swap->error); - if(!query) - return; - - if(FFWmiRecord record = query.next()) - { - //MB - record.getUnsigned(L"AllocatedBaseSize", &swap->bytesTotal); - record.getUnsigned(L"CurrentUsage", &swap->bytesUsed); - swap->bytesTotal *= 1024 * 1024; - swap->bytesUsed *= 1024 * 1024; - } - else - ffStrbufInitS(&swap->error, "No Wmi result returned"); -} - -#endif diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index 38d5dd5e17..f3c74a7fcc 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -287,10 +287,10 @@ static void detectFromWindowsTeriminal(const FFinstance* instance, const FFstrbu FF_MAYBE_UNUSED static bool detectKitty(const FFinstance* instance, FFTerminalFontResult* result) { - FFstrbuf fontName; + FF_STRBUF_AUTO_DESTROY fontName; ffStrbufInit(&fontName); - FFstrbuf fontSize; + FF_STRBUF_AUTO_DESTROY fontSize; ffStrbufInit(&fontSize); FFpropquery fontQuery[] = { @@ -308,9 +308,6 @@ FF_MAYBE_UNUSED static bool detectKitty(const FFinstance* instance, FFTerminalFo ffFontInitValues(&result->font, fontName.chars, fontSize.chars); - ffStrbufDestroy(&fontName); - ffStrbufDestroy(&fontSize); - return true; } @@ -373,6 +370,32 @@ static bool detectWezterm(FF_MAYBE_UNUSED const FFinstance* instance, FFTerminal return true; } +static bool detectTabby(FF_MAYBE_UNUSED const FFinstance* instance, FFTerminalFontResult* result) +{ + FF_STRBUF_AUTO_DESTROY fontName; + ffStrbufInit(&fontName); + + FF_STRBUF_AUTO_DESTROY fontSize; + ffStrbufInit(&fontSize); + + FFpropquery fontQuery[] = { + {"font: ", &fontName}, + {"fontSize: ", &fontSize}, + }; + + if(!ffParsePropFileConfigValues(instance, "tabby/config.yaml", 2, fontQuery)) + return false; + + if(fontName.length == 0) + ffStrbufSetS(&fontName, "monospace"); + if(fontSize.length == 0) + ffStrbufSetS(&fontSize, "14"); + + ffFontInitValues(&result->font, fontName.chars, fontSize.chars); + + return true; +} + void ffDetectTerminalFontPlatform(const FFinstance* instance, const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont); static bool detectTerminalFontCommon(const FFinstance* instance, const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont) @@ -383,6 +406,8 @@ static bool detectTerminalFontCommon(const FFinstance* instance, const FFTermina detectTerminator(instance, terminalFont); else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalProcessName, "wezterm-gui")) detectWezterm(instance, terminalFont); + else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalProcessName, "tabby")) + detectTabby(instance, terminalFont); #ifndef _WIN32 else if(ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "kitty")) diff --git a/src/detection/terminalfont/terminalfont_apple.m b/src/detection/terminalfont/terminalfont_apple.m index 71ecc8b22f..2dd3d03b78 100644 --- a/src/detection/terminalfont/terminalfont_apple.m +++ b/src/detection/terminalfont/terminalfont_apple.m @@ -86,7 +86,8 @@ static void detectWarpTerminal(const FFinstance* instance, FFTerminalFontResult* void ffDetectTerminalFontPlatform(const FFinstance* instance, const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont) { - if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "iterm.app") == 0) + if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "iterm.app") == 0 || + ffStrbufStartsWithIgnCaseS(&terminalShell->terminalProcessName, "iTermServer-")) detectIterm2(instance, terminalFont); else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "Apple_Terminal") == 0) detectAppleTerminal(terminalFont); diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index 2c732b25de..3117f6cb59 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -5,6 +5,8 @@ #ifdef _WIN32 +#include "util/mallocHelper.h" + #include static bool getFileVersion(const char* exePath, FFstrbuf* version) @@ -13,7 +15,7 @@ static bool getFileVersion(const char* exePath, FFstrbuf* version) DWORD size = GetFileVersionInfoSizeA(exePath, &handle); if(size > 0) { - void* versionData = malloc(size); + FF_AUTO_FREE void* versionData = malloc(size); if(GetFileVersionInfoA(exePath, handle, size, versionData)) { VS_FIXEDFILEINFO* verInfo; @@ -26,11 +28,9 @@ static bool getFileVersion(const char* exePath, FFstrbuf* version) (unsigned)(( verInfo->dwFileVersionLS >> 16 ) & 0xffff), (unsigned)(( verInfo->dwFileVersionLS >> 0 ) & 0xffff) ); - free(versionData); return true; } } - free(versionData); } return false; @@ -136,6 +136,11 @@ bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version) return getExeVersionGeneral(exe, version); //tcsh 6.24.07 (Astron) 2022-12-21 (aarch64-apple-darwin) options wide,nls,dl,al,kan,sm,rh,color,filec if(strcasecmp(exeName, "nu") == 0) return getExeVersionRaw(exe, version); //0.73.0 + if(strcasecmp(exeName, "python") == 0 && getenv("XONSH_VERSION")) + { + ffStrbufSetS(version, getenv("XONSH_VERSION")); + return true; + } #ifdef _WIN32 if(strcasecmp(exeName, "powershell") == 0 || strcasecmp(exeName, "powershell_ise") == 0) @@ -190,11 +195,7 @@ FF_MAYBE_UNUSED static bool getTerminalVersionKonsole(FFstrbuf* exe, FFstrbuf* v FF_MAYBE_UNUSED static bool getTerminalVersionFoot(FFstrbuf* exe, FFstrbuf* version) { - if(ffProcessAppendStdOut(version, (char* const[]){ - exe->chars, - "--version", - NULL - })) return false; + if(!getExeVersionRaw(exe, version)) return false; //foot version: 1.13.1 -pgo +ime -graphemes -assertions ffStrbufSubstrAfterFirstS(version, "version: "); @@ -274,6 +275,9 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe if(ffStrbufIgnCaseEqualS(processName, "kitty")) return getExeVersionGeneral(exe, version); //kitty 0.21.2 created by Kovid Goyal + if (ffStrbufIgnCaseEqualS(processName, "Tabby") && getExeVersionRaw(exe, version)) + return true; + #endif if(ffStrbufStartsWithIgnCaseS(processName, "alacritty")) @@ -286,7 +290,8 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe if(termProgram) { if(ffStrbufStartsWithIgnCaseS(processName, termProgram) || // processName ends with `.exe` on Windows - (strcmp(termProgram, "vscode") == 0 && ffStrbufStartsWithIgnCaseS(processName, "code")) + (strcmp(termProgram, "vscode") == 0 && ffStrbufStartsWithIgnCaseS(processName, "code")) || + (strcmp(termProgram, "iTerm.app") == 0 && ffStrbufStartsWithIgnCaseS(processName, "iTermServer-")) ) { ffStrbufSetS(version, termProgramVersion); return true; diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index 8db9f29013..6fb5cc0081 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -148,7 +148,7 @@ static void getTerminalShell(FFTerminalShellResult* result, pid_t pid) } //Known shells - if( + if ( strcasecmp(name, "bash") == 0 || strcasecmp(name, "zsh") == 0 || strcasecmp(name, "ksh") == 0 || @@ -158,7 +158,8 @@ static void getTerminalShell(FFTerminalShellResult* result, pid_t pid) strcasecmp(name, "dash") == 0 || strcasecmp(name, "pwsh") == 0 || strcasecmp(name, "nu") == 0 || - strcasecmp(name, "git-shell") == 0 + strcasecmp(name, "git-shell") == 0 || + (strcasecmp(name, "python") == 0 && getenv("XONSH_VERSION")) ) { if (result->shellProcessName.length == 0) { @@ -369,13 +370,15 @@ const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance) ffStrbufInitS(&result.shellPrettyName, "PowerShell"); else if(ffStrbufEqualS(&result.shellProcessName, "nu")) ffStrbufInitS(&result.shellPrettyName, "nushell"); + else if(ffStrbufIgnCaseEqualS(&result.shellProcessName, "python") && getenv("XONSH_VERSION")) + ffStrbufInitS(&result.shellPrettyName, "xonsh"); else { // https://github.com/LinusDierheimer/fastfetch/discussions/280#discussioncomment-3831734 ffStrbufInitS(&result.shellPrettyName, result.shellExeName); } - if(ffStrbufEqualS(&result.terminalProcessName, "iTerm.app")) + if(ffStrbufEqualS(&result.terminalProcessName, "iTerm.app") || ffStrbufStartsWithS(&result.terminalProcessName, "iTermServer-")) ffStrbufInitS(&result.terminalPrettyName, "iTerm"); else if(ffStrbufEqualS(&result.terminalProcessName, "Apple_Terminal")) ffStrbufInitS(&result.terminalPrettyName, "Apple Terminal"); diff --git a/src/detection/terminalshell/terminalshell_windows.cpp b/src/detection/terminalshell/terminalshell_windows.c similarity index 78% rename from src/detection/terminalshell/terminalshell_windows.cpp rename to src/detection/terminalshell/terminalshell_windows.c index 83bd37c169..9af70f8cad 100644 --- a/src/detection/terminalshell/terminalshell_windows.cpp +++ b/src/detection/terminalshell/terminalshell_windows.c @@ -1,19 +1,41 @@ -extern "C" { #include "terminalshell.h" #include "common/processing.h" #include "common/thread.h" #include "util/mallocHelper.h" -} #include #include #include - -#ifdef FF_USE_WIN_NTAPI - #include #include +static bool getProductVersion(const wchar_t* filePath, FFstrbuf* version) +{ + DWORD handle; + DWORD size = GetFileVersionInfoSizeW(filePath, &handle); + if(size > 0) + { + FF_AUTO_FREE void* versionData = malloc(size); + if(GetFileVersionInfoW(filePath, handle, size, versionData)) + { + VS_FIXEDFILEINFO* verInfo; + UINT len; + if(VerQueryValueW(versionData, L"\\", (void**)&verInfo, &len) && len && verInfo->dwSignature == 0xFEEF04BD) + { + ffStrbufAppendF(version, "%u.%u.%u.%u", + (unsigned)(( verInfo->dwProductVersionMS >> 16 ) & 0xffff), + (unsigned)(( verInfo->dwProductVersionMS >> 0 ) & 0xffff), + (unsigned)(( verInfo->dwProductVersionLS >> 16 ) & 0xffff), + (unsigned)(( verInfo->dwProductVersionLS >> 0 ) & 0xffff) + ); + return true; + } + } + } + + return false; +} + static bool getProcessInfo(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFstrbuf* exe, const char** exeName) { HANDLE hProcess = pid == 0 @@ -59,7 +81,7 @@ static bool getProcessInfo(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFstrb static bool getTerminalInfoByEnumeratingChildProcesses(FFTerminalShellResult* result, uint32_t ppid) { ULONG size = 0; - if(NtQuerySystemInformation(SystemProcessInformation, nullptr, 0, &size) != STATUS_INFO_LENGTH_MISMATCH) + if(NtQuerySystemInformation(SystemProcessInformation, NULL, 0, &size) != STATUS_INFO_LENGTH_MISMATCH) return false; size += sizeof(SystemProcessInformation) * 5; //What if new processes are created during two syscalls? @@ -68,12 +90,12 @@ static bool getTerminalInfoByEnumeratingChildProcesses(FFTerminalShellResult* re if(!pstart) return false; - if(!NT_SUCCESS(NtQuerySystemInformation(SystemProcessInformation, pstart, size, nullptr))) + if(!NT_SUCCESS(NtQuerySystemInformation(SystemProcessInformation, pstart, size, NULL))) return false; uint32_t currentProcessId = (uint32_t) GetCurrentProcessId(); - for (auto ptr = pstart; ptr->NextEntryOffset; ptr = (SYSTEM_PROCESS_INFORMATION*)((uint8_t*)ptr + ptr->NextEntryOffset)) + for (SYSTEM_PROCESS_INFORMATION* ptr = pstart; ptr->NextEntryOffset; ptr = (SYSTEM_PROCESS_INFORMATION*)((uint8_t*)ptr + ptr->NextEntryOffset)) { if ((uint32_t)(uintptr_t) ptr->InheritedFromUniqueProcessId != ppid) continue; @@ -82,7 +104,7 @@ static bool getTerminalInfoByEnumeratingChildProcesses(FFTerminalShellResult* re if (pid == currentProcessId) continue; - if(!getProcessInfo(pid, nullptr, &result->terminalProcessName, &result->terminalExe, &result->terminalExeName)) + if(!getProcessInfo(pid, NULL, &result->terminalProcessName, &result->terminalExe, &result->terminalExeName)) return false; result->terminalPid = pid; @@ -95,77 +117,7 @@ static bool getTerminalInfoByEnumeratingChildProcesses(FFTerminalShellResult* re return false; } -#else - -#include "util/windows/wmi.hpp" -#include - -static bool getProcessInfo(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFstrbuf* exe, const char** exeName) -{ - if(pid == 0) - pid = GetCurrentProcessId(); - - wchar_t sql[256] = {}; - swprintf(sql, 256, L"SELECT %ls %ls ParentProcessId FROM Win32_Process WHERE ProcessId = %" PRIu32, - pname ? L"Name," : L"", - pname ? L"ExecutablePath," : L"", - pid); - - FFWmiQuery query(sql); - if(!query) - return false; - - if(FFWmiRecord record = query.next()) - { - if(ppid) - { - uint64_t value; - record.getUnsigned(L"ParentProcessId", &value); - *ppid = (uint32_t) value; - } - - if(pname) - record.getString(L"Name", pname); - - if(exe) - record.getString(L"ExecutablePath", exe); - - if(exeName) - *exeName = exe->chars + ffStrbufLastIndexC(exe, '\\') + 1; - } - return true; -} - -static bool getTerminalInfoByEnumeratingChildProcesses(FFTerminalShellResult* result, uint32_t ppid) -{ - wchar_t sql[256] = {}; - swprintf(sql, 256, L"SELECT Name, ExecutablePath, ProcessId FROM Win32_Process WHERE ProcessId <> %" PRIu32 " AND ParentProcessId = %" PRIu32, - (uint32_t) GetCurrentProcessId(), - ppid); - - FFWmiQuery query(sql); - if(!query) - return false; - - if(FFWmiRecord record = query.next()) - { - record.getString(L"Name", &result->terminalProcessName); - record.getString(L"ExecutablePath", &result->terminalExe); - result->terminalExeName = result->terminalExe.chars + ffStrbufLastIndexC(&result->terminalExe, '\\') + 1; - uint64_t pid; - record.getUnsigned(L"ProcessId", &pid); - result->terminalPid = (uint32_t) pid; - ffStrbufSet(&result->terminalPrettyName, &result->terminalProcessName); - if(ffStrbufEndsWithIgnCaseS(&result->terminalPrettyName, ".exe")) - ffStrbufSubstrBefore(&result->terminalPrettyName, result->terminalPrettyName.length - 4); - return true; - } - return false; -} - -#endif - -extern "C" bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version); +bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version); static uint32_t getShellInfo(const FFinstance* instance, FFTerminalShellResult* result, uint32_t pid) { @@ -195,7 +147,7 @@ static uint32_t getShellInfo(const FFinstance* instance, FFTerminalShellResult* ffStrbufClear(&result->shellProcessName); ffStrbufClear(&result->shellPrettyName); ffStrbufClear(&result->shellExe); - result->shellExeName = nullptr; + result->shellExeName = NULL; return getShellInfo(instance, result, ppid); } @@ -225,7 +177,9 @@ static uint32_t getShellInfo(const FFinstance* instance, FFTerminalShellResult* { if(wcsncmp(module.szModule, L"clink_dll_", strlen("clink_dll_")) == 0) { - ffStrbufAppendS(&result->shellPrettyName, "CMD (with Clink)"); + ffStrbufAppendS(&result->shellPrettyName, "CMD (with Clink "); + getProductVersion(module.szExePath, &result->shellPrettyName); + ffStrbufAppendC(&result->shellPrettyName, ')'); break; } } @@ -316,23 +270,23 @@ static void getTerminalFromEnv(FFTerminalShellResult* result) ffStrbufIgnCaseCompS(&result->terminalProcessName, "explorer") != 0 ) return; - const char* term = nullptr; + const char* term = NULL; //SSH - if(getenv("SSH_CONNECTION") != nullptr) + if(getenv("SSH_CONNECTION") != NULL) term = getenv("SSH_TTY"); //Windows Terminal if(!term && ( - getenv("WT_SESSION") != nullptr || - getenv("WT_PROFILE_ID") != nullptr + getenv("WT_SESSION") != NULL || + getenv("WT_PROFILE_ID") != NULL )) term = "Windows Terminal"; //Alacritty if(!term && ( - getenv("ALACRITTY_SOCKET") != nullptr || - getenv("ALACRITTY_LOG") != nullptr || - getenv("ALACRITTY_WINDOW_ID") != nullptr + getenv("ALACRITTY_SOCKET") != NULL || + getenv("ALACRITTY_LOG") != NULL || + getenv("ALACRITTY_WINDOW_ID") != NULL )) term = "Alacritty"; if(!term) @@ -351,7 +305,7 @@ static void getTerminalFromEnv(FFTerminalShellResult* result) } } -extern "C" bool fftsGetTerminalVersion(FFstrbuf* processName, FFstrbuf* exe, FFstrbuf* version); +bool fftsGetTerminalVersion(FFstrbuf* processName, FFstrbuf* exe, FFstrbuf* version); const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance) { @@ -386,7 +340,7 @@ const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance) ffStrbufInit(&result.userShellVersion); uint32_t ppid; - if(!getProcessInfo(0, &ppid, nullptr, nullptr, nullptr)) + if(!getProcessInfo(0, &ppid, NULL, NULL, NULL)) goto exit; ppid = getShellInfo(instance, &result, ppid); diff --git a/src/detection/vulkan/vulkan.c b/src/detection/vulkan/vulkan.c index 29769da5ac..878017e95e 100644 --- a/src/detection/vulkan/vulkan.c +++ b/src/detection/vulkan/vulkan.c @@ -176,8 +176,17 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu if(physicalDeviceProperties.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU) continue; + // #456 + FF_LIST_FOR_EACH(FFGPUResult, gpu, result->gpus) + { + if (gpu->vulkanDeviceId == physicalDeviceProperties.properties.deviceID) + goto next; + } + FFGPUResult* gpu = ffListAdd(&result->gpus); + gpu->vulkanDeviceId = physicalDeviceProperties.properties.deviceID; + ffStrbufInit(&gpu->name); ffStrbufAppendS(&gpu->name, physicalDeviceProperties.properties.deviceName); @@ -215,6 +224,9 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu //No way to detect those using vulkan gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->temperature = FF_GPU_TEMP_UNSET; + + next: + continue; } //If the highest device version is lower than the instance version, use it as our vulkan version diff --git a/src/detection/wifi/wifi_windows.c b/src/detection/wifi/wifi_windows.c index e94f0cebd1..a0bd0af4b0 100644 --- a/src/detection/wifi/wifi_windows.c +++ b/src/detection/wifi/wifi_windows.c @@ -72,7 +72,7 @@ const char* ffDetectWifi(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* res WLAN_INTERFACE_INFO* ifInfo = (WLAN_INTERFACE_INFO*)&ifList->InterfaceInfo[index]; FFWifiResult* item = (FFWifiResult*)ffListAdd(result); - ffStrbufInit(&item->inf.description); + ffStrbufInitWS(&item->inf.description, ifInfo->strInterfaceDescription); ffStrbufInit(&item->inf.status); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); @@ -83,7 +83,6 @@ const char* ffDetectWifi(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* res item->conn.rxRate = 0.0/0.0; item->conn.txRate = 0.0/0.0; - ffStrbufSetWS(&item->inf.description, ifInfo->strInterfaceDescription); convertIfStateToString(ifInfo->isState, &item->inf.status); if(ifInfo->isState != wlan_interface_state_connected) diff --git a/src/fastfetch.h b/src/fastfetch.h index 0d25d31a86..cd43cdb01d 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -326,7 +326,7 @@ void ffPrintCPU(FFinstance* instance); void ffPrintCPUUsage(FFinstance* instance); void ffPrintGPU(FFinstance* instance); void ffPrintMemory(FFinstance* instance); -void ffPrintSwap(FFinstance* instance); //Also in modules/memory.c +void ffPrintSwap(FFinstance* instance); void ffPrintDisk(FFinstance* instance); void ffPrintBattery(FFinstance* instance); void ffPrintPowerAdapter(FFinstance* instance); diff --git a/src/logo/builtin.c b/src/logo/builtin.c index 3fa4cf45ba..656babf3e7 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -188,7 +188,7 @@ static const FFlogo* getLogoArch() FF_LOGO_INIT FF_LOGO_NAMES("arch", "archlinux", "arch-linux") FF_LOGO_LINES( - " -`\n" + "$1 -`\n" " .o+`\n" " `ooo/\n" " `+oooo:\n" @@ -197,9 +197,9 @@ static const FFlogo* getLogoArch() " `/:-:++oooo+:\n" " `/++++/+++++++:\n" " `/++++++++++++++:\n" - " `/+++ooooooooooooo/`\n" - " ./ooosssso++osssssso+`\n" - " .oossssso-````/ossssss+`\n" + " `/+++o$2oooooooo$1oooo/`\n" + " ./$2ooosssso++osssssso$1+`\n" + "$2 .oossssso-````/ossssss+`\n" " -osssssso. :ssssssso.\n" " :osssssss/ osssso+++.\n" " /ossssssss/ +ssssooo/-\n" @@ -209,6 +209,7 @@ static const FFlogo* getLogoArch() ".` `/"; ) FF_LOGO_COLORS( + "36", //cyan "36" //cyan ) FF_LOGO_COLOR_KEYS("36"); //cyan @@ -734,7 +735,7 @@ static const FFlogo* getLogoEndeavour() "$2`-////+$1ssssssssssssssssssssssssssso$3++++-\n" " $2`..-+$1oosssssssssssssssssssssssso$3+++++/`\n" " $3./++++++++++++++++++++++++++++++/:.\n" - " `:::::::::::::::::::::::::------``" + " `:::::::::::::::::::::::::------``" ) FF_LOGO_COLORS( "35", //magenta @@ -1186,6 +1187,56 @@ static const FFlogo* getLogoMacOS() FF_LOGO_RETURN } +static const FFlogo* getLogoMacOSSmall() +{ + FF_LOGO_INIT + FF_LOGO_NAMES("macos_small", "mac_small", "apple_small", "darwin_small", "osx_small") + FF_LOGO_LINES( + "$1 .:'\n" + " __ :'__\n" + "$2 .'`__`-'__``.\n" + "$3:__________.-'\n" + "$4:_________:\n" + " :_________`-;\n" + "$5 `.__.-.__.'" + ) + FF_LOGO_COLORS( + "32", //green + "33", //yellow + "31", //red + "35", //magenta + "34" //blue + ) + FF_LOGO_COLOR_KEYS("33"); //yellow + FF_LOGO_COLOR_TITLE("32"); //green + FF_LOGO_RETURN +} + +static const FFlogo* getLogoMacOSSmall2() +{ + FF_LOGO_INIT + FF_LOGO_NAMES("macos_small2", "mac_small2", "apple_small2", "darwin_small2", "osx_small2") + FF_LOGO_LINES( + "$1 .:'\n" + " __ :'__\n" + "$2 .'` `-' ``.\n" + "$3: .-'\n" + "$4: :\n" + " : `-;\n" + "$5 `.__.-.__.'" + ) + FF_LOGO_COLORS( + "32", //green + "33", //yellow + "31", //red + "35", //magenta + "34" //blue + ) + FF_LOGO_COLOR_KEYS("33"); //yellow + FF_LOGO_COLOR_TITLE("32"); //green + FF_LOGO_RETURN +} + static const FFlogo* getLogoManjaro() { FF_LOGO_INIT @@ -1369,23 +1420,23 @@ static const FFlogo* getLogoWindows11() FF_LOGO_NAMES("Windows 11", "Windows Server 2022") FF_LOGO_LINES( "$1\n" - ",,**************/ ///////////////()\n" - "****************/ ///////////////((\n" - "***************// //////////////(((\n" - "**************/// ////////////(((((\n" - "************///// /////////((((((((\n" - "*********//////// /////((((((((((((\n" - "*******////////// ///((((((((((((((\n" - "****///////////// (((((((((((((((((\n" + "///////////////// /////////////////\n" + "///////////////// /////////////////\n" + "///////////////// /////////////////\n" + "///////////////// /////////////////\n" + "///////////////// /////////////////\n" + "///////////////// /////////////////\n" + "///////////////// /////////////////\n" + "///////////////// /////////////////\n" "\n" - "/////////////(((( (((((((((((((((((\n" - "////////////((((( (((((((((((((((((\n" - "///////////(((((( (((((((((((((((((\n" - "/////////(((((((( (((((((((((((((((\n" - "///////(((((((((( (((((((((((((((((\n" - "////((((((((((((( (((((((((((((((((\n" - "((((((((((((((((( (((((((((((((((((\n" - "((((((((((((((((( (((((((((((((((()" + "///////////////// /////////////////\n" + "///////////////// /////////////////\n" + "///////////////// /////////////////\n" + "///////////////// /////////////////\n" + "///////////////// /////////////////\n" + "///////////////// /////////////////\n" + "///////////////// /////////////////\n" + "///////////////// /////////////////" ) FF_LOGO_COLORS( "34" //blue @@ -2217,6 +2268,39 @@ static const FFlogo* getLogoSolus() FF_LOGO_RETURN } +static const FFlogo* getLogoSteamOS() +{ + FF_LOGO_INIT + FF_LOGO_NAMES("steamos") + FF_LOGO_LINES( + "$1 .,,,,.\n" + " .,'onNMMMMMNNnn',.\n" + " .'oNMANKMMMMMMMMMMMNNn'.\n" + " .'ANMMMMMMMXKNNWWWPFFWNNMNn.\n" + " ;NNMMMMMMMMMMNWW'' ,.., 'WMMM,\n" + " ;NMMMMV+##+VNWWW' .+;'':+, 'WMW,\n" + ",VNNWP+$2######$1+WW, $2+: $1:+, +MMM,\n" + "'$2+#############, +. ,+' $1+NMMM\n" + "$2 '*#########*' '*,,*' $1.+NMMMM.\n" + "$2 `'*###*' ,.,;###$1+WNM,\n" + "$2 .,;;, .;##########$1+W\n" + "$2,',. '; ,+##############'\n" + " '###+. :,. .,; ,###############'\n" + " '####.. `'' .,###############'\n" + " '#####+++################'\n" + " '*##################*'\n" + " ''*##########*''\n" + " ''''''\n" + ) + FF_LOGO_COLORS( + "34", //blue + "37" //white + ) + FF_LOGO_COLOR_KEYS("34"); //blue + FF_LOGO_COLOR_TITLE("34"); //blue + FF_LOGO_RETURN +} + static const FFlogo* getLogoUbuntu() { FF_LOGO_INIT @@ -2469,6 +2553,8 @@ GetLogoMethod* ffLogoBuiltinGetAll() getLogoLangitKetujuh, getLogoLinux, getLogoMacOS, + getLogoMacOSSmall, + getLogoMacOSSmall2, getLogoManjaro, getLogoManjaroSmall, getLogoMint, @@ -2503,6 +2589,7 @@ GetLogoMethod* ffLogoBuiltinGetAll() getLogoSlackware, getLogoSlackwareSmall, getLogoSolus, + getLogoSteamOS, getLogoUbuntu, getLogoUbuntuOld, getLogoUbuntuSmall, diff --git a/src/logo/image/image.c b/src/logo/image/image.c index 7010dd8158..9da6584fc6 100644 --- a/src/logo/image/image.c +++ b/src/logo/image/image.c @@ -4,6 +4,8 @@ #ifdef __APPLE__ #include +#elif _WIN32 + #include #endif static FFstrbuf base64Encode(FFstrbuf* in) diff --git a/src/modules/colors.c b/src/modules/colors.c index 40a936e007..186a225cf2 100644 --- a/src/modules/colors.c +++ b/src/modules/colors.c @@ -5,13 +5,7 @@ void ffPrintColors(FFinstance* instance) { if(instance->config.pipe) - { - ffLogoPrintLine(instance); - puts("████████████████████████"); - ffLogoPrintLine(instance); - puts("████████████████████████"); return; - } ffLogoPrintLine(instance); diff --git a/src/modules/cpuUsage.c b/src/modules/cpuUsage.c index f46de62595..cb952a06a3 100644 --- a/src/modules/cpuUsage.c +++ b/src/modules/cpuUsage.c @@ -21,7 +21,7 @@ void ffPrintCPUUsage(FFinstance* instance) { ffPrintLogoAndKey(instance, FF_CPU_USAGE_MODULE_NAME, 0, &instance->config.cpuUsage.key); - FFstrbuf str; + FF_STRBUF_AUTO_DESTROY str; ffStrbufInit(&str); if(instance->config.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) ffAppendPercentBar(instance, &str, (uint8_t)percentage, 0, 5, 8); @@ -32,7 +32,6 @@ void ffPrintCPUUsage(FFinstance* instance) ffAppendPercentNum(instance, &str, (uint8_t) percentage, 50, 80, str.length > 0); } ffStrbufPutTo(&str, stdout); - ffStrbufDestroy(&str); } else { diff --git a/src/modules/font.c b/src/modules/font.c index 3d6f91e379..c33d144fef 100644 --- a/src/modules/font.c +++ b/src/modules/font.c @@ -4,77 +4,10 @@ #include "detection/displayserver/displayserver.h" #define FF_FONT_MODULE_NAME "Font" -#define FF_FONT_NUM_FORMAT_ARGS 4 - -#if defined(__linux__) || defined(__FreeBSD__) -#include "common/parsing.h" - -static void printFont(const FFFontResult* font) -{ - FFstrbuf gtk; - ffStrbufInit(>k); - ffParseGTK(>k, &font->fonts[1], &font->fonts[2], &font->fonts[3]); - - if(font->fonts[0].length > 0) - { - printf("%s [QT]", font->fonts[0].chars); - if(gtk.length > 0) - fputs(", ", stdout); - } - - ffStrbufWriteTo(>k, stdout); - ffStrbufDestroy(>k); -} - -#elif defined(__APPLE__) - -static void printFont(const FFFontResult* font) -{ - if(font->fonts[0].length > 0) - { - printf("%s [System]", font->fonts[0].chars); - if(font->fonts[1].length > 0) - fputs(", ", stdout); - } - - if(font->fonts[1].length > 0) - printf("%s [User]", font->fonts[1].chars); -} - -#elif defined(_WIN32) - -static void printFont(const FFFontResult* font) -{ - const char* types[] = { "Caption", "Menu", "Message", "Status" }; - for(uint32_t i = 0; i < sizeof(types) / sizeof(types[0]); ++i) - { - if(i == 0 || !ffStrbufEqual(&font->fonts[i - 1], &font->fonts[i])) - { - if(i > 0) - fputs("], ", stdout); - printf("%s [%s", font->fonts[i].chars, types[i]); - } - else - { - printf(" / %s", types[i]); - } - } - putchar(']'); -} - -#else - -static void printFont(const FFFontResult* font) -{ - FF_UNUSED(font); -} - -#endif +#define FF_FONT_NUM_FORMAT_ARGS (FF_DETECT_FONT_NUM_FONTS + 1) void ffPrintFont(FFinstance* instance) { - assert(FF_DETECT_FONT_NUM_FONTS == FF_FONT_NUM_FORMAT_ARGS); - const FFFontResult* font = ffDetectFont(instance); if(font->error.length > 0) @@ -86,8 +19,7 @@ void ffPrintFont(FFinstance* instance) if(instance->config.font.outputFormat.length == 0) { ffPrintLogoAndKey(instance, FF_FONT_MODULE_NAME, 0, &instance->config.font.key); - printFont(font); - putchar('\n'); + ffStrbufPutTo(&font->display, stdout); } else { @@ -95,7 +27,8 @@ void ffPrintFont(FFinstance* instance) {FF_FORMAT_ARG_TYPE_STRBUF, &font->fonts[0]}, {FF_FORMAT_ARG_TYPE_STRBUF, &font->fonts[1]}, {FF_FORMAT_ARG_TYPE_STRBUF, &font->fonts[2]}, - {FF_FORMAT_ARG_TYPE_STRBUF, &font->fonts[3]} + {FF_FORMAT_ARG_TYPE_STRBUF, &font->fonts[3]}, + {FF_FORMAT_ARG_TYPE_STRBUF, &font->display}, }); } } diff --git a/src/modules/gamepad.c b/src/modules/gamepad.c index 7b935a9726..6bcb332f8b 100644 --- a/src/modules/gamepad.c +++ b/src/modules/gamepad.c @@ -6,14 +6,14 @@ static void printDevice(FFinstance* instance, const FFGamepadDevice* device, uint8_t index) { - if(instance->config.sound.outputFormat.length == 0) + if(instance->config.gamepad.outputFormat.length == 0) { - ffPrintLogoAndKey(instance, FF_GAMEPAD_MODULE_NAME, index, &instance->config.sound.key); + ffPrintLogoAndKey(instance, FF_GAMEPAD_MODULE_NAME, index, &instance->config.gamepad.key); ffStrbufPutTo(&device->name, stdout); } else { - ffPrintFormat(instance, FF_GAMEPAD_MODULE_NAME, index, &instance->config.sound, FF_GAMEPAD_NUM_FORMAT_ARGS, (FFformatarg[]) { + ffPrintFormat(instance, FF_GAMEPAD_MODULE_NAME, index, &instance->config.gamepad, FF_GAMEPAD_NUM_FORMAT_ARGS, (FFformatarg[]) { {FF_FORMAT_ARG_TYPE_STRBUF, &device->name}, {FF_FORMAT_ARG_TYPE_STRBUF, &device->identifier}, }); @@ -28,13 +28,13 @@ void ffPrintGamepad(FFinstance* instance) if(error) { - ffPrintError(instance, FF_GAMEPAD_MODULE_NAME, 0, &instance->config.sound, "%s", error); + ffPrintError(instance, FF_GAMEPAD_MODULE_NAME, 0, &instance->config.gamepad, "%s", error); return; } if(!result.length) { - ffPrintError(instance, FF_GAMEPAD_MODULE_NAME, 0, &instance->config.sound, "No devices detected"); + ffPrintError(instance, FF_GAMEPAD_MODULE_NAME, 0, &instance->config.gamepad, "No devices detected"); return; } diff --git a/src/modules/icons.c b/src/modules/icons.c index 81fa3af9db..50a0978fe3 100644 --- a/src/modules/icons.c +++ b/src/modules/icons.c @@ -36,7 +36,8 @@ void ffPrintIcons(FFinstance* instance) return; } - FF_STRBUF_CREATE(gtkPretty); + FF_STRBUF_AUTO_DESTROY gtkPretty; + ffStrbufInit(>kPretty); ffParseGTK(>kPretty, gtk2, gtk3, gtk4); if(instance->config.icons.outputFormat.length == 0) @@ -65,7 +66,5 @@ void ffPrintIcons(FFinstance* instance) }); } - ffStrbufDestroy(>kPretty); - #endif } diff --git a/src/modules/memory.c b/src/modules/memory.c index 05d7c33cf3..3c82b1a7b3 100644 --- a/src/modules/memory.c +++ b/src/modules/memory.c @@ -3,47 +3,41 @@ #include "common/parsing.h" #include "common/bar.h" #include "detection/memory/memory.h" -#include "detection/swap/swap.h" #define FF_MEMORY_MODULE_NAME "Memory" -#define FF_SWAP_MODULE_NAME "Swap" - #define FF_MEMORY_NUM_FORMAT_ARGS 3 -static uint8_t calculatePercentage(const FFMemoryStorage* storage) +void ffPrintMemory(FFinstance* instance) { - if(storage->error.length != 0 || storage->bytesTotal == 0) - return 0; - else - return (uint8_t) (((long double) storage->bytesUsed / (long double) storage->bytesTotal) * 100.0); -} + FFMemoryResult storage; + const char* error = ffDetectMemory(&storage); -static void printMemory(FFinstance* instance, const char* name, const FFModuleArgs* moduleArgs, const FFMemoryStorage* storage) -{ - if(storage->error.length > 0) + if(error) { - ffPrintError(instance, name, 0, moduleArgs, "%s", storage->error.chars); + ffPrintError(instance, FF_MEMORY_MODULE_NAME, 0, &instance->config.memory, "%s", error); return; } - FFstrbuf usedPretty; + FF_STRBUF_AUTO_DESTROY usedPretty; ffStrbufInit(&usedPretty); - ffParseSize(storage->bytesUsed, instance->config.binaryPrefixType, &usedPretty); + ffParseSize(storage.bytesUsed, instance->config.binaryPrefixType, &usedPretty); - FFstrbuf totalPretty; + FF_STRBUF_AUTO_DESTROY totalPretty; ffStrbufInit(&totalPretty); - ffParseSize(storage->bytesTotal, instance->config.binaryPrefixType, &totalPretty); + ffParseSize(storage.bytesTotal, instance->config.binaryPrefixType, &totalPretty); - uint8_t percentage = calculatePercentage(storage); + uint8_t percentage = storage.bytesTotal == 0 + ? 0 + : (uint8_t) (((long double) storage.bytesUsed / (long double) storage.bytesTotal) * 100.0); - if(moduleArgs->outputFormat.length == 0) + if(instance->config.memory.outputFormat.length == 0) { - ffPrintLogoAndKey(instance, name, 0, &moduleArgs->key); - if (storage->bytesTotal == 0) + ffPrintLogoAndKey(instance, FF_MEMORY_MODULE_NAME, 0, &instance->config.memory.key); + if (storage.bytesTotal == 0) puts("Disabled"); else { - FFstrbuf str; + FF_STRBUF_AUTO_DESTROY str; ffStrbufInit(&str); if(instance->config.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) @@ -60,36 +54,14 @@ static void printMemory(FFinstance* instance, const char* name, const FFModuleAr ffStrbufTrimRight(&str, ' '); ffStrbufPutTo(&str, stdout); - ffStrbufDestroy(&str); } } else { - ffPrintFormat(instance, name, 0, moduleArgs, FF_MEMORY_NUM_FORMAT_ARGS, (FFformatarg[]){ + ffPrintFormat(instance, FF_MEMORY_MODULE_NAME, 0, &instance->config.memory, FF_MEMORY_NUM_FORMAT_ARGS, (FFformatarg[]){ {FF_FORMAT_ARG_TYPE_STRBUF, &usedPretty}, {FF_FORMAT_ARG_TYPE_STRBUF, &totalPretty}, {FF_FORMAT_ARG_TYPE_UINT8, &percentage}, }); } - - ffStrbufDestroy(&usedPretty); - ffStrbufDestroy(&totalPretty); -} - -void ffPrintMemory(FFinstance* instance) -{ - FFMemoryStorage result; - ffStrbufInit(&result.error); - ffDetectMemory(&result); - printMemory(instance, FF_MEMORY_MODULE_NAME, &instance->config.memory, &result); - ffStrbufDestroy(&result.error); -} - -void ffPrintSwap(FFinstance* instance) -{ - FFMemoryStorage result; - ffStrbufInit(&result.error); - ffDetectSwap(&result); - printMemory(instance, FF_SWAP_MODULE_NAME, &instance->config.swap, &result); - ffStrbufDestroy(&result.error); } diff --git a/src/modules/opencl.c b/src/modules/opencl.c index 621165742f..c9d33b10d3 100644 --- a/src/modules/opencl.c +++ b/src/modules/opencl.c @@ -1,126 +1,39 @@ #include "fastfetch.h" #include "common/printing.h" +#include "detection/opencl/opencl.h" #define FF_OPENCL_MODULE_NAME "OpenCL" #define FF_OPENCL_NUM_FORMAT_ARGS 3 -#if defined(FF_HAVE_OPENCL) || defined(__APPLE__) -#include "common/library.h" -#include "common/parsing.h" -#include "util/stringUtils.h" -#include - -#define CL_TARGET_OPENCL_VERSION 100 -#ifdef FF_HAVE_OPENCL - #include -#else - #include -#endif - -typedef struct OpenCLData -{ - FF_LIBRARY_SYMBOL(clGetPlatformIDs) - FF_LIBRARY_SYMBOL(clGetDeviceIDs) - FF_LIBRARY_SYMBOL(clGetDeviceInfo) -} OpenCLData; - -static const char* openCLHandleData(FFinstance* instance, OpenCLData* data) +void ffPrintOpenCL(FFinstance* instance) { - cl_platform_id platformID; - cl_uint numPlatforms; - data->ffclGetPlatformIDs(1, &platformID, &numPlatforms); - - if(numPlatforms == 0) - return "clGetPlatformIDs returned 0 platforms"; - - cl_device_id deviceID; - cl_uint numDevices; - data->ffclGetDeviceIDs(platformID, CL_DEVICE_TYPE_GPU, 1, &deviceID, &numDevices); - - if(numDevices == 0) - data->ffclGetDeviceIDs(platformID, CL_DEVICE_TYPE_ALL, 1, &deviceID, &numDevices); - - if(numDevices == 0) - return "clGetDeviceIDs returned 0 devices"; - - char version[64]; - data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VERSION, sizeof(version), version, NULL); - if(!ffStrSet(version)) - return "clGetDeviceInfo returned NULL or empty string"; + FFOpenCLResult opencl; + ffStrbufInit(&opencl.version); + ffStrbufInit(&opencl.device); + ffStrbufInit(&opencl.vendor); - const char* versionPretty = version; - const char* prefix = "OpenCL "; - if(strncasecmp(version, prefix, sizeof(prefix) - 1) == 0) - versionPretty = version + sizeof(prefix) - 1; + const char* error = ffDetectOpenCL(instance, &opencl); - char device[128]; - data->ffclGetDeviceInfo(deviceID, CL_DEVICE_NAME, sizeof(device), device, NULL); - - char vendor[32]; - data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VENDOR, sizeof(vendor), vendor, NULL); - - if(instance->config.openCL.outputFormat.length == 0) - { - ffPrintLogoAndKey(instance, FF_OPENCL_MODULE_NAME, 0, &instance->config.openCL.key); - puts(versionPretty); - } + if(error != NULL) + ffPrintError(instance, FF_OPENCL_MODULE_NAME, 0, &instance->config.openCL, "%s", error); else { - ffPrintFormat(instance, FF_OPENCL_MODULE_NAME, 0, &instance->config.openCL, FF_OPENCL_NUM_FORMAT_ARGS, (FFformatarg[]) { - {FF_FORMAT_ARG_TYPE_STRING, versionPretty}, - {FF_FORMAT_ARG_TYPE_STRING, device}, - {FF_FORMAT_ARG_TYPE_STRING, vendor} - }); + if(instance->config.openCL.outputFormat.length == 0) + { + ffPrintLogoAndKey(instance, FF_OPENCL_MODULE_NAME, 0, &instance->config.openCL.key); + ffStrbufPutTo(&opencl.version, stdout); + } + else + { + ffPrintFormat(instance, FF_OPENCL_MODULE_NAME, 0, &instance->config.openCL, FF_OPENCL_NUM_FORMAT_ARGS, (FFformatarg[]) { + {FF_FORMAT_ARG_TYPE_STRBUF, &opencl.version}, + {FF_FORMAT_ARG_TYPE_STRBUF, &opencl.device}, + {FF_FORMAT_ARG_TYPE_STRBUF, &opencl.vendor}, + }); + } } - return NULL; -} - -#endif // FF_HAVE_OPENCL || __APPLE__ - -#ifdef FF_HAVE_OPENCL - -static const char* printOpenCL(FFinstance* instance) -{ - OpenCLData data; - - FF_LIBRARY_LOAD(opencl, &instance->config.libOpenCL, "dlopen libOpenCL"FF_LIBRARY_EXTENSION" failed", - #ifdef _WIN32 - "OpenCL"FF_LIBRARY_EXTENSION, -1, - #endif - "libOpenCL"FF_LIBRARY_EXTENSION, 1 - ); - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opencl, data, clGetPlatformIDs); - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opencl, data, clGetDeviceIDs); - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opencl, data, clGetDeviceInfo); - - return openCLHandleData(instance, &data); -} - -#elif defined(__APPLE__) // FF_HAVE_OPENCL - -static const char* printOpenCL(FFinstance* instance) -{ - OpenCLData data; - data.ffclGetPlatformIDs = clGetPlatformIDs; - data.ffclGetDeviceIDs = clGetDeviceIDs; - data.ffclGetDeviceInfo = clGetDeviceInfo; - - return openCLHandleData(instance, &data); -} - -#endif // FF_HAVE_OPENCL - -void ffPrintOpenCL(FFinstance* instance) -{ - const char* error; - - #if defined(FF_HAVE_OPENCL) || defined(__APPLE__) - error = printOpenCL(instance); - #else - error = "Fastfetch was build without OpenCL support"; - #endif - - if(error != NULL) - ffPrintError(instance, FF_OPENCL_MODULE_NAME, 0, &instance->config.openCL, "%s", error); + ffStrbufDestroy(&opencl.version); + ffStrbufDestroy(&opencl.device); + ffStrbufDestroy(&opencl.vendor); } diff --git a/src/modules/processes.c b/src/modules/processes.c index 5157f79b6f..70a64ad832 100644 --- a/src/modules/processes.c +++ b/src/modules/processes.c @@ -7,17 +7,14 @@ void ffPrintProcesses(FFinstance* instance) { - FFstrbuf error; - ffStrbufInit(&error); - uint32_t numProcesses = ffDetectProcesses(&error); + uint32_t numProcesses = 0; + const char* error = ffDetectProcesses(&numProcesses); - if(error.length > 0) + if(error) { - ffPrintError(instance, FF_PROCESSES_MODULE_NAME, 0, &instance->config.processes, "%*s", error.length, error.chars); - ffStrbufDestroy(&error); + ffPrintError(instance, FF_PROCESSES_MODULE_NAME, 0, &instance->config.processes, "%s", error); return; } - ffStrbufDestroy(&error); if(instance->config.processes.outputFormat.length == 0) { diff --git a/src/modules/sound.c b/src/modules/sound.c index 4ef58cdc22..ffc4aee76d 100644 --- a/src/modules/sound.c +++ b/src/modules/sound.c @@ -11,10 +11,13 @@ static void printDevice(FFinstance* instance, const FFSoundDevice* device, uint8 ffPrintLogoAndKey(instance, FF_SOUND_MODULE_NAME, index, &instance->config.sound.key); ffStrbufWriteTo(&device->name, stdout); - if(device->volume > 0) - printf(" (%d%%)", device->volume); - else - fputs(" (muted)", stdout); + if(device->volume != FF_SOUND_VOLUME_UNKNOWN) + { + if(device->volume > 0) + printf(" (%d%%)", device->volume); + else + fputs(" (muted)", stdout); + } if(device->main && index > 0) fputs(" (*)", stdout); diff --git a/src/modules/swap.c b/src/modules/swap.c new file mode 100644 index 0000000000..1f6175b15c --- /dev/null +++ b/src/modules/swap.c @@ -0,0 +1,67 @@ +#include "fastfetch.h" +#include "common/printing.h" +#include "common/parsing.h" +#include "common/bar.h" +#include "detection/swap/swap.h" + +#define FF_SWAP_MODULE_NAME "Swap" +#define FF_SWAP_NUM_FORMAT_ARGS 3 + +void ffPrintSwap(FFinstance* instance) +{ + FFSwapResult storage; + const char* error = ffDetectSwap(&storage); + + if(error) + { + ffPrintError(instance, FF_SWAP_MODULE_NAME, 0, &instance->config.swap, "%s", error); + return; + } + + FF_STRBUF_AUTO_DESTROY usedPretty; + ffStrbufInit(&usedPretty); + ffParseSize(storage.bytesUsed, instance->config.binaryPrefixType, &usedPretty); + + FF_STRBUF_AUTO_DESTROY totalPretty; + ffStrbufInit(&totalPretty); + ffParseSize(storage.bytesTotal, instance->config.binaryPrefixType, &totalPretty); + + uint8_t percentage = storage.bytesTotal == 0 + ? 0 + : (uint8_t) (((long double) storage.bytesUsed / (long double) storage.bytesTotal) * 100.0); + + if(instance->config.swap.outputFormat.length == 0) + { + ffPrintLogoAndKey(instance, FF_SWAP_MODULE_NAME, 0, &instance->config.swap.key); + if (storage.bytesTotal == 0) + puts("Disabled"); + else + { + FF_STRBUF_AUTO_DESTROY str; + ffStrbufInit(&str); + + if(instance->config.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + { + ffAppendPercentBar(instance, &str, percentage, 0, 5, 8); + ffStrbufAppendC(&str, ' '); + } + + if(!(instance->config.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) + ffStrbufAppendF(&str, "%s / %s ", usedPretty.chars, totalPretty.chars); + + if(instance->config.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + ffAppendPercentNum(instance, &str, (uint8_t) percentage, 50, 80, str.length > 0); + + ffStrbufTrimRight(&str, ' '); + ffStrbufPutTo(&str, stdout); + } + } + else + { + ffPrintFormat(instance, FF_SWAP_MODULE_NAME, 0, &instance->config.swap, FF_SWAP_NUM_FORMAT_ARGS, (FFformatarg[]){ + {FF_FORMAT_ARG_TYPE_STRBUF, &usedPretty}, + {FF_FORMAT_ARG_TYPE_STRBUF, &totalPretty}, + {FF_FORMAT_ARG_TYPE_UINT8, &percentage}, + }); + } +} diff --git a/src/modules/theme.c b/src/modules/theme.c index 04a2e1d7b1..9dde574d79 100644 --- a/src/modules/theme.c +++ b/src/modules/theme.c @@ -36,7 +36,8 @@ void ffPrintTheme(FFinstance* instance) return; } - FF_STRBUF_CREATE(plasmaColorPretty); + FF_STRBUF_AUTO_DESTROY plasmaColorPretty; + ffStrbufInit(&plasmaColorPretty); if(ffStrbufStartsWithIgnCase(&plasma->colorScheme, &plasma->widgetStyle)) ffStrbufAppendNS(&plasmaColorPretty, plasma->colorScheme.length - plasma->widgetStyle.length, &plasma->colorScheme.chars[plasma->widgetStyle.length]); else @@ -44,7 +45,8 @@ void ffPrintTheme(FFinstance* instance) ffStrbufTrim(&plasmaColorPretty, ' '); - FF_STRBUF_CREATE(gtkPretty); + FF_STRBUF_AUTO_DESTROY gtkPretty; + ffStrbufInit(>kPretty); ffParseGTK(>kPretty, gtk2, gtk3, gtk4); if(instance->config.theme.outputFormat.length == 0) @@ -98,8 +100,5 @@ void ffPrintTheme(FFinstance* instance) }); } - ffStrbufDestroy(&plasmaColorPretty); - ffStrbufDestroy(>kPretty); - #endif } diff --git a/src/util/FFstrbuf.h b/src/util/FFstrbuf.h index 3d6b12e8f7..d80a994835 100644 --- a/src/util/FFstrbuf.h +++ b/src/util/FFstrbuf.h @@ -28,8 +28,6 @@ typedef struct FFstrbuf char* chars; } FFstrbuf; -#define FF_STRBUF_CREATE(name) FFstrbuf name; ffStrbufInit(&name); - void ffStrbufInitA(FFstrbuf* strbuf, uint32_t allocate); void ffStrbufInitCopy(FFstrbuf* strbuf, const FFstrbuf* src); void ffStrbufInitMove(FFstrbuf* strbuf, FFstrbuf* src); @@ -206,11 +204,21 @@ static inline FF_C_NODISCARD bool ffStrbufContainS(const FFstrbuf* strbuf, const return strstr(strbuf->chars, str) != NULL; } +static inline FF_C_NODISCARD bool ffStrbufContain(const FFstrbuf* strbuf, const FFstrbuf* str) +{ + return ffStrbufContainS(strbuf, str->chars); +} + static inline FF_C_NODISCARD bool ffStrbufContainIgnCaseS(const FFstrbuf* strbuf, const char* str) { return strcasestr(strbuf->chars, str) != NULL; } +static inline FF_C_NODISCARD bool ffStrbufContainIgnCase(const FFstrbuf* strbuf, const FFstrbuf* str) +{ + return ffStrbufContainIgnCaseS(strbuf, str->chars); +} + static inline FF_C_NODISCARD uint32_t ffStrbufFirstIndexC(const FFstrbuf* strbuf, char c) { return ffStrbufNextIndexC(strbuf, 0, c); diff --git a/src/util/apple/cf_helpers.c b/src/util/apple/cf_helpers.c index f5c37b7ad3..797b51b591 100644 --- a/src/util/apple/cf_helpers.c +++ b/src/util/apple/cf_helpers.c @@ -2,6 +2,12 @@ const char* ffCfStrGetString(CFStringRef str, FFstrbuf* result) { + if (!str) + { + ffStrbufClear(result); + return NULL; + } + uint32_t length = (uint32_t)CFStringGetLength(str); //CFString stores UTF16 characters, therefore may require larger buffer to convert to UTF8 string ffStrbufEnsureFree(result, length * 2); diff --git a/src/util/platform/FFPlatform_unix.c b/src/util/platform/FFPlatform_unix.c index a971d75c55..251edef542 100644 --- a/src/util/platform/FFPlatform_unix.c +++ b/src/util/platform/FFPlatform_unix.c @@ -35,6 +35,7 @@ static void getConfigDirs(FFPlatform* platform) #if defined(__APPLE__) ffPlatformPathAddHome(&platform->configDirs, platform, "Library/Preferences/"); + ffPlatformPathAddHome(&platform->configDirs, platform, "Library/Application Support/"); #endif ffPlatformPathAddHome(&platform->configDirs, platform, ""); diff --git a/src/util/platform/FFPlatform_windows.c b/src/util/platform/FFPlatform_windows.c index bb793c1d1f..bfa5e1a7e3 100644 --- a/src/util/platform/FFPlatform_windows.c +++ b/src/util/platform/FFPlatform_windows.c @@ -1,11 +1,9 @@ #include "FFPlatform_private.h" #include "util/stringUtils.h" +#include "util/windows/unicode.h" #include #include - -#include "util/windows/unicode.h" - static void getHomeDir(FFPlatform* platform) { PWSTR pPath; @@ -41,8 +39,7 @@ static void platformPathAddKnownFolder(FFlist* dirs, REFKNOWNFOLDERID folderId) if(SUCCEEDED(SHGetKnownFolderPath(folderId, 0, NULL, &pPath))) { FFstrbuf* buffer = (FFstrbuf*) ffListAdd(dirs); - ffStrbufInit(buffer); - ffStrbufSetWS(buffer, pPath); + ffStrbufInitWS(buffer, pPath); ffStrbufReplaceAllC(buffer, '\\', '/'); ffStrbufEnsureEndsWithC(buffer, '/'); FF_PLATFORM_PATH_UNIQUE(dirs, buffer); @@ -159,7 +156,7 @@ static void getSystemReleaseAndVersion(FFPlatform* platform) DWORD ubr; bufSize = sizeof(ubr); - if(RegGetValueA(hKey, NULL, "UBR", RRF_RT_REG_DWORD, NULL, &ubr, &bufSize) != ERROR_SUCCESS || bufSize != sizeof(ubr)) + if(RegGetValueW(hKey, NULL, L"UBR", RRF_RT_REG_DWORD, NULL, &ubr, &bufSize) != ERROR_SUCCESS || bufSize != sizeof(ubr)) ubr = 0; ffStrbufAppendF(&platform->systemRelease, "%s.%s.%u", currentVersion, currentBuildNumber, (unsigned)ubr); diff --git a/src/util/windows/unicode.c b/src/util/windows/unicode.c index 57b3677aad..cf75a071cd 100644 --- a/src/util/windows/unicode.c +++ b/src/util/windows/unicode.c @@ -17,20 +17,17 @@ void ffStrbufSetNWS(FFstrbuf* result, uint32_t length, const wchar_t* source) result->chars[size_needed] = '\0'; } -FFstrbuf ffStrbufCreateNWS(uint32_t length, const wchar_t* source) +void ffStrbufInitNWS(FFstrbuf* result, uint32_t length, const wchar_t* source) { - FFstrbuf result; - - if(length == 0) - ffStrbufInit(&result); - else + if(!length) { - int size_needed = WideCharToMultiByte(CP_UTF8, 0, source, (int)length, NULL, 0, NULL, NULL); - ffStrbufInitA(&result, (uint32_t)size_needed); - WideCharToMultiByte(CP_UTF8, 0, source, (int)length, result.chars, size_needed, NULL, NULL); - result.length = (uint32_t)size_needed; - result.chars[size_needed] = '\0'; + ffStrbufInit(result); + return; } - return result; + int size_needed = WideCharToMultiByte(CP_UTF8, 0, source, (int)length, NULL, 0, NULL, NULL); + ffStrbufInitA(result, (uint32_t)size_needed + 1); + WideCharToMultiByte(CP_UTF8, 0, source, (int)length, result->chars, size_needed, NULL, NULL); + result->length = (uint32_t)size_needed; + result->chars[size_needed] = '\0'; } diff --git a/src/util/windows/unicode.h b/src/util/windows/unicode.h index f01080b0a9..6892134dc2 100644 --- a/src/util/windows/unicode.h +++ b/src/util/windows/unicode.h @@ -13,7 +13,19 @@ static inline void ffStrbufSetWS(FFstrbuf* result, const wchar_t* source) return ffStrbufSetNWS(result, (uint32_t)wcslen(source), source); } -FFstrbuf ffStrbufCreateNWS(uint32_t length, const wchar_t* source); +void ffStrbufInitNWS(FFstrbuf* result, uint32_t length, const wchar_t* source); + +static inline void ffStrbufInitWS(FFstrbuf* result, const wchar_t* source) +{ + return ffStrbufInitNWS(result, (uint32_t)wcslen(source), source); +} + +static inline FFstrbuf ffStrbufCreateNWS(uint32_t length, const wchar_t* source) +{ + FFstrbuf result; + ffStrbufInitNWS(&result, length, source); + return result; +} static inline FFstrbuf ffStrbufCreateWS(const wchar_t* source) {