diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a3c50f40..379c12bcb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,54 @@ +# 2.30.0 + +Changes: +* Percent: bar type must be enabled in `percent.type` before using percent bar in custom format + +Features: +* Port to MidnightBSD; add mport package manager support +* Support bluetooth battery detection for macOS and Windows (Bluetooth, macOS / Windows) +* Support M4 model detection (Host, macOS) +* Support CPU temperature detection on OpenBSD (CPU, OpenBSD) +* Display Android icon in Android devices (OS, Android) +* Support qi package manager detection (Packages, Linux) +* Detect WM / DE by enumerating running processes (WM / DE, NetBSD) +* Generate manual pages from `help.json` (Doc) +* Detect marketing name of vivo smartphone (Host, Android) +* Add txDrops detection if supported (NetIO, *BSD) +* Support tilix version detection (Terminal, Linux) +* Support percent type config in module level. Example: + +```json +{ + "type": "memory", + "percent": { + "green": 20, // [0%, 20%) will be displayed in green + "yellow": 40, // [20, 40) will be displayed in yellow and [40, 100] will be displayed in red + "type": [ // Display percent value in monochrome bar, same as 10 + "bar", + "bar-monochrome" + ] + } +} +``` + +Bugfixes: +* Don't display `()` in key if display name is not available (Display) +* Fix & normalize bluetooth mac address detection (Bluetooth, macOS / Windows) +* Don't print index in multi-battery devices (Battery) +* Fix segfault in macOS (#1388, macOS) +* Fix `CFStringGetCString() failed` errors (#1394, Media, macOS) +* Fix CPU frequency detection on Apple M4 (#1394, CPU, macOS) +* Fix exe path detection on macOS (Shell / Terminal, macOS) +* Fix logo fails to load from symlinked files on macOS (#1395, Logo, macOS) +* Fix 32-bit truncation (NetIO, macOS) + +Logos: +* Fix Lilidog +* Add MidnightBSD +* Add Unifi +* Add Cosmic DE +* Update openSUSE Tumbleweed + # 2.29.0 Changes: diff --git a/CMakeLists.txt b/CMakeLists.txt index cc33bf5be..ec7725f46 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 2.29.0 + VERSION 2.30.0 LANGUAGES C DESCRIPTION "Fast neofetch-like system information tool" HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch" @@ -20,6 +20,9 @@ elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "FreeBSD") set(FreeBSD TRUE CACHE BOOL "..." FORCE) elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "OpenBSD") set(OpenBSD TRUE CACHE BOOL "..." FORCE) +elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "MidnightBSD") + set(FreeBSD TRUE CACHE BOOL "..." FORCE) + set(MidnightBSD TRUE CACHE BOOL "..." FORCE) elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "NetBSD") set(NetBSD TRUE CACHE BOOL "..." FORCE) elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "DragonFly") @@ -253,6 +256,7 @@ endfunction(fastfetch_load_text) find_package(Python) if(Python_FOUND) + message(STATUS "Minifying 'help.json'") execute_process(COMMAND ${Python_EXECUTABLE} -c "import json,sys;json.dump(json.load(sys.stdin),sys.stdout,separators=(',',':'))" INPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/src/data/help.json" OUTPUT_VARIABLE DATATEXT_JSON_HELP) @@ -260,20 +264,31 @@ if(Python_FOUND) message(ERROR "DATATEXT_JSON_HELP is empty, which should not happen!") endif() else() - message(STATUS "Python3 is not found, 'help.json' will not be minified") + message(WARNING "Python3 is not found, 'help.json' will not be minified") file(READ "src/data/help.json" DATATEXT_JSON_HELP) endif() if(ENABLE_EMBEDDED_PCIIDS AND NOT EXISTS "fastfetch_pciids.c.inc") if(Python_FOUND) + message(STATUS "Generating 'fastfetch_pciids.c.inc'") execute_process(COMMAND ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/scripts/gen-pciids.py" OUTPUT_FILE "fastfetch_pciids.c.inc") else() - message(STATUS "Python3 is not found, 'fastfetch_pciids.c.inc' will not be generated") + message(WARNING "Python3 is not found, 'fastfetch_pciids.c.inc' will not be generated") set(ENABLE_EMBEDDED_PCIIDS OFF) endif() endif() +if(Python_FOUND) + message(STATUS "Generating 'fastfetch.1'") + execute_process(COMMAND ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/scripts/gen-man.py" + OUTPUT_FILE "fastfetch.1") +else() + message(WARNING "Python3 is not found, use basic 'fastfetch.1.in' instead") + string(TIMESTAMP FASTFETCH_BUILD_DATE "%d %B %Y" UTC) + configure_file(doc/fastfetch.1.in fastfetch.1 @ONLY) +endif() + fastfetch_encode_c_string("${DATATEXT_JSON_HELP}" DATATEXT_JSON_HELP) fastfetch_load_text(src/data/structure.txt DATATEXT_STRUCTURE) fastfetch_load_text(src/data/help_footer.txt DATATEXT_HELP_FOOTER) @@ -286,9 +301,6 @@ if(APPLE) configure_file(src/util/apple/Info.plist.in Info.plist @ONLY) endif() -string(TIMESTAMP FASTFETCH_BUILD_DATE "%d %B %Y" UTC) -configure_file(doc/fastfetch.1.in fastfetch.1 @ONLY) - #################### # Ascii image data # #################### @@ -875,7 +887,7 @@ elseif(APPLE) src/detection/media/media_apple.m src/detection/memory/memory_apple.c src/detection/mouse/mouse_apple.c - src/detection/netio/netio_bsd.c + src/detection/netio/netio_apple.c src/detection/opengl/opengl_apple.c src/detection/os/os_apple.m src/detection/packages/packages_apple.c @@ -912,6 +924,7 @@ elseif(WIN32) src/detection/battery/battery_windows.c src/detection/bios/bios_windows.c src/detection/bluetooth/bluetooth_windows.c + src/detection/bluetooth/bluetooth_windows.cpp src/detection/bluetoothradio/bluetoothradio_windows.c src/detection/board/board_windows.c src/detection/bootmgr/bootmgr_windows.c @@ -1123,17 +1136,25 @@ if(APPLE AND EXISTS "/usr/bin/otool") target_compile_definitions(libfastfetch PUBLIC FF_LIBSYSTEM_VERSION="${CMAKE_MATCH_1}") endif() endif() -if(FreeBSD AND EXISTS "/usr/local/bin/objdump") +if(MidnightBSD AND EXISTS "/usr/bin/objdump") + execute_process(COMMAND /bin/sh -c "/usr/bin/objdump -T /lib/libc.so.* | grep 'FBSD_[0-9][0-9]*\\.[0-9][0-9]*' -o | sort -Vru | head -1" + OUTPUT_VARIABLE OBJDUMP_T_RESULT) + if("${OBJDUMP_T_RESULT}" MATCHES "FBSD_([0-9]+\\.[0-9]+)") + message(STATUS "Found FBSD ${CMAKE_MATCH_1}") + target_compile_definitions(libfastfetch PUBLIC FF_FBSD_VERSION="${CMAKE_MATCH_1}") + endif() +elseif(FreeBSD AND EXISTS "/usr/local/bin/objdump") execute_process(COMMAND /bin/sh -c "/usr/local/bin/objdump -T /lib/libc.so.* | grep 'FBSD_[0-9][0-9]*\\.[0-9][0-9]*' -o | sort -Vru | head -1" OUTPUT_VARIABLE OBJDUMP_T_RESULT) if("${OBJDUMP_T_RESULT}" MATCHES "FBSD_([0-9]+\\.[0-9]+)") + message(STATUS "Found FBSD ${CMAKE_MATCH_1}") target_compile_definitions(libfastfetch PUBLIC FF_FBSD_VERSION="${CMAKE_MATCH_1}") endif() -endif() -if(DragonFly AND EXISTS "/usr/local/bin/objdump") +elseif(DragonFly AND EXISTS "/usr/local/bin/objdump") execute_process(COMMAND /bin/sh -c "/usr/local/bin/objdump -T /lib/libc.so.* | grep 'DF[0-9][0-9]*\\.[0-9][0-9]*' -o | sort -Vru | head -1" OUTPUT_VARIABLE OBJDUMP_T_RESULT) if("${OBJDUMP_T_RESULT}" MATCHES "DF([0-9]+\\.[0-9]+)") + message(STATUS "Found DF ${CMAKE_MATCH_1}") target_compile_definitions(libfastfetch PUBLIC FF_DF_VERSION="${CMAKE_MATCH_1}") endif() endif() @@ -1143,7 +1164,7 @@ if(LINUX) elseif(ANDROID) target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE _FILE_OFFSET_BITS=64 "$<$:__BIONIC_FORTIFY>" "$<$:__BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED>") elseif(WIN32) - target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE WIN32_LEAN_AND_MEAN=1 _WIN32_WINNT=0x0A00 NOMINMAX) # "$<$:_FORTIFY_SOURCE=3>" + target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE WIN32_LEAN_AND_MEAN _WIN32_WINNT=0x0A00 NOMINMAX UNICODE) # "$<$:_FORTIFY_SOURCE=3>" elseif(APPLE) target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE __STDC_WANT_LIB_EXT1__ _FILE_OFFSET_BITS=64 _DARWIN_C_SOURCE) elseif(OpenBSD) @@ -1159,6 +1180,16 @@ elseif(NetBSD) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,/usr/X11R7/lib -Wl,-rpath,/usr/pkg/lib") # ditto endif() +if(FreeBSD OR OpenBSD OR NetBSD) + include(CheckStructHasMember) + set(CMAKE_REQUIRED_DEFINITIONS "-D_IFI_OQDROPS=1") + CHECK_STRUCT_HAS_MEMBER("struct if_data" ifi_oqdrops net/if.h HAVE_IFI_OQDROPS LANGUAGE C) + if(HAVE_IFI_OQDROPS) + target_compile_definitions(libfastfetch PUBLIC _IFI_OQDROPS FF_HAVE_IFI_OQDROPS) + endif() + unset(CMAKE_REQUIRED_DEFINITIONS) +endif() + if(HAVE_STATX) target_compile_definitions(libfastfetch PUBLIC FF_HAVE_STATX) endif() @@ -1425,6 +1456,7 @@ elseif(WIN32) PRIVATE "imagehlp" PRIVATE "cfgmgr32" PRIVATE "winbrand" + PRIVATE "propsys" ) elseif(FreeBSD) target_link_libraries(libfastfetch diff --git a/README.md b/README.md index 6487d0e70..01f9d44bf 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,6 @@ Some distros package an outdated fastfetch version. Older versions receive no su * openSUSE: `zypper install fastfetch` * ALT Linux: `apt-get install fastfetch` * Exherbo: `cave resolve --execute app-misc/fastfetch` -* GNU Guix: `guix install fastfetch` * Solus: `eopkg install fastfetch` * Slackware: `sbopkg -i fastfetch` * Void Linux: `xbps-install fastfetch` @@ -194,7 +193,7 @@ See [#1096](https://github.com/fastfetch-cli/fastfetch/issues/1096). Neofetch incorrectly counts `rc` packages ( the package has been removed, but that the configuration files remain ). Bug https://github.com/dylanaraps/neofetch/issues/2278 -### Q: I use Debian / Ubuntu / Debian deserved distro. My GPU is detected as `XXXX Device XXXX (VGA compatible)`. Is it a bug? +### Q: I use Debian / Ubuntu / Debian derived distro. My GPU is detected as `XXXX Device XXXX (VGA compatible)`. Is it a bug? Try upgrading `pci.ids`: Download and overwrite file `/usr/share/hwdata/pci.ids`. For AMD GPUs, you should also upgrade `amdgpu.ids`: Download and overwrite file `/usr/share/libdrm/amdgpu.ids` diff --git a/debian/changelog b/debian/changelog index d7fed4125..7fac832e2 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +fastfetch (2.29.0) jammy; urgency=medium + + * Update to 2.29.0 + + -- Carter Li Mon, 04 Nov 2024 15:05:02 +0800 + fastfetch (2.28.0) jammy; urgency=medium * Update to 2.28.0 diff --git a/debian/files b/debian/files index 386b6ac11..b90fea35f 100644 --- a/debian/files +++ b/debian/files @@ -1 +1 @@ -fastfetch_2.28.0_source.buildinfo universe/utils optional +fastfetch_2.29.0_source.buildinfo universe/utils optional diff --git a/doc/json_schema.json b/doc/json_schema.json index 6c30442c4..3c0c9fa76 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -34,6 +34,35 @@ "description": "Output color of the module. Left empty to use `display.color.output`", "$ref": "#/$defs/colors" }, + "percentType": { + "description": "Set the percentage output type", + "oneOf": [ + { + "type": "number", + "description": "1 for percentage number, 2 for multi-color bar, 3 for both, 6 for bar only, 9 for colored number, 10 for monochrome bar", + "minimum": 0, + "maximum": 255, + "default": 9 + }, + { + "type": "array", + "description": "array of string flags", + "items": { + "enum": [ + "num", + "bar", + "hide-others", + "num-color", + "bar-monochrome" + ] + }, + "default": [ + "num", + "num-color" + ] + } + ] + }, "percent": { "description": "Threshold of percentage colors", "type": "object", @@ -50,6 +79,9 @@ "minimum": 0, "maximum": 100, "description": "Value greater than green and less then yellow will be shown in yellow.\nValue greater than yellow will be shown in red" + }, + "type": { + "$ref": "#/$defs/percentType" } } }, @@ -576,11 +608,7 @@ "description": "Set how a percentage value should be displayed", "properties": { "type": { - "type": "number", - "description": "Set the percentage output type. 1 for percentage number, 2 for multi-color bar, 3 for both, 6 for bar only, 9 for colored number, 10 for monochrome bar", - "minimum": 0, - "maximum": 255, - "default": 9 + "$ref": "#/$defs/percentType" }, "ndigits": { "type": "number", @@ -1942,15 +1970,19 @@ "eopkg", "flatpak", "guix", + "linglong", "lpkg", "lpkgbuild", "macports", + "mport", "nix", "opkg", "pacman", + "pacstall", "paludis", "pkg", "pkgtool", + "qi", "rpm", "scoop", "snap", diff --git a/scripts/gen-man.py b/scripts/gen-man.py new file mode 100755 index 000000000..def48b072 --- /dev/null +++ b/scripts/gen-man.py @@ -0,0 +1,256 @@ +#!/usr/bin/env python3 + +""" +Python script to generate a man page for the command `fastfetch`. +The man content will be printed to stdout so you will need to +pipe it to a file if you want to save it. +The command options will be generated using a JSON file. +For the format of the JSON file, see https://github.com/fastfetch-cli/fastfetch/blob/dev/src/data/help.json +""" + +from json import load +from datetime import date +from time import time +from re import search +from os import environ, path + + +###### Text Decorations Tags ###### + +startUnderline = r"\fI" # start underline text tag +endUnderline = r"\fR" # end underline text tag + +startBold = r"\fB" # start bold text tag +endBold = r"\fR" # end bold text tag + + +###### Parameters ###### + +# path to the current directory +pathToCurrentDir = path.dirname(__file__) +# path to the JSON option file +pathToHelpFile = path.join(pathToCurrentDir, "../src/data/help.json") +# man page section +manSection = 1 +# title (center header) +titlePage = "Fastfetch man page" +# date (center footer) +# format : "Month (abbreviation) Day Year" +todayDate = date.fromtimestamp( + int(environ.get("SOURCE_DATE_EPOCH", time()))).strftime("%b %d %Y") +# file to fastfetch version (left footer) +pathToVersionFile = path.join(pathToCurrentDir, "../CMakeLists.txt") + + +###### Sections Text ###### + +# text displayed in the "NAME" section +nameSection = r"fastfetch \- A maintained, feature\-rich and performance oriented, neofetch like system information tool" + +# text displayed at the beginning of the "OPTIONS" section +optionSection = r""" +Parsing is not case sensitive. E.g. \fB--logo-type\fR is +equal to \fB--LOGO-TYPE\fR. + +If a value is between square brakets, it is optional. +An optional boolean value defaults to true if not specified. + +More detailed help messages for each options can be printed +with \fB-h \fR. + +All options can be made permanent with command +\fBfastfetch --gen-config\fR. +""" + +# text displayed in the "CONFIGURATION" +configurationSection = f""" +.SS Fetch Structure + +The structure of a fetch describes the modules that should +be included in the output. It consists of a string of modules, +separated by a colon (:). To list all available modules, +use --list-modules. + + +.SS Config Files + +Fastfetch uses JSONC based format for configuration. +Fastfetch doesn't generate config file automatically; +it should be generated manually by {startBold}--gen-config{endBold}. +The config file will be saved in +{startBold}~/.config/fastfetch/config.jsonc{endBold} by default. + +A JSONC config file is a JSON file that also supports comments +with (// and /* */). Those files must have the extension '.jsonc'. + +The specified configuration/preset files are searched in the following order: + +{startBold}1.{endBold} relative to the current working directory + +{startBold}2.{endBold} relative to ~/.local/share/fastfetch/presets/ + +{startBold}3.{endBold} relative to /usr/share/fastfetch/presets/ + +Fastfetch provides some default presets. List them with --list-presets. +""" + +# text displayed in the "EXAMPLE" section +exampleSection = """ +.SS Config files: +.nf +// ~/.config/fastfetch/config.jsonc +{ + "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json", + "modules": [ + "title", + "separator", + "module1", + { + "type": "module2", + "module2-option": "value" + } + ] +} +.fi +""" + +# text displayed in the "BUGS" section +bugSection = "Please report bugs to : \ +https://github.com/fastfetch-cli/fastfetch/issues" + +# text displayed in the "WIKI" section +wikiSection = "Fastfetch github wiki : https://github.com/fastfetch-cli/fastfetch/wiki/Configuration" + + +###### Argument decoration ###### + +### optional arguments tags ### + +# if an optional argument is displayed as [?optArg] (with "optArg" underlined) +# this value should be f"[?{startUnderline}" +startOptionalArgument = f"[{startUnderline}?" +# if an optional argument is displayed as [?optArg] (with "optArg underlined") +# this value should be f"{endUnderline}]" +endOptionalArgument = f"{endUnderline}]" + +### mandatory arguments tags ### +startMandatoryArgument = f"{startUnderline}" +endMandatoryArgument = f"{endUnderline}" + +def main(): + + # importing the JSON file + with open(pathToHelpFile, 'r') as jsonFile: + helpFileData = load(jsonFile) # json.load + + + ######## Start printing the generated .1 file ######## + + + ###### header, footer & config ##### + + print(f".TH FASTFETCH {manSection} ", end=" ") + print(f"\"{todayDate}\"", end=" ") + + # version number + with open(pathToVersionFile, 'r') as versionFile: + + # research version number in file with regex + for line in versionFile: + researchVersion = search(r"^\s*VERSION (\d+\.\d+\.\d+)$", line) + if (researchVersion): + print(f"\"{researchVersion.group(1)}\"", end=" ") + break + + print(f"\"{titlePage}\"") + + + ###### Name ###### + + print(".SH NAME") + print(nameSection) + + + ##### Synopsis ###### + + print(".SH SYNOPSIS") + print(".B fastfetch") + print(f"[{startUnderline}OPTIONS{endUnderline}]")\ + + + ###### Wiki ###### + + print(".SH WIKI") + print(wikiSection) + + + ###### Configuration ###### + + print(".SH CONFIGURATION") + print(configurationSection) + + + ###### Options ###### + + print(".SH OPTIONS") + print(optionSection) + print() + + # loop through every options sections + for key, value in helpFileData.items(): + + # print new subsection + print(f".SS {key}:") + + # loop through every option in a section + for option in value: + # list of existing keys for this option + keyList = option.keys() + + # start a new "option" entry + print(".TP") + print(startBold, end="") + + # short option (-opt) + if "short" in keyList: + print(fr"\-{ option['short'] }", end="") + # if also have a long option, print a comma + if "long" in keyList: + print(", ", end="") + + # long option (--option) + if "long" in keyList: + print(fr"\-\-{ option['long'] }", end="") + + print(endBold, end=" ") + + # arguments + if "arg" in keyList: + # if argument is optional, print "[arg]" + if "optional" in option["arg"].keys() and option["arg"]["optional"]: + print(startOptionalArgument + option['arg']['type'] + endOptionalArgument, end="") + + # if argument is mandatory, print "arg" + else: + print(startMandatoryArgument + option['arg']['type'] + endMandatoryArgument, end="") + + # description + print(f"\n {option['desc']} \n") + + + ###### Examples ###### + + print(".SH EXAMPLES") + print(exampleSection) + + + ###### Bugs ###### + + print(".SH BUGS") + print(bugSection) + + + + +if __name__ == "__main__": + main() diff --git a/scripts/gen-pciids.py b/scripts/gen-pciids.py old mode 100644 new mode 100755 index 80e7304fb..875b8511a --- a/scripts/gen-pciids.py +++ b/scripts/gen-pciids.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + from requests import get as http_get class PciDeviceModel: diff --git a/src/common/format.h b/src/common/format.h index 79e1c90f4..fa092b40a 100644 --- a/src/common/format.h +++ b/src/common/format.h @@ -2,7 +2,7 @@ #include "util/FFstrbuf.h" -typedef enum FFformatArgType +typedef enum __attribute__((__packed__)) FFformatArgType { FF_FORMAT_ARG_TYPE_NULL = 0, FF_FORMAT_ARG_TYPE_UINT, diff --git a/src/common/io/io.h b/src/common/io/io.h index 84b3ec988..4cee2e471 100644 --- a/src/common/io/io.h +++ b/src/common/io/io.h @@ -87,11 +87,12 @@ static inline bool ffReadFileBufferRelative(FFNativeFD dfd, const char* fileName } //Bit flags, combine with | -typedef enum FFPathType +typedef enum __attribute__((__packed__)) FFPathType { FF_PATHTYPE_FILE = 1 << 0, FF_PATHTYPE_DIRECTORY = 1 << 1, FF_PATHTYPE_ANY = FF_PATHTYPE_FILE | FF_PATHTYPE_DIRECTORY, + FF_PATHTYPE_FORCE_UNSIGNED = UINT8_MAX, } FFPathType; static inline bool ffPathExists(const char* path, FFPathType pathType) @@ -118,6 +119,19 @@ static inline bool ffPathExists(const char* path, FFPathType pathType) } else { + #if __APPLE__ // #1395 + struct stat fileStat; + if(stat(path, &fileStat) != 0) + return false; + + unsigned int mode = fileStat.st_mode & S_IFMT; + + if(pathType & FF_PATHTYPE_FILE && mode != S_IFDIR) + return true; + + if(pathType & FF_PATHTYPE_DIRECTORY && mode == S_IFDIR) + return true; + #else size_t len = strlen(path); assert(len < PATH_MAX); if (len == 0) return false; @@ -134,6 +148,7 @@ static inline bool ffPathExists(const char* path, FFPathType pathType) else ret = access(path, F_OK); return pathType == FF_PATHTYPE_DIRECTORY ? ret == 0 : ret == -1 && errno == ENOTDIR; + #endif } #endif diff --git a/src/common/option.h b/src/common/option.h index 10576c0ff..b9f3fb311 100644 --- a/src/common/option.h +++ b/src/common/option.h @@ -45,12 +45,13 @@ static inline void ffOptionInitModuleBaseInfo( baseInfo->generateJsonConfig = (__typeof__(baseInfo->generateJsonConfig)) generateJsonConfig; } -typedef enum FFModuleKeyType +typedef enum __attribute__((__packed__)) FFModuleKeyType { FF_MODULE_KEY_TYPE_NONE = 0, FF_MODULE_KEY_TYPE_STRING = 1 << 0, FF_MODULE_KEY_TYPE_ICON = 1 << 1, FF_MODULE_KEY_TYPE_BOTH = FF_MODULE_KEY_TYPE_STRING | FF_MODULE_KEY_TYPE_ICON, + FF_MODULE_KEY_TYPE_FORCE_UNSIGNED = UINT8_MAX, } FFModuleKeyType; typedef struct FFModuleArgs diff --git a/src/common/percent.c b/src/common/percent.c index 9cc6e9d45..8a1dffc14 100644 --- a/src/common/percent.c +++ b/src/common/percent.c @@ -14,7 +14,46 @@ static void appendOutputColor(FFstrbuf* buffer, const FFModuleArgs* module) ffStrbufAppendF(buffer, "\e[%sm", instance.config.display.colorOutput.chars); } -void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFColorRangeConfig config, const FFModuleArgs* module) +const char* ffPercentParseTypeJsonConfig(yyjson_val* jsonVal, FFPercentageTypeFlags* result) +{ + if (yyjson_is_uint(jsonVal)) + { + *result = (FFPercentageTypeFlags) yyjson_get_uint(jsonVal); + return NULL; + } + if (yyjson_is_arr(jsonVal)) + { + FFPercentageTypeFlags flags = 0; + + yyjson_val* item; + size_t idx, max; + yyjson_arr_foreach(jsonVal, idx, max, item) + { + const char* flag = yyjson_get_str(item); + if (!flag) + return "Error: percent.type: invalid flag string"; + if (ffStrEqualsIgnCase(flag, "num")) + flags |= FF_PERCENTAGE_TYPE_NUM_BIT; + else if (ffStrEqualsIgnCase(flag, "bar")) + flags |= FF_PERCENTAGE_TYPE_BAR_BIT; + else if (ffStrEqualsIgnCase(flag, "hide-others")) + flags |= FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT; + else if (ffStrEqualsIgnCase(flag, "num-color")) + flags |= FF_PERCENTAGE_TYPE_NUM_COLOR_BIT; + else if (ffStrEqualsIgnCase(flag, "bar-monochrome")) + flags |= FF_PERCENTAGE_TYPE_BAR_MONOCHROME_BIT; + else + return "Error: percent.type: unknown flag string"; + } + + *result = flags; + return NULL; + } + + return "Error: usage: percent.type must be a number or an array of strings"; +} + +void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFPercentageModuleConfig config, const FFModuleArgs* module) { uint8_t green = config.green, yellow = config.yellow; assert(green <= 100 && yellow <= 100); @@ -41,15 +80,18 @@ void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFColorRangeConfig con } else { - const char* colorGreen = instance.config.display.percentColorGreen.chars; - const char* colorYellow = instance.config.display.percentColorYellow.chars; - const char* colorRed = instance.config.display.percentColorRed.chars; + const char* colorGreen = options->percentColorGreen.chars; + const char* colorYellow = options->percentColorYellow.chars; + const char* colorRed = options->percentColorRed.chars; + + FFPercentageTypeFlags percentType = config.type == 0 ? options->percentType : config.type; + bool monochrome = !!(percentType & FF_PERCENTAGE_TYPE_BAR_MONOCHROME_BIT); for (uint32_t i = 0; i < blocksPercent; ++i) { if(!options->pipe) { - if (options->percentType & FF_PERCENTAGE_TYPE_BAR_MONOCHROME_BIT) + if (monochrome) { const char* color = NULL; if (green <= yellow) @@ -104,14 +146,15 @@ void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFColorRangeConfig con } } -void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFColorRangeConfig config, bool parentheses, const FFModuleArgs* module) +void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFPercentageModuleConfig config, bool parentheses, const FFModuleArgs* module) { uint8_t green = config.green, yellow = config.yellow; assert(green <= 100 && yellow <= 100); const FFOptionsDisplay* options = &instance.config.display; + FFPercentageTypeFlags percentType = config.type == 0 ? options->percentType : config.type; - bool colored = !!(options->percentType & FF_PERCENTAGE_TYPE_NUM_COLOR_BIT); + bool colored = !!(percentType & FF_PERCENTAGE_TYPE_NUM_COLOR_BIT); if (parentheses) ffStrbufAppendC(buffer, '('); @@ -156,7 +199,7 @@ void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFColorRangeConfig con ffStrbufAppendC(buffer, ')'); } -bool ffPercentParseCommandOptions(const char* key, const char* subkey, const char* value, FFColorRangeConfig* config) +bool ffPercentParseCommandOptions(const char* key, const char* subkey, const char* value, FFPercentageModuleConfig* config) { if (!ffStrStartsWithIgnCase(subkey, "percent-")) return false; @@ -187,10 +230,16 @@ bool ffPercentParseCommandOptions(const char* key, const char* subkey, const cha return true; } + if (ffStrEqualsIgnCase(subkey, "type")) + { + config->type = (FFPercentageTypeFlags) ffOptionParseUInt32(key, value); + return true; + } + return false; } -bool ffPercentParseJsonObject(const char* key, yyjson_val* value, FFColorRangeConfig* config) +bool ffPercentParseJsonObject(const char* key, yyjson_val* value, FFPercentageModuleConfig* config) { if (!ffStrEqualsIgnCase(key, "percent")) return false; @@ -225,10 +274,21 @@ bool ffPercentParseJsonObject(const char* key, yyjson_val* value, FFColorRangeCo config->yellow = (uint8_t) num; } + yyjson_val* typeVal = yyjson_obj_get(value, "type"); + if (typeVal) + { + const char* error = ffPercentParseTypeJsonConfig(typeVal, &config->type); + if (error) + { + fputs(error, stderr); + exit(480); + } + } + return true; } -void ffPercentGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFColorRangeConfig defaultConfig, FFColorRangeConfig config) +void ffPercentGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFPercentageModuleConfig defaultConfig, FFPercentageModuleConfig config) { if (config.green == defaultConfig.green && config.yellow == defaultConfig.yellow) return; @@ -238,4 +298,6 @@ void ffPercentGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FF yyjson_mut_obj_add_uint(doc, percent, "green", config.green); if (config.yellow != defaultConfig.yellow) yyjson_mut_obj_add_uint(doc, percent, "yellow", config.yellow); + if (config.type != defaultConfig.type) + yyjson_mut_obj_add_uint(doc, percent, "type", config.type); } diff --git a/src/common/percent.h b/src/common/percent.h index 33921f689..7341b7ba0 100644 --- a/src/common/percent.h +++ b/src/common/percent.h @@ -4,14 +4,24 @@ #include "common/parsing.h" #include "common/option.h" -enum FFPercentageTypeFlags +typedef enum __attribute__((__packed__)) FFPercentageTypeFlags { + FF_PERCENTAGE_TYPE_NONE = 0, FF_PERCENTAGE_TYPE_NUM_BIT = 1 << 0, FF_PERCENTAGE_TYPE_BAR_BIT = 1 << 1, FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT = 1 << 2, FF_PERCENTAGE_TYPE_NUM_COLOR_BIT = 1 << 3, FF_PERCENTAGE_TYPE_BAR_MONOCHROME_BIT = FF_PERCENTAGE_TYPE_NUM_COLOR_BIT, -}; + FF_PERCENTAGE_TYPE_FORCE_UNSIGNED_ = UINT8_MAX, +} FFPercentageTypeFlags; +static_assert(sizeof(FFPercentageTypeFlags) == 1, ""); + +typedef struct FFPercentageModuleConfig +{ + uint8_t green; + uint8_t yellow; + FFPercentageTypeFlags type; +} FFPercentageModuleConfig; // if (green <= yellow) // [0, green]: print green @@ -23,12 +33,13 @@ enum FFPercentageTypeFlags // [yellow, green): print yellow // [0, yellow): print red -void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFColorRangeConfig config, const FFModuleArgs* module); -void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFColorRangeConfig config, bool parentheses, const FFModuleArgs* module); +void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFPercentageModuleConfig config, const FFModuleArgs* module); +void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFPercentageModuleConfig config, bool parentheses, const FFModuleArgs* module); typedef struct yyjson_val yyjson_val; typedef struct yyjson_mut_doc yyjson_mut_doc; typedef struct yyjson_mut_val yyjson_mut_val; -bool ffPercentParseCommandOptions(const char* key, const char* subkey, const char* value, FFColorRangeConfig* config); -bool ffPercentParseJsonObject(const char* key, yyjson_val* value, FFColorRangeConfig* config); -void ffPercentGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFColorRangeConfig defaultConfig, FFColorRangeConfig config); +bool ffPercentParseCommandOptions(const char* key, const char* subkey, const char* value, FFPercentageModuleConfig* config); +bool ffPercentParseJsonObject(const char* key, yyjson_val* value, FFPercentageModuleConfig* config); +void ffPercentGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFPercentageModuleConfig defaultConfig, FFPercentageModuleConfig config); +const char* ffPercentParseTypeJsonConfig(yyjson_val* value, FFPercentageTypeFlags* result); diff --git a/src/common/printing.h b/src/common/printing.h index 2060337c5..94479dc03 100644 --- a/src/common/printing.h +++ b/src/common/printing.h @@ -3,12 +3,13 @@ #include "fastfetch.h" #include "common/format.h" -typedef enum FFPrintType { +typedef enum __attribute__((__packed__)) FFPrintType { FF_PRINT_TYPE_DEFAULT = 0, FF_PRINT_TYPE_NO_CUSTOM_KEY = 1 << 0, // key has been formatted outside FF_PRINT_TYPE_NO_CUSTOM_KEY_COLOR = 1 << 1, FF_PRINT_TYPE_NO_CUSTOM_KEY_WIDTH = 1 << 2, FF_PRINT_TYPE_NO_CUSTOM_OUTPUT_FORMAT = 1 << 3, // reserved + FF_PRINT_TYPE_FORCE_UNSIGNED = UINT8_MAX, } FFPrintType; void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType); diff --git a/src/common/processing_linux.c b/src/common/processing_linux.c index fb5db6260..3b290bc3d 100644 --- a/src/common/processing_linux.c +++ b/src/common/processing_linux.c @@ -147,7 +147,7 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons if (length > 0) // doesn't contain trailing NUL { buf[length] = '\0'; - ffStrbufEnsureFixedLengthFree(exePath, (uint32_t)length + 1); // +1 for the NUL + ffStrbufEnsureFixedLengthFree(exePath, (uint32_t)length); ffStrbufAppendNS(exePath, (uint32_t)length, buf); } } @@ -158,10 +158,8 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons int mibs[] = { CTL_KERN, KERN_PROCARGS2, pid }; if (sysctl(mibs, ARRAY_SIZE(mibs), NULL, &len, NULL, 0) == 0) {// try get arg0 - #ifndef MAC_OS_X_VERSION_10_15 //don't know why if don't let len longer, proArgs2 and len will change during the following sysctl() in old MacOS version. len++; - #endif FF_AUTO_FREE char* const procArgs2 = malloc(len); if (sysctl(mibs, ARRAY_SIZE(mibs), procArgs2, &len, NULL, 0) == 0) { @@ -195,11 +193,12 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons } else { - ffStrbufEnsureFixedLengthFree(exe, PATH_MAX); - int length = proc_pidpath(pid, exe->chars, exe->allocated); + char buf[PROC_PIDPATHINFO_MAXSIZE]; + int length = proc_pidpath(pid, buf, ARRAY_SIZE(buf)); if (length > 0) { - exe->length = (uint32_t) length; + ffStrbufEnsureFixedLengthFree(exe, (uint32_t) length); + ffStrbufAppendNS(exe, (uint32_t) length, buf); if (exePath) ffStrbufSet(exePath, exe); } @@ -275,7 +274,7 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons if (length > 0) // doesn't contain trailing NUL { buf[length] = '\0'; - ffStrbufEnsureFixedLengthFree(exePath, (uint32_t)length + 1); // +1 for the NUL + ffStrbufEnsureFixedLengthFree(exePath, (uint32_t)length); ffStrbufAppendNS(exePath, (uint32_t)length, buf); } } diff --git a/src/common/settings.h b/src/common/settings.h index 0b87bb33e..cfe6d093e 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -2,7 +2,7 @@ #include "fastfetch.h" -typedef enum FFvarianttype +typedef enum __attribute__((__packed__)) FFvarianttype { FF_VARIANT_TYPE_STRING, FF_VARIANT_TYPE_BOOL, diff --git a/src/data/help.json b/src/data/help.json index c7e4a88ec..481b3a3e2 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -1602,6 +1602,24 @@ }, "pseudo": true }, + { + "long": "-percent-type", + "desc": "Set the percentage output type", + "remark": [ + "0 for use global `--percent-type` value", + "1 for percentage number", + "2 for multi-color bar", + "3 for both", + "6 for bar only", + "9 for colored number", + "10 for monochrome bar" + ], + "arg": { + "type": "num", + "default": 0 + }, + "pseudo": true + }, { "long": "-temp-green", "desc": [ diff --git a/src/detection/bluetooth/bluetooth_apple.m b/src/detection/bluetooth/bluetooth_apple.m index abd31a0c2..4f29deb56 100644 --- a/src/detection/bluetooth/bluetooth_apple.m +++ b/src/detection/bluetooth/bluetooth_apple.m @@ -2,6 +2,14 @@ #import +@interface IOBluetoothDevice() + @property (nonatomic) uint8_t batteryPercentCase; + @property (nonatomic) uint8_t batteryPercentCombined; + @property (nonatomic) uint8_t batteryPercentLeft; + @property (nonatomic) uint8_t batteryPercentRight; + @property (nonatomic) uint8_t batteryPercentSingle; +@end + const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */) { NSArray* ioDevices = IOBluetoothDevice.pairedDevices; @@ -13,8 +21,17 @@ const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */) FFBluetoothResult* device = ffListAdd(devices); ffStrbufInitS(&device->name, ioDevice.name.UTF8String); ffStrbufInitS(&device->address, ioDevice.addressString.UTF8String); + ffStrbufReplaceAllC(&device->address, '-', ':'); + ffStrbufUpperCase(&device->address); ffStrbufInit(&device->type); - device->battery = 0; + + if (ioDevice.batteryPercentSingle) + device->battery = ioDevice.batteryPercentSingle; + else if (ioDevice.batteryPercentCombined) + device->battery = ioDevice.batteryPercentCombined; + else if (ioDevice.batteryPercentCase) + device->battery = ioDevice.batteryPercentCase; + device->connected = !!ioDevice.isConnected; if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorLimitedDiscoverableMode) ffStrbufAppendS(&device->type, "Limited Discoverable Mode, "); diff --git a/src/detection/bluetooth/bluetooth_windows.c b/src/detection/bluetooth/bluetooth_windows.c index acb2f4bb4..80b83837a 100644 --- a/src/detection/bluetooth/bluetooth_windows.c +++ b/src/detection/bluetooth/bluetooth_windows.c @@ -33,13 +33,13 @@ const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */) do { FFBluetoothResult* device = ffListAdd(devices); ffStrbufInitWS(&device->name, btdi.szName); - ffStrbufInitF(&device->address, "%02x:%02x:%02x:%02x:%02x:%02x", - btdi.Address.rgBytes[0], - btdi.Address.rgBytes[1], - btdi.Address.rgBytes[2], - btdi.Address.rgBytes[3], + ffStrbufInitF(&device->address, "%02X:%02X:%02X:%02X:%02X:%02X", + btdi.Address.rgBytes[5], btdi.Address.rgBytes[4], - btdi.Address.rgBytes[5]); + btdi.Address.rgBytes[3], + btdi.Address.rgBytes[2], + btdi.Address.rgBytes[1], + btdi.Address.rgBytes[0]); ffStrbufInit(&device->type); device->battery = 0; device->connected = !!btdi.fConnected; @@ -121,5 +121,8 @@ const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */) ffBluetoothFindDeviceClose(hFind); + const char* ffBluetoothDetectBattery(FFlist* result); + ffBluetoothDetectBattery(devices); + return NULL; } diff --git a/src/detection/bluetooth/bluetooth_windows.cpp b/src/detection/bluetooth/bluetooth_windows.cpp new file mode 100644 index 000000000..70fc1de18 --- /dev/null +++ b/src/detection/bluetooth/bluetooth_windows.cpp @@ -0,0 +1,122 @@ +extern "C" +{ +#include "bluetooth.h" +} +#include "util/windows/wmi.hpp" +#include "util/windows/unicode.hpp" + +STDAPI InitVariantFromStringArray(_In_reads_(cElems) PCWSTR *prgsz, _In_ ULONG cElems, _Out_ VARIANT *pvar); + +template +struct on_scope_exit { + on_scope_exit(Fn &&fn): _fn(std::move(fn)) {} + ~on_scope_exit() { this->_fn(); } + +private: + Fn _fn; +}; + +extern "C" +const char* ffBluetoothDetectBattery(FFlist* devices) +{ + FFWmiQuery query(L"SELECT __PATH FROM Win32_PnPEntity WHERE Service = 'BthHFEnum'", nullptr, FFWmiNamespace::CIMV2); + if(!query) + return "Query WMI service failed"; + + IWbemClassObject* pInParams = nullptr; + on_scope_exit releaseInParams([&] { pInParams && pInParams->Release(); }); + { + IWbemClassObject* pnpEntityClass = nullptr; + + if (FAILED(query.pService->GetObjectW(bstr_t(L"Win32_PnPEntity"), 0, nullptr, &pnpEntityClass, nullptr))) + return "Failed to get PnP entity class"; + on_scope_exit releasePnpEntityClass([&] { pnpEntityClass && pnpEntityClass->Release(); }); + + if (FAILED(pnpEntityClass->GetMethod(bstr_t(L"GetDeviceProperties"), 0, &pInParams, NULL))) + return "Failed to get GetDeviceProperties method"; + + VARIANT devicePropertyKeys; + PCWSTR props[] = { L"{104EA319-6EE2-4701-BD47-8DDBF425BBE5} 2", L"DEVPKEY_Bluetooth_DeviceAddress" }; + + if (FAILED(InitVariantFromStringArray(props, ARRAY_SIZE(props), &devicePropertyKeys))) + return "Failed to init variant from string array"; + on_scope_exit releaseDevicePropertyKeys([&] { VariantClear(&devicePropertyKeys); }); + + if (FAILED(pInParams->Put(L"devicePropertyKeys", 0, &devicePropertyKeys, CIM_FLAG_ARRAY | CIM_STRING))) + return "Failed to put devicePropertyKeys"; + } + + while (FFWmiRecord record = query.next()) + { + IWbemCallResult* pCallResult = nullptr; + + if (FAILED(query.pService->ExecMethod(record.get(L"__PATH").bstrVal, bstr_t(L"GetDeviceProperties"), 0, nullptr, pInParams, nullptr, &pCallResult))) + continue; + on_scope_exit releaseCallResult([&] { pCallResult && pCallResult->Release(); }); + + IWbemClassObject* pResultObject = nullptr; + if (FAILED(pCallResult->GetResultObject(WBEM_INFINITE, &pResultObject))) + continue; + on_scope_exit releaseResultObject([&] { pResultObject && pResultObject->Release(); }); + + VARIANT propArray; + if (FAILED(pResultObject->Get(L"deviceProperties", 0, &propArray, nullptr, nullptr))) + continue; + on_scope_exit releasePropArray([&] { VariantClear(&propArray); }); + + if (propArray.vt != (VT_ARRAY | VT_UNKNOWN) || + (propArray.parray->fFeatures & FADF_UNKNOWN) == 0 || + propArray.parray->cDims != 1 || + propArray.parray->rgsabound[0].cElements != 2 + ) + continue; + + uint8_t batt = 0; + for (LONG i = 0; i < 2; i++) + { + IWbemClassObject* object = nullptr; + if (FAILED(SafeArrayGetElement(propArray.parray, &i, &object))) + continue; + + FFWmiRecord rec(object); + auto data = rec.get(L"Data"); + if (data.vt == VT_EMPTY) + break; + + if (i == 0) + batt = data.get(); + else + { + FF_STRBUF_AUTO_DESTROY addr; // MAC address without colon + ffStrbufInitWSV(&addr, data.get()); + if (__builtin_expect(addr.length != 12, 0)) + continue; + + FF_LIST_FOR_EACH(FFBluetoothResult, bt, *devices) + { + if (bt->address.length != 12 + 5) + continue; + + if (addr.chars[0] == bt->address.chars[0] && + addr.chars[1] == bt->address.chars[1] && + addr.chars[2] == bt->address.chars[3] && + addr.chars[3] == bt->address.chars[4] && + addr.chars[4] == bt->address.chars[6] && + addr.chars[5] == bt->address.chars[7] && + addr.chars[6] == bt->address.chars[9] && + addr.chars[7] == bt->address.chars[10] && + addr.chars[8] == bt->address.chars[12] && + addr.chars[9] == bt->address.chars[13] && + addr.chars[10] == bt->address.chars[15] && + addr.chars[11] == bt->address.chars[16]) + { + bt->battery = batt; + break; + } + } + } + } + } + + return NULL; +} diff --git a/src/detection/bluetoothradio/bluetoothradio_windows.c b/src/detection/bluetoothradio/bluetoothradio_windows.c index c8471d442..c4482f14d 100644 --- a/src/detection/bluetoothradio/bluetoothradio_windows.c +++ b/src/detection/bluetoothradio/bluetoothradio_windows.c @@ -84,12 +84,12 @@ const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */) BLUETOOTH_ADDRESS_STRUCT addr = { .ullLong = blri.localInfo.address }; ffStrbufInitF(&device->address, "%02x:%02x:%02x:%02x:%02x:%02x", - addr.rgBytes[0], - addr.rgBytes[1], - addr.rgBytes[2], - addr.rgBytes[3], + addr.rgBytes[5], addr.rgBytes[4], - addr.rgBytes[5]); + addr.rgBytes[3], + addr.rgBytes[2], + addr.rgBytes[1], + addr.rgBytes[0]); device->lmpVersion = blri.radioInfo.lmpVersion; device->lmpSubversion = blri.radioInfo.lmpSubversion; diff --git a/src/detection/cpu/cpu.c b/src/detection/cpu/cpu.c index 774e747ae..a3b47416c 100644 --- a/src/detection/cpu/cpu.c +++ b/src/detection/cpu/cpu.c @@ -37,6 +37,8 @@ const char* ffCPUAppleCodeToName(uint32_t code) case 6031: case 6034: return "Apple M3 Max"; case 8132: return "Apple M4"; + case 6040: return "Apple M4 Pro"; + case 6041: return "Apple M4 Max"; default: return NULL; } } diff --git a/src/detection/cpu/cpu_apple.c b/src/detection/cpu/cpu_apple.c index 3c5f45940..1d94b005e 100644 --- a/src/detection/cpu/cpu_apple.c +++ b/src/detection/cpu/cpu_apple.c @@ -59,7 +59,12 @@ static const char* detectFrequency(FFCPUResult* cpu) pMax = pMax > pStart[i] ? pMax : pStart[i]; if (pMax > 0) - cpu->frequencyMax = pMax / 1000 / 1000; + { + if (pMax > 100000000) // Assume that pMax is in Hz, M1~M3 + cpu->frequencyMax = pMax / 1000 / 1000; + else // Assume that pMax is in kHz, M4 and later (#1394) + cpu->frequencyMax = pMax / 1000; + } return NULL; } diff --git a/src/detection/cpu/cpu_obsd.c b/src/detection/cpu/cpu_obsd.c index 04d550198..298f064d6 100644 --- a/src/detection/cpu/cpu_obsd.c +++ b/src/detection/cpu/cpu_obsd.c @@ -1,6 +1,9 @@ #include "cpu.h" #include "common/sysctl.h" +#include +#include + const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) { if (ffSysctlGetString(CTL_HW, HW_MODEL, &cpu->name)) @@ -13,7 +16,14 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) ffCPUDetectSpeedByCpuid(cpu); cpu->frequencyBase = (uint32_t) ffSysctlGetInt(CTL_HW, HW_CPUSPEED, 0); - cpu->temperature = FF_CPU_TEMP_UNSET; // HW_SENSORS? + cpu->temperature = FF_CPU_TEMP_UNSET; + if (options->temp) + { + struct sensor sensors; + size_t size = sizeof(sensors); + if (sysctl((int[]) {CTL_HW, HW_SENSORS, 0, SENSOR_TEMP, 0}, 5, &sensors, &size, NULL, 0) == 0) + cpu->temperature = (double) (sensors.value - 273150000) / 1E6; + } return NULL; } diff --git a/src/detection/cpucache/cpucache.h b/src/detection/cpucache/cpucache.h index fb8170c4a..f63964240 100644 --- a/src/detection/cpucache/cpucache.h +++ b/src/detection/cpucache/cpucache.h @@ -2,7 +2,7 @@ #include "fastfetch.h" -typedef enum FFCPUCacheType +typedef enum __attribute__((__packed__)) FFCPUCacheType { FF_CPU_CACHE_TYPE_UNIFIED = 0, FF_CPU_CACHE_TYPE_INSTRUCTION = 1, diff --git a/src/detection/cpucache/cpucache_apple.c b/src/detection/cpucache/cpucache_apple.c index 363733f8b..b0e315a14 100644 --- a/src/detection/cpucache/cpucache_apple.c +++ b/src/detection/cpucache/cpucache_apple.c @@ -20,35 +20,35 @@ const char* ffDetectCPUCache(FFCPUCacheResult* result) { *pNum = (char) ('0' + i); - ffStrCopyN(pSubkey, "physicalcpu", lenLeft); + ffStrCopy(pSubkey, "physicalcpu", lenLeft); uint32_t ncpu = (uint32_t) ffSysctlGetInt(sysctlKey, 0); if (ncpu <= 0) continue; - ffStrCopyN(pSubkey, "l1icachesize", lenLeft); + ffStrCopy(pSubkey, "l1icachesize", lenLeft); uint32_t size = (uint32_t) ffSysctlGetInt(sysctlKey, 0); if (size) ffCPUCacheAddItem(result, 1, size, lineSize, FF_CPU_CACHE_TYPE_INSTRUCTION)->num = ncpu; - ffStrCopyN(pSubkey, "l1dcachesize", lenLeft); + ffStrCopy(pSubkey, "l1dcachesize", lenLeft); size = (uint32_t) ffSysctlGetInt(sysctlKey, 0); if (size) ffCPUCacheAddItem(result, 1, size, lineSize, FF_CPU_CACHE_TYPE_DATA)->num = ncpu; - ffStrCopyN(pSubkey, "l2cachesize", lenLeft); + ffStrCopy(pSubkey, "l2cachesize", lenLeft); size = (uint32_t) ffSysctlGetInt(sysctlKey, 0); if (size) { - ffStrCopyN(pSubkey, "cpusperl2", lenLeft); + ffStrCopy(pSubkey, "cpusperl2", lenLeft); uint32_t cpuSper = (uint32_t) ffSysctlGetInt(sysctlKey, 0); if (cpuSper) ffCPUCacheAddItem(result, 2, size, lineSize, FF_CPU_CACHE_TYPE_UNIFIED)->num = ncpu / cpuSper; } - ffStrCopyN(pSubkey, "l3cachesize", lenLeft); + ffStrCopy(pSubkey, "l3cachesize", lenLeft); size = (uint32_t) ffSysctlGetInt(sysctlKey, 0); if (size) { - ffStrCopyN(pSubkey, "cpusperl3", lenLeft); + ffStrCopy(pSubkey, "cpusperl3", lenLeft); uint32_t cpuSper = (uint32_t) ffSysctlGetInt(sysctlKey, 0); if (cpuSper) ffCPUCacheAddItem(result, 3, size, lineSize, FF_CPU_CACHE_TYPE_UNIFIED)->num = ncpu / cpuSper; diff --git a/src/detection/displayserver/displayserver.h b/src/detection/displayserver/displayserver.h index d1d21839e..4de3bdd4d 100644 --- a/src/detection/displayserver/displayserver.h +++ b/src/detection/displayserver/displayserver.h @@ -42,13 +42,13 @@ #define FF_WM_PROTOCOL_X11 "X11" #define FF_WM_PROTOCOL_WAYLAND "Wayland" -typedef enum FFDisplayType { +typedef enum __attribute__((__packed__)) FFDisplayType { FF_DISPLAY_TYPE_UNKNOWN, FF_DISPLAY_TYPE_BUILTIN, FF_DISPLAY_TYPE_EXTERNAL, } FFDisplayType; -typedef enum FFDisplayHdrStatus +typedef enum __attribute__((__packed__)) FFDisplayHdrStatus { FF_DISPLAY_HDR_STATUS_UNKNOWN, FF_DISPLAY_HDR_STATUS_UNSUPPORTED, diff --git a/src/detection/displayserver/displayserver_apple.c b/src/detection/displayserver/displayserver_apple.c index d51584923..520750110 100644 --- a/src/detection/displayserver/displayserver_apple.c +++ b/src/detection/displayserver/displayserver_apple.c @@ -36,6 +36,8 @@ static void detectDisplays(FFDisplayServerResult* ds) if (refreshRate == 0) { + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" CVDisplayLinkRef link; if(CVDisplayLinkCreateWithCGDisplay(screen, &link) == kCVReturnSuccess) { @@ -44,6 +46,7 @@ static void detectDisplays(FFDisplayServerResult* ds) refreshRate = time.timeScale / (double) time.timeValue; //59.97... CVDisplayLinkRelease(link); } + #pragma clang diagnostic pop } ffStrbufClear(&buffer); @@ -99,6 +102,10 @@ static void detectDisplays(FFDisplayServerResult* ds) ); if (display) { + #ifndef MAC_OS_X_VERSION_10_11 + FF_CFTYPE_AUTO_RELEASE CFStringRef pe = CGDisplayModeCopyPixelEncoding(mode); + if (pe) display->bitDepth = (uint8_t) (CFStringGetLength(pe) - CFStringFind(pe, CFSTR("B"), 0).location); + #else // https://stackoverflow.com/a/33519316/9976392 // Also shitty, but better than parsing `CFCopyDescription(mode)` CFDictionaryRef dict = (CFDictionaryRef) *((int64_t *)mode + 2); @@ -108,6 +115,7 @@ static void detectDisplays(FFDisplayServerResult* ds) ffCfDictGetInt(dict, kCGDisplayBitsPerSample, &bitDepth); display->bitDepth = (uint8_t) bitDepth; } + #endif if (display->type == FF_DISPLAY_TYPE_BUILTIN) display->hdrStatus = CFDictionaryContainsKey(displayInfo, CFSTR("ReferencePeakHDRLuminance")) diff --git a/src/detection/displayserver/linux/wayland/wayland.h b/src/detection/displayserver/linux/wayland/wayland.h index 3c3b64a94..c19d88199 100644 --- a/src/detection/displayserver/linux/wayland/wayland.h +++ b/src/detection/displayserver/linux/wayland/wayland.h @@ -9,7 +9,7 @@ #include "../displayserver_linux.h" -typedef enum WaylandProtocolType +typedef enum __attribute__((__packed__)) WaylandProtocolType { FF_WAYLAND_PROTOCOL_TYPE_NONE, FF_WAYLAND_PROTOCOL_TYPE_GLOBAL, diff --git a/src/detection/displayserver/linux/wmde.c b/src/detection/displayserver/linux/wmde.c index aa1f0eafd..7a8554caa 100644 --- a/src/detection/displayserver/linux/wmde.c +++ b/src/detection/displayserver/linux/wmde.c @@ -8,16 +8,19 @@ #include #include -#ifdef __FreeBSD__ +#if __FreeBSD__ #include #include #include -#elif defined(__OpenBSD__) +#elif __OpenBSD__ #include #include #include -#elif defined(__sun) +#elif __sun #include +#elif __NetBSD__ + #include + #include #endif static const char* parseEnv(void) @@ -388,6 +391,29 @@ static const char* getFromProcesses(FFDisplayServerResult* result) if(result->wmPrettyName.length == 0) applyNameIfWM(result, processName.chars); + if(result->dePrettyName.length > 0 && result->wmPrettyName.length > 0) + break; + } +#elif __NetBSD__ + int request[] = {CTL_KERN, KERN_PROC2, KERN_PROC_UID, (int) userId, sizeof(struct kinfo_proc2), INT_MAX}; + + size_t size = 0; + if(sysctl(request, ARRAY_SIZE(request), NULL, &size, NULL, 0) != 0) + return "sysctl(KERN_PROC_UID, NULL) failed"; + + FF_AUTO_FREE struct kinfo_proc2* procs = malloc(size); + + if(sysctl(request, ARRAY_SIZE(request), procs, &size, NULL, 0) != 0) + return "sysctl(KERN_PROC_UID, procs) failed"; + + for(struct kinfo_proc2* proc = procs; proc < procs + (size / sizeof(struct kinfo_proc2)); proc++) + { + if(result->dePrettyName.length == 0) + applyPrettyNameIfDE(result, proc->p_comm); + + if(result->wmPrettyName.length == 0) + applyNameIfWM(result, proc->p_comm); + if(result->dePrettyName.length > 0 && result->wmPrettyName.length > 0) break; } diff --git a/src/detection/gpu/gpu_amd.c b/src/detection/gpu/gpu_amd.c index 72e1d9fc0..7bc535382 100644 --- a/src/detection/gpu/gpu_amd.c +++ b/src/detection/gpu/gpu_amd.c @@ -66,7 +66,7 @@ const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResu *result.type = device->isAPU ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; if (result.index) - *result.type = (uint32_t) device->adlAdapterIndex; + *result.index = (uint32_t) device->adlAdapterIndex; if (result.name) ffStrbufSetS(result.name, device->adapterString); diff --git a/src/detection/gpu/gpu_apple.c b/src/detection/gpu/gpu_apple.c index 16f9f9c0c..cc35ef0ee 100644 --- a/src/detection/gpu/gpu_apple.c +++ b/src/detection/gpu/gpu_apple.c @@ -68,7 +68,13 @@ static const char* detectFrequency(FFGPUResult* gpu) pMax = pMax > pStart[i] ? pMax : pStart[i]; if (pMax > 0) - gpu->frequency = pMax / 1000 / 1000; + { + // While this is not necessary for now (seems), we add this logic just in case. See cpu_apple.c + if (pMax > 100000000) // Assume that pMax is in Hz + gpu->frequency = pMax / 1000 / 1000; + else // Assume that pMax is in kHz + gpu->frequency = pMax / 1000; + } return NULL; } diff --git a/src/detection/gpu/gpu_driver_specific.h b/src/detection/gpu/gpu_driver_specific.h index 989ef6093..258dc68f1 100644 --- a/src/detection/gpu/gpu_driver_specific.h +++ b/src/detection/gpu/gpu_driver_specific.h @@ -2,11 +2,12 @@ #include "gpu.h" -typedef enum FFGpuDriverConditionType +typedef enum __attribute__((__packed__)) FFGpuDriverConditionType { FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID = 1 << 0, FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID = 1 << 1, FF_GPU_DRIVER_CONDITION_TYPE_LUID = 1 << 2, + FF_GPU_DRIVER_CONDITION_TYPE_FORCE_UNSIGNED = UINT8_MAX, } FFGpuDriverConditionType; typedef struct FFGpuDriverPciBusId diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index a915a25e9..bf9cc1add 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -460,7 +460,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf { if (ffStrStartsWith(entry->d_name, "card")) { - ffStrCopyN(drmKeyBuffer, entry->d_name, ARRAY_SIZE(drmKeyBuffer)); + ffStrCopy(drmKeyBuffer, entry->d_name, ARRAY_SIZE(drmKeyBuffer)); drmKey = drmKeyBuffer; break; } diff --git a/src/detection/gtk_qt/qt.c b/src/detection/gtk_qt/qt.c index 02c578a16..cefdf86dc 100644 --- a/src/detection/gtk_qt/qt.c +++ b/src/detection/gtk_qt/qt.c @@ -18,7 +18,7 @@ static inline bool allValuesSet(const FFQtResult* result) result->wallpaper.length > 0; } -typedef enum PlasmaCategory +typedef enum __attribute__((__packed__)) PlasmaCategory { PLASMA_CATEGORY_GENERAL, PLASMA_CATEGORY_KDE, diff --git a/src/detection/host/host_android.c b/src/detection/host/host_android.c index b496029a8..7e6d9638b 100644 --- a/src/detection/host/host_android.c +++ b/src/detection/host/host_android.c @@ -9,11 +9,12 @@ const char* ffDetectHost(FFHostResult* host) ffSettingsGetAndroidProperty("ro.product.marketname", &host->name) || ffSettingsGetAndroidProperty("ro.vendor.product.display", &host->name) + || ffSettingsGetAndroidProperty("ro.vivo.market.name", &host->name) + || ffSettingsGetAndroidProperty("ro.product.oppo_model", &host->name) + || ffSettingsGetAndroidProperty("ro.oppo.market.name", &host->name) || ffSettingsGetAndroidProperty("ro.config.devicename", &host->name) || ffSettingsGetAndroidProperty("ro.config.marketing_name", &host->name) || ffSettingsGetAndroidProperty("ro.product.vendor.model", &host->name) - || ffSettingsGetAndroidProperty("ro.product.oppo_model", &host->name) - || ffSettingsGetAndroidProperty("ro.oppo.market.name", &host->name) || ffSettingsGetAndroidProperty("ro.product.brand", &host->name); if (ffSettingsGetAndroidProperty("ro.product.model", &host->version)) diff --git a/src/detection/host/host_apple.c b/src/detection/host/host_apple.c index 61a14e642..552ab8978 100644 --- a/src/detection/host/host_apple.c +++ b/src/detection/host/host_apple.c @@ -111,6 +111,15 @@ static const char* getProductNameWithHwModel(const FFstrbuf* hwModel) else if(ffStrbufStartsWithS(hwModel, "Mac")) { const char* version = hwModel->chars + strlen("Mac"); + if(ffStrEquals(version, "16,3")) return "iMac (24-inch, 2024, Four Thunderbolt / USB 4 ports)"; + if(ffStrEquals(version, "16,2")) return "iMac (24-inch, 2024, Two Thunderbolt / USB 4 ports)"; + if(ffStrEquals(version, "16,1") || + ffStrEquals(version, "16,6") || + ffStrEquals(version, "16,8")) return "MacBook Pro (14-inch, 2024, Three Thunderbolt 4 ports)"; + if(ffStrEquals(version, "16,7") || + ffStrEquals(version, "16,5")) return "MacBook Pro (16-inch, 2024, Three Thunderbolt 4 ports)"; + if(ffStrEquals(version, "16,15") || + ffStrEquals(version, "16,10")) return "Mac mini (2024)"; if(ffStrEquals(version, "15,13")) return "MacBook Air (15-inch, M3, 2024)"; if(ffStrEquals(version, "15,2")) return "MacBook Air (13-inch, M3, 2024)"; if(ffStrEquals(version, "15,3")) return "MacBook Pro (14-inch, Nov 2023, Two Thunderbolt / USB 4 ports)"; diff --git a/src/detection/localip/localip_linux.c b/src/detection/localip/localip_linux.c index 00e64b990..7a8552811 100644 --- a/src/detection/localip/localip_linux.c +++ b/src/detection/localip/localip_linux.c @@ -231,7 +231,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) FF_LIST_FOR_EACH(FFLocalIpResult, iface, *results) { struct ifreq ifr; - ffStrCopyN(ifr.ifr_name, iface->name.chars, IFNAMSIZ); + ffStrCopy(ifr.ifr_name, iface->name.chars, IFNAMSIZ); if (options->showType & FF_LOCALIP_TYPE_MTU_BIT) { @@ -248,7 +248,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) iface->speed = (edata.speed_hi << 16) | edata.speed; // ethtool_cmd_speed is not available on Android #elif __FreeBSD__ || __APPLE__ || __OpenBSD__ || __NetBSD__ struct ifmediareq ifmr = {}; - ffStrCopyN(ifmr.ifm_name, iface->name.chars, IFNAMSIZ); + ffStrCopy(ifmr.ifm_name, iface->name.chars, IFNAMSIZ); if (ioctl(sockfd, SIOCGIFMEDIA, &ifmr) == 0 && (IFM_TYPE(ifmr.ifm_active) & IFM_ETHER)) { switch (IFM_SUBTYPE(ifmr.ifm_active)) diff --git a/src/detection/netio/netio_apple.c b/src/detection/netio/netio_apple.c new file mode 100644 index 000000000..cd5106026 --- /dev/null +++ b/src/detection/netio/netio_apple.c @@ -0,0 +1,56 @@ +#include "netio.h" + +#include "common/netif/netif.h" +#include "util/mallocHelper.h" + +#include +#include +#include + +const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options) +{ + int mib[] = {CTL_NET, PF_LINK, NETLINK_GENERIC, + options->defaultRouteOnly ? IFMIB_IFDATA : IFMIB_IFALLDATA, + options->defaultRouteOnly ? (int) ffNetifGetDefaultRouteIfIndex() : 0, + IFDATA_GENERAL}; + + size_t bufSize = 0; + if (sysctl(mib, ARRAY_SIZE(mib), NULL, &bufSize, 0, 0) < 0) + return "sysctl(mib, ARRAY_SIZE(mib), NULL, &bufSize, 0, 0) failed"; + + assert(bufSize % sizeof(struct ifmibdata) == 0); + + FF_AUTO_FREE struct ifmibdata* buf = (struct ifmibdata*) malloc(bufSize); + if (sysctl(mib, ARRAY_SIZE(mib), buf, &bufSize, 0, 0) < 0) + return "sysctl(mib, ARRAY_SIZE(mib), buf, &bufSize, 0, 0) failed"; + + size_t ifCount = bufSize / sizeof(struct ifmibdata); + + const char* defaultRouteIfName = ffNetifGetDefaultRouteIfName(); + + for (size_t i = 0; i < ifCount; i++) + { + struct ifmibdata* mibdata = &buf[i]; + if (!(mibdata->ifmd_flags & IFF_RUNNING) || (mibdata->ifmd_flags & IFF_NOARP)) + continue; + + if (options->namePrefix.length && strncmp(mibdata->ifmd_name, options->namePrefix.chars, options->namePrefix.length) != 0) + continue; + + FFNetIOResult* counters = (FFNetIOResult*) ffListAdd(result); + *counters = (FFNetIOResult) { + .name = ffStrbufCreateS(mibdata->ifmd_name), + .txBytes = mibdata->ifmd_data.ifi_obytes, + .rxBytes = mibdata->ifmd_data.ifi_ibytes, + .txPackets = mibdata->ifmd_data.ifi_opackets, + .rxPackets = mibdata->ifmd_data.ifi_ipackets, + .txErrors = mibdata->ifmd_data.ifi_oerrors, + .rxErrors = mibdata->ifmd_data.ifi_ierrors, + .txDrops = mibdata->ifmd_snd_drops, + .rxDrops = mibdata->ifmd_data.ifi_iqdrops, + .defaultRoute = strncmp(mibdata->ifmd_name, defaultRouteIfName, IFNAMSIZ) == 0, + }; + } + + return NULL; +} diff --git a/src/detection/netio/netio_bsd.c b/src/detection/netio/netio_bsd.c index 5328949a9..9044600e5 100644 --- a/src/detection/netio/netio_bsd.c +++ b/src/detection/netio/netio_bsd.c @@ -1,8 +1,6 @@ #include "netio.h" -#include "common/io/io.h" #include "common/netif/netif.h" -#include "util/stringUtils.h" #include "util/mallocHelper.h" #include @@ -32,7 +30,6 @@ const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options) struct sockaddr_dl* sdl = (struct sockaddr_dl*) (ifm + 1); assert(sdl->sdl_family == AF_LINK); - if (sdl->sdl_type != IFT_ETHER && !(ifm->ifm_flags & IFF_LOOPBACK)) continue; sdl->sdl_data[sdl->sdl_nlen] = 0; @@ -48,8 +45,8 @@ const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options) .rxPackets = ifm->ifm_data.ifi_ipackets, .txErrors = ifm->ifm_data.ifi_oerrors, .rxErrors = ifm->ifm_data.ifi_ierrors, - #ifdef _IFI_OQDROPS - .txDrops = if2m->ifm_data.ifi_oqdrops, + #ifdef FF_HAVE_IFI_OQDROPS + .txDrops = ifm->ifm_data.ifi_oqdrops, #else .txDrops = 0, // unsupported #endif diff --git a/src/detection/packages/packages.h b/src/detection/packages/packages.h index aef482d84..261c8acb0 100644 --- a/src/detection/packages/packages.h +++ b/src/detection/packages/packages.h @@ -20,22 +20,24 @@ typedef struct FFPackagesResult uint32_t linglong; uint32_t lpkg; uint32_t lpkgbuild; + uint32_t macports; + uint32_t mport; uint32_t nixDefault; uint32_t nixSystem; uint32_t nixUser; uint32_t opkg; uint32_t pacman; + uint32_t pacstall; uint32_t paludis; uint32_t pkg; uint32_t pkgtool; - uint32_t macports; + uint32_t qi; uint32_t rpm; uint32_t scoop; uint32_t snap; uint32_t sorcery; uint32_t winget; uint32_t xbps; - uint32_t pacstall; uint32_t all; //Make sure this goes last diff --git a/src/detection/packages/packages_bsd.c b/src/detection/packages/packages_bsd.c index 511af569b..4ad2d8b49 100644 --- a/src/detection/packages/packages_bsd.c +++ b/src/detection/packages/packages_bsd.c @@ -21,7 +21,7 @@ static uint32_t getSQLite3Int(const char* dbPath, const char* query, const char* void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options) { if (!(options->disabled & FF_PACKAGES_FLAG_PKG_BIT)) - { result->pkg = getSQLite3Int(FASTFETCH_TARGET_DIR_ROOT "/var/db/pkg/local.sqlite", "SELECT count(*) FROM packages", "pkg"); - } + if (!(options->disabled & FF_PACKAGES_FLAG_MPORT_BIT)) + result->mport = getSQLite3Int(FASTFETCH_TARGET_DIR_ROOT "/var/db/mport/master.db", "SELECT count(*) FROM packages", "mport"); } diff --git a/src/detection/packages/packages_linux.c b/src/detection/packages/packages_linux.c index a978929c4..6d5eff079 100644 --- a/src/detection/packages/packages_linux.c +++ b/src/detection/packages/packages_linux.c @@ -573,6 +573,7 @@ static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts, } if (!(options->disabled & FF_PACKAGES_FLAG_LINGLONG_BIT)) packageCounts->linglong += getNumElements(baseDir, "/var/lib/linglong/repo/refs/heads/main", DT_DIR); if (!(options->disabled & FF_PACKAGES_FLAG_PACSTALL_BIT)) packageCounts->pacstall += getNumElements(baseDir, "/var/lib/pacstall/metadata", DT_REG); + if (!(options->disabled & FF_PACKAGES_FLAG_QI_BIT)) packageCounts->qi += getNumStrings(baseDir, "/var/qi/installed_packages.list", "\n", "qi"); } static void getPackageCountsRegular(FFstrbuf* baseDir, FFPackagesResult* packageCounts, FFPackagesOptions* options) diff --git a/src/detection/packages/packages_windows.c b/src/detection/packages/packages_windows.c index afa2b12e9..a9fa9df6d 100644 --- a/src/detection/packages/packages_windows.c +++ b/src/detection/packages/packages_windows.c @@ -58,8 +58,8 @@ static void detectChoco(FF_MAYBE_UNUSED FFPackagesResult* result) return; char chocoPath[MAX_PATH + 3]; - char* pend = ffStrCopyN(chocoPath, chocoInstall, ARRAY_SIZE(chocoPath)); - ffStrCopyN(pend, "/lib/*", ARRAY_SIZE(chocoPath) - (size_t) (pend - chocoPath)); + char* pend = ffStrCopy(chocoPath, chocoInstall, ARRAY_SIZE(chocoPath)); + ffStrCopy(pend, "/lib/*", ARRAY_SIZE(chocoPath) - (size_t) (pend - chocoPath)); result->choco = getNumElements(chocoPath, FILE_ATTRIBUTE_DIRECTORY, "choco"); } @@ -71,8 +71,8 @@ static void detectPacman(FFPackagesResult* result) // MSYS2 char pacmanPath[MAX_PATH + 3]; - char* pend = ffStrCopyN(pacmanPath, msystemPrefix, ARRAY_SIZE(pacmanPath)); - ffStrCopyN(pend, "/../var/lib/pacman/local/*", ARRAY_SIZE(pacmanPath) - (size_t) (pend - pacmanPath)); + char* pend = ffStrCopy(pacmanPath, msystemPrefix, ARRAY_SIZE(pacmanPath)); + ffStrCopy(pend, "/../var/lib/pacman/local/*", ARRAY_SIZE(pacmanPath) - (size_t) (pend - pacmanPath)); result->pacman = getNumElements(pacmanPath, FILE_ATTRIBUTE_DIRECTORY, NULL); } diff --git a/src/detection/physicaldisk/physicaldisk.h b/src/detection/physicaldisk/physicaldisk.h index 76863f783..fbed2f52c 100644 --- a/src/detection/physicaldisk/physicaldisk.h +++ b/src/detection/physicaldisk/physicaldisk.h @@ -2,7 +2,7 @@ #define FF_PHYSICALDISK_TEMP_UNSET (0/0.0) -typedef enum FFPhysicalDiskType +typedef enum __attribute__((__packed__)) FFPhysicalDiskType { FF_PHYSICALDISK_TYPE_NONE = 0, @@ -15,7 +15,10 @@ typedef enum FFPhysicalDiskType FF_PHYSICALDISK_TYPE_READWRITE = 1 << 4, FF_PHYSICALDISK_TYPE_READONLY = 1 << 5, + + FF_PHYSICALDISK_TYPE_FORCE_UNSIGNED = UINT8_MAX, } FFPhysicalDiskType; +static_assert(sizeof(FFPhysicalDiskType) == sizeof(uint8_t), ""); typedef struct FFPhysicalDiskResult { diff --git a/src/detection/sound/sound_bsd.c b/src/detection/sound/sound_bsd.c index af601b5a5..4487b42a4 100644 --- a/src/detection/sound/sound_bsd.c +++ b/src/detection/sound/sound_bsd.c @@ -39,6 +39,7 @@ const char* ffDetectSound(FFlist* devices) FFSoundDevice* device = ffListAdd(devices); ffStrbufInitS(&device->identifier, path); ffStrbufInitF(&device->name, "%s %s", ci.longname, ci.hw_info); + ffStrbufTrimRightSpace(&device->name); device->volume = mutemask & SOUND_MASK_VOLUME ? 0 : ((uint8_t) volume /*left*/ + (uint8_t) (volume >> 8) /*right*/) / 2; diff --git a/src/detection/terminalfont/terminalfont_windows.c b/src/detection/terminalfont/terminalfont_windows.c index 6e59cbdfb..3adcd8eaa 100644 --- a/src/detection/terminalfont/terminalfont_windows.c +++ b/src/detection/terminalfont/terminalfont_windows.c @@ -98,12 +98,12 @@ static void detectFromWindowsTerminal(const FFstrbuf* terminalExe, FFTerminalFon if(terminalExe && terminalExe->length > 0 && !ffStrbufEqualS(terminalExe, "Windows Terminal")) { char jsonPath[MAX_PATH + 1]; - char* pathEnd = ffStrCopyN(jsonPath, terminalExe->chars, ffStrbufLastIndexC(terminalExe, '\\') + 1); - ffStrCopyN(pathEnd, ".portable", ARRAY_SIZE(jsonPath) - (size_t) (pathEnd - jsonPath) - 1); + char* pathEnd = ffStrCopy(jsonPath, terminalExe->chars, ffStrbufLastIndexC(terminalExe, '\\') + 1); + ffStrCopy(pathEnd, ".portable", ARRAY_SIZE(jsonPath) - (size_t) (pathEnd - jsonPath) - 1); if(ffPathExists(jsonPath, FF_PATHTYPE_ANY)) { - ffStrCopyN(pathEnd, "settings\\settings.json", ARRAY_SIZE(jsonPath) - (size_t) (pathEnd - jsonPath) - 1); + ffStrCopy(pathEnd, "settings\\settings.json", ARRAY_SIZE(jsonPath) - (size_t) (pathEnd - jsonPath) - 1); if(!ffAppendFileBuffer(jsonPath, &json)) error = "Error reading Windows Terminal portable settings JSON file"; } diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index b8f6e1159..7ce6854a5 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -641,6 +641,26 @@ FF_MAYBE_UNUSED static bool getTerminalVersionPtyxis(FF_MAYBE_UNUSED FFstrbuf* e ffStrbufSubstrAfterFirstC(version, ' '); return true; } + +FF_MAYBE_UNUSED static bool getTerminalVersionTilix(FFstrbuf* exe, FFstrbuf* version) +{ + if(ffProcessAppendStdOut(version, (char* const[]) { + exe->chars, + "--version", + NULL + }) != NULL) + return false; + + uint32_t index = ffStrbufFirstIndexS(version, "Tilix version: "); + if (index == version->length) return false; + + index += (uint32_t) strlen("Tilix version:"); + uint32_t end = ffStrbufNextIndexC(version, index, '\n'); + + ffStrbufSubstrBefore(version, end); + ffStrbufSubstrAfter(version, index); + return true; +} #endif #ifdef _WIN32 @@ -740,6 +760,9 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe if(ffStrbufIgnCaseEqualS(processName, "ptyxis-agent")) return getTerminalVersionPtyxis(exe, version); + if(ffStrbufIgnCaseEqualS(processName, "tilix")) + return getTerminalVersionTilix(exe, version); + #endif #ifdef _WIN32 diff --git a/src/detection/version/version.c b/src/detection/version/version.c index 8b230eecb..1f1deb348 100644 --- a/src/detection/version/version.c +++ b/src/detection/version/version.c @@ -28,6 +28,8 @@ #define FF_SYSNAME "Linux" #elif defined(__DragonFly__) // We define `__FreeBSD__` on DragonFly BSD for simplification #define FF_SYSNAME "DragonFly" +#elif defined(__MidnightBSD__) + #define FF_SYSNAME "MidnightBSD" #elif defined(__FreeBSD__) #define FF_SYSNAME "FreeBSD" #elif defined(__APPLE__) diff --git a/src/detection/wifi/wifi_linux.c b/src/detection/wifi/wifi_linux.c index 732c5afc8..cd99a271a 100644 --- a/src/detection/wifi/wifi_linux.c +++ b/src/detection/wifi/wifi_linux.c @@ -190,7 +190,7 @@ static const char* detectWifiWithIoctls(FFWifiResult* item) return "socket() failed"; struct iwreq iwr; - ffStrCopyN(iwr.ifr_name, item->inf.description.chars, IFNAMSIZ); + ffStrCopy(iwr.ifr_name, item->inf.description.chars, IFNAMSIZ); ffStrbufEnsureFree(&item->conn.ssid, IW_ESSID_MAX_SIZE); iwr.u.essid.pointer = (caddr_t) item->conn.ssid.chars; iwr.u.essid.length = IW_ESSID_MAX_SIZE + 1; diff --git a/src/logo/ascii/cosmic.txt b/src/logo/ascii/cosmic.txt new file mode 100644 index 000000000..10fd4e18f --- /dev/null +++ b/src/logo/ascii/cosmic.txt @@ -0,0 +1,11 @@ + .xMMMMMMMMMMMMMMMMMMMMMMx. +JDMMMMMMMMMMMMMMMMMMMMMMMMOL +IMMMY' 'YMMMI +MMMM MMMM +MMMM MMMM +IMMMb dMMMI +'YMMMMMMMMb. .dMMMMMMMMK' + 'OMMMMMMMP' 'YMMMMMMMP' + + $2.x76767$36767676$476767$5676x. + $2'*76767$36767676$476767$5676*' diff --git a/src/logo/ascii/midnightbsd.txt b/src/logo/ascii/midnightbsd.txt new file mode 100644 index 000000000..39b338461 --- /dev/null +++ b/src/logo/ascii/midnightbsd.txt @@ -0,0 +1,16 @@ + ..:::'''':::.. + .:'''` `''':. + .:'` .::` `':: + :' .::' ':. + .:` .:::' `:. + :` :::: `: +:: ::::: :: +: ::::: :: : +: :::::: .:::' : +:: ::::::. : .:::::: :: + :. :::::::. : :::::::' .: + `:. `':::::::.'.:::::': .:' + `:. '':::::::::::::.: .:` + ':. `''::::::::''' .:' + '':.. ``'`` ..:'' + ''''::::::'''' \ No newline at end of file diff --git a/src/logo/ascii/opensuse_tumbleweed.txt b/src/logo/ascii/opensuse_tumbleweed.txt index bf857a76a..111a61fcb 100644 --- a/src/logo/ascii/opensuse_tumbleweed.txt +++ b/src/logo/ascii/opensuse_tumbleweed.txt @@ -1,21 +1,22 @@ - .,:looooooc;. - ,ool oo,;oo: + ,..., + .,:lloooooc;. + ,ool' oo,;oo: .lo' oo. oo: - oo. oo. oo: +.oo. oo. oo: :ol oo. 'oo :oo .oo. .oo. .oooooooooooooo. .oo. ;oo. .oo. - oo, .oo. - .ooc,'..........:ooc.......... - .cooooooooooooooooooooooooool;. + 'oo, .oo. + "ooc,',,,,,,,,,,:ooc,,,,,,,,,,, + ':cooooooooooooooooooooooooool;. .oo. .oo; .oo. .oo. - .oo. oooooooooo:ooo. - .oo. .oo. col - oo' .oo col - coo .oo oo' - coc .oo lo, - .oo, .oo .:oo - .oooooc,,,:lol - ,clc' \ No newline at end of file + .oo. 'oooooooooo:ooo. + .oo. 'oo. col + .oo' 'oo col + coo 'oo oo' + coc 'oo .lo, + `oo, 'oo .:oo + 'ooooc,, ,:lol + `''"clc"' \ No newline at end of file diff --git a/src/logo/ascii/unifi.txt b/src/logo/ascii/unifi.txt new file mode 100644 index 000000000..dff463228 --- /dev/null +++ b/src/logo/ascii/unifi.txt @@ -0,0 +1,6 @@ + ___ ___ .__________.__ + | | |____ |__\_ ____/__| + | | / \| || __) | | + | | | | \ || \ | | + |______|___| /__||__/ |__| + |_/ \ No newline at end of file diff --git a/src/logo/builtin.c b/src/logo/builtin.c index c20cbc927..77d2e05c0 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -1070,6 +1070,20 @@ static const FFlogo C[] = { .colorKeys = FF_COLOR_FG_BLUE, .colorTitle = FF_COLOR_FG_WHITE, }, + // Cosmic DE + { + .names = {"Cosmic"}, + .lines = FASTFETCH_DATATEXT_LOGO_COSMIC, + .colors = { + FF_COLOR_FG_WHITE, + FF_COLOR_FG_LIGHT_YELLOW, + FF_COLOR_FG_YELLOW, + FF_COLOR_FG_LIGHT_RED, + FF_COLOR_FG_RED, + }, + .colorKeys = FF_COLOR_FG_LIGHT_RED, + .colorTitle = FF_COLOR_FG_YELLOW, + }, // CRUX { .names = {"CRUX"}, @@ -2392,7 +2406,7 @@ static const FFlogo L[] = { // Lilidog { .names = {"Lilidog"}, - .lines = FASTFETCH_DATATEXT_LOGO_LIBREELEC, + .lines = FASTFETCH_DATATEXT_LOGO_LILIDOG, .colors = { FF_COLOR_FG_BLUE, }, @@ -2809,6 +2823,16 @@ static const FFlogo M[] = { .colorKeys = FF_COLOR_FG_BLUE, .colorTitle = FF_COLOR_FG_WHITE, }, + // MidnightBSD + { + .names = {"MidnightBSD"}, + .lines = FASTFETCH_DATATEXT_LOGO_MIDNIGHTBSD, + .colors = { + FF_COLOR_FG_WHITE, + }, + .colorKeys = FF_COLOR_FG_LIGHT_BLACK, + .colorTitle = FF_COLOR_FG_WHITE, + }, // MidOS { .names = {"MidOS"}, @@ -4592,6 +4616,15 @@ static const FFlogo U[] = { FF_COLOR_FG_WHITE, }, }, + // Unifi + { + .names = {"Unifi"}, + .lines = FASTFETCH_DATATEXT_LOGO_UNIFI, + .colors = { + FF_COLOR_FG_WHITE, + FF_COLOR_FG_WHITE, + }, + }, // Univalent { .names = {"Univalent"}, diff --git a/src/logo/image/image.h b/src/logo/image/image.h index 608286392..58a2f6289 100644 --- a/src/logo/image/image.h +++ b/src/logo/image/image.h @@ -4,7 +4,7 @@ #if defined(FF_HAVE_IMAGEMAGICK7) || defined(FF_HAVE_IMAGEMAGICK6) -typedef enum FFLogoImageResult +typedef enum __attribute__((__packed__)) FFLogoImageResult { FF_LOGO_IMAGE_RESULT_SUCCESS, //Logo printed FF_LOGO_IMAGE_RESULT_INIT_ERROR, //Failed to load library, try again with next IM version diff --git a/src/logo/logo.c b/src/logo/logo.c index 26da1eed7..09dfd8696 100644 --- a/src/logo/logo.c +++ b/src/logo/logo.c @@ -9,7 +9,7 @@ #include #include -typedef enum FFLogoSize +typedef enum __attribute__((__packed__)) FFLogoSize { FF_LOGO_SIZE_UNKNOWN, FF_LOGO_SIZE_NORMAL, diff --git a/src/logo/logo.h b/src/logo/logo.h index e9bea9788..92a1683a6 100644 --- a/src/logo/logo.h +++ b/src/logo/logo.h @@ -2,11 +2,12 @@ #include "fastfetch.h" -typedef enum FFLogoLineType +typedef enum __attribute__((__packed__)) FFLogoLineType { FF_LOGO_LINE_TYPE_NORMAL = 0, FF_LOGO_LINE_TYPE_SMALL_BIT = 1 << 0, // The names of small logo must end with `_small` or `-small` FF_LOGO_LINE_TYPE_ALTER_BIT = 1 << 1, + FF_LOGO_LINE_TYPE_FORCE_UNSIGNED = UINT8_MAX, } FFLogoLineType; typedef struct FFlogo diff --git a/src/modules/battery/battery.c b/src/modules/battery/battery.c index f27ff29e7..c40f7a629 100644 --- a/src/modules/battery/battery.c +++ b/src/modules/battery/battery.c @@ -39,24 +39,26 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin timeRemaining /= 24; uint32_t days = timeRemaining; + FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type; + if(options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(key.chars, index, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY); + ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY); FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate(); bool showStatus = - !(instance.config.display.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT) && + !(percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT) && result->status.length > 0 && ffStrbufIgnCaseCompS(&result->status, "Unknown") != 0; if(result->capacity >= 0) { - if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + if(percentType & FF_PERCENTAGE_TYPE_BAR_BIT) { ffPercentAppendBar(&str, result->capacity, options->percent, &options->moduleArgs); } - if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + if(percentType & FF_PERCENTAGE_TYPE_NUM_BIT) { if(str.length > 0) ffStrbufAppendC(&str, ' '); @@ -95,12 +97,15 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin else { FF_STRBUF_AUTO_DESTROY capacityNum = ffStrbufCreate(); - ffPercentAppendNum(&capacityNum, result->capacity, options->percent, false, &options->moduleArgs); + if(percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + ffPercentAppendNum(&capacityNum, result->capacity, options->percent, false, &options->moduleArgs); FF_STRBUF_AUTO_DESTROY capacityBar = ffStrbufCreate(); - ffPercentAppendBar(&capacityBar, result->capacity, options->percent, &options->moduleArgs); + if(percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + ffPercentAppendBar(&capacityBar, result->capacity, options->percent, &options->moduleArgs); FF_STRBUF_AUTO_DESTROY tempStr = ffStrbufCreate(); ffTempsAppendNum(result->temperature, &tempStr, options->tempConfig, &options->moduleArgs); - FF_PRINT_FORMAT_CHECKED(key.chars, index, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_BATTERY_NUM_FORMAT_ARGS, ((FFformatarg[]) { + + FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_BATTERY_NUM_FORMAT_ARGS, ((FFformatarg[]) { FF_FORMAT_ARG(result->manufacturer, "manufacturer"), FF_FORMAT_ARG(result->modelName, "model-name"), FF_FORMAT_ARG(result->technology, "technology"), @@ -301,7 +306,7 @@ void ffInitBatteryOptions(FFBatteryOptions* options) ffOptionInitModuleArg(&options->moduleArgs, ""); options->temp = false; options->tempConfig = (FFColorRangeConfig) { 60, 80 }; - options->percent = (FFColorRangeConfig) { 50, 20 }; + options->percent = (FFPercentageModuleConfig) { 50, 20, 0 }; #ifdef _WIN32 options->useSetupApi = false; diff --git a/src/modules/battery/option.h b/src/modules/battery/option.h index ecaa45ccc..8b04ef1b4 100644 --- a/src/modules/battery/option.h +++ b/src/modules/battery/option.h @@ -12,7 +12,7 @@ typedef struct FFBatteryOptions bool temp; FFColorRangeConfig tempConfig; - FFColorRangeConfig percent; + FFPercentageModuleConfig percent; #ifdef _WIN32 bool useSetupApi; diff --git a/src/modules/bluetooth/bluetooth.c b/src/modules/bluetooth/bluetooth.c index b00ff013c..0116ce236 100644 --- a/src/modules/bluetooth/bluetooth.c +++ b/src/modules/bluetooth/bluetooth.c @@ -9,13 +9,24 @@ static void printDevice(FFBluetoothOptions* options, const FFBluetoothResult* device, uint8_t index) { + FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type; if(options->moduleArgs.outputFormat.length == 0) { ffPrintLogoAndKey(FF_BLUETOOTH_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); - FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreateCopy(&device->name); + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + bool showBatteryLevel = device->battery > 0 && device->battery <= 100; - if (device->battery > 0 && device->battery <= 100) + if (showBatteryLevel && (percentType & FF_PERCENTAGE_TYPE_BAR_BIT)) + { + ffPercentAppendBar(&buffer, device->battery, options->percent, &options->moduleArgs); + ffStrbufAppendC(&buffer, ' '); + } + + if (!(percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) + ffStrbufAppend(&buffer, &device->name); + + if (showBatteryLevel && (percentType & FF_PERCENTAGE_TYPE_NUM_BIT)) { if (buffer.length) ffStrbufAppendC(&buffer, ' '); @@ -30,9 +41,11 @@ static void printDevice(FFBluetoothOptions* options, const FFBluetoothResult* de else { FF_STRBUF_AUTO_DESTROY percentageNum = ffStrbufCreate(); - ffPercentAppendNum(&percentageNum, device->battery, options->percent, false, &options->moduleArgs); + if(percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + ffPercentAppendNum(&percentageNum, device->battery, options->percent, false, &options->moduleArgs); FF_STRBUF_AUTO_DESTROY percentageBar = ffStrbufCreate(); - ffPercentAppendBar(&percentageBar, device->battery, options->percent, &options->moduleArgs); + if(percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + ffPercentAppendBar(&percentageBar, device->battery, options->percent, &options->moduleArgs); FF_PRINT_FORMAT_CHECKED(FF_BLUETOOTH_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_BLUETOOTH_NUM_FORMAT_ARGS, ((FFformatarg[]) { FF_FORMAT_ARG(device->name, "name"), @@ -202,7 +215,7 @@ void ffInitBluetoothOptions(FFBluetoothOptions* options) ); ffOptionInitModuleArg(&options->moduleArgs, ""); options->showDisconnected = false; - options->percent = (FFColorRangeConfig) { 50, 20 }; + options->percent = (FFPercentageModuleConfig) { 50, 20, 0 }; } void ffDestroyBluetoothOptions(FFBluetoothOptions* options) diff --git a/src/modules/bluetooth/option.h b/src/modules/bluetooth/option.h index 7938e77f0..4de6fff72 100644 --- a/src/modules/bluetooth/option.h +++ b/src/modules/bluetooth/option.h @@ -11,5 +11,5 @@ typedef struct FFBluetoothOptions FFModuleArgs moduleArgs; bool showDisconnected; - FFColorRangeConfig percent; + FFPercentageModuleConfig percent; } FFBluetoothOptions; diff --git a/src/modules/brightness/brightness.c b/src/modules/brightness/brightness.c index c5740bc57..dc7e2f455 100644 --- a/src/modules/brightness/brightness.c +++ b/src/modules/brightness/brightness.c @@ -25,6 +25,8 @@ void ffPrintBrightness(FFBrightnessOptions* options) return; } + FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type; + if (options->compact) { FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate(); @@ -48,7 +50,7 @@ void ffPrintBrightness(FFBrightnessOptions* options) uint32_t index = 0; FF_LIST_FOR_EACH(FFBrightnessResult, item, result) { - if(options->moduleArgs.key.length == 0) + if (options->moduleArgs.key.length == 0) { ffStrbufAppendF(&key, "%s (%s)", FF_BRIGHTNESS_MODULE_NAME, item->name.chars); } @@ -64,17 +66,17 @@ void ffPrintBrightness(FFBrightnessOptions* options) const double percent = (item->current - item->min) / (item->max - item->min) * 100; - if(options->moduleArgs.outputFormat.length == 0) + if (options->moduleArgs.outputFormat.length == 0) { FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate(); ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY); - if (instance.config.display.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + if (percentType & FF_PERCENTAGE_TYPE_BAR_BIT) { ffPercentAppendBar(&str, percent, options->percent, &options->moduleArgs); } - if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) { if(str.length > 0) ffStrbufAppendC(&str, ' '); @@ -87,16 +89,19 @@ void ffPrintBrightness(FFBrightnessOptions* options) else { FF_STRBUF_AUTO_DESTROY valueNum = ffStrbufCreate(); - ffPercentAppendNum(&valueNum, percent, options->percent, false, &options->moduleArgs); + if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + ffPercentAppendNum(&valueNum, percent, options->percent, false, &options->moduleArgs); FF_STRBUF_AUTO_DESTROY valueBar = ffStrbufCreate(); - ffPercentAppendBar(&valueBar, percent, options->percent, &options->moduleArgs); + if (percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + ffPercentAppendBar(&valueBar, percent, options->percent, &options->moduleArgs); + FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_BRIGHTNESS_NUM_FORMAT_ARGS, ((FFformatarg[]) { FF_FORMAT_ARG(valueNum, "percentage"), FF_FORMAT_ARG(item->name, "name"), FF_FORMAT_ARG(item->max, "max"), FF_FORMAT_ARG(item->min, "min"), FF_FORMAT_ARG(item->current, "current"), - FF_FORMAT_ARG(item->current, "percentage-bar"), + FF_FORMAT_ARG(valueBar, "percentage-bar"), })); } @@ -237,7 +242,7 @@ void ffInitBrightnessOptions(FFBrightnessOptions* options) ffOptionInitModuleArg(&options->moduleArgs, "󰯪"); options->ddcciSleep = 10; - options->percent = (FFColorRangeConfig) { 100, 100 }; + options->percent = (FFPercentageModuleConfig) { 100, 100, 0 }; options->compact = false; } diff --git a/src/modules/brightness/option.h b/src/modules/brightness/option.h index e359cdc3e..70337f59e 100644 --- a/src/modules/brightness/option.h +++ b/src/modules/brightness/option.h @@ -11,6 +11,6 @@ typedef struct FFBrightnessOptions FFModuleArgs moduleArgs; uint32_t ddcciSleep; // ms - FFColorRangeConfig percent; + FFPercentageModuleConfig percent; bool compact; } FFBrightnessOptions; diff --git a/src/modules/btrfs/btrfs.c b/src/modules/btrfs/btrfs.c index 77e7ba1ad..e295a2a26 100644 --- a/src/modules/btrfs/btrfs.c +++ b/src/modules/btrfs/btrfs.c @@ -45,6 +45,8 @@ static void printBtrfs(FFBtrfsOptions* options, FFBtrfsResult* result, uint8_t i double usedPercentage = total > 0 ? (double) used / (double) total * 100.0 : 0; double allocatedPercentage = total > 0 ? (double) allocated / (double) total * 100.0 : 0; + FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type; + if(options->moduleArgs.outputFormat.length == 0) { ffPrintLogoAndKey(buffer.chars, index, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY); @@ -60,14 +62,18 @@ static void printBtrfs(FFBtrfsOptions* options, FFBtrfsResult* result, uint8_t i else { FF_STRBUF_AUTO_DESTROY usedPercentageNum = ffStrbufCreate(); - ffPercentAppendNum(&usedPercentageNum, usedPercentage, options->percent, false, &options->moduleArgs); + if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + ffPercentAppendNum(&usedPercentageNum, usedPercentage, options->percent, false, &options->moduleArgs); FF_STRBUF_AUTO_DESTROY usedPercentageBar = ffStrbufCreate(); - ffPercentAppendBar(&usedPercentageBar, usedPercentage, options->percent, &options->moduleArgs); + if (percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + ffPercentAppendBar(&usedPercentageBar, usedPercentage, options->percent, &options->moduleArgs); FF_STRBUF_AUTO_DESTROY allocatedPercentageNum = ffStrbufCreate(); - ffPercentAppendNum(&allocatedPercentageNum, allocatedPercentage, options->percent, false, &options->moduleArgs); + if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + ffPercentAppendNum(&allocatedPercentageNum, allocatedPercentage, options->percent, false, &options->moduleArgs); FF_STRBUF_AUTO_DESTROY allocatedPercentageBar = ffStrbufCreate(); - ffPercentAppendBar(&allocatedPercentageBar, allocatedPercentage, options->percent, &options->moduleArgs); + if (percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + ffPercentAppendBar(&allocatedPercentageBar, allocatedPercentage, options->percent, &options->moduleArgs); FF_STRBUF_AUTO_DESTROY nodeSizePretty = ffStrbufCreate(); ffParseSize(result->nodeSize, &nodeSizePretty); @@ -245,7 +251,7 @@ void ffInitBtrfsOptions(FFBtrfsOptions* options) ffGenerateBtrfsJsonConfig ); ffOptionInitModuleArg(&options->moduleArgs, "󱑛"); - options->percent = (FFColorRangeConfig) { 50, 80 }; + options->percent = (FFPercentageModuleConfig) { 50, 80, 0 }; } void ffDestroyBtrfsOptions(FFBtrfsOptions* options) diff --git a/src/modules/btrfs/option.h b/src/modules/btrfs/option.h index 504b15768..2e4b069b4 100644 --- a/src/modules/btrfs/option.h +++ b/src/modules/btrfs/option.h @@ -10,5 +10,5 @@ typedef struct FFBtrfsOptions FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; - FFColorRangeConfig percent; + FFPercentageModuleConfig percent; } FFBtrfsOptions; diff --git a/src/modules/colors/option.h b/src/modules/colors/option.h index 54a8e496d..1a948a9b1 100644 --- a/src/modules/colors/option.h +++ b/src/modules/colors/option.h @@ -4,7 +4,7 @@ #include "common/option.h" -typedef enum FFColorsSymbol +typedef enum __attribute__((__packed__)) FFColorsSymbol { FF_COLORS_SYMBOL_BLOCK, FF_COLORS_SYMBOL_BACKGROUND, diff --git a/src/modules/cpuusage/cpuusage.c b/src/modules/cpuusage/cpuusage.c index ab5e4b9d2..a224517c6 100644 --- a/src/modules/cpuusage/cpuusage.c +++ b/src/modules/cpuusage/cpuusage.c @@ -44,6 +44,8 @@ void ffPrintCPUUsage(FFCPUUsageOptions* options) } double avgValue = sumValue / (double) valueCount; + FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type; + if(options->moduleArgs.outputFormat.length == 0) { ffPrintLogoAndKey(FF_CPUUSAGE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); @@ -51,9 +53,9 @@ void ffPrintCPUUsage(FFCPUUsageOptions* options) FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate(); if (!options->separate) { - if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + if(percentType & FF_PERCENTAGE_TYPE_BAR_BIT) ffPercentAppendBar(&str, avgValue, options->percent, &options->moduleArgs); - if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + if(percentType & FF_PERCENTAGE_TYPE_NUM_BIT) { if(str.length > 0) ffStrbufAppendC(&str, ' '); @@ -74,17 +76,24 @@ void ffPrintCPUUsage(FFCPUUsageOptions* options) else { FF_STRBUF_AUTO_DESTROY avgNum = ffStrbufCreate(); - ffPercentAppendNum(&avgNum, avgValue, options->percent, false, &options->moduleArgs); + if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + ffPercentAppendNum(&avgNum, avgValue, options->percent, false, &options->moduleArgs); FF_STRBUF_AUTO_DESTROY avgBar = ffStrbufCreate(); - ffPercentAppendBar(&avgBar, avgValue, options->percent, &options->moduleArgs); + if (percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + ffPercentAppendBar(&avgBar, avgValue, options->percent, &options->moduleArgs); FF_STRBUF_AUTO_DESTROY minNum = ffStrbufCreate(); - ffPercentAppendNum(&minNum, minValue, options->percent, false, &options->moduleArgs); + if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + ffPercentAppendNum(&minNum, minValue, options->percent, false, &options->moduleArgs); FF_STRBUF_AUTO_DESTROY minBar = ffStrbufCreate(); - ffPercentAppendBar(&minBar, minValue, options->percent, &options->moduleArgs); + if (percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + ffPercentAppendBar(&minBar, minValue, options->percent, &options->moduleArgs); FF_STRBUF_AUTO_DESTROY maxNum = ffStrbufCreate(); - ffPercentAppendNum(&maxNum, maxValue, options->percent, false, &options->moduleArgs); + if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + ffPercentAppendNum(&maxNum, maxValue, options->percent, false, &options->moduleArgs); FF_STRBUF_AUTO_DESTROY maxBar = ffStrbufCreate(); - ffPercentAppendBar(&maxBar, maxValue, options->percent, &options->moduleArgs); + if (percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + ffPercentAppendBar(&maxBar, maxValue, options->percent, &options->moduleArgs); + FF_PRINT_FORMAT_CHECKED(FF_CPUUSAGE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_CPUUSAGE_NUM_FORMAT_ARGS, ((FFformatarg[]){ FF_FORMAT_ARG(avgNum, "avg"), FF_FORMAT_ARG(maxNum, "max"), @@ -214,7 +223,7 @@ void ffInitCPUUsageOptions(FFCPUUsageOptions* options) ); ffOptionInitModuleArg(&options->moduleArgs, "󰓅"); options->separate = false; - options->percent = (FFColorRangeConfig) { 50, 80 }; + options->percent = (FFPercentageModuleConfig) { 50, 80, 0 }; options->waitTime = 200; } diff --git a/src/modules/cpuusage/option.h b/src/modules/cpuusage/option.h index 844828b94..9f65f701d 100644 --- a/src/modules/cpuusage/option.h +++ b/src/modules/cpuusage/option.h @@ -11,6 +11,6 @@ typedef struct FFCPUUsageOptions FFModuleArgs moduleArgs; bool separate; - FFColorRangeConfig percent; + FFPercentageModuleConfig percent; uint32_t waitTime; // in ms } FFCPUUsageOptions; diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index 69ed5f8b6..a095d8c59 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -10,7 +10,7 @@ #define FF_DISK_NUM_FORMAT_ARGS 14 #pragma GCC diagnostic ignored "-Wsign-conversion" -static void printDisk(FFDiskOptions* options, const FFDisk* disk) +static void printDisk(FFDiskOptions* options, const FFDisk* disk, uint32_t index) { FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate(); @@ -35,11 +35,12 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk) } else { - FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, 4, ((FFformatarg[]){ + FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, 5, ((FFformatarg[]){ FF_FORMAT_ARG(disk->mountpoint, "mountpoint"), FF_FORMAT_ARG(disk->name, "name"), FF_FORMAT_ARG(disk->mountFrom, "mount-from"), FF_FORMAT_ARG(options->moduleArgs.keyIcon, "icon"), + FF_FORMAT_ARG(index, "index"), })); } @@ -50,6 +51,7 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk) ffParseSize(disk->bytesTotal, &totalPretty); double bytesPercentage = disk->bytesTotal > 0 ? (double) disk->bytesUsed / (double) disk->bytesTotal * 100.0 : 0; + FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type; if(options->moduleArgs.outputFormat.length == 0) { @@ -59,16 +61,16 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk) if(disk->bytesTotal > 0) { - if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + if(percentType & FF_PERCENTAGE_TYPE_BAR_BIT) { ffPercentAppendBar(&str, bytesPercentage, options->percent, &options->moduleArgs); ffStrbufAppendC(&str, ' '); } - if(!(instance.config.display.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) + if(!(percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) ffStrbufAppendF(&str, "%s / %s ", usedPretty.chars, totalPretty.chars); - if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + if(percentType & FF_PERCENTAGE_TYPE_NUM_BIT) { ffPercentAppendNum(&str, bytesPercentage, options->percent, str.length > 0, &options->moduleArgs); ffStrbufAppendC(&str, ' '); @@ -77,7 +79,7 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk) else ffStrbufAppendS(&str, "Unknown "); - if(!(instance.config.display.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) + if(!(percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) { if(disk->filesystem.length) ffStrbufAppendF(&str, "- %s ", disk->filesystem.chars); @@ -106,15 +108,19 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk) else { FF_STRBUF_AUTO_DESTROY bytesPercentageNum = ffStrbufCreate(); - ffPercentAppendNum(&bytesPercentageNum, bytesPercentage, options->percent, false, &options->moduleArgs); + if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + ffPercentAppendNum(&bytesPercentageNum, bytesPercentage, options->percent, false, &options->moduleArgs); FF_STRBUF_AUTO_DESTROY bytesPercentageBar = ffStrbufCreate(); - ffPercentAppendBar(&bytesPercentageBar, bytesPercentage, options->percent, &options->moduleArgs); + if (percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + ffPercentAppendBar(&bytesPercentageBar, bytesPercentage, options->percent, &options->moduleArgs); double filesPercentage = disk->filesTotal > 0 ? ((double) disk->filesUsed / (double) disk->filesTotal) * 100.0 : 0; FF_STRBUF_AUTO_DESTROY filesPercentageNum = ffStrbufCreate(); - ffPercentAppendNum(&filesPercentageNum, filesPercentage, options->percent, false, &options->moduleArgs); + if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + ffPercentAppendNum(&filesPercentageNum, filesPercentage, options->percent, false, &options->moduleArgs); FF_STRBUF_AUTO_DESTROY filesPercentageBar = ffStrbufCreate(); - ffPercentAppendBar(&filesPercentageBar, filesPercentage, options->percent, &options->moduleArgs); + if (percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + ffPercentAppendBar(&filesPercentageBar, filesPercentage, options->percent, &options->moduleArgs); bool isExternal = !!(disk->type & FF_DISK_VOLUME_TYPE_EXTERNAL_BIT); bool isHidden = !!(disk->type & FF_DISK_VOLUME_TYPE_HIDDEN_BIT); @@ -150,12 +156,13 @@ void ffPrintDisk(FFDiskOptions* options) } else { + uint32_t index = 0; FF_LIST_FOR_EACH(FFDisk, disk, disks) { if(__builtin_expect(options->folders.length == 0, 1) && (disk->type & ~options->showTypes)) continue; - printDisk(options, disk); + printDisk(options, disk, ++index); } } @@ -471,7 +478,7 @@ void ffInitDiskOptions(FFDiskOptions* options) ffStrbufInit(&options->folders); options->showTypes = FF_DISK_VOLUME_TYPE_REGULAR_BIT | FF_DISK_VOLUME_TYPE_EXTERNAL_BIT | FF_DISK_VOLUME_TYPE_READONLY_BIT; options->calcType = FF_DISK_CALC_TYPE_FREE; - options->percent = (FFColorRangeConfig) { 50, 80 }; + options->percent = (FFPercentageModuleConfig) { 50, 80, 0 }; } void ffDestroyDiskOptions(FFDiskOptions* options) diff --git a/src/modules/disk/option.h b/src/modules/disk/option.h index 7c2abdcaa..eb2323f4c 100644 --- a/src/modules/disk/option.h +++ b/src/modules/disk/option.h @@ -5,7 +5,7 @@ #include "common/option.h" #include "common/percent.h" -typedef enum FFDiskVolumeType +typedef enum __attribute__((__packed__)) FFDiskVolumeType { FF_DISK_VOLUME_TYPE_NONE = 0, FF_DISK_VOLUME_TYPE_REGULAR_BIT = 1 << 0, @@ -14,9 +14,10 @@ typedef enum FFDiskVolumeType FF_DISK_VOLUME_TYPE_SUBVOLUME_BIT = 1 << 3, FF_DISK_VOLUME_TYPE_UNKNOWN_BIT = 1 << 4, FF_DISK_VOLUME_TYPE_READONLY_BIT = 1 << 5, + FF_DISK_VOLUME_TYPE_FORCE_UNSIGNED = UINT8_MAX, } FFDiskVolumeType; -typedef enum FFDiskCalcType +typedef enum __attribute__((__packed__)) FFDiskCalcType { FF_DISK_CALC_TYPE_FREE, FF_DISK_CALC_TYPE_AVAILABLE, @@ -30,5 +31,5 @@ typedef struct FFDiskOptions FFstrbuf folders; FFDiskVolumeType showTypes; FFDiskCalcType calcType; - FFColorRangeConfig percent; + FFPercentageModuleConfig percent; } FFDiskOptions; diff --git a/src/modules/display/display.c b/src/modules/display/display.c index 98255ed46..6c720f31b 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -6,7 +6,7 @@ #include -#define FF_DISPLAY_NUM_FORMAT_ARGS 19 +#define FF_DISPLAY_NUM_FORMAT_ARGS 20 static int sortByNameAsc(FFDisplayResult* a, FFDisplayResult* b) { @@ -124,11 +124,21 @@ void ffPrintDisplay(FFDisplayOptions* options) if (inch > 1) ffStrbufAppendF(&buffer, " in %i\"", (uint32_t) (inch + 0.5)); - if(result->type != FF_DISPLAY_TYPE_UNKNOWN) - ffStrbufAppendS(&buffer, result->type == FF_DISPLAY_TYPE_BUILTIN ? " [Built-in]" : " [External]"); + bool flag = false; + if (result->type != FF_DISPLAY_TYPE_UNKNOWN) + { + ffStrbufAppendS(&buffer, result->type == FF_DISPLAY_TYPE_BUILTIN ? " [Built-in" : " [External"); + flag = true; + } if (result->hdrStatus == FF_DISPLAY_HDR_STATUS_ENABLED) - ffStrbufAppendS(&buffer, " [HDR]"); + { + ffStrbufAppendS(&buffer, flag ? ", HDR" : " [HDR"); + flag = true; + } + + if (flag) + ffStrbufAppendS(&buffer, "]"); if(moduleIndex > 0 && result->primary) ffStrbufAppendS(&buffer, " *"); @@ -140,6 +150,7 @@ void ffPrintDisplay(FFDisplayOptions* options) { double ppi = sqrt(result->width * result->width + result->height * result->height) / inch; bool hdrEnabled = result->hdrStatus == FF_DISPLAY_HDR_STATUS_ENABLED; + bool hdrCompatible = result->hdrStatus == FF_DISPLAY_HDR_STATUS_SUPPORTED || result->hdrStatus == FF_DISPLAY_HDR_STATUS_ENABLED; uint32_t iInch = (uint32_t) (inch + 0.5), iPpi = (uint32_t) (ppi + 0.5); char refreshRate[16]; @@ -182,6 +193,7 @@ void ffPrintDisplay(FFDisplayOptions* options) FF_FORMAT_ARG(result->manufactureWeek, "manufacture-week"), FF_FORMAT_ARG(buf, "serial"), FF_FORMAT_ARG(result->platformApi, "platform-api"), + FF_FORMAT_ARG(hdrCompatible, "hdr-compatible"), })); } } @@ -423,6 +435,7 @@ void ffPrintDisplayHelpFormat(void) "Nth week of manufacturing in the year - manufacture-week", "Serial number - serial", "The platform API used when detecting the display - platform-api", + "True if the display is HDR compatible - hdr-compatible", })); } diff --git a/src/modules/display/option.h b/src/modules/display/option.h index d6238e1b1..7233b2dd3 100644 --- a/src/modules/display/option.h +++ b/src/modules/display/option.h @@ -4,15 +4,16 @@ #include "common/option.h" -typedef enum FFDisplayCompactType +typedef enum __attribute__((__packed__)) FFDisplayCompactType { FF_DISPLAY_COMPACT_TYPE_NONE = 0, FF_DISPLAY_COMPACT_TYPE_ORIGINAL_BIT = 1 << 0, FF_DISPLAY_COMPACT_TYPE_SCALED_BIT = 1 << 1, FF_DISPLAY_COMPACT_TYPE_REFRESH_RATE_BIT = 1 << 2, + FF_DISPLAY_COMPACT_TYPE_UNSIGNED = UINT8_MAX, } FFDisplayCompactType; -typedef enum FFDisplayOrder +typedef enum __attribute__((__packed__)) FFDisplayOrder { FF_DISPLAY_ORDER_NONE, FF_DISPLAY_ORDER_ASC, diff --git a/src/modules/dns/dns.c b/src/modules/dns/dns.c index 63a744885..fe4654f23 100644 --- a/src/modules/dns/dns.c +++ b/src/modules/dns/dns.c @@ -122,6 +122,8 @@ void ffGenerateDNSJsonConfig(FFDNSOptions* options, yyjson_mut_doc* doc, yyjson_ if (defaultOptions.showType != options->showType) { + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wswitch" // FF_DNS_TYPE_FORCE_UNSIGNED switch (options->showType) { case FF_DNS_TYPE_IPV4_BIT: @@ -134,6 +136,7 @@ void ffGenerateDNSJsonConfig(FFDNSOptions* options, yyjson_mut_doc* doc, yyjson_ yyjson_mut_obj_add_str(doc, module, "showType", "both"); break; } + #pragma GCC diagnostic pop } } diff --git a/src/modules/dns/option.h b/src/modules/dns/option.h index d261d7e06..18dbb147b 100644 --- a/src/modules/dns/option.h +++ b/src/modules/dns/option.h @@ -4,10 +4,11 @@ #include "common/option.h" -typedef enum FFDNSShowType { +typedef enum __attribute__((__packed__)) FFDNSShowType { FF_DNS_TYPE_IPV4_BIT = 1, FF_DNS_TYPE_IPV6_BIT = 2, FF_DNS_TYPE_BOTH = FF_DNS_TYPE_IPV4_BIT | FF_DNS_TYPE_IPV6_BIT, + FF_DNS_TYPE_FORCE_UNSIGNED = UINT8_MAX, } FFDNSShowType; typedef struct FFDNSOptions diff --git a/src/modules/gamepad/gamepad.c b/src/modules/gamepad/gamepad.c index b1b3457f0..82e1b29af 100644 --- a/src/modules/gamepad/gamepad.c +++ b/src/modules/gamepad/gamepad.c @@ -9,13 +9,24 @@ static void printDevice(FFGamepadOptions* options, const FFGamepadDevice* device, uint8_t index) { + FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type; if(options->moduleArgs.outputFormat.length == 0) { ffPrintLogoAndKey(FF_GAMEPAD_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); - FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreateCopy(&device->name); + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + bool showBatteryLevel = device->battery > 0 && device->battery <= 100; - if (device->battery > 0 && device->battery <= 100) + if (showBatteryLevel && (percentType & FF_PERCENTAGE_TYPE_BAR_BIT)) + { + ffPercentAppendBar(&buffer, device->battery, options->percent, &options->moduleArgs); + ffStrbufAppendC(&buffer, ' '); + } + + if (!(percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) + ffStrbufAppend(&buffer, &device->name); + + if (showBatteryLevel && (percentType & FF_PERCENTAGE_TYPE_NUM_BIT)) { if (buffer.length) ffStrbufAppendC(&buffer, ' '); @@ -26,9 +37,11 @@ static void printDevice(FFGamepadOptions* options, const FFGamepadDevice* device else { FF_STRBUF_AUTO_DESTROY percentageNum = ffStrbufCreate(); - ffPercentAppendNum(&percentageNum, device->battery, options->percent, false, &options->moduleArgs); + if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + ffPercentAppendNum(&percentageNum, device->battery, options->percent, false, &options->moduleArgs); FF_STRBUF_AUTO_DESTROY percentageBar = ffStrbufCreate(); - ffPercentAppendBar(&percentageBar, device->battery, options->percent, &options->moduleArgs); + if (percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + ffPercentAppendBar(&percentageBar, device->battery, options->percent, &options->moduleArgs); FF_PRINT_FORMAT_CHECKED(FF_GAMEPAD_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_GAMEPAD_NUM_FORMAT_ARGS, ((FFformatarg[]) { FF_FORMAT_ARG(device->name, "name"), @@ -160,7 +173,7 @@ void ffInitGamepadOptions(FFGamepadOptions* options) ffGenerateGamepadJsonConfig ); ffOptionInitModuleArg(&options->moduleArgs, "󰺵"); - options->percent = (FFColorRangeConfig) { 50, 20 }; + options->percent = (FFPercentageModuleConfig) { 50, 20, 0 }; } void ffDestroyGamepadOptions(FFGamepadOptions* options) diff --git a/src/modules/gamepad/option.h b/src/modules/gamepad/option.h index b4ecaf94d..d1b570bf8 100644 --- a/src/modules/gamepad/option.h +++ b/src/modules/gamepad/option.h @@ -9,5 +9,5 @@ typedef struct FFGamepadOptions FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; - FFColorRangeConfig percent; + FFPercentageModuleConfig percent; } FFGamepadOptions; diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index 57a7b9a8a..3489fc57e 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -439,7 +439,7 @@ void ffInitGPUOptions(FFGPUOptions* options) options->temp = false; options->hideType = FF_GPU_TYPE_UNKNOWN; options->tempConfig = (FFColorRangeConfig) { 60, 80 }; - options->percent = (FFColorRangeConfig) { 50, 80 }; + options->percent = (FFPercentageModuleConfig) { 50, 80, 0 }; } void ffDestroyGPUOptions(FFGPUOptions* options) diff --git a/src/modules/gpu/option.h b/src/modules/gpu/option.h index 5f53d2f6f..98362940b 100644 --- a/src/modules/gpu/option.h +++ b/src/modules/gpu/option.h @@ -5,14 +5,14 @@ #include "common/option.h" #include "common/percent.h" -typedef enum FFGPUType +typedef enum __attribute__((__packed__)) FFGPUType { FF_GPU_TYPE_UNKNOWN, FF_GPU_TYPE_INTEGRATED, FF_GPU_TYPE_DISCRETE, } FFGPUType; -typedef enum FFGPUDetectionMethod +typedef enum __attribute__((__packed__)) FFGPUDetectionMethod { FF_GPU_DETECTION_METHOD_AUTO, FF_GPU_DETECTION_METHOD_PCI, @@ -32,5 +32,5 @@ typedef struct FFGPUOptions bool driverSpecific; bool forceMethod; FFColorRangeConfig tempConfig; - FFColorRangeConfig percent; + FFPercentageModuleConfig percent; } FFGPUOptions; diff --git a/src/modules/loadavg/loadavg.c b/src/modules/loadavg/loadavg.c index d53b12ff4..27e74a98e 100644 --- a/src/modules/loadavg/loadavg.c +++ b/src/modules/loadavg/loadavg.c @@ -59,18 +59,19 @@ void ffPrintLoadavg(FFLoadavgOptions* options) ffStrbufClear(&buffer); double percent = result[index] * 100 / cpu.coresOnline; + FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type; - if (instance.config.display.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + if (percentType & FF_PERCENTAGE_TYPE_BAR_BIT) ffPercentAppendBar(&buffer, percent, options->percent, &options->moduleArgs); - if (!(instance.config.display.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) + if (!(percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) { if (buffer.length > 0) ffStrbufAppendC(&buffer, ' '); ffStrbufAppendF(&buffer, "%.*f", options->ndigits, result[index]); } - if (instance.config.display.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) { if (buffer.length > 0) ffStrbufAppendC(&buffer, ' '); @@ -204,7 +205,7 @@ void ffInitLoadavgOptions(FFLoadavgOptions* options) ); ffOptionInitModuleArg(&options->moduleArgs, ""); - options->percent = (FFColorRangeConfig) { 50, 80 }; + options->percent = (FFPercentageModuleConfig) { 50, 80, 0 }; options->ndigits = 2; options->compact = true; } diff --git a/src/modules/loadavg/option.h b/src/modules/loadavg/option.h index 0bcce0037..aee5f435c 100644 --- a/src/modules/loadavg/option.h +++ b/src/modules/loadavg/option.h @@ -9,7 +9,7 @@ typedef struct FFLoadavgOptions FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; - FFColorRangeConfig percent; + FFPercentageModuleConfig percent; uint8_t ndigits; bool compact; } FFLoadavgOptions; diff --git a/src/modules/localip/option.h b/src/modules/localip/option.h index 511ec729d..c95b77d8b 100644 --- a/src/modules/localip/option.h +++ b/src/modules/localip/option.h @@ -4,7 +4,7 @@ #include "common/option.h" -typedef enum FFLocalIpType +typedef enum __attribute__((__packed__)) FFLocalIpType { FF_LOCALIP_TYPE_NONE, FF_LOCALIP_TYPE_LOOP_BIT = 1 << 0, @@ -19,7 +19,9 @@ typedef enum FFLocalIpType FF_LOCALIP_TYPE_COMPACT_BIT = 1 << 10, FF_LOCALIP_TYPE_DEFAULT_ROUTE_ONLY_BIT = 1 << 11, FF_LOCALIP_TYPE_ALL_IPS_BIT = 1 << 12, + FF_LOCALIP_TYPE_FORCE_UNSIGNED = UINT16_MAX, } FFLocalIpType; +static_assert(sizeof(FFLocalIpType) == sizeof(uint16_t), ""); typedef struct FFLocalIpOptions { diff --git a/src/modules/memory/memory.c b/src/modules/memory/memory.c index 05f58a0e7..8cad52839 100644 --- a/src/modules/memory/memory.c +++ b/src/modules/memory/memory.c @@ -29,6 +29,7 @@ void ffPrintMemory(FFMemoryOptions* options) ? 0 : (double) storage.bytesUsed / (double) storage.bytesTotal * 100.0; + FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type; if(options->moduleArgs.outputFormat.length == 0) { ffPrintLogoAndKey(FF_MEMORY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); @@ -38,16 +39,16 @@ void ffPrintMemory(FFMemoryOptions* options) { FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate(); - if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + if(percentType & FF_PERCENTAGE_TYPE_BAR_BIT) { ffPercentAppendBar(&str, percentage, options->percent, &options->moduleArgs); ffStrbufAppendC(&str, ' '); } - if(!(instance.config.display.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) + if(!(percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) ffStrbufAppendF(&str, "%s / %s ", usedPretty.chars, totalPretty.chars); - if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + if(percentType & FF_PERCENTAGE_TYPE_NUM_BIT) ffPercentAppendNum(&str, percentage, options->percent, str.length > 0, &options->moduleArgs); ffStrbufTrimRight(&str, ' '); @@ -57,9 +58,12 @@ void ffPrintMemory(FFMemoryOptions* options) else { FF_STRBUF_AUTO_DESTROY percentageNum = ffStrbufCreate(); - ffPercentAppendNum(&percentageNum, percentage, options->percent, false, &options->moduleArgs); + if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + ffPercentAppendNum(&percentageNum, percentage, options->percent, false, &options->moduleArgs); FF_STRBUF_AUTO_DESTROY percentageBar = ffStrbufCreate(); - ffPercentAppendBar(&percentageBar, percentage, options->percent, &options->moduleArgs); + if (percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + ffPercentAppendBar(&percentageBar, percentage, options->percent, &options->moduleArgs); + FF_PRINT_FORMAT_CHECKED(FF_MEMORY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_MEMORY_NUM_FORMAT_ARGS, ((FFformatarg[]){ FF_FORMAT_ARG(usedPretty, "used"), FF_FORMAT_ARG(totalPretty, "total"), @@ -152,7 +156,7 @@ void ffInitMemoryOptions(FFMemoryOptions* options) ffGenerateMemoryJsonConfig ); ffOptionInitModuleArg(&options->moduleArgs, ""); - options->percent = (FFColorRangeConfig) { 50, 80 }; + options->percent = (FFPercentageModuleConfig) { 50, 80, 0 }; } void ffDestroyMemoryOptions(FFMemoryOptions* options) diff --git a/src/modules/memory/option.h b/src/modules/memory/option.h index 4936b252b..76fc9fd06 100644 --- a/src/modules/memory/option.h +++ b/src/modules/memory/option.h @@ -10,5 +10,5 @@ typedef struct FFMemoryOptions FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; - FFColorRangeConfig percent; + FFPercentageModuleConfig percent; } FFMemoryOptions; diff --git a/src/modules/monitor/monitor.c b/src/modules/monitor/monitor.c index 701444c29..93ce917db 100644 --- a/src/modules/monitor/monitor.c +++ b/src/modules/monitor/monitor.c @@ -29,7 +29,9 @@ void ffPrintMonitor(FFMonitorOptions* options) ffStrbufClear(&key); if(options->moduleArgs.key.length == 0) { - ffStrbufAppendF(&key, "%s (%s)", FF_MONITOR_MODULE_NAME, display->name.chars); + ffStrbufAppendS(&key, FF_MONITOR_MODULE_NAME); + if (display->name.length > 0) + ffStrbufAppendF(&key, " (%s)", display->name.chars); } else { diff --git a/src/modules/opengl/option.h b/src/modules/opengl/option.h index 8c9db6309..54fd466c9 100644 --- a/src/modules/opengl/option.h +++ b/src/modules/opengl/option.h @@ -4,7 +4,7 @@ #include "common/option.h" -typedef enum FFOpenGLLibrary +typedef enum __attribute__((__packed__)) FFOpenGLLibrary { FF_OPENGL_LIBRARY_AUTO, FF_OPENGL_LIBRARY_EGL, diff --git a/src/modules/os/os.c b/src/modules/os/os.c index 8224b65c5..cc488382f 100644 --- a/src/modules/os/os.c +++ b/src/modules/os/os.c @@ -224,10 +224,10 @@ void ffInitOSOptions(FFOSOptions* options) "" #elif __FreeBSD__ "󰣠" - #elif __linux__ - "" #elif __ANDROID__ "" + #elif __linux__ + "" #elif __sun "" #elif __OpenBSD__ diff --git a/src/modules/packages/option.h b/src/modules/packages/option.h index e3f3d54c7..cab933592 100644 --- a/src/modules/packages/option.h +++ b/src/modules/packages/option.h @@ -4,7 +4,7 @@ #include "common/option.h" -typedef enum FFPackagesFlags +typedef enum __attribute__((__packed__)) FFPackagesFlags { FF_PACKAGES_FLAG_NONE = 0, FF_PACKAGES_FLAG_APK_BIT = 1 << 0, @@ -33,7 +33,11 @@ typedef enum FFPackagesFlags FF_PACKAGES_FLAG_GUIX_BIT = 1 << 23, FF_PACKAGES_FLAG_LINGLONG_BIT = 1 << 24, FF_PACKAGES_FLAG_PACSTALL_BIT = 1 << 25, + FF_PACKAGES_FLAG_MPORT_BIT = 1 << 26, + FF_PACKAGES_FLAG_QI_BIT = 1 << 27, + FF_PACKAGES_FLAG_FORCE_UNSIGNED = UINT32_MAX, } FFPackagesFlags; +static_assert(sizeof(FFPackagesFlags) == sizeof(uint32_t), ""); typedef struct FFPackagesOptions { diff --git a/src/modules/packages/packages.c b/src/modules/packages/packages.c index e33b18d49..3241b714d 100644 --- a/src/modules/packages/packages.c +++ b/src/modules/packages/packages.c @@ -4,7 +4,7 @@ #include "modules/packages/packages.h" #include "util/stringUtils.h" -#define FF_PACKAGES_NUM_FORMAT_ARGS 38 +#define FF_PACKAGES_NUM_FORMAT_ARGS 40 void ffPrintPackages(FFPackagesOptions* options) { @@ -73,6 +73,8 @@ void ffPrintPackages(FFPackagesOptions* options) FF_PRINT_PACKAGE_NAME(guixHome, "guix-home") FF_PRINT_PACKAGE(linglong) FF_PRINT_PACKAGE(pacstall) + FF_PRINT_PACKAGE(mport) + FF_PRINT_PACKAGE(qi) putchar('\n'); } @@ -117,6 +119,8 @@ void ffPrintPackages(FFPackagesOptions* options) FF_FORMAT_ARG(counts.guixHome, "guix-home"), FF_FORMAT_ARG(counts.linglong, "linglong"), FF_FORMAT_ARG(counts.pacstall, "pacstall"), + FF_FORMAT_ARG(counts.mport, "mport"), + FF_FORMAT_ARG(counts.qi, "qi"), FF_FORMAT_ARG(nixAll, "nix-all"), FF_FORMAT_ARG(flatpakAll, "flatpak-all"), FF_FORMAT_ARG(brewAll, "brew-all"), @@ -179,6 +183,7 @@ bool ffParsePackagesCommandOptions(FFPackagesOptions* options, const char* key, break; case 'M': if (false); FF_TEST_PACKAGE_NAME(MACPORTS) + FF_TEST_PACKAGE_NAME(MPORT) break; case 'N': if (false); FF_TEST_PACKAGE_NAME(NIX) @@ -193,6 +198,9 @@ bool ffParsePackagesCommandOptions(FFPackagesOptions* options, const char* key, FF_TEST_PACKAGE_NAME(PKG) FF_TEST_PACKAGE_NAME(PKGTOOL) break; + case 'Q': if (false); + FF_TEST_PACKAGE_NAME(QI) + break; case 'R': if (false); FF_TEST_PACKAGE_NAME(RPM) break; @@ -279,7 +287,7 @@ void ffParsePackagesJsonObject(FFPackagesOptions* options, yyjson_val* module) case 'F': if (false); FF_TEST_PACKAGE_NAME(FLATPAK) break; - case 'G': if (false); + case 'G': if (false); FF_TEST_PACKAGE_NAME(GUIX) break; case 'L': if (false); @@ -289,6 +297,7 @@ void ffParsePackagesJsonObject(FFPackagesOptions* options, yyjson_val* module) break; case 'M': if (false); FF_TEST_PACKAGE_NAME(MACPORTS) + FF_TEST_PACKAGE_NAME(MPORT) break; case 'N': if (false); FF_TEST_PACKAGE_NAME(NIX) @@ -303,6 +312,9 @@ void ffParsePackagesJsonObject(FFPackagesOptions* options, yyjson_val* module) FF_TEST_PACKAGE_NAME(PKG) FF_TEST_PACKAGE_NAME(PKGTOOL) break; + case 'Q': if (false); + FF_TEST_PACKAGE_NAME(QI) + break; case 'R': if (false); FF_TEST_PACKAGE_NAME(RPM) break; @@ -353,6 +365,7 @@ void ffGeneratePackagesJsonConfig(FFPackagesOptions* options, yyjson_mut_doc* do FF_TEST_PACKAGE_NAME(LPKG) FF_TEST_PACKAGE_NAME(LPKGBUILD) FF_TEST_PACKAGE_NAME(MACPORTS) + FF_TEST_PACKAGE_NAME(MPORT) FF_TEST_PACKAGE_NAME(NIX) FF_TEST_PACKAGE_NAME(OPKG) FF_TEST_PACKAGE_NAME(PACMAN) @@ -360,6 +373,7 @@ void ffGeneratePackagesJsonConfig(FFPackagesOptions* options, yyjson_mut_doc* do FF_TEST_PACKAGE_NAME(PALUDIS) FF_TEST_PACKAGE_NAME(PKG) FF_TEST_PACKAGE_NAME(PKGTOOL) + FF_TEST_PACKAGE_NAME(QI) FF_TEST_PACKAGE_NAME(RPM) FF_TEST_PACKAGE_NAME(SCOOP) FF_TEST_PACKAGE_NAME(SNAP) @@ -388,6 +402,7 @@ void ffGeneratePackagesJsonResult(FF_MAYBE_UNUSED FFPackagesOptions* options, yy #define FF_APPEND_PACKAGE_COUNT(name) yyjson_mut_obj_add_uint(doc, obj, #name, counts.name); FF_APPEND_PACKAGE_COUNT(all) + FF_APPEND_PACKAGE_COUNT(am) FF_APPEND_PACKAGE_COUNT(apk) FF_APPEND_PACKAGE_COUNT(brew) FF_APPEND_PACKAGE_COUNT(brewCask) @@ -397,33 +412,34 @@ void ffGeneratePackagesJsonResult(FF_MAYBE_UNUSED FFPackagesOptions* options, yy FF_APPEND_PACKAGE_COUNT(eopkg) FF_APPEND_PACKAGE_COUNT(flatpakSystem) FF_APPEND_PACKAGE_COUNT(flatpakUser) - FF_APPEND_PACKAGE_COUNT(nixDefault) - FF_APPEND_PACKAGE_COUNT(nixSystem) - FF_APPEND_PACKAGE_COUNT(nixUser) - FF_APPEND_PACKAGE_COUNT(pacman) - FF_APPEND_PACKAGE_COUNT(paludis) - FF_APPEND_PACKAGE_COUNT(pkg) - FF_APPEND_PACKAGE_COUNT(pkgtool) - FF_APPEND_PACKAGE_COUNT(macports) - FF_APPEND_PACKAGE_COUNT(rpm) - FF_APPEND_PACKAGE_COUNT(scoop) - FF_APPEND_PACKAGE_COUNT(snap) - FF_APPEND_PACKAGE_COUNT(winget) - FF_APPEND_PACKAGE_COUNT(xbps) - FF_APPEND_PACKAGE_COUNT(opkg) - FF_APPEND_PACKAGE_COUNT(am) - FF_APPEND_PACKAGE_COUNT(sorcery) FF_APPEND_PACKAGE_COUNT(guixSystem) FF_APPEND_PACKAGE_COUNT(guixUser) FF_APPEND_PACKAGE_COUNT(guixHome) FF_APPEND_PACKAGE_COUNT(linglong) + FF_APPEND_PACKAGE_COUNT(mport) + FF_APPEND_PACKAGE_COUNT(nixDefault) + FF_APPEND_PACKAGE_COUNT(nixSystem) + FF_APPEND_PACKAGE_COUNT(nixUser) + FF_APPEND_PACKAGE_COUNT(opkg) + FF_APPEND_PACKAGE_COUNT(pacman) FF_APPEND_PACKAGE_COUNT(pacstall) + FF_APPEND_PACKAGE_COUNT(paludis) + FF_APPEND_PACKAGE_COUNT(pkg) + FF_APPEND_PACKAGE_COUNT(pkgtool) + FF_APPEND_PACKAGE_COUNT(qi) + FF_APPEND_PACKAGE_COUNT(macports) + FF_APPEND_PACKAGE_COUNT(rpm) + FF_APPEND_PACKAGE_COUNT(scoop) + FF_APPEND_PACKAGE_COUNT(snap) + FF_APPEND_PACKAGE_COUNT(sorcery) + FF_APPEND_PACKAGE_COUNT(winget) + FF_APPEND_PACKAGE_COUNT(xbps) yyjson_mut_obj_add_strbuf(doc, obj, "pacmanBranch", &counts.pacmanBranch); } void ffPrintPackagesHelpFormat(void) { - FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_PACKAGES_MODULE_NAME, "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (emerge), {7} (eopkg), {8} (xbps), {9} (nix-system), {10} (nix-user), {11} (nix-default), {12} (apk), {13} (pkg), {14} (flatpak-system), {15} (flatpack-user), {16} (snap), {17} (brew), {18} (brew-cask), {19} (MacPorts), {20} (scoop), {21} (choco), {22} (pkgtool), {23} (paludis), {24} (winget), {25} (opkg), {26} (am), {27} (sorcery), {28} (lpkg), {29} (lpkgbuild), {30} (guix-system), {31} (guix-user), {32} (guix-home), {33} (linglong)", FF_PACKAGES_NUM_FORMAT_ARGS, ((const char* []) { + FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_PACKAGES_MODULE_NAME, "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (emerge), {7} (eopkg), {8} (xbps), {9} (nix-system), {10} (nix-user), {11} (nix-default), {12} (apk), {13} (pkg), {14} (flatpak-system), {15} (flatpack-user), {16} (snap), {17} (brew), {18} (brew-cask), {19} (MacPorts), {20} (scoop), {21} (choco), {22} (pkgtool), {23} (paludis), {24} (winget), {25} (opkg), {26} (am), {27} (sorcery), {28} (lpkg), {29} (lpkgbuild), {30} (guix-system), {31} (guix-user), {32} (guix-home), {33} (linglong), {34} (pacstall), {35} (mport), {36} qi", FF_PACKAGES_NUM_FORMAT_ARGS, ((const char* []) { "Number of all packages - all", "Number of pacman packages - pacman", "Pacman branch on manjaro - pacman-branch", @@ -458,6 +474,8 @@ void ffPrintPackagesHelpFormat(void) "Number of guix-home packages - guix-home", "Number of linglong packages - linglong", "Number of pacstall packages - pacstall", + "Number of mport packages - mport", + "Number of qi packages - qi", "Total number of all nix packages - nix-all", "Total number of all flatpak app packages - flatpak-all", "Total number of all brew packages - brew-all", diff --git a/src/modules/sound/option.h b/src/modules/sound/option.h index ad659a557..7ec2c1614 100644 --- a/src/modules/sound/option.h +++ b/src/modules/sound/option.h @@ -5,7 +5,7 @@ #include "common/option.h" #include "common/percent.h" -typedef enum FFSoundType +typedef enum __attribute__((__packed__)) FFSoundType { FF_SOUND_TYPE_MAIN, FF_SOUND_TYPE_ACTIVE, @@ -18,5 +18,5 @@ typedef struct FFSoundOptions FFModuleArgs moduleArgs; FFSoundType soundType; - FFColorRangeConfig percent; + FFPercentageModuleConfig percent; } FFSoundOptions; diff --git a/src/modules/sound/sound.c b/src/modules/sound/sound.c index 3d24b2be6..1e0cd7e84 100644 --- a/src/modules/sound/sound.c +++ b/src/modules/sound/sound.c @@ -9,17 +9,18 @@ static void printDevice(FFSoundOptions* options, const FFSoundDevice* device, uint8_t index) { + FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type; if(options->moduleArgs.outputFormat.length == 0) { ffPrintLogoAndKey(FF_SOUND_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate(); - if (!(instance.config.display.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) + if (!(percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) ffStrbufAppend(&str, &device->name); if(device->volume != FF_SOUND_VOLUME_UNKNOWN) { - if (instance.config.display.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + if (percentType & FF_PERCENTAGE_TYPE_BAR_BIT) { if (str.length) ffStrbufAppendC(&str, ' '); @@ -27,7 +28,7 @@ static void printDevice(FFSoundOptions* options, const FFSoundDevice* device, ui ffPercentAppendBar(&str, device->volume, options->percent, &options->moduleArgs); } - if (instance.config.display.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) { if (str.length) ffStrbufAppendC(&str, ' '); @@ -36,7 +37,7 @@ static void printDevice(FFSoundOptions* options, const FFSoundDevice* device, ui } } - if (!(instance.config.display.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) + if (!(percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) { if (device->main && index > 0) ffStrbufAppendS(&str, " (*)"); @@ -47,9 +48,11 @@ static void printDevice(FFSoundOptions* options, const FFSoundDevice* device, ui else { FF_STRBUF_AUTO_DESTROY percentageNum = ffStrbufCreate(); - ffPercentAppendNum(&percentageNum, device->volume, options->percent, false, &options->moduleArgs); + if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + ffPercentAppendNum(&percentageNum, device->volume, options->percent, false, &options->moduleArgs); FF_STRBUF_AUTO_DESTROY percentageBar = ffStrbufCreate(); - ffPercentAppendBar(&percentageBar, device->volume, options->percent, &options->moduleArgs); + if (percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + ffPercentAppendBar(&percentageBar, device->volume, options->percent, &options->moduleArgs); FF_PRINT_FORMAT_CHECKED(FF_SOUND_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_SOUND_NUM_FORMAT_ARGS, ((FFformatarg[]) { FF_FORMAT_ARG(device->main, "is-main"), @@ -253,7 +256,7 @@ void ffInitSoundOptions(FFSoundOptions* options) ffOptionInitModuleArg(&options->moduleArgs, ""); options->soundType = FF_SOUND_TYPE_MAIN; - options->percent = (FFColorRangeConfig) { 80, 90 }; + options->percent = (FFPercentageModuleConfig) { 80, 90, 0 }; } void ffDestroySoundOptions(FFSoundOptions* options) diff --git a/src/modules/swap/option.h b/src/modules/swap/option.h index 1c96ce41f..d6e7965ad 100644 --- a/src/modules/swap/option.h +++ b/src/modules/swap/option.h @@ -10,5 +10,5 @@ typedef struct FFSwapOptions FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; - FFColorRangeConfig percent; + FFPercentageModuleConfig percent; } FFSwapOptions; diff --git a/src/modules/swap/swap.c b/src/modules/swap/swap.c index 210351631..6fba1f3aa 100644 --- a/src/modules/swap/swap.c +++ b/src/modules/swap/swap.c @@ -29,34 +29,36 @@ void ffPrintSwap(FFSwapOptions* options) ? 0 : (double) storage.bytesUsed / (double) storage.bytesTotal * 100.0; + FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type; if(options->moduleArgs.outputFormat.length == 0) { ffPrintLogoAndKey(FF_SWAP_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate(); + if (storage.bytesTotal == 0) { - if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + if(percentType & FF_PERCENTAGE_TYPE_BAR_BIT) { ffPercentAppendBar(&str, 0, options->percent, &options->moduleArgs); ffStrbufAppendC(&str, ' '); } - if(!(instance.config.display.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) + if(!(percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) ffStrbufAppendS(&str, "Disabled"); else ffPercentAppendNum(&str, 0, options->percent, str.length > 0, &options->moduleArgs); } else { - if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + if(percentType & FF_PERCENTAGE_TYPE_BAR_BIT) { ffPercentAppendBar(&str, percentage, options->percent, &options->moduleArgs); ffStrbufAppendC(&str, ' '); } - if(!(instance.config.display.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) + if(!(percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) ffStrbufAppendF(&str, "%s / %s ", usedPretty.chars, totalPretty.chars); - if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + if(percentType & FF_PERCENTAGE_TYPE_NUM_BIT) ffPercentAppendNum(&str, percentage, options->percent, str.length > 0, &options->moduleArgs); } @@ -66,9 +68,11 @@ void ffPrintSwap(FFSwapOptions* options) else { FF_STRBUF_AUTO_DESTROY percentageNum = ffStrbufCreate(); - ffPercentAppendNum(&percentageNum, percentage, options->percent, false, &options->moduleArgs); + if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + ffPercentAppendNum(&percentageNum, percentage, options->percent, false, &options->moduleArgs); FF_STRBUF_AUTO_DESTROY percentageBar = ffStrbufCreate(); - ffPercentAppendBar(&percentageBar, percentage, options->percent, &options->moduleArgs); + if (percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + ffPercentAppendBar(&percentageBar, percentage, options->percent, &options->moduleArgs); FF_PRINT_FORMAT_CHECKED(FF_SWAP_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_SWAP_NUM_FORMAT_ARGS, ((FFformatarg[]){ FF_FORMAT_ARG(usedPretty, "used"), FF_FORMAT_ARG(totalPretty, "total"), @@ -161,7 +165,7 @@ void ffInitSwapOptions(FFSwapOptions* options) ffGenerateSwapJsonConfig ); ffOptionInitModuleArg(&options->moduleArgs, "󰓡"); - options->percent = (FFColorRangeConfig) { 50, 80 }; + options->percent = (FFPercentageModuleConfig) { 50, 80, 0 }; } void ffDestroySwapOptions(FFSwapOptions* options) diff --git a/src/modules/wifi/option.h b/src/modules/wifi/option.h index 305a95a47..3628df69d 100644 --- a/src/modules/wifi/option.h +++ b/src/modules/wifi/option.h @@ -9,5 +9,5 @@ typedef struct FFWifiOptions FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; - FFColorRangeConfig percent; + FFPercentageModuleConfig percent; } FFWifiOptions; diff --git a/src/modules/wifi/wifi.c b/src/modules/wifi/wifi.c index d000c7e6b..b2d829d42 100644 --- a/src/modules/wifi/wifi.c +++ b/src/modules/wifi/wifi.c @@ -22,6 +22,8 @@ void ffPrintWifi(FFWifiOptions* options) return; } + FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type; + for(uint32_t index = 0; index < result.length; ++index) { FFWifiResult* item = FF_LIST_GET(FFWifiResult, result, index); @@ -36,14 +38,14 @@ void ffPrintWifi(FFWifiOptions* options) { if(item->conn.signalQuality == item->conn.signalQuality) { - if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + if(percentType & FF_PERCENTAGE_TYPE_BAR_BIT) { ffPercentAppendBar(&buffer, item->conn.signalQuality, options->percent, &options->moduleArgs); ffStrbufAppendC(&buffer, ' '); } } - if (!(instance.config.display.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) + if (!(percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) { ffStrbufAppend(&buffer, &item->conn.ssid); @@ -62,7 +64,7 @@ void ffPrintWifi(FFWifiOptions* options) if(item->conn.signalQuality == item->conn.signalQuality) { - if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + if(percentType & FF_PERCENTAGE_TYPE_NUM_BIT) ffPercentAppendNum(&buffer, item->conn.signalQuality, options->percent, buffer.length > 0, &options->moduleArgs); } @@ -77,9 +79,12 @@ void ffPrintWifi(FFWifiOptions* options) else { FF_STRBUF_AUTO_DESTROY percentNum = ffStrbufCreate(); - ffPercentAppendNum(&percentNum, item->conn.signalQuality, options->percent, false, &options->moduleArgs); + if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + ffPercentAppendNum(&percentNum, item->conn.signalQuality, options->percent, false, &options->moduleArgs); FF_STRBUF_AUTO_DESTROY percentBar = ffStrbufCreate(); - ffPercentAppendBar(&percentBar, item->conn.signalQuality, options->percent, &options->moduleArgs); + if (percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + ffPercentAppendBar(&percentBar, item->conn.signalQuality, options->percent, &options->moduleArgs); + FF_PRINT_FORMAT_CHECKED(FF_WIFI_MODULE_NAME, moduleIndex, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_WIFI_NUM_FORMAT_ARGS, ((FFformatarg[]){ FF_FORMAT_ARG(item->inf.description, "inf-desc"), FF_FORMAT_ARG(item->inf.status, "inf-status"), @@ -222,7 +227,7 @@ void ffInitWifiOptions(FFWifiOptions* options) ); ffOptionInitModuleArg(&options->moduleArgs, ""); - options->percent = (FFColorRangeConfig) { 50, 20 }; + options->percent = (FFPercentageModuleConfig) { 50, 20, 0 }; } void ffDestroyWifiOptions(FFWifiOptions* options) diff --git a/src/modules/zpool/option.h b/src/modules/zpool/option.h index 3143cf91b..ac4f8ff3f 100644 --- a/src/modules/zpool/option.h +++ b/src/modules/zpool/option.h @@ -10,5 +10,5 @@ typedef struct FFZpoolOptions FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; - FFColorRangeConfig percent; + FFPercentageModuleConfig percent; } FFZpoolOptions; diff --git a/src/modules/zpool/zpool.c b/src/modules/zpool/zpool.c index 719d411bf..a47cb244d 100644 --- a/src/modules/zpool/zpool.c +++ b/src/modules/zpool/zpool.c @@ -34,6 +34,7 @@ static void printZpool(FFZpoolOptions* options, FFZpoolResult* result, uint8_t i ffParseSize(result->total, &totalPretty); double bytesPercentage = result->total > 0 ? (double) result->used / (double) result->total * 100.0 : 0; + FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type; if(options->moduleArgs.outputFormat.length == 0) { @@ -50,14 +51,18 @@ static void printZpool(FFZpoolOptions* options, FFZpoolResult* result, uint8_t i else { FF_STRBUF_AUTO_DESTROY bytesPercentageNum = ffStrbufCreate(); - ffPercentAppendNum(&bytesPercentageNum, bytesPercentage, options->percent, false, &options->moduleArgs); + if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + ffPercentAppendNum(&bytesPercentageNum, bytesPercentage, options->percent, false, &options->moduleArgs); FF_STRBUF_AUTO_DESTROY bytesPercentageBar = ffStrbufCreate(); - ffPercentAppendBar(&bytesPercentageBar, bytesPercentage, options->percent, &options->moduleArgs); + if (percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + ffPercentAppendBar(&bytesPercentageBar, bytesPercentage, options->percent, &options->moduleArgs); FF_STRBUF_AUTO_DESTROY fragPercentageNum = ffStrbufCreate(); - ffPercentAppendNum(&fragPercentageNum, result->fragmentation, options->percent, false, &options->moduleArgs); + if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + ffPercentAppendNum(&fragPercentageNum, result->fragmentation, options->percent, false, &options->moduleArgs); FF_STRBUF_AUTO_DESTROY fragPercentageBar = ffStrbufCreate(); - ffPercentAppendBar(&fragPercentageBar, result->fragmentation, options->percent, &options->moduleArgs); + if (percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + ffPercentAppendBar(&fragPercentageBar, result->fragmentation, options->percent, &options->moduleArgs); FF_PRINT_FORMAT_CHECKED(buffer.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_ZPOOL_NUM_FORMAT_ARGS, ((FFformatarg[]) { FF_FORMAT_ARG(result->name, "name"), @@ -205,7 +210,7 @@ void ffInitZpoolOptions(FFZpoolOptions* options) ffGenerateZpoolJsonConfig ); ffOptionInitModuleArg(&options->moduleArgs, "󱑛"); - options->percent = (FFColorRangeConfig) { 50, 80 }; + options->percent = (FFPercentageModuleConfig) { 50, 80, 0 }; } void ffDestroyZpoolOptions(FFZpoolOptions* options) diff --git a/src/options/display.c b/src/options/display.c index 0dc0ad6a9..111a5cdfc 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -1,6 +1,7 @@ #include "fastfetch.h" #include "common/color.h" #include "common/jsonconfig.h" +#include "common/percent.h" #include "util/stringUtils.h" #include "options/display.h" @@ -166,7 +167,11 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va return "display.percent must be an object"; yyjson_val* type = yyjson_obj_get(val, "type"); - if (type) options->percentType = (uint8_t) yyjson_get_uint(type); + if (type) + { + const char* error = ffPercentParseTypeJsonConfig(type, &options->percentType); + if (error) return error; + } yyjson_val* ndigits = yyjson_obj_get(val, "ndigits"); if (ndigits) options->percentNdigits = (uint8_t) yyjson_get_uint(ndigits); diff --git a/src/options/display.h b/src/options/display.h index fe1f0ba5d..47aaed0d6 100644 --- a/src/options/display.h +++ b/src/options/display.h @@ -2,14 +2,14 @@ #include "util/FFstrbuf.h" -typedef enum FFSizeBinaryPrefixType +typedef enum __attribute__((__packed__)) FFSizeBinaryPrefixType { FF_SIZE_BINARY_PREFIX_TYPE_IEC, // 1024 Bytes = 1 KiB, 1024 KiB = 1 MiB, ... (standard) FF_SIZE_BINARY_PREFIX_TYPE_SI, // 1000 Bytes = 1 KB, 1000 KB = 1 MB, ... FF_SIZE_BINARY_PREFIX_TYPE_JEDEC, // 1024 Bytes = 1 kB, 1024 kB = 1 MB, ... } FFSizeBinaryPrefixType; -typedef enum FFTemperatureUnit +typedef enum __attribute__((__packed__)) FFTemperatureUnit { FF_TEMPERATURE_UNIT_CELSIUS, FF_TEMPERATURE_UNIT_FAHRENHEIT, @@ -46,7 +46,7 @@ typedef struct FFOptionsDisplay FFstrbuf barBorderLeft; FFstrbuf barBorderRight; uint8_t barWidth; - uint8_t percentType; + FFPercentageTypeFlags percentType; uint8_t percentNdigits; FFstrbuf percentColorGreen; FFstrbuf percentColorYellow; diff --git a/src/options/general.h b/src/options/general.h index f1f0f3ff8..8cb0d4884 100644 --- a/src/options/general.h +++ b/src/options/general.h @@ -2,7 +2,7 @@ #include "util/FFstrbuf.h" -typedef enum FFDsForceDrmType +typedef enum __attribute__((__packed__)) FFDsForceDrmType { FF_DS_FORCE_DRM_TYPE_FALSE = 0, // Disable FF_DS_FORCE_DRM_TYPE_TRUE = 1, // Try `libdrm`, then `sysfs` if libdrm failed diff --git a/src/options/logo.h b/src/options/logo.h index ab22843b9..a4a031d5f 100644 --- a/src/options/logo.h +++ b/src/options/logo.h @@ -5,7 +5,7 @@ #define FASTFETCH_LOGO_MAX_NAMES 9 #define FASTFETCH_LOGO_MAX_COLORS 9 //two digits would make parsing much more complicated (index 1 - 9) -typedef enum FFLogoType +typedef enum __attribute__((__packed__)) FFLogoType { FF_LOGO_TYPE_AUTO, //if something is given, first try builtin, then file. Otherwise detect logo FF_LOGO_TYPE_BUILTIN, //builtin ascii art @@ -23,7 +23,7 @@ typedef enum FFLogoType FF_LOGO_TYPE_NONE, //--logo none } FFLogoType; -typedef enum FFLogoPosition +typedef enum __attribute__((__packed__)) FFLogoPosition { FF_LOGO_POSITION_LEFT, FF_LOGO_POSITION_TOP, diff --git a/src/util/FFstrbuf.c b/src/util/FFstrbuf.c index 4387a5d7b..68240f00e 100644 --- a/src/util/FFstrbuf.c +++ b/src/util/FFstrbuf.c @@ -33,7 +33,7 @@ void ffStrbufEnsureFree(FFstrbuf* strbuf, uint32_t free) return; uint32_t allocate = strbuf->allocated; - if(allocate < 2) + if(allocate < FASTFETCH_STRBUF_DEFAULT_ALLOC) allocate = FASTFETCH_STRBUF_DEFAULT_ALLOC; while((strbuf->length + free + 1) > allocate) // + 1 for the null byte diff --git a/src/util/FFstrbuf.h b/src/util/FFstrbuf.h index c40f411e5..2ac123352 100644 --- a/src/util/FFstrbuf.h +++ b/src/util/FFstrbuf.h @@ -12,7 +12,7 @@ #ifdef _WIN32 // #include - __stdcall const char* StrStrIA(const char* lpFirst, const char* lpSrch); + __stdcall char* StrStrIA(const char* lpFirst, const char* lpSrch); #define strcasestr StrStrIA #endif diff --git a/src/util/apple/Info.plist.in b/src/util/apple/Info.plist.in index 4fd959cfd..9e24ccb7c 100644 --- a/src/util/apple/Info.plist.in +++ b/src/util/apple/Info.plist.in @@ -10,5 +10,7 @@ @PROJECT_VERSION@ CFBundleDevelopmentRegion English + NSBluetoothAlwaysUsageDescription + For detecting Bluetooth devices diff --git a/src/util/apple/cf_helpers.c b/src/util/apple/cf_helpers.c index a0bc534c7..e63df9727 100644 --- a/src/util/apple/cf_helpers.c +++ b/src/util/apple/cf_helpers.c @@ -49,18 +49,20 @@ const char* ffCfStrGetString(CFTypeRef cf, FFstrbuf* result) if (CFGetTypeID(cf) == CFStringGetTypeID()) { CFStringRef cfStr = (CFStringRef)cf; - uint32_t length = (uint32_t)CFStringGetLength(cfStr); - //CFString stores UTF16 characters, therefore may require larger buffer to convert to UTF8 string - ffStrbufEnsureFree(result, length * 2); - if (!CFStringGetCString(cfStr, result->chars, result->allocated, kCFStringEncodingUTF8)) + + const char* cstr = CFStringGetCStringPtr(cfStr, kCFStringEncodingUTF8); + if (cstr) + ffStrbufSetS(result, cstr); + else { - ffStrbufEnsureFree(result, length * 4); + uint32_t length = (uint32_t) CFStringGetLength(cfStr); + ffStrbufEnsureFixedLengthFree(result, (uint32_t) CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8)); if(!CFStringGetCString(cfStr, result->chars, result->allocated, kCFStringEncodingUTF8)) return "CFStringGetCString() failed"; + // CFStringGetCString ensures the buffer is NUL terminated + // https://developer.apple.com/documentation/corefoundation/1542721-cfstringgetcstring + result->length = (uint32_t) strnlen(result->chars, (uint32_t)result->allocated); } - // CFStringGetCString ensures the buffer is NUL terminated - // https://developer.apple.com/documentation/corefoundation/1542721-cfstringgetcstring - result->length = (uint32_t) strnlen(result->chars, (uint32_t)result->allocated); } else if (CFGetTypeID(cf) == CFDataGetTypeID()) { diff --git a/src/util/smbiosHelper.c b/src/util/smbiosHelper.c index 8ce226fa0..9366f8a9f 100644 --- a/src/util/smbiosHelper.c +++ b/src/util/smbiosHelper.c @@ -13,6 +13,7 @@ bool ffIsSmbiosValueSet(FFstrbuf* value) !ffStrbufStartsWithIgnCaseS(value, "OEM") && !ffStrbufStartsWithIgnCaseS(value, "O.E.M.") && !ffStrbufStartsWithIgnCaseS(value, "System Product") && + !ffStrbufStartsWithIgnCaseS(value, "Unknown Product") && !ffStrbufIgnCaseEqualS(value, "None") && !ffStrbufIgnCaseEqualS(value, "System Name") && !ffStrbufIgnCaseEqualS(value, "System Version") && @@ -29,6 +30,7 @@ bool ffIsSmbiosValueSet(FFstrbuf* value) !ffStrbufIgnCaseEqualS(value, "Chassis Version") && !ffStrbufIgnCaseEqualS(value, "All Series") && !ffStrbufIgnCaseEqualS(value, "N/A") && + !ffStrbufIgnCaseEqualS(value, "Unknown") && !ffStrbufIgnCaseEqualS(value, "0x0000") ; } diff --git a/src/util/stringUtils.h b/src/util/stringUtils.h index 6c641517b..c22d1976e 100644 --- a/src/util/stringUtils.h +++ b/src/util/stringUtils.h @@ -80,12 +80,12 @@ static inline bool ffCharIsDigit(char c) return '0' <= c && c <= '9'; } -static inline char* ffStrCopyN(char* __restrict__ dst, const char* __restrict__ src, size_t nDst) +// Copies at most (dstBufSiz - 1) bytes from src to dst; dst is always null-terminated +static inline char* ffStrCopy(char* __restrict__ dst, const char* __restrict__ src, size_t dstBufSiz) { - assert(dst != NULL); if (__builtin_expect(dst == NULL, false)) return dst; - size_t len = strnlen(src, nDst - 1); + size_t len = strnlen(src, dstBufSiz - 1); memcpy(dst, src, len); dst[len] = '\0'; return dst + len; diff --git a/src/util/windows/wmi.cpp b/src/util/windows/wmi.cpp index 6e8db9615..34cfb06d6 100644 --- a/src/util/windows/wmi.cpp +++ b/src/util/windows/wmi.cpp @@ -6,21 +6,6 @@ #include #include -namespace -{ - // Provide our bstr_t to avoid libstdc++ dependency - struct bstr_t - { - explicit bstr_t(const wchar_t* str) noexcept: _bstr(SysAllocString(str)) {} - ~bstr_t(void) noexcept { SysFreeString(_bstr); } - explicit operator const wchar_t*(void) const noexcept { return _bstr; } - operator BSTR(void) const noexcept { return _bstr; } - - private: - BSTR _bstr; - }; -} - static const char* doInitService(const wchar_t* networkResource, IWbemServices** result) { HRESULT hres; @@ -59,30 +44,11 @@ static const char* doInitService(const wchar_t* networkResource, IWbemServices** if (FAILED(hres)) return "Could not connect WMI server"; - // Set security levels on the proxy ------------------------- - hres = CoSetProxyBlanket( - pSvc, // Indicates the proxy to set - RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx - RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx - nullptr, // Server principal name - RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx - RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx - nullptr, // client identity - EOAC_NONE // proxy capabilities - ); - - if (FAILED(hres)) - { - pSvc->Release(); - return "Could not set proxy blanket"; - } - *result = pSvc; return NULL; } FFWmiQuery::FFWmiQuery(const wchar_t* queryStr, FFstrbuf* error, FFWmiNamespace wmiNs) - : pEnumerator(nullptr) { const char* errStr; if ((errStr = ffInitCom())) @@ -95,7 +61,7 @@ FFWmiQuery::FFWmiQuery(const wchar_t* queryStr, FFstrbuf* error, FFWmiNamespace static IWbemServices* contexts[(int) FFWmiNamespace::LAST]; IWbemServices* context = contexts[(int)wmiNs]; - if (!contexts[(int)wmiNs]) + if (!context) { if ((errStr = doInitService(wmiNs == FFWmiNamespace::CIMV2 ? L"ROOT\\CIMV2" : L"ROOT\\WMI", &context))) { @@ -106,13 +72,15 @@ FFWmiQuery::FFWmiQuery(const wchar_t* queryStr, FFstrbuf* error, FFWmiNamespace contexts[(int)wmiNs] = context; } + this->pService = context; + // Use the IWbemServices pointer to make requests of WMI HRESULT hres = context->ExecQuery( bstr_t(L"WQL"), bstr_t(queryStr), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, nullptr, - &pEnumerator); + &this->pEnumerator); if (FAILED(hres)) { diff --git a/src/util/windows/wmi.hpp b/src/util/windows/wmi.hpp index f9e3e9ae3..f4340ae7b 100644 --- a/src/util/windows/wmi.hpp +++ b/src/util/windows/wmi.hpp @@ -20,15 +20,9 @@ enum class FFWmiNamespace { struct FFWmiRecord { - IWbemClassObject* obj; + IWbemClassObject* obj = nullptr; - explicit FFWmiRecord(IEnumWbemClassObject* pEnumerator): obj(nullptr) { - if(!pEnumerator) return; - - ULONG ret; - bool ok = SUCCEEDED(pEnumerator->Next(instance.config.general.wmiTimeout, 1, &obj, &ret)) && ret; - if(!ok) obj = nullptr; - } + explicit FFWmiRecord(IWbemClassObject* obj): obj(obj) {}; FFWmiRecord(const FFWmiRecord&) = delete; FFWmiRecord(FFWmiRecord&& other) { *this = (FFWmiRecord&&)other; } ~FFWmiRecord() { if(obj) obj->Release(); } @@ -53,6 +47,7 @@ struct FFWmiRecord struct FFWmiQuery { + IWbemServices* pService = nullptr; IEnumWbemClassObject* pEnumerator = nullptr; FFWmiQuery(const wchar_t* queryStr, FFstrbuf* error = nullptr, FFWmiNamespace wmiNs = FFWmiNamespace::CIMV2); @@ -70,11 +65,30 @@ struct FFWmiQuery } FFWmiRecord next() { - FFWmiRecord result(pEnumerator); + IWbemClassObject* obj = nullptr; + ULONG ret; + pEnumerator->Next(instance.config.general.wmiTimeout, 1, &obj, &ret); + + FFWmiRecord result(obj); return result; } }; +namespace +{ + // Provide our bstr_t to avoid libstdc++ dependency + struct bstr_t + { + explicit bstr_t(const wchar_t* str) noexcept: _bstr(SysAllocString(str)) {} + ~bstr_t(void) noexcept { SysFreeString(_bstr); } + explicit operator const wchar_t*(void) const noexcept { return _bstr; } + operator BSTR(void) const noexcept { return _bstr; } + + private: + BSTR _bstr; + }; +} + #else // Win32 COM headers requires C++ compiler #error Must be included in C++ source file diff --git a/tests/list.c b/tests/list.c index 5119b046f..c7c1752eb 100644 --- a/tests/list.c +++ b/tests/list.c @@ -116,7 +116,7 @@ int main(void) { FF_LIST_AUTO_DESTROY test = ffListCreate(1); - VERIFY(test.elementSize = 1); + VERIFY(test.elementSize == 1); VERIFY(test.capacity == 0); VERIFY(test.length == 0); } diff --git a/tests/strbuf.c b/tests/strbuf.c index d901faab1..92141d4b9 100644 --- a/tests/strbuf.c +++ b/tests/strbuf.c @@ -381,6 +381,9 @@ int main(void) ffStrbufEnsureFixedLengthFree(&strbuf, 10); VERIFY(strbuf.length == 0); VERIFY(strbuf.allocated == 11); + ffStrbufEnsureFixedLengthFree(&strbuf, 12); + VERIFY(strbuf.length == 0); + VERIFY(strbuf.allocated == 13); ffStrbufDestroy(&strbuf); //ffStrbufEnsureFixedLengthFree / empty buffer with zero free length @@ -442,6 +445,19 @@ int main(void) VERIFY(ffStrbufEqualS(&strbuf, "AA12BB3456CCDD")); ffStrbufDestroy(&strbuf); + // smallest allocation test + { + FF_STRBUF_AUTO_DESTROY strbuf1 = ffStrbufCreateA(10); + VERIFY(strbuf1.allocated == 10); + ffStrbufEnsureFree(&strbuf1, 16); + VERIFY(strbuf1.allocated == 32); + + FF_STRBUF_AUTO_DESTROY strbuf2 = ffStrbufCreate(); + VERIFY(strbuf2.allocated == 0); + ffStrbufEnsureFree(&strbuf2, 16); + VERIFY(strbuf2.allocated == 32); + } + //Success puts("\e[32mAll tests passed!" FASTFETCH_TEXT_MODIFIER_RESET); }