From 4890cb641cbf6e5afcc1fc7a529c75326ddcf9fc Mon Sep 17 00:00:00 2001 From: IamNotARobot Date: Sat, 31 Dec 2022 17:52:47 +0100 Subject: [PATCH 001/142] RaspberryPi Logo, RaspberryPi small logo --- src/logo/builtin.c | 73 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/src/logo/builtin.c b/src/logo/builtin.c index d13b7e4f8..f56050a85 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -1032,8 +1032,8 @@ static const FFlogo* getLogoKDENeon() FF_LOGO_COLORS( "32" //green ) - FF_LOGO_COLOR_KEYS("32"); //green - FF_LOGO_COLOR_TITLE("32"); //green + FF_LOGO_COLOR_KEYS("31"); //red + FF_LOGO_COLOR_TITLE("31"); //red FF_LOGO_RETURN } @@ -1872,6 +1872,73 @@ static const FFlogo* getLogoPopSmall() FF_LOGO_RETURN } +static const FFlogo* getLogoRaspberryPi() +{ + FF_LOGO_INIT + FF_LOGO_NAMES("raspbian", "raspi", "raspberrypi" "raspberrypios" "pios") + FF_LOGO_LINES( + " $2`.::///+:/-. --///+//-:`\n" + " `+oooooooooooo: `+oooooooooooo:\n" + " /oooo++//ooooo: ooooo+//+ooooo.\n" + " `+ooooooo:-:oo- +o+::/ooooooo:\n" + " `:oooooooo+`` `.oooooooo+-\n" + " `:++ooo/. :+ooo+/.`$1\n" + " ...` `.----.` ``..\n" + " .::::-``:::::::::.`-:::-`\n" + " -:::-` .:::::::-` `-:::-\n" + " `::. `.--.` `` `.---.``.::`\n" + " .::::::::` -::::::::` `\n" + " .::` .:::::::::- `::::::::::``::.\n" + "-:::` ::::::::::. ::::::::::.`:::-\n" + ":::: -::::::::. `-:::::::: ::::\n" + "-::- .-:::-.``....``.-::-. -::-\n" + " .. `` .::::::::. `..`..\n" + " -:::-` -::::::::::` .:::::`\n" + " :::::::` -::::::::::` :::::::.\n" + " .::::::: -::::::::. ::::::::\n" + " `-:::::` ..--.` ::::::.\n" + " `...` `...--..` `...`\n" + " .::::::::::\n" + " `.-::::-`" + ) + FF_LOGO_COLORS( + "31", //red + "32" //green + ) + FF_LOGO_COLOR_KEYS("31"); //red + FF_LOGO_COLOR_TITLE("32"); //green + FF_LOGO_RETURN +} + + +static const FFlogo* getLogoRaspberryPiSmall() +{ + FF_LOGO_INIT + FF_LOGO_NAMES("raspbian_small", "raspi_small", "raspberrypi_small" "pios_small") + FF_LOGO_LINES( + " $2.~~. .~~.\n" + " '. \ ' ' / .'$1\n" + " .~ .~~~..~.\n" + " : .~.'~'.~. :\n" + " ~ ( ) ( ) ~\n" + "( : '~'.~.'~' : )\n" + " ~ .~ ( ) ~. ~\n" + " ( : '~' : )\n" + " '~ .~~~. ~'\n" + " '~'" + ) + FF_LOGO_COLORS( + "31", //red + "32" //green + ) + FF_LOGO_COLOR_KEYS("31"); //red + FF_LOGO_COLOR_TITLE("32"); //green + FF_LOGO_RETURN +} + + + + static const FFlogo* getLogoReborn() { FF_LOGO_INIT @@ -2428,6 +2495,8 @@ GetLogoMethod* ffLogoBuiltinGetAll() getLogoOpenMandriva, getLogoPop, getLogoPopSmall, + getLogoRaspberryPi, + getLogoRaspberryPiSmall, getLogoParabola, getLogoParabolaSmall, getLogoReborn, From 9f93ca8019d7a76c4030c25b3a71704e1e97acdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 1 Jan 2023 12:29:08 +0800 Subject: [PATCH 002/142] README: document image logo support --- README.md | 10 +++++++++- src/logo/image/image.c | 6 ++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 54d51b7ec..17c17b890 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,15 @@ AlmaLinux, Alpine, Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, CRUX, C * Some logos have an old variant. Access it by appending _old to the logo name. * To disable the logo, use `--logo none`. * Get a list of all available logos with `fastfetch --print-logos`. -* Printing images as logo is supported using Sixel / Kitty / iTerm graphics protocol or chafas image to text conversion. + +###### Image logo + +Printing images as logo is supported using Sixel / Kitty / iTerm graphics protocol or chafas image to text conversion. + +* Sixel: fastfetch must be built with imagemagick support to convert image to sixel format +* Kitty: Because [kitty support png](https://sw.kovidgoyal.net/kitty/graphics-protocol/#png-data) natively, using `png` image file with both `--logo-width` and `--logo-height` being specified is recommanded to get maximum performance. Otherwise, imagemagick is required to convert image to RGBA data. +* iTerm: [Since iTerm supports a lot of image format](https://iterm2.com/documentation-images.html), imagemagick support is not required. However, both `--logo-width` and `--logo-height` must be specified since fastfetch has no idea about the size of the image. +* Chafa: Requires imagemagick support. ##### Package managers ``` diff --git a/src/logo/image/image.c b/src/logo/image/image.c index aed67ca6a..ed0f0677f 100644 --- a/src/logo/image/image.c +++ b/src/logo/image/image.c @@ -30,12 +30,18 @@ static FFstrbuf base64Encode(FFstrbuf* in) static bool printImageIterm(FFinstance* instance) { if(instance->config.logo.width == 0 || instance->config.logo.height == 0) + { + fputs("Logo: `item` protocol only works when both `--logo-width` and `--logo-height` being specified\n", stderr); return false; + } FFstrbuf buf; ffStrbufInit(&buf); if(!ffAppendFileBuffer(instance->config.logo.source.chars, &buf)) + { + fputs("Logo: failed to load image file\n", stderr); return false; + } ffPrintCharTimes(' ', instance->config.logo.paddingLeft); FFstrbuf base64 = base64Encode(&buf); From 4a781d84714b98e44449860d26b63f5fd1460171 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 1 Jan 2023 12:37:39 +0800 Subject: [PATCH 003/142] Logo: support raw image type For raw image type, fastfetch nether parses the file content, nor tries to detect the image size from the file. It's useful to print pre-converted sixel image. --- README.md | 10 ++++++++++ src/fastfetch.c | 6 ++++++ src/fastfetch.h | 1 + src/logo/image/image.c | 2 +- src/logo/logo.c | 36 ++++++++++++++++++++++++++++++------ 5 files changed, 48 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 17c17b890..6bf6d278e 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,16 @@ Printing images as logo is supported using Sixel / Kitty / iTerm graphics protoc * Kitty: Because [kitty support png](https://sw.kovidgoyal.net/kitty/graphics-protocol/#png-data) natively, using `png` image file with both `--logo-width` and `--logo-height` being specified is recommanded to get maximum performance. Otherwise, imagemagick is required to convert image to RGBA data. * iTerm: [Since iTerm supports a lot of image format](https://iterm2.com/documentation-images.html), imagemagick support is not required. However, both `--logo-width` and `--logo-height` must be specified since fastfetch has no idea about the size of the image. * Chafa: Requires imagemagick support. +* Raw: use a pre-converted image file so that fastfetch don't need to convert the image format on the fly. +```shell +# brew install libsixel +$ img2sixel image.png -o image.sixel +$ fastfetch --raw image.sixel --logo-width 30 --logo-height 15 + +# wget https://iterm2.com/utilities/imgcat && chmod +x imgcat +$ imgcat image.png > image.raw +$ fastfetch --raw image.raw --logo-width 30 --logo-height 15 +``` ##### Package managers ``` diff --git a/src/fastfetch.c b/src/fastfetch.c index fd36ebc1d..c13130c0e 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -958,6 +958,7 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con "sixel", FF_LOGO_TYPE_IMAGE_SIXEL, "kitty", FF_LOGO_TYPE_IMAGE_KITTY, "chafa", FF_LOGO_TYPE_IMAGE_CHAFA, + "raw", FF_LOGO_TYPE_IMAGE_RAW, NULL ); } @@ -1036,6 +1037,11 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con optionParseString(key, value, &instance->config.logo.source); instance->config.logo.type = FF_LOGO_TYPE_IMAGE_ITERM; } + else if(strcasecmp(key, "--raw") == 0) + { + optionParseString(key, value, &instance->config.logo.source); + instance->config.logo.type = FF_LOGO_TYPE_IMAGE_RAW; + } else if(strcasecmp(key, "--chafa-fg-only") == 0) instance->config.logo.chafaFgOnly = optionParseBoolean(value); else if(strcasecmp(key, "--chafa-symbols") == 0) diff --git a/src/fastfetch.h b/src/fastfetch.h index a99eadc44..d292e5983 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -37,6 +37,7 @@ typedef enum FFLogoType FF_LOGO_TYPE_IMAGE_KITTY, //image file, printed as kitty graphics protocol FF_LOGO_TYPE_IMAGE_ITERM, //image file, printed as iterm graphics protocol FF_LOGO_TYPE_IMAGE_CHAFA, //image file, printed as ascii art using libchafa + FF_LOGO_TYPE_IMAGE_RAW, //image file, printed as raw binary string } FFLogoType; typedef enum FFBinaryPrefixType diff --git a/src/logo/image/image.c b/src/logo/image/image.c index ed0f0677f..bb1b2f46a 100644 --- a/src/logo/image/image.c +++ b/src/logo/image/image.c @@ -39,7 +39,7 @@ static bool printImageIterm(FFinstance* instance) ffStrbufInit(&buf); if(!ffAppendFileBuffer(instance->config.logo.source.chars, &buf)) { - fputs("Logo: failed to load image file\n", stderr); + fputs("Logo: Failed to load image file\n", stderr); return false; } diff --git a/src/logo/logo.c b/src/logo/logo.c index 3c48e0854..c259d8ca9 100644 --- a/src/logo/logo.c +++ b/src/logo/logo.c @@ -8,6 +8,16 @@ #include #include +static void ffLogoPrintCharsRaw(FFinstance* instance, const char* data, size_t length) +{ + fputs(FASTFETCH_TEXT_MODIFIER_BOLT, stdout); + ffPrintCharTimes(' ', instance->config.logo.paddingLeft); + fwrite(data, length, 1, stdout); + printf("\033[9999999D\n\033[%uA", instance->config.logo.height); + instance->state.logoWidth = instance->config.logo.paddingLeft + instance->config.logo.width + instance->config.logo.paddingRight; + instance->state.logoHeight = instance->config.logo.height; +} + void ffLogoPrintChars(FFinstance* instance, const char* data, bool doColorReplacement) { uint32_t currentlineLength = 0; @@ -271,19 +281,23 @@ static void logoPrintData(FFinstance* instance, bool doColorReplacement) { logoApplyColorsDetected(instance); } -static bool logoPrintFileIfExists(FFinstance* instance, bool doColorReplacement) +static bool logoPrintFileIfExists(FFinstance* instance, bool doColorReplacement, bool raw) { FFstrbuf content; - ffStrbufInitA(&content, 2047); + ffStrbufInit(&content); if(!ffAppendFileBuffer(instance->config.logo.source.chars, &content)) { ffStrbufDestroy(&content); + fputs("Logo: Failed to load file content from logo source\n", stderr); return false; } logoApplyColorsDetected(instance); - ffLogoPrintChars(instance, content.chars, doColorReplacement); + if(raw) + ffLogoPrintCharsRaw(instance, content.chars, content.length); + else + ffLogoPrintChars(instance, content.chars, doColorReplacement); ffStrbufDestroy(&content); return true; } @@ -304,13 +318,23 @@ static void logoPrintKnownType(FFinstance* instance) if(instance->config.logo.type == FF_LOGO_TYPE_BUILTIN) successfull = logoPrintBuiltinIfExists(instance, instance->config.logo.source.chars); else if(instance->config.logo.type == FF_LOGO_TYPE_FILE) - successfull = logoPrintFileIfExists(instance, true); + successfull = logoPrintFileIfExists(instance, true, false); else if(instance->config.logo.type == FF_LOGO_TYPE_FILE_RAW) - successfull = logoPrintFileIfExists(instance, false); + successfull = logoPrintFileIfExists(instance, false, false); else if(instance->config.logo.type == FF_LOGO_TYPE_DATA) logoPrintData(instance, true); else if(instance->config.logo.type == FF_LOGO_TYPE_DATA_RAW) logoPrintData(instance, false); + else if(instance->config.logo.type == FF_LOGO_TYPE_IMAGE_RAW) + { + if(instance->config.logo.width == 0 || instance->config.logo.height == 0) + { + fputs("both `--logo-width` and `--logo-height` must be specified\n", stderr); + successfull = false; + } + else + successfull = logoPrintFileIfExists(instance, false, true); + } else //image successfull = logoPrintImageIfExists(instance, instance->config.logo.type); @@ -362,7 +386,7 @@ void ffLogoPrint(FFinstance* instance) return; //Try to load the logo as a file. If it succeeds, print it and return. - if(logoPrintFileIfExists(instance, true)) + if(logoPrintFileIfExists(instance, true, false)) return; logoPrintDetected(instance); From 8e3b6280af206ba3a2f880066519586457943891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 1 Jan 2023 17:09:30 +0800 Subject: [PATCH 004/142] Image: support iterm protocol with `--logo-type` fixes #374 --- src/fastfetch.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/fastfetch.c b/src/fastfetch.c index c13130c0e..246f6b037 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -957,6 +957,7 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con "data-raw", FF_LOGO_TYPE_DATA_RAW, "sixel", FF_LOGO_TYPE_IMAGE_SIXEL, "kitty", FF_LOGO_TYPE_IMAGE_KITTY, + "iterm", FF_LOGO_TYPE_IMAGE_ITERM, "chafa", FF_LOGO_TYPE_IMAGE_CHAFA, "raw", FF_LOGO_TYPE_IMAGE_RAW, NULL From 39d8ebc3c9370a0cd996f95c49819ab270686ffb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 1 Jan 2023 17:24:37 +0800 Subject: [PATCH 005/142] Logo: support `--logo-padding-top` --- completions/bash | 1 + src/common/init.c | 1 + src/common/printing.c | 3 +++ src/data/config_user.txt | 6 ++++++ src/data/help.txt | 1 + src/fastfetch.c | 3 +++ src/fastfetch.h | 1 + src/logo/image/image.c | 16 ++++++++++------ src/logo/logo.c | 8 ++++++-- 9 files changed, 32 insertions(+), 8 deletions(-) diff --git a/completions/bash b/completions/bash index 10356ce85..22d6142c5 100644 --- a/completions/bash +++ b/completions/bash @@ -196,6 +196,7 @@ __fastfetch_completion() "--logo-padding" "--logo-padding-left" "--logo-padding-right" + "--logo-padding-top" "--logo-color-1" "--logo-color-2" "--logo-color-3" diff --git a/src/common/init.c b/src/common/init.c index 37cf2f9aa..6bd70680b 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -130,6 +130,7 @@ static void defaultConfig(FFinstance* instance) ffStrbufInit(&instance->config.logo.colors[i]); instance->config.logo.width = 0; instance->config.logo.height = 0; //preserve aspect ratio + instance->config.logo.paddingTop = 0; instance->config.logo.paddingLeft = 0; instance->config.logo.paddingRight = 4; instance->config.logo.printRemaining = true; diff --git a/src/common/printing.c b/src/common/printing.c index 4b593001a..31775d8c7 100644 --- a/src/common/printing.c +++ b/src/common/printing.c @@ -130,6 +130,9 @@ void ffPrintColor(const FFstrbuf* colorValue) void ffPrintCharTimes(char c, uint32_t times) { + if(times == 0) + return; + char str[32]; memset(str, c, sizeof(str)); //2 instructions when compiling with AVX2 enabled for(uint32_t i = sizeof(str); i <= times; i += sizeof(str)) diff --git a/src/data/config_user.txt b/src/data/config_user.txt index 9725c0f81..bd3563640 100644 --- a/src/data/config_user.txt +++ b/src/data/config_user.txt @@ -114,6 +114,12 @@ # Default is 0. #--logo-padding-right 0 +# Logo padding top option: +# Adds a padding to the top side of the logo. +# Must be a positive integer. +# Default is 0. +#--logo-padding-top 0 + # Logo print remaining option: # Sets if the remaining logo should be printed, it is has more lines than modules to show. # Must be true or false. diff --git a/src/data/help.txt b/src/data/help.txt index dea266a24..be4d1b329 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -31,6 +31,7 @@ Logo options: --logo-padding : Set the padding on the left and the right of the logo --logo-padding-left : Set the padding on the left of the logo --logo-padding-right : Set the padding on the right of the logo + --logo-padding-top : Set the padding on the top of the logo --logo-print-remaining : Whether to print the remaining logo, if it has more lines than modules to display --file : Short for --logo-type file --logo --file-raw : Short for --logo-type file-raw --logo diff --git a/src/fastfetch.c b/src/fastfetch.c index 246f6b037..f5c522864 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -939,6 +939,7 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con //this is usally wanted when using the none logo if(strcasecmp(value, "none") == 0) { + instance->config.logo.paddingTop = 0; instance->config.logo.paddingRight = 0; instance->config.logo.paddingLeft = 0; } @@ -987,6 +988,8 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con instance->config.logo.paddingLeft = padding; instance->config.logo.paddingRight = padding; } + else if(strcasecmp(subkey, "-padding-top") == 0) + instance->config.logo.paddingTop = optionParseUInt32(key, value); else if(strcasecmp(subkey, "-padding-left") == 0) instance->config.logo.paddingLeft = optionParseUInt32(key, value); else if(strcasecmp(subkey, "-padding-right") == 0) diff --git a/src/fastfetch.h b/src/fastfetch.h index d292e5983..58ca227b0 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -71,6 +71,7 @@ typedef struct FFconfig FFstrbuf colors[FASTFETCH_LOGO_MAX_COLORS]; uint32_t width; uint32_t height; + uint32_t paddingTop; uint32_t paddingLeft; uint32_t paddingRight; bool printRemaining; diff --git a/src/logo/image/image.c b/src/logo/image/image.c index bb1b2f46a..f17cd8a09 100644 --- a/src/logo/image/image.c +++ b/src/logo/image/image.c @@ -44,16 +44,17 @@ static bool printImageIterm(FFinstance* instance) } ffPrintCharTimes(' ', instance->config.logo.paddingLeft); + ffPrintCharTimes('\n', instance->config.logo.paddingTop); FFstrbuf base64 = base64Encode(&buf); + instance->state.logoWidth = instance->config.logo.width + instance->config.logo.paddingLeft + instance->config.logo.paddingRight; + instance->state.logoHeight = instance->config.logo.paddingTop + instance->config.logo.height; printf("\033]1337;File=inline=1;width=%u;height=%u;preserveAspectRatio=%u:%s\a\033[9999999D\n\033[%uA", (unsigned) instance->config.logo.width, (unsigned) instance->config.logo.height, (unsigned) instance->config.logo.preserveAspectRadio, base64.chars, - (unsigned) instance->config.logo.height + (unsigned) instance->state.logoHeight ); - instance->state.logoWidth = instance->config.logo.width + instance->config.logo.paddingLeft + instance->config.logo.paddingRight; - instance->state.logoHeight = instance->config.logo.height; ffStrbufDestroy(&buf); ffStrbufDestroy(&base64); @@ -64,6 +65,7 @@ static bool printImageIterm(FFinstance* instance) static bool printImageKittyDirect(FFinstance* instance) { ffPrintCharTimes(' ', instance->config.logo.paddingLeft); + ffPrintCharTimes('\n', instance->config.logo.paddingTop); FFstrbuf base64 = base64Encode(&instance->config.logo.source); printf("\033_Ga=T,f=100,t=f,c=%u,r=%u,C=1;%s\033\\\033[9999999D", (unsigned) instance->config.logo.width, @@ -72,7 +74,7 @@ static bool printImageKittyDirect(FFinstance* instance) ); instance->state.logoWidth = instance->config.logo.width + instance->config.logo.paddingLeft + instance->config.logo.paddingRight; - instance->state.logoHeight = instance->config.logo.height; + instance->state.logoHeight = instance->config.logo.paddingTop + instance->config.logo.height; ffStrbufDestroy(&base64); @@ -205,7 +207,7 @@ static void printImagePixels(FFinstance* instance, FFLogoRequestData* requestDat //Calculate character dimensions instance->state.logoWidth = requestData->logoCharacterWidth + instance->config.logo.paddingLeft + instance->config.logo.paddingRight; - instance->state.logoHeight = requestData->logoCharacterHeight; + instance->state.logoHeight = requestData->logoCharacterHeight + instance->config.logo.paddingTop; if(requestData->type == FF_LOGO_TYPE_IMAGE_KITTY) instance->state.logoHeight -= 1; @@ -219,6 +221,7 @@ static void printImagePixels(FFinstance* instance, FFLogoRequestData* requestDat writeCacheUint32(requestData, instance->state.logoHeight, FF_CACHE_FILE_HEIGHT); //Write result to stdout + ffPrintCharTimes('\n', instance->config.logo.paddingTop); ffPrintCharTimes(' ', instance->config.logo.paddingLeft); fflush(stdout); ffWriteFDBuffer(STDOUT_FILENO, result); @@ -600,6 +603,7 @@ static bool printCachedPixel(FFinstance* instance, FFLogoRequestData* requestDat if(fd == -1) return false; + ffPrintCharTimes('\n', instance->config.logo.paddingTop); ffPrintCharTimes(' ', instance->config.logo.paddingLeft); fflush(stdout); @@ -611,7 +615,7 @@ static bool printCachedPixel(FFinstance* instance, FFLogoRequestData* requestDat close(fd); instance->state.logoWidth = requestData->logoCharacterWidth + instance->config.logo.paddingLeft + instance->config.logo.paddingRight; - instance->state.logoHeight = requestData->logoCharacterHeight; + instance->state.logoHeight = requestData->logoCharacterHeight + instance->config.logo.paddingTop; //Go to upper left corner fputs("\033[9999999D", stdout); diff --git a/src/logo/logo.c b/src/logo/logo.c index c259d8ca9..85ed46791 100644 --- a/src/logo/logo.c +++ b/src/logo/logo.c @@ -11,11 +11,12 @@ static void ffLogoPrintCharsRaw(FFinstance* instance, const char* data, size_t length) { fputs(FASTFETCH_TEXT_MODIFIER_BOLT, stdout); + ffPrintCharTimes('\n', instance->config.logo.paddingTop); ffPrintCharTimes(' ', instance->config.logo.paddingLeft); fwrite(data, length, 1, stdout); - printf("\033[9999999D\n\033[%uA", instance->config.logo.height); + instance->state.logoHeight = instance->config.logo.paddingTop + instance->config.logo.height; instance->state.logoWidth = instance->config.logo.paddingLeft + instance->config.logo.width + instance->config.logo.paddingRight; - instance->state.logoHeight = instance->config.logo.height; + printf("\033[9999999D\n\033[%uA", instance->state.logoHeight); } void ffLogoPrintChars(FFinstance* instance, const char* data, bool doColorReplacement) @@ -23,8 +24,11 @@ void ffLogoPrintChars(FFinstance* instance, const char* data, bool doColorReplac uint32_t currentlineLength = 0; fputs(FASTFETCH_TEXT_MODIFIER_BOLT, stdout); + ffPrintCharTimes('\n', instance->config.logo.paddingTop); ffPrintCharTimes(' ', instance->config.logo.paddingLeft); + instance->state.logoHeight = instance->config.logo.paddingTop; + //Use logoColor[0] as the default color if(doColorReplacement) ffPrintColor(&instance->config.logo.colors[0]); From 4247d15672cc0896b2bab5f6af9bbe11b451bc6e Mon Sep 17 00:00:00 2001 From: JesseBot Date: Sun, 1 Jan 2023 15:39:03 +0100 Subject: [PATCH 006/142] Fix error text typo from item to iterm --- src/logo/image/image.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logo/image/image.c b/src/logo/image/image.c index f17cd8a09..fec6bbf6c 100644 --- a/src/logo/image/image.c +++ b/src/logo/image/image.c @@ -31,7 +31,7 @@ static bool printImageIterm(FFinstance* instance) { if(instance->config.logo.width == 0 || instance->config.logo.height == 0) { - fputs("Logo: `item` protocol only works when both `--logo-width` and `--logo-height` being specified\n", stderr); + fputs("Logo: `iterm` protocol only works when both `--logo-width` and `--logo-height` being specified\n", stderr); return false; } From 34c33dd42f16ce6c752217a0f835c11d13286ecf Mon Sep 17 00:00:00 2001 From: IamNoRobot Date: Sun, 1 Jan 2023 18:05:09 +0100 Subject: [PATCH 007/142] RaspberryPi Logo, RaspberryPi small logo --- README.md | 2 +- src/logo/builtin.c | 19 +++++++------------ 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 54d51b7ec..3d856516e 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ Title, Separator, OS, Host, Bios, Board, Kernel, Uptime, Processes, Packages, Sh ##### Logos ``` -AlmaLinux, Alpine, Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, CRUX, Crystal, Debian, Devuan, Deepin, Endeavour, Enso, Fedora, FreeBSD, Garuda, Gentoo, KDE Neon, KISS, Kubuntu, LangitKetujuh, Linux, MacOS, Manjaro, Mint, MSYS2, NixOS, Nobara, OpenSUSE, OpenSUSE Tumbleweed, OpenSUSE LEAP, Parabola, Pop!_OS, RebornOS, RedstarOS, Rocky, Rosa, Slackware, Solus, Ubuntu, Vanilla, Void, Windows 11, Windows 8, Windows, Zorin +AlmaLinux, Alpine, Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, CRUX, Crystal, Debian, Devuan, Deepin, Endeavour, Enso, Fedora, FreeBSD, Garuda, Gentoo, KDE Neon, KISS, Kubuntu, LangitKetujuh, Linux, MacOS, Manjaro, Mint, MSYS2, NixOS, Nobara, OpenSUSE, OpenSUSE Tumbleweed, OpenSUSE LEAP, Parabola, Raspbian, Pop!_OS, RebornOS, RedstarOS, Rocky, Rosa, Slackware, Solus, Ubuntu, Vanilla, Void, Windows 11, Windows 8, Windows, Zorin ``` * Most of the logos have a small variant. Access it by appending _small to the logo name. * Some logos have an old variant. Access it by appending _old to the logo name. diff --git a/src/logo/builtin.c b/src/logo/builtin.c index f56050a85..9f1e097d8 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -1032,8 +1032,8 @@ static const FFlogo* getLogoKDENeon() FF_LOGO_COLORS( "32" //green ) - FF_LOGO_COLOR_KEYS("31"); //red - FF_LOGO_COLOR_TITLE("31"); //red + FF_LOGO_COLOR_KEYS("32"); //green + FF_LOGO_COLOR_TITLE("32"); //green FF_LOGO_RETURN } @@ -1871,8 +1871,7 @@ static const FFlogo* getLogoPopSmall() FF_LOGO_COLOR_TITLE("36"); //cyan FF_LOGO_RETURN } - -static const FFlogo* getLogoRaspberryPi() +static const FFlogo* getLogoRaspbian() { FF_LOGO_INIT FF_LOGO_NAMES("raspbian", "raspi", "raspberrypi" "raspberrypios" "pios") @@ -1910,11 +1909,10 @@ static const FFlogo* getLogoRaspberryPi() FF_LOGO_RETURN } - -static const FFlogo* getLogoRaspberryPiSmall() +static const FFlogo* getLogoRaspbianSmall() { FF_LOGO_INIT - FF_LOGO_NAMES("raspbian_small", "raspi_small", "raspberrypi_small" "pios_small") + FF_LOGO_NAMES("raspbian_small", "raspi_small", "raspberrypi_small" "raspberrypios_small" "pios_small") FF_LOGO_LINES( " $2.~~. .~~.\n" " '. \ ' ' / .'$1\n" @@ -1936,9 +1934,6 @@ static const FFlogo* getLogoRaspberryPiSmall() FF_LOGO_RETURN } - - - static const FFlogo* getLogoReborn() { FF_LOGO_INIT @@ -2495,10 +2490,10 @@ GetLogoMethod* ffLogoBuiltinGetAll() getLogoOpenMandriva, getLogoPop, getLogoPopSmall, - getLogoRaspberryPi, - getLogoRaspberryPiSmall, getLogoParabola, getLogoParabolaSmall, + getLogoRaspbian, + getLogoRaspbianSmall, getLogoReborn, getLogoRebornSmall, getLogoRedHatEnterpriseLinux, From 02abc07bc11920c31be989c3cc15bb64d40a0ce4 Mon Sep 17 00:00:00 2001 From: IamNoRobot Date: Sun, 1 Jan 2023 18:18:01 +0100 Subject: [PATCH 008/142] fixed formatting error --- src/logo/builtin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logo/builtin.c b/src/logo/builtin.c index 9f1e097d8..09d13a2f0 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -1915,7 +1915,7 @@ static const FFlogo* getLogoRaspbianSmall() FF_LOGO_NAMES("raspbian_small", "raspi_small", "raspberrypi_small" "raspberrypios_small" "pios_small") FF_LOGO_LINES( " $2.~~. .~~.\n" - " '. \ ' ' / .'$1\n" + " '. \\ ' ' / .'$1\n" " .~ .~~~..~.\n" " : .~.'~'.~. :\n" " ~ ( ) ( ) ~\n" From 8533dc234bd3f5bfd06a86c29173cd6a966c0c08 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Sun, 1 Jan 2023 18:33:24 +0100 Subject: [PATCH 009/142] Update Changelog --- CHANGELOG.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4f01fb0d..06ec714e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,18 @@ +# dev + +Features: +* `--logo-padding-top` option (@CarterLi, #372) +* Raw image file as logo support (@CarterLi) + +Logos: +* Raspbian (@IamNoRobot, #373) + +Bugfixes: +* `--logo-type` now does accept `iterm` too (@CarterLi, #374) + +Other: +* Fixed a Typo in iterm error message (@jessebot, #376) + # 1.8.2 Bugfixes: From 822496808d84265ebde19d1aeff264bc874c968f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 2 Jan 2023 11:49:41 +0800 Subject: [PATCH 010/142] Windows: look for config files in $LOCALAPPDATA --- CHANGELOG.md | 1 + src/common/init.c | 19 ++++++++++++++++++- src/util/FFstrbuf.c | 6 ++++++ src/util/FFstrbuf.h | 2 ++ src/util/windows/pwd.c | 7 ++++++- tests/strbuf.c | 6 ++++++ 6 files changed, 39 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 06ec714e3..7b3866154 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ Features: * `--logo-padding-top` option (@CarterLi, #372) * Raw image file as logo support (@CarterLi) +* Look for config files in $LOCALAPPDATA (Windows) (@CarterLi) Logos: * Raspbian (@IamNoRobot, #373) diff --git a/src/common/init.c b/src/common/init.c index 6bd70680b..8522c0cd9 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -12,6 +12,8 @@ #ifdef _WIN32 #include #include + #include + #include "util/windows/unicode.h" #else #include #endif @@ -20,7 +22,22 @@ static void initConfigDirs(FFstate* state) { ffListInit(&state->configDirs, sizeof(FFstrbuf)); - #if !(defined(_WIN32) || defined(__APPLE__) || defined(__ANDROID__)) + #ifdef _WIN32 + + { + PWSTR pPath; + if(SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_LocalAppData, 0, NULL, &pPath))) + { + FFstrbuf* buffer = (FFstrbuf*) ffListAdd(&state->configDirs); + ffStrbufInit(buffer); + ffStrbufSetWS(buffer, pPath); + ffStrbufReplaceAllC(buffer, '\\', '/'); + ffStrbufEnsureEndsWithC(buffer, '/'); + } + CoTaskMemFree(pPath); + } + + #elif !(defined(__APPLE__) || defined(__ANDROID__)) const char* xdgConfigHome = getenv("XDG_CONFIG_HOME"); if(ffStrSet(xdgConfigHome)) diff --git a/src/util/FFstrbuf.c b/src/util/FFstrbuf.c index 27150ef24..94f436d51 100644 --- a/src/util/FFstrbuf.c +++ b/src/util/FFstrbuf.c @@ -328,6 +328,12 @@ uint32_t ffStrbufPreviousIndexC(const FFstrbuf* strbuf, uint32_t start, char c) return strbuf->length; } +void ffStrbufReplaceAllC(FFstrbuf* strbuf, char find, char replace) +{ + for (char *current_pos = strchr(strbuf->chars, find); current_pos; current_pos = strchr(current_pos + 1, find)) + *current_pos = replace; +} + void ffStrbufSubstrBefore(FFstrbuf* strbuf, uint32_t index) { if(strbuf->length <= index) diff --git a/src/util/FFstrbuf.h b/src/util/FFstrbuf.h index 22133a7ea..94adc6b03 100644 --- a/src/util/FFstrbuf.h +++ b/src/util/FFstrbuf.h @@ -69,6 +69,8 @@ FF_C_NODISCARD uint32_t ffStrbufNextIndexS(const FFstrbuf* strbuf, uint32_t star FF_C_NODISCARD uint32_t ffStrbufPreviousIndexC(const FFstrbuf* strbuf, uint32_t start, char c); +void ffStrbufReplaceAllC(FFstrbuf* strbuf, char find, char replace); + void ffStrbufSubstrBefore(FFstrbuf* strbuf, uint32_t index); void ffStrbufSubstrBeforeFirstC(FFstrbuf* strbuf, char c); void ffStrbufSubstrBeforeLastC(FFstrbuf* strbuf, char c); diff --git a/src/util/windows/pwd.c b/src/util/windows/pwd.c index a52f2689a..ce37aabc7 100644 --- a/src/util/windows/pwd.c +++ b/src/util/windows/pwd.c @@ -11,7 +11,12 @@ struct passwd* ffGetPasswd() DWORD len = sizeof(res.pw_name); GetUserNameA(res.pw_name, &len); - SHGetFolderPathA(NULL, CSIDL_PROFILE, NULL, 0, res.pw_dir); + PWSTR pPath; + if(SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_Profile, KF_FLAG_DEFAULT, NULL, &pPath))) + WideCharToMultiByte(CP_UTF8, 0, pPath, -1, res.pw_dir, sizeof(res.pw_dir), NULL, NULL); //res has been NULL inited + CoTaskMemFree(pPath); + for (char *current_pos = strchr(res.pw_dir, '\\'); current_pos; current_pos = strchr(current_pos + 1, '\\')) + *current_pos = '/'; return &res; } diff --git a/tests/strbuf.c b/tests/strbuf.c index 3b55142ec..3d8d3d057 100644 --- a/tests/strbuf.c +++ b/tests/strbuf.c @@ -208,6 +208,12 @@ int main(void) VERIFY(ffStrbufContainC(&strbuf, '1')); VERIFY(!ffStrbufContainC(&strbuf, '-')); + //replaceAllC + ffStrbufReplaceAllC(&strbuf, '1', '-'); + VERIFY(ffStrbufEqualS(&strbuf, "-234567890-234567890-234567890-")); + ffStrbufReplaceAllC(&strbuf, '1', '-'); + VERIFY(ffStrbufEqualS(&strbuf, "-234567890-234567890-234567890-")); + ffStrbufDestroy(&strbuf); //Success From d692fe91fb6e5b2dcaab79dfa8141cf7117b4a42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 2 Jan 2023 11:57:23 +0800 Subject: [PATCH 011/142] Windows: don't try to load config file in `/etc` --- CHANGELOG.md | 3 ++- src/fastfetch.c | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b3866154..47e783744 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,9 +10,10 @@ Logos: Bugfixes: * `--logo-type` now does accept `iterm` too (@CarterLi, #374) - + Other: * Fixed a Typo in iterm error message (@jessebot, #376) +* Don't try to load config file in `/etc` (Windows) (@jessebot, #376) # 1.8.2 diff --git a/src/fastfetch.c b/src/fastfetch.c index f5c522864..b7a9c8cb8 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -1423,7 +1423,10 @@ int main(int argc, const char** argv) ffStrbufInitA(&data.structure, 256); data.loadUserConfig = true; + #ifndef _WIN32 parseConfigFileSystem(&instance, &data); + #endif + parseConfigFileUser(&instance, &data); parseArguments(&instance, &data, argc, argv); From ae6d921f2386e0d0cd70e27af79122eecb5b43d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 2 Jan 2023 12:43:11 +0800 Subject: [PATCH 012/142] Config: don't generate a config file silently Instead, provide a new flag `--gen-config` and print the path to the config file, so that users can know where to find the file. --- CHANGELOG.md | 3 +++ README.md | 2 +- completions/bash | 2 ++ src/data/config_user.txt | 4 ++-- src/data/help.txt | 2 ++ src/fastfetch.c | 32 +++++++++++++++++++++++++++----- 6 files changed, 37 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 47e783744..2a92bd6b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # dev +Notable Changes: +* fastfetch no longer creates a sample config file silently. Use `--gen-config` to generate one. + Features: * `--logo-padding-top` option (@CarterLi, #372) * Raw image file as logo support (@CarterLi) diff --git a/README.md b/README.md index 87959f14d..42ec1e3d0 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for With customization and speed being two competing goals, this project actually builds two executables. -* The main one being `fastfetch`, which can be very greatly configured via flags. These flags can be made persistent in `~/.config/fastfetch/config.conf`. To view the available options run `fastfetch --help`. +* The main one being `fastfetch`, which can be very greatly configured via flags. These flags can be made persistent in `$XDG_CONFIG_HOME/fastfetch/config.conf`. To view the available options run `fastfetch --help`. * The second executable being built is called `flashfetch`, which is configured at compile time to eliminate any possible overhead. Configuration of it can be very easily done in [`src/flashfetch.c`](src/flashfetch.c). At the moment the performance difference is measurable, but too small to be human recognizable. But the leap will get bigger with more and more options coming, and on slow machines this might actually make a difference. diff --git a/completions/bash b/completions/bash index 22d6142c5..5dedf5f6f 100644 --- a/completions/bash +++ b/completions/bash @@ -160,6 +160,8 @@ __fastfetch_completion() "--print-config-system" "--print-config-user" "--print-structure" + "--gen-config" + "--gen-config-force" ) local FF_OPTIONS_HELP=( diff --git a/src/data/config_user.txt b/src/data/config_user.txt index bd3563640..a76e24686 100644 --- a/src/data/config_user.txt +++ b/src/data/config_user.txt @@ -6,7 +6,7 @@ # Empty lines or lines starting with # are ignored. # This file was shipped with $" FASTFETCH_PROJECT_VERSION $". -# Use fastfetch --print-config-user > ~/.config/fastfetch/config.conf to overwrite this file with the current defaults +# Use fastfetch --gen-config-force to overwrite this file with the current defaults # Below some often usefull options are listed. Uncomment and modify them so they take affect. # Note that there are a lot more options than the ones listed here, take a look at "fastfetch --help". @@ -16,7 +16,7 @@ # Load additional config files. # Some are shipped with fastfetch, list them with "fastfetch --list-presets". # Must be a path to a config file or the name of a shipped preset. -# The config file is completly loaded before continuing in the current file, so the placement of this option matters, as later options overwrite already set ones. +# The config file is completely loaded before continuing in the current file, so the placement of this option matters, as later options overwrite already set ones. # Can be used multiple times to load multiple config files / presets. #--load-config /path/to/config.txt diff --git a/src/data/help.txt b/src/data/help.txt index be4d1b329..88a56f2dc 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -12,6 +12,8 @@ Informative options: --print-config-system: Print the default system config --print-config-user: Print the default user config --print-structure: Print the default structure + --gen-config: Generate a sample config file in the default path + --gen-config-force: Generate a sample config file in the default path. Overwrite the existing one General options: --load-config : Load a config file or preset (+) diff --git a/src/fastfetch.c b/src/fastfetch.c index b7a9c8cb8..8fa3cf973 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -603,6 +603,25 @@ static bool parseConfigFile(FFinstance* instance, FFdata* data, const char* path return true; } +static void generateConfigFile(FFinstance* instance, bool force) +{ + FFstrbuf* filename = (FFstrbuf*) ffListGet(&instance->state.configDirs, 0); + // Paths generated in `init.c/initConfigDirs` end with `/` + ffStrbufAppendS(filename, "fastfetch/config.conf"); + + if (!force && ffFileExists(filename->chars, S_IFREG)) + { + fprintf(stderr, "Config file exists in `%s`, use `--gen-config-force` to overwrite\n", filename->chars); + exit(1); + } + else + { + ffWriteFileData(filename->chars, sizeof(FASTFETCH_DATATEXT_CONFIG_USER), FASTFETCH_DATATEXT_CONFIG_USER); + printf("A sample config file has been written in `%s`", filename->chars); + exit(0); + } +} + static void optionParseConfigFile(FFinstance* instance, FFdata* data, const char* key, const char* value) { if(value == NULL) @@ -912,6 +931,10 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con fputs("`--nocache` are obsoleted. Caching functions other than image caching are removed.\n\n", stderr); else if(strcasecmp(key, "--load-config") == 0) optionParseConfigFile(instance, data, key, value); + else if(strcasecmp(key, "--gen-config") == 0) + generateConfigFile(instance, false); + else if(strcasecmp(key, "--gen-config-force") == 0) + generateConfigFile(instance, true); else if(strcasecmp(key, "--thread") == 0 || strcasecmp(key, "--multithreading") == 0) instance->config.multithreading = optionParseBoolean(value); else if(strcasecmp(key, "--stat") == 0) @@ -1265,7 +1288,7 @@ error: } } -static void parseConfigFileSystem(FFinstance* instance, FFdata* data) +FF_UNUSED_PARAM static void parseConfigFileSystem(FFinstance* instance, FFdata* data) { parseConfigFile(instance, data, FASTFETCH_TARGET_DIR_INSTALL_SYSCONF"/fastfetch/config.conf"); } @@ -1278,10 +1301,9 @@ static void parseConfigFileUser(FFinstance* instance, FFdata* data) FFstrbuf* filename = ffListGet(&instance->state.configDirs, 0); uint32_t filenameLength = filename->length; - ffStrbufAppendS(filename, "/fastfetch/config.conf"); + ffStrbufAppendS(filename, "fastfetch/config.conf"); - if(!parseConfigFile(instance, data, filename->chars)) - ffWriteFileData(filename->chars, sizeof(FASTFETCH_DATATEXT_CONFIG_USER), FASTFETCH_DATATEXT_CONFIG_USER); + parseConfigFile(instance, data, filename->chars); ffStrbufSubstrBefore(filename, filenameLength); } @@ -1424,7 +1446,7 @@ int main(int argc, const char** argv) data.loadUserConfig = true; #ifndef _WIN32 - parseConfigFileSystem(&instance, &data); + parseConfigFileSystem(&instance, &data); #endif parseConfigFileUser(&instance, &data); From 3caa92c5674fa9040c3fdbfc0dca1ef2517ee033 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 2 Jan 2023 15:38:29 +0800 Subject: [PATCH 013/142] macOS: looking for config files in `~/Library/Preferences` --- CHANGELOG.md | 5 +++-- src/common/init.c | 10 +++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a92bd6b5..680134cd3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,8 @@ Notable Changes: Features: * `--logo-padding-top` option (@CarterLi, #372) * Raw image file as logo support (@CarterLi) -* Look for config files in $LOCALAPPDATA (Windows) (@CarterLi) +* Look for config files in `$LOCALAPPDATA` (Windows) +* Look for config files in `~/Library/Preferences` (macOS) Logos: * Raspbian (@IamNoRobot, #373) @@ -16,7 +17,7 @@ Bugfixes: Other: * Fixed a Typo in iterm error message (@jessebot, #376) -* Don't try to load config file in `/etc` (Windows) (@jessebot, #376) +* Don't try to load config file in `/etc` (Windows) # 1.8.2 diff --git a/src/common/init.c b/src/common/init.c index 8522c0cd9..b571bf753 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -37,7 +37,15 @@ static void initConfigDirs(FFstate* state) CoTaskMemFree(pPath); } - #elif !(defined(__APPLE__) || defined(__ANDROID__)) + #elif defined(__APPLE__) + + { + FFstrbuf* buffer = (FFstrbuf*) ffListAdd(&state->configDirs); + ffStrbufInitS(buffer, state->passwd->pw_dir); + ffStrbufAppendS(buffer, "/Library/Preferences/"); + } + + #elif !defined(__ANDROID__) const char* xdgConfigHome = getenv("XDG_CONFIG_HOME"); if(ffStrSet(xdgConfigHome)) From 0d722ebe0beb02c18b19da5f6e2534466094e213 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 2 Jan 2023 16:51:11 +0800 Subject: [PATCH 014/142] Config: add `--list-config-paths` option --- CHANGELOG.md | 1 + src/data/help.txt | 1 + src/fastfetch.c | 14 ++++++++++++++ src/util/FFlist.h | 6 ++++++ tests/list.c | 10 ++++++++++ 5 files changed, 32 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 680134cd3..fa60ad865 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ Features: * Raw image file as logo support (@CarterLi) * Look for config files in `$LOCALAPPDATA` (Windows) * Look for config files in `~/Library/Preferences` (macOS) +* Add `--list-config-paths` option which list search paths of config files Logos: * Raspbian (@IamNoRobot, #373) diff --git a/src/data/help.txt b/src/data/help.txt index 88a56f2dc..ec2086cc3 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -4,6 +4,7 @@ Informative options: -h,--help: Show this message -h,--help : Show help for a specific command -v,--version: Show the version of fastfetch + --list-config-paths: List search paths of config files --list-logos: List available logos --list-modules: List available modules --list-presets: List presets fastfetch knows about; they can be loaded with --load-config (+) diff --git a/src/fastfetch.c b/src/fastfetch.c index 8fa3cf973..cfd51195d 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -538,6 +538,15 @@ static inline void listAvailablePresets(FFinstance* instance) ffStrbufDestroy(&folder); } +static void listConfigPaths(FFinstance* instance) +{ + FF_LIST_FOR_EACH(FFstrbuf, folder, instance->state.configDirs) + { + ffStrbufAppendS(folder, "fastfetch/config.conf"); + printf("%s%s\n", folder->chars, ffFileExists(folder->chars, S_IFREG) ? " (*)" : ""); + } +} + static void parseOption(FFinstance* instance, FFdata* data, const char* key, const char* value); static bool parseConfigFile(FFinstance* instance, FFdata* data, const char* path) @@ -902,6 +911,11 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con listAvailablePresets(instance); exit(0); } + else if(strcasecmp(subkey, "-config-paths") == 0) + { + listConfigPaths(instance); + exit(0); + } else if(strcasecmp(subkey, "-features") == 0) { ffListFeatures(); diff --git a/src/util/FFlist.h b/src/util/FFlist.h index fd7a0f5ca..86b20bc5c 100644 --- a/src/util/FFlist.h +++ b/src/util/FFlist.h @@ -45,6 +45,12 @@ static inline void ffListSort(FFlist* list, int(*compar)(const void*, const void qsort(list->data, list->length, list->elementSize, compar); } +#define FF_LIST_FOR_EACH(itemType, itemVarName, listVar) \ + assert(sizeof(itemType) == (listVar).elementSize); \ + for(itemType* itemVarName = (itemType*)(listVar).data; \ + itemVarName - (itemType*)(listVar).data < (listVar).length; \ + ++itemVarName) + #if defined(_WIN32) || defined(__APPLE__) #define FF_LIST_AUTO_DESTROY FFlist __attribute__((__cleanup__(ffListDestroy))) #endif diff --git a/tests/list.c b/tests/list.c index e9c10423e..b42ef4b18 100644 --- a/tests/list.c +++ b/tests/list.c @@ -40,6 +40,10 @@ int main(void) VERIFY(list.capacity == 0); VERIFY(list.length == 0); + //forEach + FF_LIST_FOR_EACH(uint32_t, item, list) + VERIFY(false); + //add for (uint32_t i = 1; i <= FF_LIST_DEFAULT_ALLOC + 1; ++i) { @@ -61,6 +65,12 @@ int main(void) VERIFY(*(uint32_t*)ffListGet(&list, i - 1) == i); } + uint32_t sum = 0; + //forEach + FF_LIST_FOR_EACH(uint32_t, item, list) + sum += *item; + VERIFY(sum == (1 + FF_LIST_DEFAULT_ALLOC + 1) * (FF_LIST_DEFAULT_ALLOC + 1) / 2); + // ffListFirstIndexComp uint32_t n = 10; VERIFY(ffListFirstIndexComp(&list, &n, numEqualsAdapter) == 9); From a98c71aab4068f1cfebb7a8828a9b95f2eef11e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 2 Jan 2023 17:27:06 +0800 Subject: [PATCH 015/142] Config: search for user config file in the order of `configDirs` This is necessary to keep forward compatibility for Windows / macOS users. Since `$LOCALAPPPATH` and `~/Library/Preferences` are now the first element of `configDirs`, config files in `~/.config` won't be used in previous manner. --- CHANGELOG.md | 1 + src/fastfetch.c | 14 +++++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa60ad865..858ea4776 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ Notable Changes: * fastfetch no longer creates a sample config file silently. Use `--gen-config` to generate one. +* fastfetch now search for user config file in the order of `fastfetch --list-config-paths` Features: * `--logo-padding-top` option (@CarterLi, #372) diff --git a/src/fastfetch.c b/src/fastfetch.c index cfd51195d..0ac0420f8 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -1312,14 +1312,18 @@ static void parseConfigFileUser(FFinstance* instance, FFdata* data) if(!data->loadUserConfig) return; - FFstrbuf* filename = ffListGet(&instance->state.configDirs, 0); - uint32_t filenameLength = filename->length; + FF_LIST_FOR_EACH(FFstrbuf, filename, instance->state.configDirs) + { + uint32_t filenameLength = filename->length; - ffStrbufAppendS(filename, "fastfetch/config.conf"); + ffStrbufAppendS(filename, "fastfetch/config.conf"); - parseConfigFile(instance, data, filename->chars); + bool found = parseConfigFile(instance, data, filename->chars); - ffStrbufSubstrBefore(filename, filenameLength); + ffStrbufSubstrBefore(filename, filenameLength); + + if(found) break; + } } static void parseArguments(FFinstance* instance, FFdata* data, int argc, const char** argv) From 30f9bcbd22ddc40950fe2cdca08f971a91f3d025 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 3 Jan 2023 16:44:27 +0800 Subject: [PATCH 016/142] TerminalFont: fix mintty terminal font detection --- CHANGELOG.md | 1 + src/common/init.c | 28 +++++++++++++++++++ .../terminalfont/terminalfont_windows.c | 8 ++++-- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 858ea4776..474deb29b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ Logos: Bugfixes: * `--logo-type` now does accept `iterm` too (@CarterLi, #374) +* Fix mintty terminal font detection Other: * Fixed a Typo in iterm error message (@jessebot, #376) diff --git a/src/common/init.c b/src/common/init.c index b571bf753..0e76a4470 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -77,6 +77,30 @@ static void initConfigDirs(FFstate* state) ffStrbufEnsureEndsWithC(userHome, '/'); FF_ENSURE_ONLY_ONCE_IN_LIST(userHome) + #ifdef _WIN32 + + if(getenv("MSYSTEM") && getenv("HOME")) + { + // We are in MSYS2 / Git Bash + + FFstrbuf* msysConfigHome = ffListAdd(&state->configDirs); + ffStrbufInitA(msysConfigHome, 64); + ffStrbufAppendS(msysConfigHome, getenv("HOME")); + ffStrbufReplaceAllC(msysConfigHome, '\\', '/'); + ffStrbufEnsureEndsWithC(msysConfigHome, '/'); + ffStrbufAppendS(msysConfigHome, ".config/"); + FF_ENSURE_ONLY_ONCE_IN_LIST(msysConfigHome) + + FFstrbuf* msysHome = ffListAdd(&state->configDirs); + ffStrbufInitA(msysHome, 64); + ffStrbufAppendS(msysHome, getenv("HOME")); + ffStrbufReplaceAllC(msysHome, '\\', '/'); + ffStrbufEnsureEndsWithC(msysHome, '/'); + FF_ENSURE_ONLY_ONCE_IN_LIST(msysHome) + } + + #endif + #if !(defined(_WIN32) || defined(__APPLE__) || defined(__ANDROID__)) FFstrbuf xdgConfigDirs; @@ -112,11 +136,15 @@ static void initConfigDirs(FFstate* state) #endif + #ifndef _WIN32 + FFstrbuf* systemConfig = ffListAdd(&state->configDirs); ffStrbufInitA(systemConfig, 64); ffStrbufAppendS(systemConfig, FASTFETCH_TARGET_DIR_ETC"/"); FF_ENSURE_ONLY_ONCE_IN_LIST(systemConfig) + #endif + #undef FF_ENSURE_ONLY_ONCE_IN_LIST } diff --git a/src/detection/terminalfont/terminalfont_windows.c b/src/detection/terminalfont/terminalfont_windows.c index ea41f018e..060108290 100644 --- a/src/detection/terminalfont/terminalfont_windows.c +++ b/src/detection/terminalfont/terminalfont_windows.c @@ -14,10 +14,14 @@ static void detectMintty(const FFinstance* instance, FFTerminalFontResult* termi FF_STRBUF_AUTO_DESTROY fontSize; ffStrbufInit(&fontSize); - ffParsePropFileHomeValues(instance, ".minttyrc", 2, (FFpropquery[]) { + if(!ffParsePropFileConfigValues(instance, "mintty/config", 2, (FFpropquery[]) { {"Font=", &fontName}, {"FontHeight=", &fontSize} - }); + })) + ffParsePropFileConfigValues(instance, ".minttyrc", 2, (FFpropquery[]) { + {"Font=", &fontName}, + {"FontHeight=", &fontSize} + }); if(fontName.length == 0) ffStrbufAppendS(&fontName, "Lucida Console"); if(fontSize.length == 0) From f3db4e49b6ac832ddb27cd712520ba8831d666fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 3 Jan 2023 16:56:18 +0800 Subject: [PATCH 017/142] Windows: store config file in RoamingAppData instead of LocalAppData --- CHANGELOG.md | 2 +- src/common/init.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 474deb29b..e9fdb4935 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ Notable Changes: Features: * `--logo-padding-top` option (@CarterLi, #372) * Raw image file as logo support (@CarterLi) -* Look for config files in `$LOCALAPPDATA` (Windows) +* Look for config files in `$APPDATA` ([RoamingAppData](https://superuser.com/questions/21458/why-are-there-directories-called-local-locallow-and-roaming-under-users-user#answer-21462)) (Windows) * Look for config files in `~/Library/Preferences` (macOS) * Add `--list-config-paths` option which list search paths of config files diff --git a/src/common/init.c b/src/common/init.c index 0e76a4470..3e4243a4f 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -26,7 +26,7 @@ static void initConfigDirs(FFstate* state) { PWSTR pPath; - if(SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_LocalAppData, 0, NULL, &pPath))) + if(SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_RoamingAppData, 0, NULL, &pPath))) { FFstrbuf* buffer = (FFstrbuf*) ffListAdd(&state->configDirs); ffStrbufInit(buffer); From a307977ec116cced88669040f02305e78bf5698f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 3 Jan 2023 15:13:39 +0800 Subject: [PATCH 018/142] Image: don't try to read image file with `--logo none` --- CHANGELOG.md | 2 +- src/fastfetch.c | 2 ++ src/fastfetch.h | 1 + src/logo/logo.c | 2 ++ 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e9fdb4935..cc1cb0891 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -136,7 +136,7 @@ Bugfixes: * Don't segfault in GPU code on Intel Macs (@CarterLi, #236) * Don't use hardcoded size units in presets (@dr460nf1r3, #255) * Don't crash with some format strings (#252) -* --logo-none keeps key color now (#264) +* --logo none keeps key color now (#264) # 1.7.2 diff --git a/src/fastfetch.c b/src/fastfetch.c index 0ac0420f8..af23ab6d4 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -979,6 +979,7 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con instance->config.logo.paddingTop = 0; instance->config.logo.paddingRight = 0; instance->config.logo.paddingLeft = 0; + instance->config.logo.type = FF_LOGO_TYPE_NONE; } } else if(startsWith(key, "--logo")) @@ -998,6 +999,7 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con "iterm", FF_LOGO_TYPE_IMAGE_ITERM, "chafa", FF_LOGO_TYPE_IMAGE_CHAFA, "raw", FF_LOGO_TYPE_IMAGE_RAW, + "none", FF_LOGO_TYPE_NONE, NULL ); } diff --git a/src/fastfetch.h b/src/fastfetch.h index 58ca227b0..1f8782a3e 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -38,6 +38,7 @@ typedef enum FFLogoType FF_LOGO_TYPE_IMAGE_ITERM, //image file, printed as iterm graphics protocol FF_LOGO_TYPE_IMAGE_CHAFA, //image file, printed as ascii art using libchafa FF_LOGO_TYPE_IMAGE_RAW, //image file, printed as raw binary string + FF_LOGO_TYPE_NONE, //--logo none } FFLogoType; typedef enum FFBinaryPrefixType diff --git a/src/logo/logo.c b/src/logo/logo.c index 85ed46791..e460ba55e 100644 --- a/src/logo/logo.c +++ b/src/logo/logo.c @@ -339,6 +339,8 @@ static void logoPrintKnownType(FFinstance* instance) else successfull = logoPrintFileIfExists(instance, false, true); } + else if(instance->config.logo.type == FF_LOGO_TYPE_NONE) + logoApplyColorsDetected(instance); else //image successfull = logoPrintImageIfExists(instance, instance->config.logo.type); From 3e2c34441787c86754880e7e983745c059388fde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 7 Jan 2023 19:44:07 +0800 Subject: [PATCH 019/142] Android: honor $XDG_CONFIG_HOME when loading user config file --- src/common/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/init.c b/src/common/init.c index 3e4243a4f..190c2f286 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -45,7 +45,7 @@ static void initConfigDirs(FFstate* state) ffStrbufAppendS(buffer, "/Library/Preferences/"); } - #elif !defined(__ANDROID__) + #else const char* xdgConfigHome = getenv("XDG_CONFIG_HOME"); if(ffStrSet(xdgConfigHome)) From 959540f17cec811ed57eab4c28c930bbdf4ac420 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 7 Jan 2023 19:46:56 +0800 Subject: [PATCH 020/142] DisplayServer: support brightness detection (macOS) --- CMakeLists.txt | 1 + README.md | 1 + src/detection/displayserver/displayserver.c | 3 ++- src/detection/displayserver/displayserver.h | 3 ++- src/detection/displayserver/displayserver_apple.c | 9 ++++++++- .../displayserver/displayserver_windows.c | 2 +- src/detection/displayserver/linux/xcb.c | 15 ++++++++++----- src/detection/displayserver/linux/xlib.c | 15 ++++++++++----- src/modules/resolution.c | 6 +++++- 9 files changed, 40 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b777ba3b..88e079485 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -652,6 +652,7 @@ if(APPLE) PRIVATE "-framework Cocoa" PRIVATE "-framework CoreWLAN" PRIVATE "-weak_framework MediaRemote -F /System/Library/PrivateFrameworks" + PRIVATE "-weak_framework DisplayServices -F /System/Library/PrivateFrameworks" ) elseif(WIN32) target_compile_definitions(libfastfetch PRIVATE -D_WIN32_WINNT=0x0601) diff --git a/README.md b/README.md index 42ec1e3d0..8bce6372b 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,7 @@ The following libraries are used if present at runtime: ### macOS * [`MediaRemote`](https://iphonedev.wiki/index.php/MediaRemote.framework): Need for Media detection. It's a private framework provided by newer macOS system. +* [`DisplayServices`](https://developer.apple.com/forums/thread/666383#663154022): Need for screen brightness detection. It's a private framework provided by newer macOS system. * [`MoltenVK`](https://github.com/KhronosGroup/MoltenVK): Vulkan driver for macOS. [`molten-vk`](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/molten-vk.rb) * [`libmagickcore` (ImageMagick)](https://www.imagemagick.org/): Images in terminal using sixel graphics protocol. [`imagemagick`](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/imagemagick.rb) * [`libchafa`](https://github.com/hpjansson/chafa): Image output as ascii art. [`chafa`](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/chafa.rb) diff --git a/src/detection/displayserver/displayserver.c b/src/detection/displayserver/displayserver.c index 4a42a21a1..e82279f4f 100644 --- a/src/detection/displayserver/displayserver.c +++ b/src/detection/displayserver/displayserver.c @@ -19,7 +19,7 @@ uint32_t ffdsParseRefreshRate(int32_t refreshRate) return (uint32_t) refreshRate; } -bool ffdsAppendResolution(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate) +bool ffdsAppendResolution(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate, int32_t brightness) { if(width == 0 || height == 0) return false; @@ -28,6 +28,7 @@ bool ffdsAppendResolution(FFDisplayServerResult* result, uint32_t width, uint32_ resolution->width = width; resolution->height = height; resolution->refreshRate = refreshRate; + resolution->brightness = brightness; return true; } diff --git a/src/detection/displayserver/displayserver.h b/src/detection/displayserver/displayserver.h index d31d5edee..16e6e67a6 100644 --- a/src/detection/displayserver/displayserver.h +++ b/src/detection/displayserver/displayserver.h @@ -10,6 +10,7 @@ typedef struct FFResolutionResult uint32_t width; uint32_t height; uint32_t refreshRate; + int32_t brightness; } FFResolutionResult; typedef struct FFDisplayServerResult @@ -27,6 +28,6 @@ const FFDisplayServerResult* ffConnectDisplayServer(const FFinstance* instance); //Used internal uint32_t ffdsParseRefreshRate(int32_t refreshRate); -bool ffdsAppendResolution(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate); +bool ffdsAppendResolution(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate, int32_t brightness); #endif diff --git a/src/detection/displayserver/displayserver_apple.c b/src/detection/displayserver/displayserver_apple.c index 4d0d802c2..88fd16477 100644 --- a/src/detection/displayserver/displayserver_apple.c +++ b/src/detection/displayserver/displayserver_apple.c @@ -7,6 +7,8 @@ #include #include +extern int DisplayServicesGetBrightness(CGDirectDisplayID display, float *brightness) __attribute__((weak_import)); + static void detectResolution(FFDisplayServerResult* ds) { CGDirectDisplayID screens[128]; @@ -20,10 +22,15 @@ static void detectResolution(FFDisplayServerResult* ds) CGDisplayModeRef mode = CGDisplayCopyDisplayMode(screen); if(mode) { + float brightness; + if(DisplayServicesGetBrightness == NULL || DisplayServicesGetBrightness(screen, &brightness) != kCGErrorSuccess) + brightness = -1; + ffdsAppendResolution(ds, (uint32_t)CGDisplayModeGetWidth(mode), (uint32_t)CGDisplayModeGetHeight(mode), - (uint32_t)CGDisplayModeGetRefreshRate(mode) + (uint32_t)CGDisplayModeGetRefreshRate(mode), + (int32_t)(brightness * 100) ); CGDisplayModeRelease(mode); } diff --git a/src/detection/displayserver/displayserver_windows.c b/src/detection/displayserver/displayserver_windows.c index f39955b8b..988d790a3 100644 --- a/src/detection/displayserver/displayserver_windows.c +++ b/src/detection/displayserver/displayserver_windows.c @@ -34,7 +34,7 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* ins if(EnumDisplaySettingsW(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &devMode) == 0) continue; - ffdsAppendResolution(ds, devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmDisplayFrequency); + ffdsAppendResolution(ds, devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmDisplayFrequency, -1); } //https://github.com/hykilpikonna/hyfetch/blob/master/neofetch#L2067 diff --git a/src/detection/displayserver/linux/xcb.c b/src/detection/displayserver/linux/xcb.c index 692be7808..f92e91e5a 100644 --- a/src/detection/displayserver/linux/xcb.c +++ b/src/detection/displayserver/linux/xcb.c @@ -119,7 +119,8 @@ void ffdsConnectXcb(const FFinstance* instance, FFDisplayServerResult* result) result, (uint32_t) iterator.data->width_in_pixels, (uint32_t) iterator.data->height_in_pixels, - 0 + 0, + -1 ); ffxcb_screen_next(&iterator); } @@ -184,7 +185,8 @@ static bool xcbRandrHandleModeInfo(XcbRandrData* data, xcb_randr_mode_info_t* mo data->result, (uint32_t) modeInfo->width, (uint32_t) modeInfo->height, - refreshRate == 0 ? data->defaultRefreshRate : refreshRate + refreshRate == 0 ? data->defaultRefreshRate : refreshRate, + -1 ); } @@ -219,7 +221,8 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc) data->result, (uint32_t) crtcInfoReply->width, (uint32_t) crtcInfoReply->height, - data->defaultRefreshRate + data->defaultRefreshRate, + -1 ); free(crtcInfoReply); @@ -262,7 +265,8 @@ static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t* data->result, (uint32_t) monitor->width, (uint32_t) monitor->height, - data->defaultRefreshRate + data->defaultRefreshRate, + -1 ); } @@ -320,7 +324,8 @@ static void xcbRandrHandleScreen(XcbRandrData* data, xcb_screen_t* screen) data->result, (uint32_t) screen->width_in_pixels, (uint32_t) screen->height_in_pixels, - data->defaultRefreshRate + data->defaultRefreshRate, + -1 ); } diff --git a/src/detection/displayserver/linux/xlib.c b/src/detection/displayserver/linux/xlib.c index 108de5946..d7429713f 100644 --- a/src/detection/displayserver/linux/xlib.c +++ b/src/detection/displayserver/linux/xlib.c @@ -83,7 +83,8 @@ void ffdsConnectXlib(const FFinstance* instance, FFDisplayServerResult* result) result, (uint32_t) screen->width, (uint32_t) screen->height, - 0 + 0, + -1 ); } @@ -142,7 +143,8 @@ static bool xrandrHandleModeInfo(XrandrData* data, XRRModeInfo* modeInfo) data->result, (uint32_t) modeInfo->width, (uint32_t) modeInfo->height, - refreshRate == 0 ? data->defaultRefreshRate : refreshRate + refreshRate == 0 ? data->defaultRefreshRate : refreshRate, + -1 ); } @@ -171,7 +173,8 @@ static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc) data->result, (uint32_t) crtcInfo->width, (uint32_t) crtcInfo->height, - data->defaultRefreshRate + data->defaultRefreshRate, + -1 ); data->ffXRRFreeCrtcInfo(crtcInfo); @@ -205,7 +208,8 @@ static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo) data->result, (uint32_t) monitorInfo->width, (uint32_t) monitorInfo->height, - data->defaultRefreshRate + data->defaultRefreshRate, + -1 ); } @@ -257,7 +261,8 @@ static void xrandrHandleScreen(XrandrData* data, Screen* screen) data->result, (uint32_t) WidthOfScreen(screen), (uint32_t) HeightOfScreen(screen), - data->defaultRefreshRate + data->defaultRefreshRate, + -1 ); } diff --git a/src/modules/resolution.c b/src/modules/resolution.c index 396d435b1..85c1b506a 100644 --- a/src/modules/resolution.c +++ b/src/modules/resolution.c @@ -27,6 +27,9 @@ void ffPrintResolution(FFinstance* instance) if(result->refreshRate > 0) printf(" @ %iHz", result->refreshRate); + if(result->brightness >= 0) + printf(" (☀️ %d%%)", result->brightness); + putchar('\n'); } else @@ -34,7 +37,8 @@ void ffPrintResolution(FFinstance* instance) ffPrintFormat(instance, FF_RESOLUTION_MODULE_NAME, moduleIndex, &instance->config.resolution, FF_RESOLUTION_NUM_FORMAT_ARGS, (FFformatarg[]) { {FF_FORMAT_ARG_TYPE_INT, &result->width}, {FF_FORMAT_ARG_TYPE_INT, &result->height}, - {FF_FORMAT_ARG_TYPE_INT, &result->refreshRate} + {FF_FORMAT_ARG_TYPE_INT, &result->refreshRate}, + {FF_FORMAT_ARG_TYPE_INT, &result->brightness}, }); } } From 2621c48f927cd3cffa14902c884acbe31f7b239f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 7 Jan 2023 21:16:14 +0800 Subject: [PATCH 021/142] DisplayServer: support brightness detection (Windows) --- CMakeLists.txt | 1 + .../displayserver/displayserver_windows.c | 32 ++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 88e079485..420716149 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -671,6 +671,7 @@ elseif(WIN32) PRIVATE "dxgi" PRIVATE "wtsapi32" PRIVATE "powrprof" + PRIVATE "dxva2" ) if(USE_WIN_NTAPI) target_compile_definitions(libfastfetch PRIVATE FF_USE_WIN_NTAPI) diff --git a/src/detection/displayserver/displayserver_windows.c b/src/detection/displayserver/displayserver_windows.c index 988d790a3..a7f0d9b76 100644 --- a/src/detection/displayserver/displayserver_windows.c +++ b/src/detection/displayserver/displayserver_windows.c @@ -1,8 +1,35 @@ #include "displayserver.h" #include "detection/os/os.h" +#include "util/mallocHelper.h" #include #include +#include +#include + +static WINBOOL enumMonitorProc(HMONITOR hMonitor, FF_UNUSED_PARAM HDC hDC, FF_UNUSED_PARAM LPRECT rc, LPARAM data) +{ + MONITORINFOEXW mi = { .cbSize = sizeof(mi) }; + DISPLAY_DEVICEW* displayDevice = (DISPLAY_DEVICEW *) data; + if(GetMonitorInfoW(hMonitor, (MONITORINFO *)&mi) && wcscmp(mi.szDevice, displayDevice->DeviceName) == 0) + { + DWORD arraySize; + if(GetNumberOfPhysicalMonitorsFromHMONITOR(hMonitor, &arraySize) && arraySize > 0) + { + PHYSICAL_MONITOR* FF_AUTO_FREE physicalMonitorArray = malloc(arraySize * sizeof(*physicalMonitorArray)); + if(GetPhysicalMonitorsFromHMONITOR(hMonitor, arraySize, physicalMonitorArray)) + { + DWORD minValue, currentValue, maxValue; + if(GetMonitorBrightness(physicalMonitorArray[0].hPhysicalMonitor, &minValue, ¤tValue, &maxValue)) + displayDevice->StateFlags = currentValue * 100 / maxValue; + + DestroyPhysicalMonitors(arraySize, physicalMonitorArray); + } + } + return FALSE; + } + return TRUE; +} void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* instance) { @@ -34,7 +61,10 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* ins if(EnumDisplaySettingsW(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &devMode) == 0) continue; - ffdsAppendResolution(ds, devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmDisplayFrequency, -1); + displayDevice.StateFlags = (DWORD) -1; + EnumDisplayMonitors(NULL, NULL, enumMonitorProc, (LPARAM)(void*) &displayDevice); + + ffdsAppendResolution(ds, devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmDisplayFrequency, (int) displayDevice.StateFlags); } //https://github.com/hykilpikonna/hyfetch/blob/master/neofetch#L2067 From d0bab2ca2212333d09482f9605ed66c820c9ca37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 7 Jan 2023 21:57:35 +0800 Subject: [PATCH 022/142] Image: fix compiler warnings (Windows) --- src/logo/image/image.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/logo/image/image.c b/src/logo/image/image.c index fec6bbf6c..26c51f1a3 100644 --- a/src/logo/image/image.c +++ b/src/logo/image/image.c @@ -109,6 +109,7 @@ static inline char* realpath(const char* restrict file_name, char* restrict reso resolved_name[1] = resolved_name[0]; // Drive Name resolved_name[0] = '/'; } + return result; } #endif From e7af38aa11c3699c006b4bfdf8f97b9a6404904c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 8 Jan 2023 01:25:15 +0800 Subject: [PATCH 023/142] DisplayServer: make display brightness actually work (Windows) --- CMakeLists.txt | 3 +- ...er_windows.c => displayserver_windows.cpp} | 57 ++++++++----------- src/modules/resolution.c | 2 +- src/util/windows/wmi.cpp | 32 ++++++----- src/util/windows/wmi.hpp | 8 ++- 5 files changed, 51 insertions(+), 51 deletions(-) rename src/detection/displayserver/{displayserver_windows.c => displayserver_windows.cpp} (56%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 420716149..fb39d390a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -463,7 +463,7 @@ elseif(WIN32) src/detection/cpuUsage/cpuUsage_windows.c src/detection/cursor/cursor_windows.c src/detection/disk/disk_windows.c - src/detection/displayserver/displayserver_windows.c + src/detection/displayserver/displayserver_windows.cpp src/detection/font/font_windows.c src/detection/gpu/gpu_windows.cpp src/detection/host/host_windows.c @@ -671,7 +671,6 @@ elseif(WIN32) PRIVATE "dxgi" PRIVATE "wtsapi32" PRIVATE "powrprof" - PRIVATE "dxva2" ) if(USE_WIN_NTAPI) target_compile_definitions(libfastfetch PRIVATE FF_USE_WIN_NTAPI) diff --git a/src/detection/displayserver/displayserver_windows.c b/src/detection/displayserver/displayserver_windows.cpp similarity index 56% rename from src/detection/displayserver/displayserver_windows.c rename to src/detection/displayserver/displayserver_windows.cpp index a7f0d9b76..7de11a9ad 100644 --- a/src/detection/displayserver/displayserver_windows.c +++ b/src/detection/displayserver/displayserver_windows.cpp @@ -1,36 +1,13 @@ +extern "C" { #include "displayserver.h" #include "detection/os/os.h" -#include "util/mallocHelper.h" +} +#include "util/windows/wmi.hpp" #include -#include -#include -#include - -static WINBOOL enumMonitorProc(HMONITOR hMonitor, FF_UNUSED_PARAM HDC hDC, FF_UNUSED_PARAM LPRECT rc, LPARAM data) -{ - MONITORINFOEXW mi = { .cbSize = sizeof(mi) }; - DISPLAY_DEVICEW* displayDevice = (DISPLAY_DEVICEW *) data; - if(GetMonitorInfoW(hMonitor, (MONITORINFO *)&mi) && wcscmp(mi.szDevice, displayDevice->DeviceName) == 0) - { - DWORD arraySize; - if(GetNumberOfPhysicalMonitorsFromHMONITOR(hMonitor, &arraySize) && arraySize > 0) - { - PHYSICAL_MONITOR* FF_AUTO_FREE physicalMonitorArray = malloc(arraySize * sizeof(*physicalMonitorArray)); - if(GetPhysicalMonitorsFromHMONITOR(hMonitor, arraySize, physicalMonitorArray)) - { - DWORD minValue, currentValue, maxValue; - if(GetMonitorBrightness(physicalMonitorArray[0].hPhysicalMonitor, &minValue, ¤tValue, &maxValue)) - displayDevice->StateFlags = currentValue * 100 / maxValue; - - DestroyPhysicalMonitors(arraySize, physicalMonitorArray); - } - } - return FALSE; - } - return TRUE; -} +#include +extern "C" void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* instance) { FF_UNUSED(instance); @@ -52,19 +29,33 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* ins ffStrbufInit(&ds->deVersion); ffListInit(&ds->resolutions, sizeof(FFResolutionResult)); - DISPLAY_DEVICEW displayDevice = { .cb = sizeof(DISPLAY_DEVICEW) }; + DISPLAY_DEVICEW displayDevice; + displayDevice.cb = sizeof(DISPLAY_DEVICEW); for(DWORD devNum = 0; EnumDisplayDevicesW(NULL, devNum, &displayDevice, 0) != 0; ++devNum) { if(!(displayDevice.StateFlags & DISPLAY_DEVICE_ACTIVE)) continue; - DEVMODEW devMode = { .dmSize = sizeof(DEVMODEW) }; + DEVMODEW devMode; + devMode.dmSize = sizeof(DEVMODEW); if(EnumDisplaySettingsW(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &devMode) == 0) continue; - displayDevice.StateFlags = (DWORD) -1; - EnumDisplayMonitors(NULL, NULL, enumMonitorProc, (LPARAM)(void*) &displayDevice); + ffdsAppendResolution(ds, devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmDisplayFrequency, -1); + } - ffdsAppendResolution(ds, devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmDisplayFrequency, (int) displayDevice.StateFlags); + //TODO: support multiple monitors + if(ds->resolutions.length == 1) + { + FFWmiQuery query(L"SELECT CurrentBrightness FROM WmiMonitorBrightness WHERE Active = true", nullptr, FFWmiNamespace::WMI); + if(FFWmiRecord record = query.next()) + { + uint64_t brightness; + record.getUnsigned(L"CurrentBrightness", &brightness); + FF_LIST_FOR_EACH(FFResolutionResult, resolution, ds->resolutions) + { + resolution->brightness = (int) brightness; + } + } } //https://github.com/hykilpikonna/hyfetch/blob/master/neofetch#L2067 diff --git a/src/modules/resolution.c b/src/modules/resolution.c index 85c1b506a..c07b45ad8 100644 --- a/src/modules/resolution.c +++ b/src/modules/resolution.c @@ -28,7 +28,7 @@ void ffPrintResolution(FFinstance* instance) printf(" @ %iHz", result->refreshRate); if(result->brightness >= 0) - printf(" (☀️ %d%%)", result->brightness); + printf(" (Brightness %d%%)", result->brightness); putchar('\n'); } diff --git a/src/util/windows/wmi.cpp b/src/util/windows/wmi.cpp index cba0c07c5..1da4ac0ff 100644 --- a/src/util/windows/wmi.cpp +++ b/src/util/windows/wmi.cpp @@ -26,7 +26,7 @@ static void CoUninitializeWrap() CoUninitialize(); } -static BOOL CALLBACK InitHandleFunction(PINIT_ONCE, PVOID, PVOID *lpContext) +static BOOL CALLBACK InitHandleFunction(PINIT_ONCE, PVOID lpParameter, PVOID* lpContext) { HRESULT hres; @@ -76,15 +76,15 @@ static BOOL CALLBACK InitHandleFunction(PINIT_ONCE, PVOID, PVOID *lpContext) // the current user and obtain pointer pSvc // to make IWbemServices calls. hres = pLoc->ConnectServer( - bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace - nullptr, // User name. nullptr = current user - nullptr, // User password. nullptr = current - 0, // Locale. nullptr indicates current - 0, // Security flags. - 0, // Authority (for example, Kerberos) - 0, // Context object - &pSvc // pointer to IWbemServices proxy - ); + bstr_t((const wchar_t*) lpParameter), // Object path of WMI namespace + nullptr, // User name. nullptr = current user + nullptr, // User password. nullptr = current + 0, // Locale. nullptr indicates current + 0, // Security flags. + 0, // Authority (for example, Kerberos) + 0, // Context object + &pSvc // pointer to IWbemServices proxy + ); pLoc->Release(); pLoc = nullptr; @@ -120,13 +120,17 @@ static BOOL CALLBACK InitHandleFunction(PINIT_ONCE, PVOID, PVOID *lpContext) return TRUE; } -FFWmiQuery::FFWmiQuery(const wchar_t* queryStr, FFstrbuf* error) +FFWmiQuery::FFWmiQuery(const wchar_t* queryStr, FFstrbuf* error, FFWmiNamespace wmiNs) : pEnumerator(nullptr) { - static INIT_ONCE s_InitOnce = INIT_ONCE_STATIC_INIT; + static INIT_ONCE s_InitOnce[(int) FFWmiNamespace::LAST] = {}; const char* context; - if (InitOnceExecuteOnce(&s_InitOnce, &InitHandleFunction, nullptr, (void**)&context) == FALSE) - { + if (InitOnceExecuteOnce( + &s_InitOnce[(int)wmiNs], + &InitHandleFunction, + (PVOID) (wmiNs == FFWmiNamespace::CIMV2 ? L"ROOT\\CIMV2" : L"ROOT\\WMI"), + (void**)&context) == FALSE + ) { if(error) ffStrbufAppendS(error, context); return; diff --git a/src/util/windows/wmi.hpp b/src/util/windows/wmi.hpp index 6f7d214cb..25bef6e91 100644 --- a/src/util/windows/wmi.hpp +++ b/src/util/windows/wmi.hpp @@ -11,6 +11,12 @@ extern "C" { #include +enum class FFWmiNamespace { + CIMV2, + WMI, + LAST, +}; + struct FFWmiRecord { IWbemClassObject* obj; @@ -43,7 +49,7 @@ struct FFWmiQuery { IEnumWbemClassObject* pEnumerator = nullptr; - FFWmiQuery(const wchar_t* queryStr, FFstrbuf* error = nullptr); + FFWmiQuery(const wchar_t* queryStr, FFstrbuf* error = nullptr, FFWmiNamespace wmiNs = FFWmiNamespace::CIMV2); explicit FFWmiQuery(IEnumWbemClassObject* pEnumerator): pEnumerator(pEnumerator) {} FFWmiQuery(const FFWmiQuery& other) = delete; FFWmiQuery(FFWmiQuery&& other) { *this = (FFWmiQuery&&)other; } From 137039f86817b139536e256400a56174e1f454cd Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Sat, 7 Jan 2023 22:37:01 +0100 Subject: [PATCH 024/142] Initialize brightness on wayland too --- src/detection/displayserver/linux/wayland.c | 1 + src/fastfetch.c | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/detection/displayserver/linux/wayland.c b/src/detection/displayserver/linux/wayland.c index 37891149c..0a0d695f4 100644 --- a/src/detection/displayserver/linux/wayland.c +++ b/src/detection/displayserver/linux/wayland.c @@ -66,6 +66,7 @@ static void waylandOutputModeListener(void* data, struct wl_output* output, uint result->width = (uint32_t) width; result->height = (uint32_t) height; result->refreshRate = ffdsParseRefreshRate(refreshRate / 1000); + result->brightness = -1; } static void waylandGlobalAddListener(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version) diff --git a/src/fastfetch.c b/src/fastfetch.c index af23ab6d4..8b6c9008d 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -176,10 +176,11 @@ static inline void printCommandHelp(const char* command) } else if(strcasecmp(command, "resolution-format") == 0) { - constructAndPrintCommandHelpFormat("resolution", "{}x{} @ {}Hz", 3, + constructAndPrintCommandHelpFormat("resolution", "{}x{} @ {}Hz", 4, "Screen width", "Screen height", - "Screen refresh rate" + "Screen refresh rate", + "Screen brightness" ); } else if(strcasecmp(command, "de-format") == 0) From bb57714ac98b6c9a901bf0ca4b260cc34e66abe6 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Sat, 7 Jan 2023 22:51:47 +0100 Subject: [PATCH 025/142] Use configDirs to look for fastfetch configs --- src/common/init.c | 8 +++++++- src/fastfetch.c | 32 ++++++++++---------------------- 2 files changed, 17 insertions(+), 23 deletions(-) diff --git a/src/common/init.c b/src/common/init.c index 190c2f286..9afdbae50 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -101,7 +101,7 @@ static void initConfigDirs(FFstate* state) #endif - #if !(defined(_WIN32) || defined(__APPLE__) || defined(__ANDROID__)) + #if !defined(_WIN32) && !defined(__APPLE__) FFstrbuf xdgConfigDirs; ffStrbufInitA(&xdgConfigDirs, 64); @@ -143,6 +143,12 @@ static void initConfigDirs(FFstate* state) ffStrbufAppendS(systemConfig, FASTFETCH_TARGET_DIR_ETC"/"); FF_ENSURE_ONLY_ONCE_IN_LIST(systemConfig) + FFstrbuf* systemConfigInstall = ffListAdd(&state->configDirs); + ffStrbufInitA(systemConfigInstall, 64); + ffStrbufAppendS(systemConfigInstall, FASTFETCH_TARGET_DIR_INSTALL_SYSCONF"/"); + FF_ENSURE_ONLY_ONCE_IN_LIST(systemConfigInstall) + + #endif #undef FF_ENSURE_ONLY_ONCE_IN_LIST diff --git a/src/fastfetch.c b/src/fastfetch.c index 8b6c9008d..326e081b0 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -1305,27 +1305,19 @@ error: } } -FF_UNUSED_PARAM static void parseConfigFileSystem(FFinstance* instance, FFdata* data) +static void parseConfigFiles(FFinstance* instance, FFdata* data) { - parseConfigFile(instance, data, FASTFETCH_TARGET_DIR_INSTALL_SYSCONF"/fastfetch/config.conf"); -} - -static void parseConfigFileUser(FFinstance* instance, FFdata* data) -{ - if(!data->loadUserConfig) - return; - - FF_LIST_FOR_EACH(FFstrbuf, filename, instance->state.configDirs) + for(uint32_t i = instance->state.configDirs.length; i > 0; --i) { - uint32_t filenameLength = filename->length; + if(!data->loadUserConfig) + return; - ffStrbufAppendS(filename, "fastfetch/config.conf"); + FFstrbuf* dir = ffListGet(&instance->state.configDirs, i - 1); + uint32_t dirLength = dir->length; - bool found = parseConfigFile(instance, data, filename->chars); - - ffStrbufSubstrBefore(filename, filenameLength); - - if(found) break; + ffStrbufAppendS(dir, "fastfetch/config.conf"); + parseConfigFile(instance, data, dir->chars); + ffStrbufSubstrBefore(dir, dirLength); } } @@ -1466,11 +1458,7 @@ int main(int argc, const char** argv) ffStrbufInitA(&data.structure, 256); data.loadUserConfig = true; - #ifndef _WIN32 - parseConfigFileSystem(&instance, &data); - #endif - - parseConfigFileUser(&instance, &data); + parseConfigFiles(&instance, &data); parseArguments(&instance, &data, argc, argv); //If we don't have a custom structure, use the default one From 2a092de8d8ab7ee1dc73efd9762104cb50437269 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Sun, 8 Jan 2023 01:41:09 +0100 Subject: [PATCH 026/142] Detect data dirs at runtime * Respecting the current platform * Using them where appropiate --- CHANGELOG.md | 1 + src/common/init.c | 233 ++++++++++-------- src/common/properties.c | 23 +- src/common/properties.h | 40 ++- src/data/help.txt | 1 + src/detection/cursor/cursor_linux.c | 2 +- src/detection/displayserver/linux/wmde.c | 38 ++- src/detection/gpu/gpu_linux.c | 10 +- .../terminalfont/terminalfont_linux.c | 6 +- src/fastfetch.c | 59 +++-- src/fastfetch.h | 3 +- 11 files changed, 225 insertions(+), 191 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc1cb0891..f11a7e894 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ Features: * Look for config files in `$APPDATA` ([RoamingAppData](https://superuser.com/questions/21458/why-are-there-directories-called-local-locallow-and-roaming-under-users-user#answer-21462)) (Windows) * Look for config files in `~/Library/Preferences` (macOS) * Add `--list-config-paths` option which list search paths of config files +* Add `--list-data-paths` option which list search paths for presets and logos Logos: * Raspbian (@IamNoRobot, #373) diff --git a/src/common/init.c b/src/common/init.c index 9afdbae50..8c526e909 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -18,140 +18,160 @@ #include #endif -static void initConfigDirs(FFstate* state) +#define FF_ENSURE_ONLY_ONCE_IN_LIST(list, element) \ + if(ffListFirstIndexComp(list, element, (bool(*)(const void*, const void*))ffStrbufEqual) < list->length - 1) \ + { \ + ffStrbufDestroy(ffListGet(list, list->length - 1)); \ + --list->length; \ + } + +#ifdef _WIN32 +void pathsAddKnownFolder(FFlist* dirs, REFKNOWNFOLDERID folderId) { - ffListInit(&state->configDirs, sizeof(FFstrbuf)); - - #ifdef _WIN32 - + PWSTR pPath; + if(SUCCEEDED(SHGetKnownFolderPath(folderId, 0, NULL, &pPath))) { - PWSTR pPath; - if(SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_RoamingAppData, 0, NULL, &pPath))) - { - FFstrbuf* buffer = (FFstrbuf*) ffListAdd(&state->configDirs); - ffStrbufInit(buffer); - ffStrbufSetWS(buffer, pPath); - ffStrbufReplaceAllC(buffer, '\\', '/'); - ffStrbufEnsureEndsWithC(buffer, '/'); - } - CoTaskMemFree(pPath); - } - - #elif defined(__APPLE__) - - { - FFstrbuf* buffer = (FFstrbuf*) ffListAdd(&state->configDirs); - ffStrbufInitS(buffer, state->passwd->pw_dir); - ffStrbufAppendS(buffer, "/Library/Preferences/"); - } - - #else - - const char* xdgConfigHome = getenv("XDG_CONFIG_HOME"); - if(ffStrSet(xdgConfigHome)) - { - FFstrbuf* buffer = (FFstrbuf*) ffListAdd(&state->configDirs); - ffStrbufInitA(buffer, 64); - ffStrbufAppendS(buffer, xdgConfigHome); + FFstrbuf* buffer = (FFstrbuf*) ffListAdd(dirs); + ffStrbufInit(buffer); + ffStrbufSetWS(buffer, pPath); + ffStrbufReplaceAllC(buffer, '\\', '/'); ffStrbufEnsureEndsWithC(buffer, '/'); + FF_ENSURE_ONLY_ONCE_IN_LIST(dirs, buffer); } + CoTaskMemFree(pPath); +} - #endif +void pathsAddEnvSuffix(FFlist* dirs, const char* env, const char* suffix) +{ + const char* value = getenv(env); + if(!ffStrSet(value)) + return; - #define FF_ENSURE_ONLY_ONCE_IN_LIST(element) \ - if(ffListFirstIndexComp(&state->configDirs, element, (bool(*)(const void*, const void*))ffStrbufEqual) < state->configDirs.length - 1) \ - { \ - ffStrbufDestroy(ffListGet(&state->configDirs, state->configDirs.length - 1)); \ - --state->configDirs.length; \ - } + FFstrbuf* buffer = ffListAdd(dirs); + ffStrbufInitA(buffer, 64); + ffStrbufAppendS(buffer, value); + ffStrbufReplaceAllC(buffer, '\\', '/'); + ffStrbufEnsureEndsWithC(buffer, '/'); + ffStrbufAppendS(buffer, suffix); + ffStrbufEnsureEndsWithC(buffer, '/'); + FF_ENSURE_ONLY_ONCE_IN_LIST(dirs, buffer); +} +#endif - FFstrbuf* userConfigHome = ffListAdd(&state->configDirs); - ffStrbufInitA(userConfigHome, 64); - ffStrbufAppendS(userConfigHome, state->passwd->pw_dir); - ffStrbufAppendS(userConfigHome, "/.config/"); - FF_ENSURE_ONLY_ONCE_IN_LIST(userConfigHome) +void pathsAddHome(FFlist* dirs, FFstate* state, const char* suffix) +{ + FFstrbuf* buffer = (FFstrbuf*) ffListAdd(dirs); + ffStrbufInitA(buffer, 64); + ffStrbufAppendS(buffer, state->passwd->pw_dir); + ffStrbufAppendS(buffer, suffix); + ffStrbufEnsureEndsWithC(buffer, '/'); + FF_ENSURE_ONLY_ONCE_IN_LIST(dirs, buffer); +} - FFstrbuf* userHome = ffListAdd(&state->configDirs); - ffStrbufInitA(userHome, 64); - ffStrbufAppendS(userHome, state->passwd->pw_dir); - ffStrbufEnsureEndsWithC(userHome, '/'); - FF_ENSURE_ONLY_ONCE_IN_LIST(userHome) +void pathsAddAbsolute(FFlist* dirs, const char* path) +{ + FFstrbuf* buffer = (FFstrbuf*) ffListAdd(dirs); + ffStrbufInitA(buffer, 64); + ffStrbufAppendS(buffer, path); + ffStrbufEnsureEndsWithC(buffer, '/'); + FF_ENSURE_ONLY_ONCE_IN_LIST(dirs, buffer); +} - #ifdef _WIN32 - - if(getenv("MSYSTEM") && getenv("HOME")) - { - // We are in MSYS2 / Git Bash - - FFstrbuf* msysConfigHome = ffListAdd(&state->configDirs); - ffStrbufInitA(msysConfigHome, 64); - ffStrbufAppendS(msysConfigHome, getenv("HOME")); - ffStrbufReplaceAllC(msysConfigHome, '\\', '/'); - ffStrbufEnsureEndsWithC(msysConfigHome, '/'); - ffStrbufAppendS(msysConfigHome, ".config/"); - FF_ENSURE_ONLY_ONCE_IN_LIST(msysConfigHome) - - FFstrbuf* msysHome = ffListAdd(&state->configDirs); - ffStrbufInitA(msysHome, 64); - ffStrbufAppendS(msysHome, getenv("HOME")); - ffStrbufReplaceAllC(msysHome, '\\', '/'); - ffStrbufEnsureEndsWithC(msysHome, '/'); - FF_ENSURE_ONLY_ONCE_IN_LIST(msysHome) - } - - #endif - - #if !defined(_WIN32) && !defined(__APPLE__) - - FFstrbuf xdgConfigDirs; - ffStrbufInitA(&xdgConfigDirs, 64); - ffStrbufAppendS(&xdgConfigDirs, getenv("XDG_CONFIG_DIRS")); +void pathsAddEnv(FFlist* dirs, const char* env) +{ + FFstrbuf value; + ffStrbufInitA(&value, 64); + ffStrbufAppendS(&value, getenv(env)); uint32_t startIndex = 0; - while (startIndex < xdgConfigDirs.length) + while (startIndex < value.length) { - uint32_t colonIndex = ffStrbufNextIndexC(&xdgConfigDirs, startIndex, ':'); - xdgConfigDirs.chars[colonIndex] = '\0'; + uint32_t colonIndex = ffStrbufNextIndexC(&value, startIndex, ':'); + value.chars[colonIndex] = '\0'; - if(!ffStrSet(xdgConfigDirs.chars + startIndex)) + if(!ffStrSet(value.chars + startIndex)) { startIndex = colonIndex + 1; continue; } - FFstrbuf* buffer = (FFstrbuf*) ffListAdd(&state->configDirs); - ffStrbufInitA(buffer, 64); - ffStrbufAppendS(buffer, xdgConfigDirs.chars + startIndex); - ffStrbufEnsureEndsWithC(buffer, '/'); - FF_ENSURE_ONLY_ONCE_IN_LIST(buffer); + pathsAddAbsolute(dirs, value.chars + startIndex); startIndex = colonIndex + 1; } - ffStrbufDestroy(&xdgConfigDirs); - FFstrbuf* systemConfigHome = ffListAdd(&state->configDirs); - ffStrbufInitA(systemConfigHome, 64); - ffStrbufAppendS(systemConfigHome, FASTFETCH_TARGET_DIR_ETC"/xdg/"); - FF_ENSURE_ONLY_ONCE_IN_LIST(systemConfigHome) + ffStrbufDestroy(&value); +} +static void initConfigDirs(FFstate* state) +{ + ffListInit(&state->configDirs, sizeof(FFstrbuf)); + + #ifdef _WIN32 + pathsAddKnownFolder(&state->configDirs, &FOLDERID_RoamingAppData); + pathsAddKnownFolder(&state->configDirs, &FOLDERID_LocalAppData); + #elif defined(__APPLE__) + pathsAddHome(&state->configDirs, state, "/Library/Preferences/"); + #else + pathsAddEnv(&state->configDirs, "XDG_CONFIG_HOME"); #endif - #ifndef _WIN32 - - FFstrbuf* systemConfig = ffListAdd(&state->configDirs); - ffStrbufInitA(systemConfig, 64); - ffStrbufAppendS(systemConfig, FASTFETCH_TARGET_DIR_ETC"/"); - FF_ENSURE_ONLY_ONCE_IN_LIST(systemConfig) - - FFstrbuf* systemConfigInstall = ffListAdd(&state->configDirs); - ffStrbufInitA(systemConfigInstall, 64); - ffStrbufAppendS(systemConfigInstall, FASTFETCH_TARGET_DIR_INSTALL_SYSCONF"/"); - FF_ENSURE_ONLY_ONCE_IN_LIST(systemConfigInstall) - + pathsAddHome(&state->configDirs, state, "/.config/"); + pathsAddHome(&state->configDirs, state, ""); + #ifdef _WIN32 + if(getenv("MSYSTEM") && getenv("HOME")) + { + // We are in MSYS2 / Git Bash + pathsAddEnvSuffix(&state->configDirs, "HOME", ".config/"); + pathsAddEnvSuffix(&state->configDirs, "HOME", ""); + } #endif - #undef FF_ENSURE_ONLY_ONCE_IN_LIST + #if !defined(_WIN32) && !defined(__APPLE__) + pathsAddEnv(&state->configDirs, "XDG_CONFIG_DIRS"); + pathsAddAbsolute(&state->configDirs, FASTFETCH_TARGET_DIR_ETC"/xdg/"); + #endif + + #if !defined(_WIN32) + pathsAddAbsolute(&state->configDirs, FASTFETCH_TARGET_DIR_ETC"/"); + pathsAddAbsolute(&state->configDirs, FASTFETCH_TARGET_DIR_INSTALL_SYSCONF"/"); + #endif +} + +static void initDataDirs(FFstate* state) +{ + ffListInit(&state->dataDirs, sizeof(FFstrbuf)); + + #ifdef _WIN32 + pathsAddKnownFolder(&state->dataDirs, &FOLDERID_RoamingAppData); + pathsAddKnownFolder(&state->dataDirs, &FOLDERID_LocalAppData); + #elif defined(__APPLE__) + pathsAddHome(&state->dataDirs, state, "/Library/Application Support/"); + #else + pathsAddEnv(&state->dataDirs, "XDG_DATA_HOME"); + #endif + + pathsAddHome(&state->dataDirs, state, "/.local/share/"); + pathsAddHome(&state->dataDirs, state, ""); + + #ifdef _WIN32 + if(getenv("MSYSTEM") && getenv("HOME")) + { + // We are in MSYS2 / Git Bash + pathsAddEnvSuffix(&state->dataDirs, "HOME", ".local/share/"); + pathsAddEnvSuffix(&state->dataDirs, "HOME", ""); + } + #endif + + #if !defined(_WIN32) && !defined(__APPLE__) + pathsAddEnv(&state->dataDirs, "XDG_DATA_DIRS"); + #endif + + #if !defined(_WIN32) + pathsAddAbsolute(&state->dataDirs, FASTFETCH_TARGET_DIR_USR"/local/share/"); + pathsAddAbsolute(&state->dataDirs, FASTFETCH_TARGET_DIR_USR"/share/"); + #endif } static void initState(FFstate* state) @@ -172,6 +192,7 @@ static void initState(FFstate* state) uname(&state->utsname); initConfigDirs(state); + initDataDirs(state); } static void initModuleArg(FFModuleArgs* args) diff --git a/src/common/properties.c b/src/common/properties.c index 064d620aa..c2038be6b 100644 --- a/src/common/properties.c +++ b/src/common/properties.c @@ -144,11 +144,6 @@ done: return true; } -bool ffParsePropFile(const char* filename, const char* start, FFstrbuf* buffer) -{ - return ffParsePropFileValues(filename, 1, (FFpropquery[]){{start, buffer}}); -} - bool ffParsePropFileHomeValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries) { FFstrbuf absolutePath; @@ -164,22 +159,17 @@ bool ffParsePropFileHomeValues(const FFinstance* instance, const char* relativeF return result; } -bool ffParsePropFileHome(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer) -{ - return ffParsePropFileHomeValues(instance, relativeFile, 1, (FFpropquery[]){{start, buffer}}); -} - -bool ffParsePropFileConfigValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries) +bool ffParsePropFileListValues(const FFlist* list, const char* relativeFile, uint32_t numQueries, FFpropquery* queries) { bool foundAFile = false; FFstrbuf baseDir; ffStrbufInitA(&baseDir, 64); - for(uint32_t i = 0; i < instance->state.configDirs.length; i++) + for(uint32_t i = 0; i < list->length; i++) { - //We need to copy the config dir each time, because it used by multiple threads, so we can't directly write to it. - ffStrbufSet(&baseDir, ffListGet(&instance->state.configDirs, i)); + //We need to copy the dir each time, because it used by multiple threads, so we can't directly write to it. + ffStrbufSet(&baseDir, ffListGet(list, i)); ffStrbufAppendS(&baseDir, relativeFile); if(ffParsePropFileValues(baseDir.chars, numQueries, queries)) @@ -203,8 +193,3 @@ bool ffParsePropFileConfigValues(const FFinstance* instance, const char* relativ return foundAFile; } - -bool ffParsePropFileConfig(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer) -{ - return ffParsePropFileConfigValues(instance, relativeFile, 1, (FFpropquery[]){{start, buffer}}); -} diff --git a/src/common/properties.h b/src/common/properties.h index dfdcad96e..f10f7caaf 100644 --- a/src/common/properties.h +++ b/src/common/properties.h @@ -14,10 +14,42 @@ typedef struct FFpropquery bool ffParsePropLine(const char* line, const char* start, FFstrbuf* buffer); bool ffParsePropLines(const char* lines, const char* start, FFstrbuf* buffer); bool ffParsePropFileValues(const char* filename, uint32_t numQueries, FFpropquery* queries); -bool ffParsePropFile(const char* filename, const char* start, FFstrbuf* buffer); bool ffParsePropFileHomeValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries); -bool ffParsePropFileHome(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer); -bool ffParsePropFileConfigValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries); -bool ffParsePropFileConfig(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer); +bool ffParsePropFileListValues(const FFlist* list, const char* relativeFile, uint32_t numQueries, FFpropquery* queries); + +static inline bool ffParsePropFile(const char* filename, const char* start, FFstrbuf* buffer) +{ + return ffParsePropFileValues(filename, 1, (FFpropquery[]){{start, buffer}}); +} + +static inline bool ffParsePropFileHome(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer) +{ + return ffParsePropFileHomeValues(instance, relativeFile, 1, (FFpropquery[]){{start, buffer}}); +} + +static inline bool ffParsePropFileList(const FFlist* list, const char* relativeFile, const char* start, FFstrbuf* buffer) +{ + return ffParsePropFileListValues(list, relativeFile, 1, (FFpropquery[]){{start, buffer}}); +} + +static inline bool ffParsePropFileConfigValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries) +{ + return ffParsePropFileListValues(&instance->state.configDirs, relativeFile, numQueries, queries); +} + +static inline bool ffParsePropFileConfig(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer) +{ + return ffParsePropFileConfigValues(instance, relativeFile, 1, (FFpropquery[]){{start, buffer}}); +} + +static inline bool ffParsePropFileDataValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries) +{ + return ffParsePropFileListValues(&instance->state.dataDirs, relativeFile, numQueries, queries); +} + +static inline bool ffParsePropFileData(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer) +{ + return ffParsePropFileDataValues(instance, relativeFile, 1, (FFpropquery[]){{start, buffer}}); +} #endif diff --git a/src/data/help.txt b/src/data/help.txt index ec2086cc3..6b6d39aea 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -5,6 +5,7 @@ Informative options: -h,--help : Show help for a specific command -v,--version: Show the version of fastfetch --list-config-paths: List search paths of config files + --list-data-paths: List search paths of presets and logos --list-logos: List available logos --list-modules: List available modules --list-presets: List presets fastfetch knows about; they can be loaded with --load-config (+) diff --git a/src/detection/cursor/cursor_linux.c b/src/detection/cursor/cursor_linux.c index a8dfb8810..09db53ed4 100644 --- a/src/detection/cursor/cursor_linux.c +++ b/src/detection/cursor/cursor_linux.c @@ -73,7 +73,7 @@ static bool detectCursorFromXDG(const FFinstance* instance, bool user, FFCursorR if(user) ffParsePropFileHome(instance, ".icons/default/index.theme", "Inherits =", &result->theme); else - ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/icons/default/index.theme", "Inherits =", &result->theme); + ffParsePropFileData(instance, "icons/default/index.theme", "Inherits =", &result->theme); return result->theme.length > 0; } diff --git a/src/detection/displayserver/linux/wmde.c b/src/detection/displayserver/linux/wmde.c index 0cb7c7493..3f564bfb6 100644 --- a/src/detection/displayserver/linux/wmde.c +++ b/src/detection/displayserver/linux/wmde.c @@ -116,38 +116,34 @@ static void applyBetterWM(FFDisplayServerResult* result, const char* processName ffStrbufAppend(&result->wmPrettyName, &result->wmProcessName); } -static void getKDE(FFDisplayServerResult* result) +static void getKDE(const FFinstance* instance, FFDisplayServerResult* result) { ffStrbufSetS(&result->deProcessName, "plasmashell"); ffStrbufSetS(&result->dePrettyName, "KDE Plasma"); - ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/xsessions/plasma.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion); + ffParsePropFileData(instance, "xsessions/plasma.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion); if(result->deVersion.length == 0) - ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/xsessions/plasma5.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion); + ffParsePropFileData(instance, "xsessions/plasma5.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion); if(result->deVersion.length == 0) - ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/wayland-sessions/plasmawayland.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion); + ffParsePropFileData(instance, "wayland-sessions/plasmawayland.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion); if(result->deVersion.length == 0) - ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/wayland-sessions/plasmawayland5.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion); - if(result->deVersion.length == 0) - ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/local/share/xsessions/plasma.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion); - if(result->deVersion.length == 0) - ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/local/share/wayland-sessions/plasmawayland.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion); + ffParsePropFileData(instance, "wayland-sessions/plasmawayland5.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion); applyBetterWM(result, getenv("KDEWM")); } -static void getGnome(FFDisplayServerResult* result) +static void getGnome(const FFinstance* instance, FFDisplayServerResult* result) { ffStrbufSetS(&result->deProcessName, "gnome-shell"); ffStrbufSetS(&result->dePrettyName, "GNOME"); - ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/gnome-shell/org.gnome.Extensions", "version :", &result->deVersion); + ffParsePropFileData(instance, "gnome-shell/org.gnome.Extensions", "version :", &result->deVersion); } -static void getCinnamon(FFDisplayServerResult* result) +static void getCinnamon(const FFinstance* instance, FFDisplayServerResult* result) { ffStrbufSetS(&result->deProcessName, "cinnamon"); ffStrbufSetS(&result->dePrettyName, "Cinnamon"); - ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/applications/cinnamon.desktop", "X-GNOME-Bugzilla-Version =", &result->deVersion); + ffParsePropFileData(instance, "applications/cinnamon.desktop", "X-GNOME-Bugzilla-Version =", &result->deVersion); } static void getMate(const FFinstance* instance, FFDisplayServerResult* result) @@ -164,7 +160,7 @@ static void getMate(const FFinstance* instance, FFDisplayServerResult* result) FFstrbuf micro; ffStrbufInit(µ); - ffParsePropFileValues(FASTFETCH_TARGET_DIR_USR"/share/mate-about/mate-version.xml", 3, (FFpropquery[]) { + ffParsePropFileDataValues(instance, "mate-about/mate-version.xml", 3, (FFpropquery[]) { {"", &major}, {"", &minor}, {"", µ} @@ -193,7 +189,7 @@ static void getXFCE4(const FFinstance* instance, FFDisplayServerResult* result) { ffStrbufSetS(&result->deProcessName, "xfce4-session"); ffStrbufSetS(&result->dePrettyName, "Xfce4"); - ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/gtk-doc/html/libxfce4ui/index.html", "

Version", &result->deVersion); + ffParsePropFileData(instance, "gtk-doc/html/libxfce4ui/index.html", "

Version", &result->deVersion); if(result->deVersion.length == 0 && instance->config.allowSlowOperations) { @@ -214,12 +210,12 @@ static void getLXQt(const FFinstance* instance, FFDisplayServerResult* result) { ffStrbufSetS(&result->deProcessName, "lxqt-session"); ffStrbufSetS(&result->dePrettyName, "LXQt"); - ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/lib/pkgconfig/lxqt.pc", "Version:", &result->deVersion); + ffParsePropFileData(instance, "gconfig/lxqt.pc", "Version:", &result->deVersion); if(result->deVersion.length == 0) - ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/cmake/lxqt/lxqt-config.cmake", "set ( LXQT_VERSION", &result->deVersion); + ffParsePropFileData(instance, "cmake/lxqt/lxqt-config.cmake", "set ( LXQT_VERSION", &result->deVersion); if(result->deVersion.length == 0) - ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/cmake/lxqt/lxqt-config-version.cmake", "set ( PACKAGE_VERSION", &result->deVersion); + ffParsePropFileData(instance, "cmake/lxqt/lxqt-config-version.cmake", "set ( PACKAGE_VERSION", &result->deVersion); if(result->deVersion.length == 0 && instance->config.allowSlowOperations) { @@ -253,19 +249,19 @@ static void applyPrettyNameIfDE(const FFinstance* instance, FFDisplayServerResul strcasecmp(name, "plasma") == 0 || strcasecmp(name, "plasmashell") == 0 || strcasecmp(name, "plasmawayland") == 0 - ) getKDE(result); + ) getKDE(instance, result); else if( strcasecmp(name, "Gnome") == 0 || strcasecmp(name, "ubuntu:GNOME") == 0 || strcasecmp(name, "ubuntu") == 0 || strcasecmp(name, "gnome-shell") == 0 - ) getGnome(result); + ) getGnome(instance, result); else if( strcasecmp(name, "X-Cinnamon") == 0 || strcasecmp(name, "Cinnamon") == 0 - ) getCinnamon(result); + ) getCinnamon(instance, result); else if( strcasecmp(name, "XFCE") == 0 || diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 50580a898..5877f6176 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -58,7 +58,7 @@ static void pciDetectVendorName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA); } -static void drmDetectDeviceName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device) +static void drmDetectDeviceName(const FFinstance* instance, FFGPUResult* gpu, PCIData* pci, struct pci_dev* device) { u8 revId; bool revIdSet = false;; @@ -82,7 +82,7 @@ static void drmDetectDeviceName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* ffStrbufInit(&query); ffStrbufAppendF(&query, "%X, %X,", device->device_id, revId); - ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/libdrm/amdgpu.ids", query.chars, &gpu->name); + ffParsePropFileData(instance, "libdrm/amdgpu.ids", query.chars, &gpu->name); ffStrbufDestroy(&query); @@ -94,11 +94,11 @@ static void drmDetectDeviceName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* ffStrbufRemoveStringsA(&gpu->name, sizeof(removeStrings) / sizeof(removeStrings[0]), removeStrings); } -static void pciDetectDeviceName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device) +static void pciDetectDeviceName(const FFinstance* instance, FFGPUResult* gpu, PCIData* pci, struct pci_dev* device) { if(ffStrbufCompS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD) == 0) { - drmDetectDeviceName(gpu, pci, device); + drmDetectDeviceName(instance, gpu, pci, device); if(gpu->name.length > 0) return; } @@ -188,7 +188,7 @@ static void pciHandleDevice(const FFinstance* instance, FFlist* results, PCIData pciDetectVendorName(gpu, pci, device); ffStrbufInit(&gpu->name); - pciDetectDeviceName(gpu, pci, device); + pciDetectDeviceName(instance, gpu, pci, device); ffStrbufInit(&gpu->driver); pciDetectDriverName(gpu, pci, device); diff --git a/src/detection/terminalfont/terminalfont_linux.c b/src/detection/terminalfont/terminalfont_linux.c index 54ea3a328..8eb90e7c5 100644 --- a/src/detection/terminalfont/terminalfont_linux.c +++ b/src/detection/terminalfont/terminalfont_linux.c @@ -88,15 +88,15 @@ static void detectKonsole(const FFinstance* instance, FFTerminalFontResult* term } FFstrbuf profilePath; - ffStrbufInitA(&profilePath, 64); - ffStrbufAppendS(&profilePath, ".local/share/konsole/"); + ffStrbufInitA(&profilePath, 32); + ffStrbufAppendS(&profilePath, "konsole/"); ffStrbufAppend(&profilePath, &profile); ffStrbufDestroy(&profile); FFstrbuf fontName; ffStrbufInit(&fontName); - ffParsePropFileHome(instance, profilePath.chars, "Font =", &fontName); + ffParsePropFileData(instance, profilePath.chars, "Font =", &fontName); if(fontName.length == 0) ffStrbufAppendF(&terminalFont->error, "Couldn't find \"Font=%%[^\\n]\" in \"%s\"", profilePath.chars); diff --git a/src/fastfetch.c b/src/fastfetch.c index 326e081b0..8de17b9f0 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -526,17 +526,11 @@ static inline void listAvailablePresetsFromFolder(FFstrbuf* folder, uint8_t inde static inline void listAvailablePresets(FFinstance* instance) { - FFstrbuf folder; - ffStrbufInitA(&folder, 64); - - ffStrbufSetS(&folder, instance->state.passwd->pw_dir); - ffStrbufAppendS(&folder, "/.local/share/fastfetch/presets/"); - listAvailablePresetsFromFolder(&folder, 0, NULL); - - ffStrbufSetS(&folder, FASTFETCH_TARGET_DIR_USR"/share/fastfetch/presets/"); - listAvailablePresetsFromFolder(&folder, 0, NULL); - - ffStrbufDestroy(&folder); + FF_LIST_FOR_EACH(FFstrbuf, path, instance->state.dataDirs) + { + ffStrbufAppendS(path, "fastfetch/presets/"); + listAvailablePresetsFromFolder(path, 0, NULL); + } } static void listConfigPaths(FFinstance* instance) @@ -548,6 +542,15 @@ static void listConfigPaths(FFinstance* instance) } } +static void listDataPaths(FFinstance* instance) +{ + FF_LIST_FOR_EACH(FFstrbuf, folder, instance->state.dataDirs) + { + ffStrbufAppendS(folder, "fastfetch/"); + puts(folder->chars); + } +} + static void parseOption(FFinstance* instance, FFdata* data, const char* key, const char* value); static bool parseConfigFile(FFinstance* instance, FFdata* data, const char* path) @@ -645,37 +648,26 @@ static void optionParseConfigFile(FFinstance* instance, FFdata* data, const char if(parseConfigFile(instance, data, value)) return; - //Try to load as an user preset + //Try to load as a relative path - FFstrbuf filename; - ffStrbufInitA(&filename, 64); - - ffStrbufAppendS(&filename, instance->state.passwd->pw_dir); - ffStrbufAppendS(&filename, "/.local/share/fastfetch/presets/"); - ffStrbufAppendS(&filename, value); - - if(parseConfigFile(instance, data, filename.chars)) + FF_LIST_FOR_EACH(FFstrbuf, path, instance->state.dataDirs) { - ffStrbufDestroy(&filename); - return; - } + uint32_t pathLength = path->length; + ffStrbufAppendS(path, "fastfetch/presets/"); + ffStrbufAppendS(path, value); - //Try to load as a system preset + bool success = parseConfigFile(instance, data, path->chars); - ffStrbufSetS(&filename, FASTFETCH_TARGET_DIR_USR"/share/fastfetch/presets/"); - ffStrbufAppendS(&filename, value); + ffStrbufSubstrBefore(path, pathLength); - if(parseConfigFile(instance, data, filename.chars)) - { - ffStrbufDestroy(&filename); - return; + if(success) + return; } //File not found fprintf(stderr, "Error: couldn't find config: %s\n", value); - ffStrbufDestroy(&filename); exit(414); } @@ -917,6 +909,11 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con listConfigPaths(instance); exit(0); } + else if(strcasecmp(subkey, "-data-paths") == 0) + { + listDataPaths(instance); + exit(0); + } else if(strcasecmp(subkey, "-features") == 0) { ffListFeatures(); diff --git a/src/fastfetch.h b/src/fastfetch.h index 1f8782a3e..fa1b11d09 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -211,7 +211,8 @@ typedef struct FFstate struct passwd* passwd; struct utsname utsname; - FFlist configDirs; + FFlist configDirs; // List of FFstrbuf, trailing slash included + FFlist dataDirs; // List of FFstrbuf, trailing slash included } FFstate; typedef struct FFinstance From b1c0a2dc1e64195ec04dd493c19ec5da4898d021 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Sun, 8 Jan 2023 11:32:43 +0100 Subject: [PATCH 027/142] Better init of config & data dirs --- src/common/init.c | 97 ++++++++++++++++++++++++----------------------- 1 file changed, 50 insertions(+), 47 deletions(-) diff --git a/src/common/init.c b/src/common/init.c index 8c526e909..bff2a643d 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -25,40 +25,7 @@ --list->length; \ } -#ifdef _WIN32 -void pathsAddKnownFolder(FFlist* dirs, REFKNOWNFOLDERID folderId) -{ - PWSTR pPath; - if(SUCCEEDED(SHGetKnownFolderPath(folderId, 0, NULL, &pPath))) - { - FFstrbuf* buffer = (FFstrbuf*) ffListAdd(dirs); - ffStrbufInit(buffer); - ffStrbufSetWS(buffer, pPath); - ffStrbufReplaceAllC(buffer, '\\', '/'); - ffStrbufEnsureEndsWithC(buffer, '/'); - FF_ENSURE_ONLY_ONCE_IN_LIST(dirs, buffer); - } - CoTaskMemFree(pPath); -} - -void pathsAddEnvSuffix(FFlist* dirs, const char* env, const char* suffix) -{ - const char* value = getenv(env); - if(!ffStrSet(value)) - return; - - FFstrbuf* buffer = ffListAdd(dirs); - ffStrbufInitA(buffer, 64); - ffStrbufAppendS(buffer, value); - ffStrbufReplaceAllC(buffer, '\\', '/'); - ffStrbufEnsureEndsWithC(buffer, '/'); - ffStrbufAppendS(buffer, suffix); - ffStrbufEnsureEndsWithC(buffer, '/'); - FF_ENSURE_ONLY_ONCE_IN_LIST(dirs, buffer); -} -#endif - -void pathsAddHome(FFlist* dirs, FFstate* state, const char* suffix) +static void pathsAddHome(FFlist* dirs, FFstate* state, const char* suffix) { FFstrbuf* buffer = (FFstrbuf*) ffListAdd(dirs); ffStrbufInitA(buffer, 64); @@ -68,7 +35,7 @@ void pathsAddHome(FFlist* dirs, FFstate* state, const char* suffix) FF_ENSURE_ONLY_ONCE_IN_LIST(dirs, buffer); } -void pathsAddAbsolute(FFlist* dirs, const char* path) +static void pathsAddAbsolute(FFlist* dirs, const char* path) { FFstrbuf* buffer = (FFstrbuf*) ffListAdd(dirs); ffStrbufInitA(buffer, 64); @@ -77,11 +44,15 @@ void pathsAddAbsolute(FFlist* dirs, const char* path) FF_ENSURE_ONLY_ONCE_IN_LIST(dirs, buffer); } -void pathsAddEnv(FFlist* dirs, const char* env) +static void pathsAddEnv(FFlist* dirs, const char* env) { + const char* envValue = getenv(env); + if(!ffStrSet(envValue)) + return; + FFstrbuf value; ffStrbufInitA(&value, 64); - ffStrbufAppendS(&value, getenv(env)); + ffStrbufAppendS(&value, envValue); uint32_t startIndex = 0; while (startIndex < value.length) @@ -103,20 +74,53 @@ void pathsAddEnv(FFlist* dirs, const char* env) ffStrbufDestroy(&value); } +#ifdef _WIN32 +static void pathsAddKnownFolder(FFlist* dirs, REFKNOWNFOLDERID folderId) +{ + PWSTR pPath; + if(SUCCEEDED(SHGetKnownFolderPath(folderId, 0, NULL, &pPath))) + { + FFstrbuf* buffer = (FFstrbuf*) ffListAdd(dirs); + ffStrbufInit(buffer); + ffStrbufSetWS(buffer, pPath); + ffStrbufReplaceAllC(buffer, '\\', '/'); + ffStrbufEnsureEndsWithC(buffer, '/'); + FF_ENSURE_ONLY_ONCE_IN_LIST(dirs, buffer); + } + CoTaskMemFree(pPath); +} + +static void pathsAddEnvSuffix(FFlist* dirs, const char* env, const char* suffix) +{ + const char* value = getenv(env); + if(!ffStrSet(value)) + return; + + FFstrbuf* buffer = ffListAdd(dirs); + ffStrbufInitA(buffer, 64); + ffStrbufAppendS(buffer, value); + ffStrbufReplaceAllC(buffer, '\\', '/'); + ffStrbufEnsureEndsWithC(buffer, '/'); + ffStrbufAppendS(buffer, suffix); + ffStrbufEnsureEndsWithC(buffer, '/'); + FF_ENSURE_ONLY_ONCE_IN_LIST(dirs, buffer); +} +#endif + static void initConfigDirs(FFstate* state) { ffListInit(&state->configDirs, sizeof(FFstrbuf)); + pathsAddEnv(&state->configDirs, "XDG_CONFIG_HOME"); // On systems where this is not set (Windows & Apple presumably), this wil do nothing + pathsAddHome(&state->configDirs, state, "/.config/"); + #ifdef _WIN32 pathsAddKnownFolder(&state->configDirs, &FOLDERID_RoamingAppData); pathsAddKnownFolder(&state->configDirs, &FOLDERID_LocalAppData); #elif defined(__APPLE__) pathsAddHome(&state->configDirs, state, "/Library/Preferences/"); - #else - pathsAddEnv(&state->configDirs, "XDG_CONFIG_HOME"); #endif - pathsAddHome(&state->configDirs, state, "/.config/"); pathsAddHome(&state->configDirs, state, ""); #ifdef _WIN32 @@ -128,8 +132,9 @@ static void initConfigDirs(FFstate* state) } #endif + pathsAddEnv(&state->configDirs, "XDG_CONFIG_DIRS"); + #if !defined(_WIN32) && !defined(__APPLE__) - pathsAddEnv(&state->configDirs, "XDG_CONFIG_DIRS"); pathsAddAbsolute(&state->configDirs, FASTFETCH_TARGET_DIR_ETC"/xdg/"); #endif @@ -143,16 +148,16 @@ static void initDataDirs(FFstate* state) { ffListInit(&state->dataDirs, sizeof(FFstrbuf)); + pathsAddEnv(&state->dataDirs, "XDG_DATA_HOME"); // On systems where this is not set (Windows & Apple presumably), this wil do nothing + pathsAddHome(&state->dataDirs, state, "/.local/share/"); + #ifdef _WIN32 pathsAddKnownFolder(&state->dataDirs, &FOLDERID_RoamingAppData); pathsAddKnownFolder(&state->dataDirs, &FOLDERID_LocalAppData); #elif defined(__APPLE__) pathsAddHome(&state->dataDirs, state, "/Library/Application Support/"); - #else - pathsAddEnv(&state->dataDirs, "XDG_DATA_HOME"); #endif - pathsAddHome(&state->dataDirs, state, "/.local/share/"); pathsAddHome(&state->dataDirs, state, ""); #ifdef _WIN32 @@ -164,9 +169,7 @@ static void initDataDirs(FFstate* state) } #endif - #if !defined(_WIN32) && !defined(__APPLE__) - pathsAddEnv(&state->dataDirs, "XDG_DATA_DIRS"); - #endif + pathsAddEnv(&state->dataDirs, "XDG_DATA_DIRS"); #if !defined(_WIN32) pathsAddAbsolute(&state->dataDirs, FASTFETCH_TARGET_DIR_USR"/local/share/"); From 1bbcd9ad0ddc94a1b3a226395e3a9d430535a5fa Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Sun, 8 Jan 2023 12:30:36 +0100 Subject: [PATCH 028/142] Look for logo files in /fastfetch/logos/ too #375 --- src/logo/logo.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/logo/logo.c b/src/logo/logo.c index e460ba55e..dd9f7ddd5 100644 --- a/src/logo/logo.c +++ b/src/logo/logo.c @@ -285,12 +285,38 @@ static void logoPrintData(FFinstance* instance, bool doColorReplacement) { logoApplyColorsDetected(instance); } +static bool loadLogoFile(const FFinstance* instance, FFstrbuf* buffer) +{ + if(ffAppendFileBuffer(instance->config.logo.source.chars, buffer)) + return true; + + FFstrbuf fullPath; + ffStrbufInit(&fullPath); + + FF_LIST_FOR_EACH(FFstrbuf, dataDir, instance->state.dataDirs) + { + //We need to copy it, because multiple threads might be using dataDirs at the same time + ffStrbufSet(&fullPath, dataDir); + ffStrbufAppendS(&fullPath, "fastfetch/logos/"); + ffStrbufAppend(&fullPath, &instance->config.logo.source); + + if(ffAppendFileBuffer(fullPath.chars, buffer)) + { + ffStrbufDestroy(&fullPath); + return true; + } + } + + ffStrbufDestroy(&fullPath); + return false; +} + static bool logoPrintFileIfExists(FFinstance* instance, bool doColorReplacement, bool raw) { FFstrbuf content; ffStrbufInit(&content); - if(!ffAppendFileBuffer(instance->config.logo.source.chars, &content)) + if(!loadLogoFile(instance, &content)) { ffStrbufDestroy(&content); fputs("Logo: Failed to load file content from logo source\n", stderr); From 9f8e256bb4f46cf93285f74541e27563d8f74666 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 8 Jan 2023 20:46:22 +0800 Subject: [PATCH 029/142] DisplayServer: support brightness detection (Linux) --- .../displayserver/linux/displayserver_linux.c | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/detection/displayserver/linux/displayserver_linux.c b/src/detection/displayserver/linux/displayserver_linux.c index 3f6fd04eb..51639f9e8 100644 --- a/src/detection/displayserver/linux/displayserver_linux.c +++ b/src/detection/displayserver/linux/displayserver_linux.c @@ -1,7 +1,56 @@ #include "displayserver_linux.h" +#include "common/io.h" #include +static void parseBacklight(FFDisplayServerResult* result) +{ + if(result->resolutions.length != 1) + return; + + //https://www.kernel.org/doc/Documentation/ABI/stable/sysfs-class-backlight + const char* backlightDirPath = "/sys/class/backlight/"; + + DIR* dirp = opendir(backlightDirPath); + if(dirp == NULL) + return; + + FFstrbuf backlightDir; + ffStrbufInitA(&backlightDir, 64); + ffStrbufAppendS(&backlightDir, backlightDirPath); + + uint32_t backlightDirLength = backlightDir.length; + + FFstrbuf buffer; + ffStrbufInit(&buffer); + + struct dirent* entry; + if((entry = readdir(dirp)) != NULL) + { + ffStrbufAppendS(&backlightDir, entry->d_name); + ffStrbufAppendS(&backlightDir, "/actual_brightness"); + if(ffReadFileBuffer(backlightDir.chars, &buffer)) + { + double actualBrightness = ffStrbufToDouble(&buffer); + ffStrbufSubstrBefore(&backlightDir, backlightDirLength); + + ffStrbufAppendS(&backlightDir, "/max_brightness"); + if(ffReadFileBuffer(backlightDir.chars, &buffer)) + { + double maxBrightness = ffStrbufToDouble(&buffer); + FF_LIST_FOR_EACH(FFResolutionResult, resolution, result->resolutions) + { + resolution->brightness = (int) (actualBrightness * 100 / maxBrightness); + } + } + } + } + + closedir(dirp); + ffStrbufDestroy(&backlightDir); + ffStrbufDestroy(&buffer); +} + static void parseDRM(FFDisplayServerResult* result) { const char* drmDirPath = "/sys/class/drm/"; @@ -83,4 +132,6 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* ins //This fills in missing information about WM / DE by using env vars and iterating processes ffdsDetectWMDE(instance, ds); + + parseBacklight(ds); } From 4daf3016f80e5a37ee3cebb21fc12b0f3ec9f670 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 9 Jan 2023 10:02:31 +0800 Subject: [PATCH 030/142] Global: fix memleaks --- src/common/init.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/common/init.c b/src/common/init.c index bff2a643d..3cf2287bd 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -554,9 +554,13 @@ static void destroyConfig(FFinstance* instance) static void destroyState(FFinstance* instance) { - for(uint32_t i = 0; i < instance->state.configDirs.length; ++i) - ffStrbufDestroy((FFstrbuf*)ffListGet(&instance->state.configDirs, i)); + FF_LIST_FOR_EACH(FFstrbuf, configDir, instance->state.configDirs) + ffStrbufDestroy(configDir); ffListDestroy(&instance->state.configDirs); + + FF_LIST_FOR_EACH(FFstrbuf, dataDir, instance->state.dataDirs) + ffStrbufDestroy(dataDir); + ffListDestroy(&instance->state.dataDirs); } void ffDestroyInstance(FFinstance* instance) From 0b12e73eefe9289456fd0380324212a01efe8966 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 9 Jan 2023 10:42:52 +0800 Subject: [PATCH 031/142] DisplayServer: make brightness detection actually work (Linux) --- src/detection/displayserver/linux/displayserver_linux.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/detection/displayserver/linux/displayserver_linux.c b/src/detection/displayserver/linux/displayserver_linux.c index 51639f9e8..f2e0910b1 100644 --- a/src/detection/displayserver/linux/displayserver_linux.c +++ b/src/detection/displayserver/linux/displayserver_linux.c @@ -25,15 +25,18 @@ static void parseBacklight(FFDisplayServerResult* result) ffStrbufInit(&buffer); struct dirent* entry; - if((entry = readdir(dirp)) != NULL) + while((entry = readdir(dirp)) != NULL) { + if(strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + ffStrbufAppendS(&backlightDir, entry->d_name); ffStrbufAppendS(&backlightDir, "/actual_brightness"); if(ffReadFileBuffer(backlightDir.chars, &buffer)) { double actualBrightness = ffStrbufToDouble(&buffer); ffStrbufSubstrBefore(&backlightDir, backlightDirLength); - + ffStrbufAppendS(&backlightDir, entry->d_name); ffStrbufAppendS(&backlightDir, "/max_brightness"); if(ffReadFileBuffer(backlightDir.chars, &buffer)) { @@ -43,6 +46,8 @@ static void parseBacklight(FFDisplayServerResult* result) resolution->brightness = (int) (actualBrightness * 100 / maxBrightness); } } + + break; } } From 0fd63084dc35cefa6a6e2eb1cddbc58e546bbc15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 9 Jan 2023 10:45:51 +0800 Subject: [PATCH 032/142] Global: fix other possible bugs where enumerating directories without ignoring `.` and `..` --- src/detection/battery/battery_linux.c | 3 +++ src/detection/displayserver/linux/displayserver_linux.c | 3 +++ src/detection/packages/packages_linux.c | 2 ++ 3 files changed, 8 insertions(+) diff --git a/src/detection/battery/battery_linux.c b/src/detection/battery/battery_linux.c index 6fe799eb0..756dd9c8a 100644 --- a/src/detection/battery/battery_linux.c +++ b/src/detection/battery/battery_linux.c @@ -99,6 +99,9 @@ const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results) { struct dirent* entry; while((entry = readdir(dirp)) != NULL) { + if(strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + ffStrbufAppendS(&baseDir, entry->d_name); parseBattery(&baseDir, results); ffStrbufSubstrBefore(&baseDir, baseDirLength); diff --git a/src/detection/displayserver/linux/displayserver_linux.c b/src/detection/displayserver/linux/displayserver_linux.c index f2e0910b1..d64128a39 100644 --- a/src/detection/displayserver/linux/displayserver_linux.c +++ b/src/detection/displayserver/linux/displayserver_linux.c @@ -73,6 +73,9 @@ static void parseDRM(FFDisplayServerResult* result) struct dirent* entry; while((entry = readdir(dirp)) != NULL) { + if(strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + ffStrbufAppendS(&drmDir, entry->d_name); ffStrbufAppendS(&drmDir, "/modes"); diff --git a/src/detection/packages/packages_linux.c b/src/detection/packages/packages_linux.c index f4b363d54..cd5babf65 100644 --- a/src/detection/packages/packages_linux.c +++ b/src/detection/packages/packages_linux.c @@ -309,6 +309,8 @@ static void getPackageCountsBedrock(const FFinstance* instance, FFstrbuf* baseDi { if(entry->d_type != DT_DIR) continue; + if(strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; ffStrbufAppendS(baseDir, entry->d_name); getPackageCounts(instance, baseDir, packageCounts); From 012c7552eb4e88ad2eec6c4f085c32567e2bf368 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 9 Jan 2023 13:42:58 +0800 Subject: [PATCH 033/142] macOS: try fixing #380 --- src/logo/image/image.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/logo/image/image.c b/src/logo/image/image.c index 26c51f1a3..171809278 100644 --- a/src/logo/image/image.c +++ b/src/logo/image/image.c @@ -2,6 +2,10 @@ #include "common/io.h" #include "common/printing.h" +#ifdef __APPLE__ + #include +#endif + static FFstrbuf base64Encode(FFstrbuf* in) { const char* base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; From ef18c8e3f7cee85841344b56cf2b72f0d05ed3e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 9 Jan 2023 14:03:46 +0800 Subject: [PATCH 034/142] Users: remove `"wtsapi32_extend"` as mingw_w64 now officially supports these APIs Ref: https://github.com/mirror/mingw-w64/commit/931ca20b233e766950e7758cff71c270937b0b64 --- src/detection/users/users_windows.c | 1 - src/detection/users/wtsapi32_extend.h | 45 --------------------------- 2 files changed, 46 deletions(-) delete mode 100644 src/detection/users/wtsapi32_extend.h diff --git a/src/detection/users/users_windows.c b/src/detection/users/users_windows.c index 7ed1c70fa..5c78cfdd7 100644 --- a/src/detection/users/users_windows.c +++ b/src/detection/users/users_windows.c @@ -2,7 +2,6 @@ #include "util/windows/unicode.h" #include -#include "wtsapi32_extend.h" void ffDetectUsers(FFlist* users, FFstrbuf* error) { diff --git a/src/detection/users/wtsapi32_extend.h b/src/detection/users/wtsapi32_extend.h deleted file mode 100644 index 5c89beb2f..000000000 --- a/src/detection/users/wtsapi32_extend.h +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -//at the time of writing, of MinGW doesn't have the definition of WTSEnumerateSessionsExW and friends - -#if (_WIN32_WINNT >= 0x0601) - -typedef struct _WTS_SESSION_INFO_1A { - DWORD ExecEnvId; - WTS_CONNECTSTATE_CLASS State; - DWORD SessionId; - LPSTR pSessionName; - LPSTR pHostName; - LPSTR pUserName; - LPSTR pDomainName; - LPSTR pFarmName; -} WTS_SESSION_INFO_1A, *PWTS_SESSION_INFO_1A; - -typedef struct _WTS_SESSION_INFO_1W { - DWORD ExecEnvId; - WTS_CONNECTSTATE_CLASS State; - DWORD SessionId; - LPWSTR pSessionName; - LPWSTR pHostName; - LPWSTR pUserName; - LPWSTR pDomainName; - LPWSTR pFarmName; -} WTS_SESSION_INFO_1W, * PWTS_SESSION_INFO_1W; - -#define WTS_SESSION_INFO_1 __MINGW_NAME_AW(WTS_SESSION_INFO_1) -#define PWTS_SESSION_INFO_1 __MINGW_NAME_AW(PWTS_SESSION_INFO_1) - -WINBOOL WINAPI WTSEnumerateSessionsExA(HANDLE hServer,DWORD* pLevel,DWORD Filter,PWTS_SESSION_INFO_1A* ppSessionInfo,DWORD* pCount); -WINBOOL WINAPI WTSEnumerateSessionsExW(HANDLE hServer,DWORD* pLevel,DWORD Filter,PWTS_SESSION_INFO_1W* ppSessionInfo,DWORD* pCount); -#define WTSEnumerateSessionsEx __MINGW_NAME_AW(WTSEnumerateSessionsEx) - -typedef enum _WTS_TYPE_CLASS { - WTSTypeProcessInfoLevel0, - WTSTypeProcessInfoLevel1, - WTSTypeSessionInfoLevel1 -} WTS_TYPE_CLASS; -BOOL WTSFreeMemoryExA(WTS_TYPE_CLASS WTSTypeClass,PVOID pMemory,ULONG NumberOfEntries); -BOOL WTSFreeMemoryExW(WTS_TYPE_CLASS WTSTypeClass,PVOID pMemory,ULONG NumberOfEntries); -#define WTSFreeMemoryEx __MINGW_NAME_AW(WTSFreeMemoryEx) - -#endif /*(_WIN32_WINNT >= 0x0601)*/ From 5cc17bc306e9ba18bea871cc73fbe67878509abf Mon Sep 17 00:00:00 2001 From: Aaron Franke Date: Sun, 8 Jan 2023 02:33:35 -0600 Subject: [PATCH 035/142] Add support for displaying the ISA string on RISC-V CPUs --- src/common/printing.c | 2 +- src/detection/cpu/cpu_linux.c | 50 ++++++++++++++++++++++++++++++++--- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/src/common/printing.c b/src/common/printing.c index 31775d8c7..f33d5cf33 100644 --- a/src/common/printing.c +++ b/src/common/printing.c @@ -135,7 +135,7 @@ void ffPrintCharTimes(char c, uint32_t times) char str[32]; memset(str, c, sizeof(str)); //2 instructions when compiling with AVX2 enabled - for(uint32_t i = sizeof(str); i <= times; i += sizeof(str)) + for(uint32_t i = sizeof(str); i <= times; i += (uint32_t)sizeof(str)) fwrite(str, 1, sizeof(str), stdout); uint32_t remaining = times % sizeof(str); if(remaining > 0) diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index 11b5ec965..47eaf6dc4 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -7,7 +7,7 @@ #include #include -static void parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer, FFstrbuf* cpuMHz) +static void parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer, FFstrbuf* cpuMHz, FFstrbuf* cpuIsa, FFstrbuf* cpuUarch) { FILE* cpuinfo = fopen("/proc/cpuinfo", "r"); if(cpuinfo == NULL) @@ -19,7 +19,7 @@ static void parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer, FFstrb while(getline(&line, &len, cpuinfo) != -1) { //Stop after the first CPU - if(cpu->name.length > 0 && (*line == '\0' || *line == '\n')) + if(*line == '\0' || *line == '\n') break; (void)( @@ -27,6 +27,8 @@ static void parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer, FFstrb ffParsePropLine(line, "vendor_id :", &cpu->vendor) || ffParsePropLine(line, "cpu cores :", physicalCoresBuffer) || ffParsePropLine(line, "cpu MHz :", cpuMHz) || + ffParsePropLine(line, "isa :", cpuIsa) || + ffParsePropLine(line, "uarch :", cpuUarch) || (cpu->name.length == 0 && ffParsePropLine(line, "Hardware :", &cpu->name)) //For Android devices ); } @@ -83,6 +85,25 @@ static double detectCPUTemp(const FFinstance* instance) return FF_CPU_TEMP_UNSET; } +static void parseIsa(FFstrbuf* cpuIsa) +{ + if(ffStrbufStartsWithS(cpuIsa, "rv")) + { + // RISC-V ISA string example: "rv64imafdch_zicsr_zifencei". + // The _z parts are not important for CPU showcasing, so we remove them. + if(ffStrbufContainC(cpuIsa, '_')) + ffStrbufSubstrBeforeFirstC(cpuIsa, '_'); + // Then we replace "imafd" with "g" since "g" is a shorthand. + if(ffStrbufContainS(cpuIsa, "imafd")) + { + // Remove 4 of the 5 characters and replace the remaining one with "g". + ffStrbufRemoveSubstr(cpuIsa, 4, 8); + cpuIsa->chars[4] = 'g'; + } + // The final ISA output of the above example is "rv64gch". + } +} + void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu) { if(instance->config.cpuTemp) @@ -96,7 +117,13 @@ void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu) FFstrbuf cpuMHz; ffStrbufInit(&cpuMHz); - parseCpuInfo(cpu, &physicalCoresBuffer, &cpuMHz); + FFstrbuf cpuIsa; + ffStrbufInit(&cpuIsa); + + FFstrbuf cpuUarch; + ffStrbufInit(&cpuUarch); + + parseCpuInfo(cpu, &physicalCoresBuffer, &cpuMHz, &cpuIsa, &cpuUarch); cpu->coresPhysical = ffStrbufToUInt16(&physicalCoresBuffer, 1); @@ -114,6 +141,23 @@ void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu) cpu->frequencyMin = cpu->frequencyMax = ffStrbufToDouble(&cpuMHz) / 1000; } + if(cpuUarch.length > 0) + { + if(cpu->name.length > 0) + ffStrbufAppendC(&cpu->name, ' '); + ffStrbufAppend(&cpu->name, &cpuUarch); + } + + if(cpuIsa.length > 0) + { + parseIsa(&cpuIsa); + if(cpu->name.length > 0) + ffStrbufAppendC(&cpu->name, ' '); + ffStrbufAppend(&cpu->name, &cpuIsa); + } + ffStrbufDestroy(&physicalCoresBuffer); ffStrbufDestroy(&cpuMHz); + ffStrbufDestroy(&cpuIsa); + ffStrbufDestroy(&cpuUarch); } From 078cb6e5b713120eed879db77e77533f3f711c87 Mon Sep 17 00:00:00 2001 From: Vanilla Date: Mon, 9 Jan 2023 14:11:35 +0800 Subject: [PATCH 036/142] fix[getNixPackagesImpl]: count line with `wc -l` instead, also fixes leak. --- src/detection/packages/packages_linux.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/detection/packages/packages_linux.c b/src/detection/packages/packages_linux.c index cd5babf65..a44d586f0 100644 --- a/src/detection/packages/packages_linux.c +++ b/src/detection/packages/packages_linux.c @@ -140,7 +140,7 @@ static uint32_t getNixPackagesImpl(char* path) ffStrbufInitA(&command, 255); ffStrbufAppendS(&command, "for x in $(nix-store --query --requisites "); ffStrbufAppendS(&command, path); - ffStrbufAppendS(&command, "); do if [ -d $x ]; then echo $x ; fi ; done | cut -d- -f2- | egrep '([0-9]{1,}\\.)+[0-9]{1,}' | egrep -v '\\-doc$|\\-man$|\\-info$|\\-dev$|\\-bin$|^nixos-system-nixos-' | uniq"); + ffStrbufAppendS(&command, "); do if [ -d $x ]; then echo $x ; fi ; done | cut -d- -f2- | egrep '([0-9]{1,}\\.)+[0-9]{1,}' | egrep -v '\\-doc$|\\-man$|\\-info$|\\-dev$|\\-bin$|^nixos-system-nixos-' | uniq | wc -l"); ffProcessAppendStdOut(&output, (char* const[]) { "sh", @@ -149,13 +149,12 @@ static uint32_t getNixPackagesImpl(char* path) NULL }); - //Each package is a new line in the output. If at least one line is found, add 1 for the last line. - uint32_t result = ffStrbufCountC(&output, '\n'); - if(result > 0) - result++; + int result = (int) strtol(output.chars, NULL, 10); + ffStrbufDestroy(&command); ffStrbufDestroy(&output); - return result; + + return (uint32_t) result; } static uint32_t getNixPackages(FFstrbuf* baseDir, const char* dirname) From 0aa7d646a71578e397eb0fb12adf32d0086d88d1 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Mon, 9 Jan 2023 15:20:30 +0100 Subject: [PATCH 037/142] Initial logo documentation --- README.md | 27 ++----------- doc/logo.md | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+), 24 deletions(-) create mode 100644 doc/logo.md diff --git a/README.md b/README.md index 8bce6372b..0957e7ec6 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,8 @@ At the moment the performance difference is measurable, but too small to be huma There are some premade config files in [`presets`](presets), including the ones used for the screenshots above. You can load them using `--load-config `. They may also serve as a good example for format arguments. +Logos can be heavily customized to. See the [logo documentation](doc/logo.md) for more information. + ## Dependencies Fastfetch dynamically loads needed libraries if they are available. On Linux, its only hard dependencies are `libc` (any implementation of the c standard library), `libdl` and [`libpthread`](https://man7.org/linux/man-pages/man7/pthreads.7.html) (if built with multithreading support). They are all shipped with [`glibc`](https://www.gnu.org/software/libc/), which is already installed on most linux distributions. @@ -88,33 +90,10 @@ All categories not listed here should work without needing a specific implementa Title, Separator, OS, Host, Bios, Board, Kernel, Uptime, Processes, Packages, Shell, Resolution, DE, WM, WMTheme, Theme, Icons, Font, Cursor, Terminal, Terminal Font, CPU, CPUUsage, GPU, Memory, Swap, Disk, Battery, Power Adapter, Player, Media, Vulkan, OpenGL, OpenCL, LocalIP, PublicIP, Wifi, DateTime, Date, Time, Locale, Colors, Break, Custom ``` -##### Logos +##### Builtin logos ``` AlmaLinux, Alpine, Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, CRUX, Crystal, Debian, Devuan, Deepin, Endeavour, Enso, Fedora, FreeBSD, Garuda, Gentoo, KDE Neon, KISS, Kubuntu, LangitKetujuh, Linux, MacOS, Manjaro, Mint, MSYS2, NixOS, Nobara, OpenSUSE, OpenSUSE Tumbleweed, OpenSUSE LEAP, Parabola, Raspbian, Pop!_OS, RebornOS, RedstarOS, Rocky, Rosa, Slackware, Solus, Ubuntu, Vanilla, Void, Windows 11, Windows 8, Windows, Zorin ``` -* Most of the logos have a small variant. Access it by appending _small to the logo name. -* Some logos have an old variant. Access it by appending _old to the logo name. -* To disable the logo, use `--logo none`. -* Get a list of all available logos with `fastfetch --print-logos`. - -###### Image logo - -Printing images as logo is supported using Sixel / Kitty / iTerm graphics protocol or chafas image to text conversion. - -* Sixel: fastfetch must be built with imagemagick support to convert image to sixel format -* Kitty: Because [kitty support png](https://sw.kovidgoyal.net/kitty/graphics-protocol/#png-data) natively, using `png` image file with both `--logo-width` and `--logo-height` being specified is recommanded to get maximum performance. Otherwise, imagemagick is required to convert image to RGBA data. -* iTerm: [Since iTerm supports a lot of image format](https://iterm2.com/documentation-images.html), imagemagick support is not required. However, both `--logo-width` and `--logo-height` must be specified since fastfetch has no idea about the size of the image. -* Chafa: Requires imagemagick support. -* Raw: use a pre-converted image file so that fastfetch don't need to convert the image format on the fly. -```shell -# brew install libsixel -$ img2sixel image.png -o image.sixel -$ fastfetch --raw image.sixel --logo-width 30 --logo-height 15 - -# wget https://iterm2.com/utilities/imgcat && chmod +x imgcat -$ imgcat image.png > image.raw -$ fastfetch --raw image.raw --logo-width 30 --logo-height 15 -``` ##### Package managers ``` diff --git a/doc/logo.md b/doc/logo.md new file mode 100644 index 000000000..c24cae948 --- /dev/null +++ b/doc/logo.md @@ -0,0 +1,112 @@ +# Logo Documentation + +## Logo options + +### General + +| Option | Default | Description | +|--------|---------|-------------| +| `--logo`, `-l` | `""` | The logo source, interpreted depending on type | +| `--logo-type` | `auto` | The logo type. See the following categories for possible values | +| `--` | `""` | Short for `--logo-type --logo ` | +| `--logo-padding` | `""` | Sets the padding left and right of the logo | +| `--logo-padding-left` | `0` | Sets the padding left of the logo | +| `--logo-padding-right` | `4` | Sets the padding right of the logo | +| `--logo-padding-top` | `0` | Sets the padding top of the logo | + +### Text + +| Option | Default | Description | +|--------|---------|-------------| +| `--logo-color-[1-9]` | `""` | Overrides a color for logos that support it | +| `--logo-print-remaining` | `true` | Print the remaining logo, if it is higher than the keys | + +* Color placeholders are in the form `$[1-9]`. To print a `$`, use `$$`. +* If a color placeholder value is not set, the placeholder is simply discarded. + +### Image + +| Option | Default | Description | +|--------|---------|-------------| +| `--logo-width` | `""` | Sets the width of the logo for logos that support it | +| `--logo-height` | `""` | Sets the height of the logo for logos that support it | + +* If one of the height / width options is set, but the other not, the aspect ratio is preserved. +* If neither height nor width is set, the original size is used. + +## Logo types + +### auto + +Trys to detect the logo type depending on the value of `--logo`, in the following order: +* If the value is empty / not set, an autodected builtin logo is displayed. +* If the value is the name of a builtin logo, it is displayed. +* If the value is the path to an image file, and the terminal emulator is known to support an image protocol, the image is displayed. +* If the value is the path to a text file, the content is displayed. +* The autodetected builtin logo is displayed. + +### builtin + +The value of `--logo` is interpreted as the name of a builtin logo. +* If the value is empty / not set, it is autodetected. +* Use `--list-logos` to get a list of all available logos. +* Use `--print-logos` to see all available logos. +* All builtin logos set default values for `--logo-color-[1-9]`. +* Use `none` to disable the logo, but keep key colors from the detected logo. + +### file + +The value of `--logo` is interpreted as the path to a file. The content of the file is displayed. +* If the file can't be read, the autodetected builtin logo is displayed. + +### file-raw + +The value of `--logo` is interpreted as the path to a file. The content of the file is displayed. +* No color placeholder replacement is done. +* If the file can't be read, the autodetected builtin logo is displayed. + +### data + +The value of `--logo` is interpreted as the logo and directly displayed. +* If the value is empty / not set, the autodetected builtin logo is displayed. + +### data-raw + +The value of `--logo` is interpreted as the logo and directly displayed. +* No color placeholder replacement is done. +* If the value is empty / not set, the autodetected builtin logo is displayed. + +### sixel + +The value of `--logo` is interpreted as the path to an image file. It is displayed using the sixel graphics protocol. +* `fastfetch` must be compiled with the `imagemagick6` or `imagemagick7` feature. + +### kitty + +The value of `--logo` is interpreted as the path to an image file. It is displayed using the kitty graphics protocol. +* If the file is a png file, and both `--logo-width` and `--logo-height` are specified, the image is directly send to the terminal emulator. +* Otherwise `fastfetch` must be compiled with the `imagemagick6` or `imagemagick7` feature. + +### iterm + +The value of `--logo` is interpreted as the path to an image file. It is displayed using the iTerm graphics protocol. +* Both `--logo-width` and `--logo-height` must be specified. + +### chafa + +The value of `--logo` is interpreted as the path to an image file. It is converted to an ascii logo using `libchafa`. +* `fastfetch` must be compiled with the `chafa` feature. +* `fastfetch` must be compiled with the `imagemagick6` or `imagemagick7` feature. +* Use `--chafa-fg-only` to set weather to render foreground only. +* Use `--chafa-symbols` to set the symbols. +* Use `--chafa-canvas-mode` to set the canvas mode. +* Use `--chafa-color-space` to set the color space. +* Use `--chafa-dither-mode` to set the dither mode. +* See the [chafa documentation](https://hpjansson.org/chafa/man/) for more information. + +### raw + +The value of `--logo` is interpreted as the path to a binary file. It is printed as-is. +* Both `--logo-width` and `--logo-height` must be specified. +* Use this to display a pre converted image file. +* If the file can't be read, the autodetected builtin logo is displayed. From d9a022ffff15d9ecfd565fa5b53f800930837ccc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 9 Jan 2023 18:59:02 +0800 Subject: [PATCH 038/142] Brightness: add new module (macOS) It turns out that merging brightness module into resolution module is a bad idea. --- CHANGELOG.md | 1 + CMakeLists.txt | 6 ++ README.md | 2 +- src/common/format.c | 2 + src/common/format.h | 1 + src/common/init.c | 1 + src/data/config_user.txt | 3 + src/detection/brightness/brightness.h | 17 +++++ src/detection/brightness/brightness_apple.c | 33 ++++++++++ .../brightness/brightness_nosupport.c | 6 ++ src/fastfetch.c | 3 + src/fastfetch.h | 4 +- src/flashfetch.c | 1 + src/modules/brightness.c | 62 +++++++++++++++++++ 14 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 src/detection/brightness/brightness.h create mode 100644 src/detection/brightness/brightness_apple.c create mode 100644 src/detection/brightness/brightness_nosupport.c create mode 100644 src/modules/brightness.c diff --git a/CHANGELOG.md b/CHANGELOG.md index f11a7e894..fc2eed5a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ Features: * Look for config files in `~/Library/Preferences` (macOS) * Add `--list-config-paths` option which list search paths of config files * Add `--list-data-paths` option which list search paths for presets and logos +* Add `Brightness` module support Logos: * Raspbian (@IamNoRobot, #373) diff --git a/CMakeLists.txt b/CMakeLists.txt index fb39d390a..3a1f122a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -254,6 +254,7 @@ set(LIBFASTFETCH_SRC src/modules/battery.c src/modules/bios.c src/modules/board.c + src/modules/brightness.c src/modules/break.c src/modules/chassis.c src/modules/colors.c @@ -309,6 +310,7 @@ if(LINUX) src/detection/battery/battery_linux.c src/detection/bios/bios_linux.c src/detection/board/board_linux.c + src/detection/brightness/brightness_nosupport.c src/detection/chassis/chassis_linux.c src/detection/cpu/cpu_linux.c src/detection/cpuUsage/cpuUsage_linux.c @@ -348,6 +350,7 @@ elseif(ANDROID) src/detection/battery/battery_nosupport.c src/detection/bios/bios_nosupport.c src/detection/board/board_nosupport.c + src/detection/brightness/brightness_nosupport.c src/detection/chassis/chassis_nosupport.c src/detection/cpu/cpu_linux.c src/detection/cursor/cursor_nosupport.c @@ -382,6 +385,7 @@ elseif(BSD) src/detection/battery/battery_nosupport.c src/detection/bios/bios_bsd.c src/detection/board/board_nosupport.c + src/detection/brightness/brightness_nosupport.c src/detection/chassis/chassis_nosupport.c src/detection/cpu/cpu_bsd.c src/detection/cpuUsage/cpuUsage_bsd.c @@ -422,6 +426,7 @@ elseif(APPLE) src/detection/battery/battery_apple.c src/detection/bios/bios_apple.c src/detection/board/board_nosupport.c + src/detection/brightness/brightness_apple.c src/detection/chassis/chassis_nosupport.c src/detection/cpu/cpu_apple.c src/detection/cpuUsage/cpuUsage_apple.c @@ -458,6 +463,7 @@ elseif(WIN32) src/detection/battery/battery_windows.c src/detection/bios/bios_windows.c src/detection/board/board_windows.c + src/detection/brightness/brightness_nosupport.c src/detection/chassis/chassis_nosupport.c src/detection/cpu/cpu_windows.c src/detection/cpuUsage/cpuUsage_windows.c diff --git a/README.md b/README.md index 0957e7ec6..78312f6a8 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ All categories not listed here should work without needing a specific implementa ##### Available Modules ``` -Title, Separator, OS, Host, Bios, Board, Kernel, Uptime, Processes, Packages, Shell, Resolution, DE, WM, WMTheme, Theme, Icons, Font, Cursor, Terminal, Terminal Font, CPU, CPUUsage, GPU, Memory, Swap, Disk, Battery, Power Adapter, Player, Media, Vulkan, OpenGL, OpenCL, LocalIP, PublicIP, Wifi, DateTime, Date, Time, Locale, Colors, Break, Custom +Title, Separator, OS, Host, Bios, Board, Kernel, Uptime, Processes, Packages, Shell, Resolution, Brightness, DE, WM, WMTheme, Theme, Icons, Font, Cursor, Terminal, Terminal Font, CPU, CPUUsage, GPU, Memory, Swap, Disk, Battery, Power Adapter, Player, Media, Vulkan, OpenGL, OpenCL, LocalIP, PublicIP, Wifi, DateTime, Date, Time, Locale, Colors, Break, Custom ``` ##### Builtin logos diff --git a/src/common/format.c b/src/common/format.c index b491713cf..1a4a688c5 100644 --- a/src/common/format.c +++ b/src/common/format.c @@ -19,6 +19,8 @@ void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg) ffStrbufAppendS(buffer, (const char*)formatarg->value); else if(formatarg->type == FF_FORMAT_ARG_TYPE_STRBUF) ffStrbufAppend(buffer, (FFstrbuf*)formatarg->value); + else if(formatarg->type == FF_FORMAT_ARG_TYPE_FLOAT) + ffStrbufAppendF(buffer, "%f", *(float*)formatarg->value); else if(formatarg->type == FF_FORMAT_ARG_TYPE_DOUBLE) ffStrbufAppendF(buffer, "%g", *(double*)formatarg->value); else if(formatarg->type == FF_FORMAT_ARG_TYPE_BOOL) diff --git a/src/common/format.h b/src/common/format.h index d860dbd29..cc7e29e6d 100644 --- a/src/common/format.h +++ b/src/common/format.h @@ -12,6 +12,7 @@ typedef enum FFformatargtype FF_FORMAT_ARG_TYPE_INT, FF_FORMAT_ARG_TYPE_STRING, FF_FORMAT_ARG_TYPE_STRBUF, + FF_FORMAT_ARG_TYPE_FLOAT, FF_FORMAT_ARG_TYPE_DOUBLE, FF_FORMAT_ARG_TYPE_LIST, FF_FORMAT_ARG_TYPE_BOOL diff --git a/src/common/init.c b/src/common/init.c index 3cf2287bd..59aee5fb1 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -247,6 +247,7 @@ static void defaultConfig(FFinstance* instance) initModuleArg(&instance->config.host); initModuleArg(&instance->config.bios); initModuleArg(&instance->config.board); + initModuleArg(&instance->config.brightness); initModuleArg(&instance->config.chassis); initModuleArg(&instance->config.kernel); initModuleArg(&instance->config.uptime); diff --git a/src/data/config_user.txt b/src/data/config_user.txt index a76e24686..2afeba65e 100644 --- a/src/data/config_user.txt +++ b/src/data/config_user.txt @@ -230,6 +230,7 @@ #--packages-key Packages #--shell-key Shell #--resolution-key Resolution {1} +#--brightness-key Brightness ({1}) #--de-key DE #--wm-key WM #--wm-theme-key WM Theme @@ -274,6 +275,7 @@ #--packages-format #--shell-format #--resolution-format +#--brightness-format #--de-format #--wm-format #--wm-theme-format @@ -317,6 +319,7 @@ #--packages-error #--shell-error #--resolution-error +#--brightness-error #--de-error #--wm-error #--wm-theme-error diff --git a/src/detection/brightness/brightness.h b/src/detection/brightness/brightness.h new file mode 100644 index 000000000..d65843947 --- /dev/null +++ b/src/detection/brightness/brightness.h @@ -0,0 +1,17 @@ +#pragma once + +#ifndef FF_INCLUDED_detection_brightness_brightness +#define FF_INCLUDED_detection_brightness_brightness + +#include "fastfetch.h" +#include "util/FFlist.h" + +typedef struct FFBrightnessResult +{ + FFstrbuf name; + float value; +} FFBrightnessResult; + +const char* ffDetectBrightness(FFlist* result); // list of FFBrightnessResult + +#endif diff --git a/src/detection/brightness/brightness_apple.c b/src/detection/brightness/brightness_apple.c new file mode 100644 index 000000000..e3a93a5ea --- /dev/null +++ b/src/detection/brightness/brightness_apple.c @@ -0,0 +1,33 @@ +#include "brightness.h" + +#include + +extern int DisplayServicesGetBrightness(CGDirectDisplayID display, float *brightness) __attribute__((weak_import)); + +const char* ffDetectBrightness(FFlist* result) +{ + if(DisplayServicesGetBrightness == NULL) + return "DisplayServices function DisplayServicesGetBrightness is not available"; + + CGDirectDisplayID screens[128]; + uint32_t screenCount; + if(CGGetOnlineDisplayList(sizeof(screens) / sizeof(screens[0]), screens, &screenCount) != kCGErrorSuccess) + return "CGGetOnlineDisplayList() failed"; + + for(uint32_t i = 0; i < screenCount; i++) + { + CGDirectDisplayID screen = screens[i]; + float brightness; + if(DisplayServicesGetBrightness(screen, &brightness) != kCGErrorSuccess) + continue; + + FFBrightnessResult* display = (FFBrightnessResult*) ffListAdd(result); + if(CGDisplayIsBuiltin(screen)) + ffStrbufInitS(&display->name, "built-in"); + else + ffStrbufInitF(&display->name, "external-%u", (unsigned) screen); + display->value = brightness * 100; + } + + return NULL; +} diff --git a/src/detection/brightness/brightness_nosupport.c b/src/detection/brightness/brightness_nosupport.c new file mode 100644 index 000000000..5661c180f --- /dev/null +++ b/src/detection/brightness/brightness_nosupport.c @@ -0,0 +1,6 @@ +#include "brightness.h" + +const char* ffDetectBrightness(FF_UNUSED_PARAM FFlist* result) +{ + return "Not supported on this platform"; +} diff --git a/src/fastfetch.c b/src/fastfetch.c index 8de17b9f0..ad63f26a3 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -1146,6 +1146,7 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con else if(optionParseModuleArgs(key, value, "packages", &instance->config.packages)) {} else if(optionParseModuleArgs(key, value, "shell", &instance->config.shell)) {} else if(optionParseModuleArgs(key, value, "resolution", &instance->config.resolution)) {} + else if(optionParseModuleArgs(key, value, "brightness", &instance->config.brightness)) {} else if(optionParseModuleArgs(key, value, "de", &instance->config.de)) {} else if(optionParseModuleArgs(key, value, "wifi", &instance->config.wifi)) {} else if(optionParseModuleArgs(key, value, "wm", &instance->config.wm)) {} @@ -1362,6 +1363,8 @@ static void parseStructureCommand(FFinstance* instance, FFdata* data, const char ffPrintBios(instance); else if(strcasecmp(line, "board") == 0) ffPrintBoard(instance); + else if(strcasecmp(line, "brightness") == 0) + ffPrintBrightness(instance); else if(strcasecmp(line, "chassis") == 0) ffPrintChassis(instance); else if(strcasecmp(line, "kernel") == 0) diff --git a/src/fastfetch.h b/src/fastfetch.h index fa1b11d09..0572ef294 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -106,8 +106,9 @@ typedef struct FFconfig FFModuleArgs os; FFModuleArgs host; FFModuleArgs bios; - FFModuleArgs chassis; FFModuleArgs board; + FFModuleArgs brightness; + FFModuleArgs chassis; FFModuleArgs kernel; FFModuleArgs uptime; FFModuleArgs processes; @@ -273,6 +274,7 @@ void ffPrintProcesses(FFinstance* instance); void ffPrintPackages(FFinstance* instance); void ffPrintShell(FFinstance* instance); void ffPrintResolution(FFinstance* instance); +void ffPrintBrightness(FFinstance* instance); void ffPrintDesktopEnvironment(FFinstance* instance); void ffPrintWM(FFinstance* instance); void ffPrintWMTheme(FFinstance* instance); diff --git a/src/flashfetch.c b/src/flashfetch.c index 196e94bb5..86729ace6 100644 --- a/src/flashfetch.c +++ b/src/flashfetch.c @@ -31,6 +31,7 @@ int main(int argc, char** argv) ffPrintPackages(&instance); ffPrintShell(&instance); ffPrintResolution(&instance); + // ffPrintBrightness(&instance); ffPrintDesktopEnvironment(&instance); ffPrintWM(&instance); ffPrintWMTheme(&instance); diff --git a/src/modules/brightness.c b/src/modules/brightness.c new file mode 100644 index 000000000..edede6543 --- /dev/null +++ b/src/modules/brightness.c @@ -0,0 +1,62 @@ +#include "fastfetch.h" +#include "common/printing.h" +#include "detection/brightness/brightness.h" + +#define FF_BRIGHTNESS_MODULE_NAME "Brightness" +#define FF_BRIGHTNESS_NUM_FORMAT_ARGS 2 + +void ffPrintBrightness(FFinstance* instance) +{ + FFlist result; + ffListInit(&result, sizeof(FFBrightnessResult)); + const char* error = ffDetectBrightness(&result); + + if(error) + { + ffPrintError(instance, FF_BRIGHTNESS_MODULE_NAME, 0, &instance->config.brightness, "%s", error); + goto exit; + } + + if(result.length == 0) + { + ffPrintError(instance, FF_BRIGHTNESS_MODULE_NAME, 0, &instance->config.brightness, "No result is detected."); + goto exit; + } + + FFstrbuf key; + ffStrbufInit(&key); + + FF_LIST_FOR_EACH(FFBrightnessResult, item, result) + { + if(instance->config.brightness.key.length == 0) + { + ffStrbufAppendF(&key, "%s (%s)", FF_BRIGHTNESS_MODULE_NAME, item->name.chars); + } + else + { + ffParseFormatString(&key, &instance->config.brightness.key, 1, (FFformatarg[]){ + {FF_FORMAT_ARG_TYPE_STRBUF, &item->name} + }); + } + + if(instance->config.brightness.outputFormat.length == 0) + { + ffPrintLogoAndKey(instance, key.chars, 0, NULL); + printf("%.0f%%\n", item->value); + } + else + { + ffPrintFormatString(instance, key.chars, 0, NULL, &instance->config.brightness.outputFormat, FF_BRIGHTNESS_NUM_FORMAT_ARGS, (FFformatarg[]) { + {FF_FORMAT_ARG_TYPE_STRBUF, &item->value}, + {FF_FORMAT_ARG_TYPE_FLOAT, &item->name} + }); + } + + ffStrbufDestroy(&item->name); + } + + ffStrbufDestroy(&key); + +exit: + ffListDestroy(&result); +} From 85098a6627d904ac8ce7608386a4dc4d4674bdfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 9 Jan 2023 19:09:22 +0800 Subject: [PATCH 039/142] Brightness: add support for Linux --- CMakeLists.txt | 2 +- src/detection/brightness/brightness_linux.c | 55 +++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 src/detection/brightness/brightness_linux.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 3a1f122a5..03763387c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -310,7 +310,7 @@ if(LINUX) src/detection/battery/battery_linux.c src/detection/bios/bios_linux.c src/detection/board/board_linux.c - src/detection/brightness/brightness_nosupport.c + src/detection/brightness/brightness_linux.c src/detection/chassis/chassis_linux.c src/detection/cpu/cpu_linux.c src/detection/cpuUsage/cpuUsage_linux.c diff --git a/src/detection/brightness/brightness_linux.c b/src/detection/brightness/brightness_linux.c new file mode 100644 index 000000000..31e346062 --- /dev/null +++ b/src/detection/brightness/brightness_linux.c @@ -0,0 +1,55 @@ +#include "brightness.h" +#include "common/io.h" + +#include + +const char* ffDetectBrightness(FF_UNUSED_PARAM FFlist* result) +{ + //https://www.kernel.org/doc/Documentation/ABI/stable/sysfs-class-backlight + const char* backlightDirPath = "/sys/class/backlight/"; + + DIR* dirp = opendir(backlightDirPath); + if(dirp == NULL) + return "Failed to open `/sys/class/backlight/`"; + + FFstrbuf backlightDir; + ffStrbufInitA(&backlightDir, 64); + ffStrbufAppendS(&backlightDir, backlightDirPath); + + uint32_t backlightDirLength = backlightDir.length; + + FFstrbuf buffer; + ffStrbufInit(&buffer); + + struct dirent* entry; + while((entry = readdir(dirp)) != NULL) + { + if(strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + + ffStrbufAppendS(&backlightDir, entry->d_name); + ffStrbufAppendS(&backlightDir, "/actual_brightness"); + if(ffReadFileBuffer(backlightDir.chars, &buffer)) + { + double actualBrightness = ffStrbufToDouble(&buffer); + ffStrbufSubstrBefore(&backlightDir, backlightDirLength); + ffStrbufAppendS(&backlightDir, entry->d_name); + ffStrbufAppendS(&backlightDir, "/max_brightness"); + if(ffReadFileBuffer(backlightDir.chars, &buffer)) + { + FFBrightnessResult* display = (FFBrightnessResult*) ffListAdd(result); + ffStrbufInitS(&display->name, entry->d_name); + double maxBrightness = ffStrbufToDouble(&buffer); + display->value = (float) (actualBrightness * 100 / maxBrightness); + } + + break; + } + } + + closedir(dirp); + ffStrbufDestroy(&backlightDir); + ffStrbufDestroy(&buffer); + + return NULL; +} From 476b0495e0f5ba7e2f254202e7de5809955d85b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 9 Jan 2023 19:24:19 +0800 Subject: [PATCH 040/142] Brightness: add support for Windows --- CMakeLists.txt | 2 +- .../brightness/brightness_windows.cpp | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/detection/brightness/brightness_windows.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 03763387c..32b57debb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -463,7 +463,7 @@ elseif(WIN32) src/detection/battery/battery_windows.c src/detection/bios/bios_windows.c src/detection/board/board_windows.c - src/detection/brightness/brightness_nosupport.c + src/detection/brightness/brightness_windows.cpp src/detection/chassis/chassis_nosupport.c src/detection/cpu/cpu_windows.c src/detection/cpuUsage/cpuUsage_windows.c diff --git a/src/detection/brightness/brightness_windows.cpp b/src/detection/brightness/brightness_windows.cpp new file mode 100644 index 000000000..3139fef4c --- /dev/null +++ b/src/detection/brightness/brightness_windows.cpp @@ -0,0 +1,27 @@ +extern "C" +{ +#include "brightness.h" +} +#include "util/windows/wmi.hpp" + +extern "C" +const char* ffDetectBrightness(FFlist* result) +{ + FFWmiQuery query(L"SELECT CurrentBrightness, InstanceName FROM WmiMonitorBrightness WHERE Active = true", nullptr, FFWmiNamespace::WMI); + if(!query) + return "Query WMI service failed"; + + while(FFWmiRecord record = query.next()) + { + FFBrightnessResult* display = (FFBrightnessResult*) ffListAdd(result); + ffStrbufInit(&display->name); + record.getString(L"InstanceName", &display->name); + ffStrbufSubstrAfterFirstC(&display->name, '\\'); + ffStrbufSubstrBeforeFirstC(&display->name, '\\'); + + uint64_t brightness; + record.getUnsigned(L"CurrentBrightness", &brightness); + display->value = (float) brightness; + } + return NULL; +} From 4cc5f35b049d1d626f5612cddd1580699e1c5080 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 9 Jan 2023 19:53:41 +0800 Subject: [PATCH 041/142] DisplayServer: revert changes of brightness partially --- CMakeLists.txt | 2 +- src/detection/displayserver/displayserver.c | 3 +- src/detection/displayserver/displayserver.h | 3 +- .../displayserver/displayserver_apple.c | 9 +-- ...er_windows.cpp => displayserver_windows.c} | 29 ++-------- .../displayserver/linux/displayserver_linux.c | 56 ------------------- src/detection/displayserver/linux/xcb.c | 15 ++--- src/detection/displayserver/linux/xlib.c | 15 ++--- src/modules/resolution.c | 6 +- 9 files changed, 19 insertions(+), 119 deletions(-) rename src/detection/displayserver/{displayserver_windows.cpp => displayserver_windows.c} (69%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 32b57debb..64f732c09 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -469,7 +469,7 @@ elseif(WIN32) src/detection/cpuUsage/cpuUsage_windows.c src/detection/cursor/cursor_windows.c src/detection/disk/disk_windows.c - src/detection/displayserver/displayserver_windows.cpp + src/detection/displayserver/displayserver_windows.c src/detection/font/font_windows.c src/detection/gpu/gpu_windows.cpp src/detection/host/host_windows.c diff --git a/src/detection/displayserver/displayserver.c b/src/detection/displayserver/displayserver.c index e82279f4f..4a42a21a1 100644 --- a/src/detection/displayserver/displayserver.c +++ b/src/detection/displayserver/displayserver.c @@ -19,7 +19,7 @@ uint32_t ffdsParseRefreshRate(int32_t refreshRate) return (uint32_t) refreshRate; } -bool ffdsAppendResolution(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate, int32_t brightness) +bool ffdsAppendResolution(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate) { if(width == 0 || height == 0) return false; @@ -28,7 +28,6 @@ bool ffdsAppendResolution(FFDisplayServerResult* result, uint32_t width, uint32_ resolution->width = width; resolution->height = height; resolution->refreshRate = refreshRate; - resolution->brightness = brightness; return true; } diff --git a/src/detection/displayserver/displayserver.h b/src/detection/displayserver/displayserver.h index 16e6e67a6..d31d5edee 100644 --- a/src/detection/displayserver/displayserver.h +++ b/src/detection/displayserver/displayserver.h @@ -10,7 +10,6 @@ typedef struct FFResolutionResult uint32_t width; uint32_t height; uint32_t refreshRate; - int32_t brightness; } FFResolutionResult; typedef struct FFDisplayServerResult @@ -28,6 +27,6 @@ const FFDisplayServerResult* ffConnectDisplayServer(const FFinstance* instance); //Used internal uint32_t ffdsParseRefreshRate(int32_t refreshRate); -bool ffdsAppendResolution(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate, int32_t brightness); +bool ffdsAppendResolution(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate); #endif diff --git a/src/detection/displayserver/displayserver_apple.c b/src/detection/displayserver/displayserver_apple.c index 88fd16477..4d0d802c2 100644 --- a/src/detection/displayserver/displayserver_apple.c +++ b/src/detection/displayserver/displayserver_apple.c @@ -7,8 +7,6 @@ #include #include -extern int DisplayServicesGetBrightness(CGDirectDisplayID display, float *brightness) __attribute__((weak_import)); - static void detectResolution(FFDisplayServerResult* ds) { CGDirectDisplayID screens[128]; @@ -22,15 +20,10 @@ static void detectResolution(FFDisplayServerResult* ds) CGDisplayModeRef mode = CGDisplayCopyDisplayMode(screen); if(mode) { - float brightness; - if(DisplayServicesGetBrightness == NULL || DisplayServicesGetBrightness(screen, &brightness) != kCGErrorSuccess) - brightness = -1; - ffdsAppendResolution(ds, (uint32_t)CGDisplayModeGetWidth(mode), (uint32_t)CGDisplayModeGetHeight(mode), - (uint32_t)CGDisplayModeGetRefreshRate(mode), - (int32_t)(brightness * 100) + (uint32_t)CGDisplayModeGetRefreshRate(mode) ); CGDisplayModeRelease(mode); } diff --git a/src/detection/displayserver/displayserver_windows.cpp b/src/detection/displayserver/displayserver_windows.c similarity index 69% rename from src/detection/displayserver/displayserver_windows.cpp rename to src/detection/displayserver/displayserver_windows.c index 7de11a9ad..f39955b8b 100644 --- a/src/detection/displayserver/displayserver_windows.cpp +++ b/src/detection/displayserver/displayserver_windows.c @@ -1,13 +1,9 @@ -extern "C" { #include "displayserver.h" #include "detection/os/os.h" -} -#include "util/windows/wmi.hpp" #include -#include +#include -extern "C" void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* instance) { FF_UNUSED(instance); @@ -29,33 +25,16 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* ins ffStrbufInit(&ds->deVersion); ffListInit(&ds->resolutions, sizeof(FFResolutionResult)); - DISPLAY_DEVICEW displayDevice; - displayDevice.cb = sizeof(DISPLAY_DEVICEW); + DISPLAY_DEVICEW displayDevice = { .cb = sizeof(DISPLAY_DEVICEW) }; for(DWORD devNum = 0; EnumDisplayDevicesW(NULL, devNum, &displayDevice, 0) != 0; ++devNum) { if(!(displayDevice.StateFlags & DISPLAY_DEVICE_ACTIVE)) continue; - DEVMODEW devMode; - devMode.dmSize = sizeof(DEVMODEW); + DEVMODEW devMode = { .dmSize = sizeof(DEVMODEW) }; if(EnumDisplaySettingsW(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &devMode) == 0) continue; - ffdsAppendResolution(ds, devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmDisplayFrequency, -1); - } - - //TODO: support multiple monitors - if(ds->resolutions.length == 1) - { - FFWmiQuery query(L"SELECT CurrentBrightness FROM WmiMonitorBrightness WHERE Active = true", nullptr, FFWmiNamespace::WMI); - if(FFWmiRecord record = query.next()) - { - uint64_t brightness; - record.getUnsigned(L"CurrentBrightness", &brightness); - FF_LIST_FOR_EACH(FFResolutionResult, resolution, ds->resolutions) - { - resolution->brightness = (int) brightness; - } - } + ffdsAppendResolution(ds, devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmDisplayFrequency); } //https://github.com/hykilpikonna/hyfetch/blob/master/neofetch#L2067 diff --git a/src/detection/displayserver/linux/displayserver_linux.c b/src/detection/displayserver/linux/displayserver_linux.c index d64128a39..526670c9d 100644 --- a/src/detection/displayserver/linux/displayserver_linux.c +++ b/src/detection/displayserver/linux/displayserver_linux.c @@ -1,61 +1,7 @@ #include "displayserver_linux.h" -#include "common/io.h" #include -static void parseBacklight(FFDisplayServerResult* result) -{ - if(result->resolutions.length != 1) - return; - - //https://www.kernel.org/doc/Documentation/ABI/stable/sysfs-class-backlight - const char* backlightDirPath = "/sys/class/backlight/"; - - DIR* dirp = opendir(backlightDirPath); - if(dirp == NULL) - return; - - FFstrbuf backlightDir; - ffStrbufInitA(&backlightDir, 64); - ffStrbufAppendS(&backlightDir, backlightDirPath); - - uint32_t backlightDirLength = backlightDir.length; - - FFstrbuf buffer; - ffStrbufInit(&buffer); - - struct dirent* entry; - while((entry = readdir(dirp)) != NULL) - { - if(strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; - - ffStrbufAppendS(&backlightDir, entry->d_name); - ffStrbufAppendS(&backlightDir, "/actual_brightness"); - if(ffReadFileBuffer(backlightDir.chars, &buffer)) - { - double actualBrightness = ffStrbufToDouble(&buffer); - ffStrbufSubstrBefore(&backlightDir, backlightDirLength); - ffStrbufAppendS(&backlightDir, entry->d_name); - ffStrbufAppendS(&backlightDir, "/max_brightness"); - if(ffReadFileBuffer(backlightDir.chars, &buffer)) - { - double maxBrightness = ffStrbufToDouble(&buffer); - FF_LIST_FOR_EACH(FFResolutionResult, resolution, result->resolutions) - { - resolution->brightness = (int) (actualBrightness * 100 / maxBrightness); - } - } - - break; - } - } - - closedir(dirp); - ffStrbufDestroy(&backlightDir); - ffStrbufDestroy(&buffer); -} - static void parseDRM(FFDisplayServerResult* result) { const char* drmDirPath = "/sys/class/drm/"; @@ -140,6 +86,4 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* ins //This fills in missing information about WM / DE by using env vars and iterating processes ffdsDetectWMDE(instance, ds); - - parseBacklight(ds); } diff --git a/src/detection/displayserver/linux/xcb.c b/src/detection/displayserver/linux/xcb.c index f92e91e5a..692be7808 100644 --- a/src/detection/displayserver/linux/xcb.c +++ b/src/detection/displayserver/linux/xcb.c @@ -119,8 +119,7 @@ void ffdsConnectXcb(const FFinstance* instance, FFDisplayServerResult* result) result, (uint32_t) iterator.data->width_in_pixels, (uint32_t) iterator.data->height_in_pixels, - 0, - -1 + 0 ); ffxcb_screen_next(&iterator); } @@ -185,8 +184,7 @@ static bool xcbRandrHandleModeInfo(XcbRandrData* data, xcb_randr_mode_info_t* mo data->result, (uint32_t) modeInfo->width, (uint32_t) modeInfo->height, - refreshRate == 0 ? data->defaultRefreshRate : refreshRate, - -1 + refreshRate == 0 ? data->defaultRefreshRate : refreshRate ); } @@ -221,8 +219,7 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc) data->result, (uint32_t) crtcInfoReply->width, (uint32_t) crtcInfoReply->height, - data->defaultRefreshRate, - -1 + data->defaultRefreshRate ); free(crtcInfoReply); @@ -265,8 +262,7 @@ static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t* data->result, (uint32_t) monitor->width, (uint32_t) monitor->height, - data->defaultRefreshRate, - -1 + data->defaultRefreshRate ); } @@ -324,8 +320,7 @@ static void xcbRandrHandleScreen(XcbRandrData* data, xcb_screen_t* screen) data->result, (uint32_t) screen->width_in_pixels, (uint32_t) screen->height_in_pixels, - data->defaultRefreshRate, - -1 + data->defaultRefreshRate ); } diff --git a/src/detection/displayserver/linux/xlib.c b/src/detection/displayserver/linux/xlib.c index d7429713f..108de5946 100644 --- a/src/detection/displayserver/linux/xlib.c +++ b/src/detection/displayserver/linux/xlib.c @@ -83,8 +83,7 @@ void ffdsConnectXlib(const FFinstance* instance, FFDisplayServerResult* result) result, (uint32_t) screen->width, (uint32_t) screen->height, - 0, - -1 + 0 ); } @@ -143,8 +142,7 @@ static bool xrandrHandleModeInfo(XrandrData* data, XRRModeInfo* modeInfo) data->result, (uint32_t) modeInfo->width, (uint32_t) modeInfo->height, - refreshRate == 0 ? data->defaultRefreshRate : refreshRate, - -1 + refreshRate == 0 ? data->defaultRefreshRate : refreshRate ); } @@ -173,8 +171,7 @@ static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc) data->result, (uint32_t) crtcInfo->width, (uint32_t) crtcInfo->height, - data->defaultRefreshRate, - -1 + data->defaultRefreshRate ); data->ffXRRFreeCrtcInfo(crtcInfo); @@ -208,8 +205,7 @@ static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo) data->result, (uint32_t) monitorInfo->width, (uint32_t) monitorInfo->height, - data->defaultRefreshRate, - -1 + data->defaultRefreshRate ); } @@ -261,8 +257,7 @@ static void xrandrHandleScreen(XrandrData* data, Screen* screen) data->result, (uint32_t) WidthOfScreen(screen), (uint32_t) HeightOfScreen(screen), - data->defaultRefreshRate, - -1 + data->defaultRefreshRate ); } diff --git a/src/modules/resolution.c b/src/modules/resolution.c index c07b45ad8..396d435b1 100644 --- a/src/modules/resolution.c +++ b/src/modules/resolution.c @@ -27,9 +27,6 @@ void ffPrintResolution(FFinstance* instance) if(result->refreshRate > 0) printf(" @ %iHz", result->refreshRate); - if(result->brightness >= 0) - printf(" (Brightness %d%%)", result->brightness); - putchar('\n'); } else @@ -37,8 +34,7 @@ void ffPrintResolution(FFinstance* instance) ffPrintFormat(instance, FF_RESOLUTION_MODULE_NAME, moduleIndex, &instance->config.resolution, FF_RESOLUTION_NUM_FORMAT_ARGS, (FFformatarg[]) { {FF_FORMAT_ARG_TYPE_INT, &result->width}, {FF_FORMAT_ARG_TYPE_INT, &result->height}, - {FF_FORMAT_ARG_TYPE_INT, &result->refreshRate}, - {FF_FORMAT_ARG_TYPE_INT, &result->brightness}, + {FF_FORMAT_ARG_TYPE_INT, &result->refreshRate} }); } } From 8f932ac3d6369be8ce35f388a2cc94d6e361e4c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 9 Jan 2023 22:33:10 +0800 Subject: [PATCH 042/142] DisplayServer: fix build (Linux) --- src/detection/displayserver/linux/wayland.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/detection/displayserver/linux/wayland.c b/src/detection/displayserver/linux/wayland.c index 0a0d695f4..37891149c 100644 --- a/src/detection/displayserver/linux/wayland.c +++ b/src/detection/displayserver/linux/wayland.c @@ -66,7 +66,6 @@ static void waylandOutputModeListener(void* data, struct wl_output* output, uint result->width = (uint32_t) width; result->height = (uint32_t) height; result->refreshRate = ffdsParseRefreshRate(refreshRate / 1000); - result->brightness = -1; } static void waylandGlobalAddListener(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version) From d4c361ae1297d0e88cf02f99dc3ec3a094b592f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 10 Jan 2023 12:27:51 +0800 Subject: [PATCH 043/142] Battery: support FreeBSD Completely untested --- CHANGELOG.md | 1 + CMakeLists.txt | 3 +- src/detection/battery/battery_bsd.c | 56 +++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 src/detection/battery/battery_bsd.c diff --git a/CHANGELOG.md b/CHANGELOG.md index fc2eed5a4..caeb3e0d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ Features: * Add `--list-config-paths` option which list search paths of config files * Add `--list-data-paths` option which list search paths for presets and logos * Add `Brightness` module support +* Add `Battery` module support for FreeBSD Logos: * Raspbian (@IamNoRobot, #373) diff --git a/CMakeLists.txt b/CMakeLists.txt index 64f732c09..393784eaf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -382,7 +382,7 @@ elseif(BSD) src/common/networking_linux.c src/common/processing_linux.c src/common/sysctl.c - src/detection/battery/battery_nosupport.c + src/detection/battery/battery_bsd.c src/detection/bios/bios_bsd.c src/detection/board/board_nosupport.c src/detection/brightness/brightness_nosupport.c @@ -424,6 +424,7 @@ elseif(APPLE) src/common/processing_linux.c src/common/sysctl.c src/detection/battery/battery_apple.c + src/detection/battery/battery_bsd.c src/detection/bios/bios_apple.c src/detection/board/board_nosupport.c src/detection/brightness/brightness_apple.c diff --git a/src/detection/battery/battery_bsd.c b/src/detection/battery/battery_bsd.c new file mode 100644 index 000000000..f1a6136be --- /dev/null +++ b/src/detection/battery/battery_bsd.c @@ -0,0 +1,56 @@ +#include "fastfetch.h" +#include "battery.h" + +#include +#include +#include +#include + +const char* ffDetectBatteryImpl(FF_UNUSED_PARAM FFinstance* instance, FFlist* results) +{ + int acpifd = open("/dev/acpi", O_RDONLY); + if(acpifd < 0) + return "open(\"/dev/acpi\", O_RDONLY) failed"; + + int units = ioctl(acpifd, ACPIIO_BATT_GET_UNITS, 0); + if(units < 0) + { + close(acpifd); + return "No acpiio battery units found"; + } + + for(int i = 0; i < units; ++i) + { + union acpi_battery_ioctl_arg battio; + battio.unit = 0; + + if(ioctl(acpifd, ACPIIO_BATT_GET_BATTINFO, &battio) < 0 || (battio.battinfo.state & ACPI_BATT_STAT_NOT_PRESENT)) + continue; + + BatteryResult* battery = ffListAdd(results); + battery->temperature = FF_BATTERY_TEMP_UNSET; + ffStrbufInit(&battery->manufacturer); + ffStrbufInit(&battery->modelName); + ffStrbufInit(&battery->status); + ffStrbufInit(&battery->technology); + + battery->capacity = battio.battinfo.cap; + if(battio.battinfo.state & ACPI_BATT_STAT_INVALID) + { + ffStrbufAppendS(&battery->status, "Invalid"); + } + else + { + if(battio.battinfo.state & ACPI_BATT_STAT_DISCHARG) + ffStrbufAppendS(&battery->status, "Discharging, "); + else if(battio.battinfo.state & ACPI_BATT_STAT_CHARGING) + ffStrbufAppendS(&battery->status, "Charging, "); + if(battio.battinfo.state & ACPI_BATT_STAT_CRITICAL) + ffStrbufAppendS(&battery->status, "Ctritical"); + ffStrbufTrimRight(&battery->status, ' '); + ffStrbufTrimRight(&battery->status, ','); + } + } + close(acpifd); + return NULL; +} From bc8a7a03c3e602f895b3b4e86dd7dbcce5dc8c75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 10 Jan 2023 12:42:15 +0800 Subject: [PATCH 044/142] Battery: fix bug on FreeBSD oops --- src/detection/battery/battery_bsd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/battery/battery_bsd.c b/src/detection/battery/battery_bsd.c index f1a6136be..17ce47a2f 100644 --- a/src/detection/battery/battery_bsd.c +++ b/src/detection/battery/battery_bsd.c @@ -22,7 +22,7 @@ const char* ffDetectBatteryImpl(FF_UNUSED_PARAM FFinstance* instance, FFlist* re for(int i = 0; i < units; ++i) { union acpi_battery_ioctl_arg battio; - battio.unit = 0; + battio.unit = i; if(ioctl(acpifd, ACPIIO_BATT_GET_BATTINFO, &battio) < 0 || (battio.battinfo.state & ACPI_BATT_STAT_NOT_PRESENT)) continue; From af03c74fba09abdab313f24ec8294fcfd8be1cf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 10 Jan 2023 16:56:56 +0800 Subject: [PATCH 045/142] Battery: fix build on macOS --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 393784eaf..586b0b305 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -424,7 +424,6 @@ elseif(APPLE) src/common/processing_linux.c src/common/sysctl.c src/detection/battery/battery_apple.c - src/detection/battery/battery_bsd.c src/detection/bios/bios_apple.c src/detection/board/board_nosupport.c src/detection/brightness/brightness_apple.c From 7f97725d7f66a30576e5e43ba0b2a66dd41bfd45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 10 Jan 2023 17:31:47 +0800 Subject: [PATCH 046/142] Disk: add `--disk-show-unknown` option Ref: https://github.com/LinusDierheimer/fastfetch/issues/383#issuecomment-1376893128 --- CHANGELOG.md | 1 + src/common/init.c | 1 + src/data/config_user.txt | 25 +++++++++++++++++++++++++ src/data/help.txt | 1 + src/fastfetch.c | 2 ++ src/fastfetch.h | 1 + src/modules/disk.c | 3 +++ 7 files changed, 34 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index caeb3e0d9..44402b68a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ Features: * Add `--list-data-paths` option which list search paths for presets and logos * Add `Brightness` module support * Add `Battery` module support for FreeBSD +* Add `--disk-show-unknown` option for Disk module Logos: * Raspbian (@IamNoRobot, #373) diff --git a/src/common/init.c b/src/common/init.c index 59aee5fb1..c333e03b6 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -320,6 +320,7 @@ static void defaultConfig(FFinstance* instance) ffStrbufInitA(&instance->config.diskFolders, 0); instance->config.diskShowRemovable = true; instance->config.diskShowHidden = false; + instance->config.diskShowUnknown = false; ffStrbufInitA(&instance->config.batteryDir, 0); diff --git a/src/data/config_user.txt b/src/data/config_user.txt index 2afeba65e..d2faddb78 100644 --- a/src/data/config_user.txt +++ b/src/data/config_user.txt @@ -212,6 +212,31 @@ # Default is auto. #--gl auto +# Disk option +# Sets if removable volume should be printed +# Must be either true or false +# Default is true. +#--disk-show-removable true + +# Disk option +# Sets if hidden volume should be printed +# Must be either true or false +# Default is false. +#--disk-show-hidden false + +# Disk option +# Sets if unknown (unable to detect sizes) volume should be printed +# Must be either true or false +# Default is false. +#--disk-show-unknown false + +# Disk option +# A colon (semicolon on Windows) separated list of folder paths for the disk output +# This option override `--disk-show-*` options above +# Must be a string +# Default is "/:/home" ("C:\\;D:\\ ..." on Windows). +#--disk-folders /:/home + # Percentage output type option # Applies to all modules that prints percentage values. Currently memory, swap, disk, battery and CPU usage are supported. # Only works with default format ( without --module-format option ). diff --git a/src/data/help.txt b/src/data/help.txt index 6b6d39aea..5fb36821a 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -106,6 +106,7 @@ Module specific options: --disk-folders : A colon (semicolon on Windows) separated list of folder paths for the disk output. Default is "/:/home" ("C:\\;D:\\ ..." on Windows) --disk-show-removable : Set if removable volume should be printed. Default is true --disk-show-hidden : Set if hidden volumes should be printed. Default is false + --disk-show-unknown : Set if unknown (unable to detect sizes) volumes should be printed. Default is false --battery-dir : The directory where the battery folders are. Standard: /sys/class/power_supply/ --cpu-temp : Detect and display CPU temperature if supported. Default is false --gpu-temp : Detect and display GPU temperature if supported. Default is false diff --git a/src/fastfetch.c b/src/fastfetch.c index ad63f26a3..62935fc73 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -1254,6 +1254,8 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con instance->config.diskShowRemovable = optionParseBoolean(value); else if(strcasecmp(key, "--disk-show-hidden") == 0) instance->config.diskShowHidden = optionParseBoolean(value); + else if(strcasecmp(key, "--disk-show-unknown") == 0) + instance->config.diskShowUnknown = optionParseBoolean(value); else if(strcasecmp(key, "--battery-dir") == 0) optionParseString(key, value, &instance->config.batteryDir); else if(strcasecmp(key, "--separator-string") == 0) diff --git a/src/fastfetch.h b/src/fastfetch.h index 0572ef294..e215d3e3f 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -180,6 +180,7 @@ typedef struct FFconfig FFstrbuf diskFolders; bool diskShowRemovable; bool diskShowHidden; + bool diskShowUnknown; FFstrbuf batteryDir; diff --git a/src/modules/disk.c b/src/modules/disk.c index eb6baeb47..ba07fb823 100644 --- a/src/modules/disk.c +++ b/src/modules/disk.c @@ -135,6 +135,9 @@ static void printAutodetected(FFinstance* instance, const FFlist* disks) if(disk->type == FF_DISK_TYPE_HIDDEN && !instance->config.diskShowHidden) continue; + if(disk->bytesTotal == 0 && !instance->config.diskShowUnknown) + continue; + printDisk(instance, disk); } } From ef2a5110fe75834efd0b67aee4fd3001790161b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 10 Jan 2023 19:24:59 +0800 Subject: [PATCH 047/142] TerminalShell: detect terminal version when available --- CHANGELOG.md | 2 ++ src/detection/terminalshell/terminalshell.c | 26 +++++++++++++++++++ src/detection/terminalshell/terminalshell.h | 1 + .../terminalshell/terminalshell_linux.c | 5 ++++ .../terminalshell/terminalshell_windows.cpp | 5 ++++ src/modules/terminal.c | 6 ++++- 6 files changed, 44 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44402b68a..4809204dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ Notable Changes: * fastfetch no longer creates a sample config file silently. Use `--gen-config` to generate one. * fastfetch now search for user config file in the order of `fastfetch --list-config-paths` +* Unknown disks are hidden by default. Features: * `--logo-padding-top` option (@CarterLi, #372) @@ -14,6 +15,7 @@ Features: * Add `Brightness` module support * Add `Battery` module support for FreeBSD * Add `--disk-show-unknown` option for Disk module +* Detect terminal version when available Logos: * Raspbian (@IamNoRobot, #373) diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index a99c498e4..3a80ce153 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -155,3 +155,29 @@ bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version) ok = false; return ok; } + +bool fftsGetTerminalVersion(FFstrbuf* processName, FF_UNUSED_PARAM FFstrbuf* exe, FFstrbuf* version) +{ + const char* termProgramVersion = getenv("TERM_PROGRAM_VERSION"); + if(termProgramVersion) + { + const char* termProgram = getenv("TERM_PROGRAM"); + if(termProgram) + { + if(ffStrbufStartsWithIgnCaseS(processName, termProgram) || // processName ends with `.exe` on Windows + (strcmp(termProgram, "vscode") == 0 && ffStrbufStartsWithIgnCaseS(processName, "code")) + ) { + ffStrbufSetS(version, termProgramVersion); + return true; + } + } + } + + #ifdef _WIN32 + + return getFileVersion(exe->chars, version); + + #endif + + return false; +} diff --git a/src/detection/terminalshell/terminalshell.h b/src/detection/terminalshell/terminalshell.h index 8783e3410..a2a1f4200 100644 --- a/src/detection/terminalshell/terminalshell.h +++ b/src/detection/terminalshell/terminalshell.h @@ -17,6 +17,7 @@ typedef struct FFTerminalShellResult FFstrbuf terminalExe; FFstrbuf terminalPrettyName; const char* terminalExeName; //pointer to a char in terminalExe + FFstrbuf terminalVersion; FFstrbuf userShellExe; const char* userShellExeName; //pointer to a char in userShellExe diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index 80c0d93d1..fb3ad0a76 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -310,6 +310,8 @@ static void getShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* versio getShellVersionGeneric(exe, exeName, version); } +bool fftsGetTerminalVersion(FFstrbuf* processName, FFstrbuf* exe, FFstrbuf* version); + const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance) { FF_UNUSED(instance); @@ -378,6 +380,9 @@ const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance) else ffStrbufInitCopy(&result.terminalPrettyName, &result.terminalProcessName); + ffStrbufInit(&result.terminalVersion); + fftsGetTerminalVersion(&result.terminalProcessName, &result.terminalExe, &result.terminalVersion); + ffThreadMutexUnlock(&mutex); return &result; } diff --git a/src/detection/terminalshell/terminalshell_windows.cpp b/src/detection/terminalshell/terminalshell_windows.cpp index cb2da1ca4..e4355666e 100644 --- a/src/detection/terminalshell/terminalshell_windows.cpp +++ b/src/detection/terminalshell/terminalshell_windows.cpp @@ -263,6 +263,8 @@ static void getTerminalFromEnv(FFTerminalShellResult* result) } } +extern "C" bool fftsGetTerminalVersion(FFstrbuf* processName, FFstrbuf* exe, FFstrbuf* version); + const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance) { FF_UNUSED(instance); @@ -302,6 +304,9 @@ const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance) if(result.terminalProcessName.length == 0) getTerminalFromEnv(&result); + ffStrbufInit(&result.terminalVersion); + fftsGetTerminalVersion(&result.terminalProcessName, &result.terminalExe, &result.terminalVersion); + exit: ffThreadMutexUnlock(&mutex); return &result; diff --git a/src/modules/terminal.c b/src/modules/terminal.c index 469ece23b..28e8d14a5 100644 --- a/src/modules/terminal.c +++ b/src/modules/terminal.c @@ -20,7 +20,11 @@ void ffPrintTerminal(FFinstance* instance) if(instance->config.terminal.outputFormat.length == 0) { ffPrintLogoAndKey(instance, FF_TERMINAL_MODULE_NAME, 0, &instance->config.terminal.key); - ffStrbufPutTo(&result->terminalPrettyName, stdout); + + if(result->terminalVersion.length) + printf("%s %s\n", result->terminalPrettyName.chars, result->terminalVersion.chars); + else + ffStrbufPutTo(&result->terminalPrettyName, stdout); } else { From c6365755c742ec336e3f280f543fcca234f404c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 10 Jan 2023 20:56:54 +0800 Subject: [PATCH 048/142] Title: fix computer name being trancated sometime --- src/util/windows/utsname.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/windows/utsname.c b/src/util/windows/utsname.c index a1f68021d..c21389f19 100644 --- a/src/util/windows/utsname.c +++ b/src/util/windows/utsname.c @@ -13,7 +13,7 @@ static int detectSysname(struct utsname *name) static int detectNodename(struct utsname *name) { DWORD bufSize = UTSNAME_MAXLENGTH - 1; - if(!GetComputerNameA(name->nodename, &bufSize)) + if(!GetComputerNameExA(ComputerNameDnsFullyQualified, name->nodename, &bufSize)) return 1; name->nodename[bufSize] = '\0'; return 0; From db17f95ce81909985d72d35caafe0402ed56efed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 10 Jan 2023 21:11:44 +0800 Subject: [PATCH 049/142] TerminalShell: detect Termux version --- src/detection/terminalshell/terminalshell.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index 3a80ce153..0b68dfbe0 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -158,6 +158,16 @@ bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version) bool fftsGetTerminalVersion(FFstrbuf* processName, FF_UNUSED_PARAM FFstrbuf* exe, FFstrbuf* version) { + #ifdef __ANDROID__ + + if(ffStrbufEqualS(processName, "Termux")) + { + ffStrbufSetS(version, getenv("TERMUX_VERSION")); + return true; + } + + #endif + const char* termProgramVersion = getenv("TERM_PROGRAM_VERSION"); if(termProgramVersion) { @@ -177,7 +187,9 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_UNUSED_PARAM FFstrbuf* exe return getFileVersion(exe->chars, version); - #endif + #else return false; + + #endif } From 8ffbae80b85ee8e231c66e37a01efc0dbaa901fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 11 Jan 2023 01:23:42 +0800 Subject: [PATCH 050/142] Windows: clarify we support Windows 7 and newer only --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 586b0b305..eecedaa4b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -102,6 +102,7 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wconversion") if(WIN32) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wconversion -fno-exceptions -fno-rtti") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--tsaware -Wl,--build-id -Wl,--subsystem,console:6.1,--major-os-version,6,--minor-os-version,1 -Wl,--relax") endif() # Used for dlopen finding dylibs installed by homebrew From a67ba713f5239eb9f4307d3542d3196f8079bcb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 11 Jan 2023 09:37:00 +0800 Subject: [PATCH 051/142] Windows: fix CLANG64 build --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index eecedaa4b..4abd15ffb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -102,7 +102,7 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wconversion") if(WIN32) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wconversion -fno-exceptions -fno-rtti") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--tsaware -Wl,--build-id -Wl,--subsystem,console:6.1,--major-os-version,6,--minor-os-version,1 -Wl,--relax") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--tsaware -Wl,--build-id -Wl,--subsystem,console:6.1,--major-os-version,6,--minor-os-version,1") endif() # Used for dlopen finding dylibs installed by homebrew From 94a8e0339ed33d00c13b220529947bd7894e3a61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 11 Jan 2023 13:51:47 +0800 Subject: [PATCH 052/142] Windows: remove outdated comments --- src/common/processing_windows.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/common/processing_windows.c b/src/common/processing_windows.c index 30e515734..736c121b3 100644 --- a/src/common/processing_windows.c +++ b/src/common/processing_windows.c @@ -4,7 +4,6 @@ #define WIN32_LEAN_AND_MEAN 1 #include -//We can't use this native version yet because we still use POSIX path ( eg /usr/bin/fish ) at a lot of places. const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[]) { SECURITY_ATTRIBUTES saAttr = { From b8393051e430f8aa4e9d0533e22f5d76e492fac1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 11 Jan 2023 13:52:14 +0800 Subject: [PATCH 053/142] Battery: add comments for future use (FreeBSD) --- src/detection/battery/battery_bsd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/detection/battery/battery_bsd.c b/src/detection/battery/battery_bsd.c index 17ce47a2f..881291af1 100644 --- a/src/detection/battery/battery_bsd.c +++ b/src/detection/battery/battery_bsd.c @@ -8,6 +8,9 @@ const char* ffDetectBatteryImpl(FF_UNUSED_PARAM FFinstance* instance, FFlist* results) { + //https://www.freebsd.org/cgi/man.cgi?acpi_battery(4) + //https://gitlab.xfce.org/panel-plugins/xfce4-battery-plugin/-/blob/master/panel-plugin/libacpi.c + int acpifd = open("/dev/acpi", O_RDONLY); if(acpifd < 0) return "open(\"/dev/acpi\", O_RDONLY) failed"; From ccdb5c54d02cc4c0926d76df55e29e95bac81e79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 11 Jan 2023 13:55:06 +0800 Subject: [PATCH 054/142] Linux: enable FF_*_AUTO_DESTROY They have been on Windows and macOS for sometime and worked well. --- src/util/FFlist.h | 4 +--- src/util/FFstrbuf.h | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/util/FFlist.h b/src/util/FFlist.h index 86b20bc5c..e65180d3a 100644 --- a/src/util/FFlist.h +++ b/src/util/FFlist.h @@ -51,8 +51,6 @@ static inline void ffListSort(FFlist* list, int(*compar)(const void*, const void itemVarName - (itemType*)(listVar).data < (listVar).length; \ ++itemVarName) -#if defined(_WIN32) || defined(__APPLE__) - #define FF_LIST_AUTO_DESTROY FFlist __attribute__((__cleanup__(ffListDestroy))) -#endif +#define FF_LIST_AUTO_DESTROY FFlist __attribute__((__cleanup__(ffListDestroy))) #endif diff --git a/src/util/FFstrbuf.h b/src/util/FFstrbuf.h index 94adc6b03..7755225a7 100644 --- a/src/util/FFstrbuf.h +++ b/src/util/FFstrbuf.h @@ -310,8 +310,6 @@ static inline FF_C_NODISCARD bool ffStrbufEndsWithIgnCase(const FFstrbuf* strbuf return ffStrbufEndsWithIgnCaseNS(strbuf, end->length, end->chars); } -#if defined(_WIN32) || defined(__APPLE__) - #define FF_STRBUF_AUTO_DESTROY FFstrbuf __attribute__((__cleanup__(ffStrbufDestroy))) -#endif +#define FF_STRBUF_AUTO_DESTROY FFstrbuf __attribute__((__cleanup__(ffStrbufDestroy))) #endif From 54ea9c23864e1aa5a0314a9e05362528358ee881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 11 Jan 2023 13:58:59 +0800 Subject: [PATCH 055/142] TerminalFont: support WezTerm font detection --- CHANGELOG.md | 1 + src/detection/terminalfont/terminalfont.c | 30 +++++++++++++++++++ .../terminalshell/terminalshell_linux.c | 2 ++ 3 files changed, 33 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4809204dc..5c49019b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ Features: * Add `Battery` module support for FreeBSD * Add `--disk-show-unknown` option for Disk module * Detect terminal version when available +* Support `WezTerm` terminal font detection (requires [`wezterm` executable](https://wezfurlong.org/wezterm/cli/general.html) being available) Logos: * Raspbian (@IamNoRobot, #373) diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index 5716b720d..a4a049276 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -320,6 +320,34 @@ static bool detectKitty(const FFinstance* instance, FFTerminalFontResult* result return true; } +static bool detectWezterm(FF_UNUSED_PARAM const FFinstance* instance, FFTerminalFontResult* result) +{ + FF_STRBUF_AUTO_DESTROY fontName; + ffStrbufInit(&fontName); + + ffStrbufSetS(&result->error, ffProcessAppendStdOut(&fontName, (char* const[]){ + "wezterm", + "ls-fonts", + "--text", + "a", + NULL + })); + if(result->error.length) + return false; + + //LeftToRight + // 0 a \u{61} x_adv=7 cells=1 glyph=a,180 wezterm.font("JetBrains Mono", {weight="Regular", stretch="Normal", style="Normal"}) + // , BuiltIn + ffStrbufSubstrAfterFirstC(&fontName, '"'); + ffStrbufSubstrBeforeFirstC(&fontName, '"'); + + if(!fontName.length) + return false; + + ffFontInitCopy(&result->font, fontName.chars); + return true; +} + void ffDetectTerminalFontPlatform(const FFinstance* instance, const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont); static bool detectTerminalFontCommon(const FFinstance* instance, const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont) @@ -328,6 +356,8 @@ static bool detectTerminalFontCommon(const FFinstance* instance, const FFTermina detectAlacritty(instance, terminalFont); else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "kitty") == 0) detectKitty(instance, terminalFont); + else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "wezterm-gui") == 0) + detectWezterm(instance, terminalFont); else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalExe, "/dev/tty")) detectTTY(terminalFont); diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index fb3ad0a76..510897287 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -375,6 +375,8 @@ const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance) ffStrbufInitS(&result.terminalPrettyName, "Apple Terminal"); else if(ffStrbufEqualS(&result.terminalProcessName, "WarpTerminal")) ffStrbufInitS(&result.terminalPrettyName, "Warp"); + else if(ffStrbufEqualS(&result.terminalProcessName, "wezterm-gui")) + ffStrbufInitS(&result.terminalPrettyName, "WezTerm"); else if(strncmp(result.terminalExeName, result.terminalProcessName.chars, result.terminalProcessName.length) == 0) // if exeName starts with processName, print it. Otherwise print processName ffStrbufInitS(&result.terminalPrettyName, result.terminalExeName); else From b1f63ab822a7bfc8ecb610ce39a83912a7d392ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 11 Jan 2023 14:47:10 +0800 Subject: [PATCH 056/142] Global: rename FF_UNUSED_PARAM to FF_MAYBE_UNUSED since it can be used on functions too. --- src/detection/battery/battery_bsd.c | 2 +- src/detection/brightness/brightness_linux.c | 2 +- src/detection/brightness/brightness_nosupport.c | 2 +- src/detection/terminalfont/terminalfont.c | 2 +- src/detection/terminalshell/terminalshell.c | 2 +- src/detection/wifi/wifi_windows.c | 2 +- src/fastfetch.h | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/detection/battery/battery_bsd.c b/src/detection/battery/battery_bsd.c index 881291af1..2cfbe4b7b 100644 --- a/src/detection/battery/battery_bsd.c +++ b/src/detection/battery/battery_bsd.c @@ -6,7 +6,7 @@ #include #include -const char* ffDetectBatteryImpl(FF_UNUSED_PARAM FFinstance* instance, FFlist* results) +const char* ffDetectBatteryImpl(FF_MAYBE_UNUSED FFinstance* instance, FFlist* results) { //https://www.freebsd.org/cgi/man.cgi?acpi_battery(4) //https://gitlab.xfce.org/panel-plugins/xfce4-battery-plugin/-/blob/master/panel-plugin/libacpi.c diff --git a/src/detection/brightness/brightness_linux.c b/src/detection/brightness/brightness_linux.c index 31e346062..0f2a9d5fd 100644 --- a/src/detection/brightness/brightness_linux.c +++ b/src/detection/brightness/brightness_linux.c @@ -3,7 +3,7 @@ #include -const char* ffDetectBrightness(FF_UNUSED_PARAM FFlist* result) +const char* ffDetectBrightness(FF_MAYBE_UNUSED FFlist* result) { //https://www.kernel.org/doc/Documentation/ABI/stable/sysfs-class-backlight const char* backlightDirPath = "/sys/class/backlight/"; diff --git a/src/detection/brightness/brightness_nosupport.c b/src/detection/brightness/brightness_nosupport.c index 5661c180f..4bd83c4de 100644 --- a/src/detection/brightness/brightness_nosupport.c +++ b/src/detection/brightness/brightness_nosupport.c @@ -1,6 +1,6 @@ #include "brightness.h" -const char* ffDetectBrightness(FF_UNUSED_PARAM FFlist* result) +const char* ffDetectBrightness(FF_MAYBE_UNUSED FFlist* result) { return "Not supported on this platform"; } diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index a4a049276..1dde994bf 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -320,7 +320,7 @@ static bool detectKitty(const FFinstance* instance, FFTerminalFontResult* result return true; } -static bool detectWezterm(FF_UNUSED_PARAM const FFinstance* instance, FFTerminalFontResult* result) +static bool detectWezterm(FF_MAYBE_UNUSED const FFinstance* instance, FFTerminalFontResult* result) { FF_STRBUF_AUTO_DESTROY fontName; ffStrbufInit(&fontName); diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index 0b68dfbe0..65b06bc78 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -156,7 +156,7 @@ bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version) return ok; } -bool fftsGetTerminalVersion(FFstrbuf* processName, FF_UNUSED_PARAM FFstrbuf* exe, FFstrbuf* version) +bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe, FFstrbuf* version) { #ifdef __ANDROID__ diff --git a/src/detection/wifi/wifi_windows.c b/src/detection/wifi/wifi_windows.c index 92322440f..a972939d7 100644 --- a/src/detection/wifi/wifi_windows.c +++ b/src/detection/wifi/wifi_windows.c @@ -40,7 +40,7 @@ static void convertIfStateToString(WLAN_INTERFACE_STATE state, FFstrbuf* result) } } -const char* ffDetectWifi(FF_UNUSED_PARAM const FFinstance* instance, FFlist* result) +const char* ffDetectWifi(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* result) { FF_LIBRARY_LOAD(wlanapi, NULL, "dlopen wlanapi"FF_LIBRARY_EXTENSION" failed", "wlanapi"FF_LIBRARY_EXTENSION, 1) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(wlanapi, WlanOpenHandle) diff --git a/src/fastfetch.h b/src/fastfetch.h index e215d3e3f..af9496c8d 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -21,7 +21,7 @@ static inline void ffUnused(int dummy, ...) { (void) dummy; } #define FF_UNUSED(...) ffUnused(0, __VA_ARGS__); -#define FF_UNUSED_PARAM __attribute__ ((__unused__)) +#define FF_MAYBE_UNUSED __attribute__ ((__unused__)) #define FASTFETCH_LOGO_MAX_COLORS 9 //two digits would make parsing much more complicated (index 1 - 9) From a0acfeed56cbebf28db08edc20015fe078209837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 11 Jan 2023 15:03:16 +0800 Subject: [PATCH 057/142] TermiinalShell: code refactor --- src/detection/terminalshell/terminalshell.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index 65b06bc78..2c139b5f2 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -156,15 +156,18 @@ bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version) return ok; } +FF_MAYBE_UNUSED static bool getTerminalVersionTermux(FFstrbuf* version) +{ + ffStrbufSetS(version, getenv("TERMUX_VERSION")); + return true; +} + bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe, FFstrbuf* version) { #ifdef __ANDROID__ if(ffStrbufEqualS(processName, "Termux")) - { - ffStrbufSetS(version, getenv("TERMUX_VERSION")); - return true; - } + return getTerminalVersionTermux(version); #endif From 76d957a144b52b293ab0936e7c47adb72e338d4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 11 Jan 2023 15:03:42 +0800 Subject: [PATCH 058/142] TerminalShell: support gnome-terminal version detection --- src/detection/terminalshell/terminalshell.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index 2c139b5f2..363fdb418 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -162,6 +162,20 @@ FF_MAYBE_UNUSED static bool getTerminalVersionTermux(FFstrbuf* version) return true; } +FF_MAYBE_UNUSED static bool getTerminalVersionGnome(FFstrbuf* version) +{ + if(ffProcessAppendStdOut(version, (char* const[]){ + "gnome-terminal", + "--version", + NULL + })) return false; + + //# GNOME Terminal 3.46.7 using VTE 0.70.2 +BIDI +GNUTLS +ICU +SYSTEMD + ffStrbufSubstrAfterFirstS(version, "Terminal "); + ffStrbufSubstrBeforeFirstC(version, ' '); + return true; +} + bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe, FFstrbuf* version) { #ifdef __ANDROID__ @@ -171,6 +185,13 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe #endif + #if defined(__linux__) || defined(__FreeBSD__) + + if(ffStrbufIgnCaseEqualS(processName, "gnome-terminal-")) + return getTerminalVersionGnome(version); + + #endif + const char* termProgramVersion = getenv("TERM_PROGRAM_VERSION"); if(termProgramVersion) { From b2f978aa7ca9c8dd50dbb3145220132bdd268a47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 11 Jan 2023 15:14:29 +0800 Subject: [PATCH 059/142] TerminalShell: support kitty version detection --- src/detection/terminalshell/terminalshell.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index 363fdb418..9e1e8c8a8 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -176,6 +176,20 @@ FF_MAYBE_UNUSED static bool getTerminalVersionGnome(FFstrbuf* version) return true; } +FF_MAYBE_UNUSED static bool getTerminalVersionKitty(FFstrbuf* exe, FFstrbuf* version) +{ + if(ffProcessAppendStdOut(version, (char* const[]){ + exe->chars, + "--version", + NULL + })) return false; + + //kitty 0.21.2 created by Kovid Goyal + ffStrbufSubstrAfterFirstC(version, ' '); + ffStrbufSubstrBeforeFirstC(version, ' '); + return true; +} + bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe, FFstrbuf* version) { #ifdef __ANDROID__ @@ -192,6 +206,13 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe #endif + #ifndef _WIN32 + + if(ffStrbufIgnCaseEqualS(processName, "kitty")) + return getTerminalVersionKitty(exe, version); + + #endif + const char* termProgramVersion = getenv("TERM_PROGRAM_VERSION"); if(termProgramVersion) { From ee903d2d07f1b282f1034ac4defcae2d6ff76dfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 11 Jan 2023 15:56:24 +0800 Subject: [PATCH 060/142] TerminalShell: support konsole version detection --- src/detection/terminalshell/terminalshell.c | 32 +++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index 9e1e8c8a8..09ae5ba9f 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -176,6 +176,35 @@ FF_MAYBE_UNUSED static bool getTerminalVersionGnome(FFstrbuf* version) return true; } +FF_MAYBE_UNUSED static bool getTerminalVersionKonsole(FFstrbuf* exe, FFstrbuf* version) +{ + const char* konsoleVersion = getenv("KONSOLE_VERSION"); + if(konsoleVersion) + { + //221201 + long major = strtol(konsoleVersion, NULL, 10); + if (major >= 0) + { + long patch = major % 100; + major /= 100; + long minor = major % 100; + major /= 100; + ffStrbufSetF(version, "%ld.%ld.%ld", major, minor, patch); + return true; + } + } + + if(ffProcessAppendStdOut(version, (char* const[]){ + exe->chars, + "--version", + NULL + })) return false; + + //konsole 22.12.1 + ffStrbufSubstrAfterFirstC(version, ' '); + return true; +} + FF_MAYBE_UNUSED static bool getTerminalVersionKitty(FFstrbuf* exe, FFstrbuf* version) { if(ffProcessAppendStdOut(version, (char* const[]){ @@ -204,6 +233,9 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe if(ffStrbufIgnCaseEqualS(processName, "gnome-terminal-")) return getTerminalVersionGnome(version); + if(ffStrbufIgnCaseEqualS(processName, "konsole")) + return getTerminalVersionKonsole(exe, version); + #endif #ifndef _WIN32 From 09ff8d35bc982d5f0685495370a4854f108d91fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 11 Jan 2023 16:07:34 +0800 Subject: [PATCH 061/142] TerminalShell: support xfce4-terminal version detection --- src/detection/terminalshell/terminalshell.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index 09ae5ba9f..96b86791c 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -205,6 +205,20 @@ FF_MAYBE_UNUSED static bool getTerminalVersionKonsole(FFstrbuf* exe, FFstrbuf* v return true; } +FF_MAYBE_UNUSED static bool getTerminalVersionXfce4(FFstrbuf* exe, FFstrbuf* version) +{ + if(ffProcessAppendStdOut(version, (char* const[]){ + exe->chars, + "--version", + NULL + })) return false; + + //xfce4-terminal 1.0.4 (Xfce 4.18)... + ffStrbufSubstrAfterFirstC(version, ' '); + ffStrbufSubstrBeforeFirstC(version, ' '); + return true; +} + FF_MAYBE_UNUSED static bool getTerminalVersionKitty(FFstrbuf* exe, FFstrbuf* version) { if(ffProcessAppendStdOut(version, (char* const[]){ @@ -236,6 +250,9 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe if(ffStrbufIgnCaseEqualS(processName, "konsole")) return getTerminalVersionKonsole(exe, version); + if(ffStrbufIgnCaseEqualS(processName, "xfce4-terminal")) + return getTerminalVersionXfce4(exe, version); + #endif #ifndef _WIN32 From 9dab23b5fca4a1fb9d3534024ba590b636ee2286 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 11 Jan 2023 16:34:37 +0800 Subject: [PATCH 062/142] TerminalShell: code refactor --- src/detection/terminalshell/terminalshell.c | 173 +++++++------------- 1 file changed, 63 insertions(+), 110 deletions(-) diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index 96b86791c..133a6281b 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -36,130 +36,119 @@ static bool getFileVersion(const char* exePath, FFstrbuf* version) #endif -static void getShellVersionBash(FFstrbuf* exe, FFstrbuf* version) +static bool getExeVersionRaw(FFstrbuf* exe, FFstrbuf* version) { - ffProcessAppendStdOut(version, (char* const[]) { + return ffProcessAppendStdOut(version, (char* const[]) { exe->chars, "--version", NULL - }); // GNU bash, version 5.1.16(1)-release (x86_64-pc-msys)\nCopyright... + }) == NULL; +} + +static bool getExeVersionGeneral(FFstrbuf* exe, FFstrbuf* version) +{ + if(!getExeVersionRaw(exe, version)) + return false; + + ffStrbufSubstrAfterFirstC(version, ' '); + ffStrbufSubstrBeforeFirstC(version, ' '); + return true; +} + +static bool getShellVersionBash(FFstrbuf* exe, FFstrbuf* version) +{ + if(!getExeVersionRaw(exe, version)) + return false; + + // GNU bash, version 5.1.16(1)-release (x86_64-pc-msys)\nCopyright... ffStrbufSubstrBeforeFirstC(version, '\n'); // GNU bash, version 5.1.16(1)-release (x86_64-pc-msys) ffStrbufSubstrBeforeLastC(version, ' '); // GNU bash, version 5.1.16(1)-release ffStrbufSubstrAfterLastC(version, ' '); // 5.1.16(1)-release ffStrbufSubstrBeforeFirstC(version, '('); // 5.1.16 + return true; } -static void getShellVersionZsh(FFstrbuf* exe, FFstrbuf* version) +static bool getShellVersionFish(FFstrbuf* exe, FFstrbuf* version) { - ffProcessAppendStdOut(version, (char* const[]) { - exe->chars, - "--version", - NULL - }); - ffStrbufSubstrBeforeLastC(version, ' '); - ffStrbufSubstrAfterFirstC(version, ' '); -} + if(!getExeVersionRaw(exe, version)) + return false; -static void getShellVersionFish(FFstrbuf* exe, FFstrbuf* version) -{ - ffProcessAppendStdOut(version, (char* const[]) { - exe->chars, - "--version", - NULL - }); + //fish, version 3.6.0 ffStrbufTrimRight(version, '\n'); ffStrbufSubstrAfterLastC(version, ' '); + return true; } -static void getShellVersionTcsh(FFstrbuf* exe, FFstrbuf* version) -{ - ffProcessAppendStdOut(version, (char* const[]) { - exe->chars, - "--version", - NULL - }); // tcsh 6.24.01 (Astron) 2022-05-12 (aarch64-apple-darwin) options wide,nls,dl,al,kan,sm,rh,color,filec - ffStrbufSubstrAfterFirstC(version, ' '); // 6.24.01 (Astron) 2022-05-12 (aarch64-apple-darwin) options wide,nls,dl,al,kan,sm,rh,color,filec - ffStrbufSubstrBeforeFirstC(version, ' '); // 6.24.01 -} - -static void getShellVersionPwsh(FFstrbuf* exe, FFstrbuf* version) +static bool getShellVersionPwsh(FFstrbuf* exe, FFstrbuf* version) { #ifdef _WIN32 if(getFileVersion(exe->chars, version)) - return; + { + ffStrbufSubstrBeforeLastC(version, '.'); + return true; + } #endif - ffProcessAppendStdOut(version, (char* const[]) { - exe->chars, - "--version", - NULL - }); + if(!getExeVersionRaw(exe, version)) + return false; + ffStrbufTrimRight(version, '\n'); ffStrbufSubstrAfterLastC(version, ' '); + return true; } #ifdef _WIN32 -static void getShellVersionWinPowerShell(FFstrbuf* exe, FFstrbuf* version) +static bool getShellVersionWinPowerShell(FFstrbuf* exe, FFstrbuf* version) { - ffProcessAppendStdOut(version, (char* const[]) { + if(ffProcessAppendStdOut(version, (char* const[]) { exe->chars, "-NoLogo", "-NoProfile", "-Command", "$PSVersionTable.PSVersion.ToString()", NULL - }); + })) return false; + ffStrbufTrimRight(version, '\n'); ffStrbufSubstrAfterLastC(version, ' '); + return true; } -static void getShellVersionCmd(FFstrbuf* exe, FFstrbuf* version) +static bool getShellVersionCmd(FFstrbuf* exe, FFstrbuf* version) { - getFileVersion(exe->chars, version); + return getFileVersion(exe->chars, version); } #endif -static void getShellVersionNu(FFstrbuf* exe, FFstrbuf* version) -{ - ffProcessAppendStdOut(version, (char* const[]) { - exe->chars, - "--version", - NULL - }); -} - bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version) { - bool ok = true; if(strcasecmp(exeName, "bash") == 0 || strcasecmp(exeName, "sh") == 0) - getShellVersionBash(exe, version); - else if(strcasecmp(exeName, "zsh") == 0) - getShellVersionZsh(exe, version); - else if(strcasecmp(exeName, "fish") == 0) - getShellVersionFish(exe, version); - else if(strcasecmp(exeName, "pwsh") == 0) - getShellVersionPwsh(exe, version); - else if(strcasecmp(exeName, "csh") == 0 || strcasecmp(exeName, "tcsh") == 0) - getShellVersionTcsh(exe, version); - else if(strcasecmp(exeName, "nu") == 0) - getShellVersionNu(exe, version); + return getShellVersionBash(exe, version); + if(strcasecmp(exeName, "zsh") == 0) + return getExeVersionGeneral(exe, version); //zsh 5.9 (arm-apple-darwin21.3.0) + if(strcasecmp(exeName, "fish") == 0) + return getShellVersionFish(exe, version); + if(strcasecmp(exeName, "pwsh") == 0) + return getShellVersionPwsh(exe, version); + if(strcasecmp(exeName, "csh") == 0 || strcasecmp(exeName, "tcsh") == 0) + return getExeVersionGeneral(exe, version); //tcsh 6.24.07 (Astron) 2022-12-21 (aarch64-apple-darwin) options wide,nls,dl,al,kan,sm,rh,color,filec + if(strcasecmp(exeName, "nu") == 0) + return getExeVersionRaw(exe, version); //0.73.0 #ifdef _WIN32 - else if(strcasecmp(exeName, "powershell") == 0 || strcasecmp(exeName, "powershell_ise") == 0) - getShellVersionWinPowerShell(exe, version); - else if(strcasecmp(exeName, "cmd") == 0) - getShellVersionCmd(exe, version); + if(strcasecmp(exeName, "powershell") == 0 || strcasecmp(exeName, "powershell_ise") == 0) + return getShellVersionWinPowerShell(exe, version); + if(strcasecmp(exeName, "cmd") == 0) + return getShellVersionCmd(exe, version); #endif - else - ok = false; - return ok; + return false; } FF_MAYBE_UNUSED static bool getTerminalVersionTermux(FFstrbuf* version) { ffStrbufSetS(version, getenv("TERMUX_VERSION")); - return true; + return version->length > 0; } FF_MAYBE_UNUSED static bool getTerminalVersionGnome(FFstrbuf* version) @@ -194,43 +183,7 @@ FF_MAYBE_UNUSED static bool getTerminalVersionKonsole(FFstrbuf* exe, FFstrbuf* v } } - if(ffProcessAppendStdOut(version, (char* const[]){ - exe->chars, - "--version", - NULL - })) return false; - - //konsole 22.12.1 - ffStrbufSubstrAfterFirstC(version, ' '); - return true; -} - -FF_MAYBE_UNUSED static bool getTerminalVersionXfce4(FFstrbuf* exe, FFstrbuf* version) -{ - if(ffProcessAppendStdOut(version, (char* const[]){ - exe->chars, - "--version", - NULL - })) return false; - - //xfce4-terminal 1.0.4 (Xfce 4.18)... - ffStrbufSubstrAfterFirstC(version, ' '); - ffStrbufSubstrBeforeFirstC(version, ' '); - return true; -} - -FF_MAYBE_UNUSED static bool getTerminalVersionKitty(FFstrbuf* exe, FFstrbuf* version) -{ - if(ffProcessAppendStdOut(version, (char* const[]){ - exe->chars, - "--version", - NULL - })) return false; - - //kitty 0.21.2 created by Kovid Goyal - ffStrbufSubstrAfterFirstC(version, ' '); - ffStrbufSubstrBeforeFirstC(version, ' '); - return true; + return getExeVersionGeneral(exe, version); } bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe, FFstrbuf* version) @@ -251,14 +204,14 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe return getTerminalVersionKonsole(exe, version); if(ffStrbufIgnCaseEqualS(processName, "xfce4-terminal")) - return getTerminalVersionXfce4(exe, version); + return getExeVersionGeneral(exe, version);//xfce4-terminal 1.0.4 (Xfce 4.18)... #endif #ifndef _WIN32 if(ffStrbufIgnCaseEqualS(processName, "kitty")) - return getTerminalVersionKitty(exe, version); + return getExeVersionGeneral(exe, version); //kitty 0.21.2 created by Kovid Goyal #endif From 7145f5252daba28b9c096691f2d9d54e67ad1584 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 11 Jan 2023 17:17:17 +0800 Subject: [PATCH 063/142] TerminalShell: add `--shell-version` and `--terminal-version` options to disable shell / terminal version detection in case that users don't like it --- CHANGELOG.md | 2 ++ completions/bash | 4 ++++ src/common/init.c | 3 +++ src/data/config_user.txt | 12 ++++++++++++ src/data/help.txt | 2 ++ .../terminalshell/terminalshell_linux.c | 19 +++++++++++++------ .../terminalshell/terminalshell_windows.cpp | 6 ++++-- src/fastfetch.c | 4 ++++ src/fastfetch.h | 3 +++ 9 files changed, 47 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c49019b0..983db0620 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,8 +15,10 @@ Features: * Add `Brightness` module support * Add `Battery` module support for FreeBSD * Add `--disk-show-unknown` option for Disk module +* Add `--disk-show-unknown` option for Disk module * Detect terminal version when available * Support `WezTerm` terminal font detection (requires [`wezterm` executable](https://wezfurlong.org/wezterm/cli/general.html) being available) +* Add `--shell-version` and `--terminal-version` options to disable shell / terminal version detection Logos: * Raspbian (@IamNoRobot, #373) diff --git a/completions/bash b/completions/bash index 5dedf5f6f..e7efe1c18 100644 --- a/completions/bash +++ b/completions/bash @@ -189,8 +189,12 @@ __fastfetch_completion() "--pipe" "--title-fqdn" "--escape-bedrock" + "--shell-version" + "--terminal-version" + "--disk-folders" "--disk-show-removable" "--disk-show-hidden" + "--disk-show-unknown" ) local FF_OPTIONS_STRING=( diff --git a/src/common/init.c b/src/common/init.c index c333e03b6..96939b2ed 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -315,6 +315,9 @@ static void defaultConfig(FFinstance* instance) instance->config.gpuTemp = false; instance->config.batteryTemp = false; + instance->config.shellVersion = true; + instance->config.terminalVersion = true; + instance->config.titleFQDN = false; ffStrbufInitA(&instance->config.diskFolders, 0); diff --git a/src/data/config_user.txt b/src/data/config_user.txt index d2faddb78..6f58aeb0e 100644 --- a/src/data/config_user.txt +++ b/src/data/config_user.txt @@ -212,6 +212,18 @@ # Default is auto. #--gl auto +# Shell option +# Sets if shell version should be detected and printed +# Must be either true or false +# Default is true. +#--shell-version true + +# Terminal option +# Sets if terminal version should be detected and printed +# Must be either true or false +# Default is true. +#--terminal-version true + # Disk option # Sets if removable volume should be printed # Must be either true or false diff --git a/src/data/help.txt b/src/data/help.txt index 5fb36821a..a3c5243fb 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -103,6 +103,8 @@ Module specific options: --title-fqdn : Set if the title should use fully qualified domain name. Default is false --separator-string : Set the string printed by the separator module --os-file : Set the path to the file containing OS information + --shell-version : Set if shell version should be detected and printed + --terminal-version : Set if terminal version should be detected and printed --disk-folders : A colon (semicolon on Windows) separated list of folder paths for the disk output. Default is "/:/home" ("C:\\;D:\\ ..." on Windows) --disk-show-removable : Set if removable volume should be printed. Default is true --disk-show-hidden : Set if hidden volumes should be printed. Default is false diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index 510897287..07b902dac 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -352,12 +352,17 @@ const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance) getTerminalFromEnv(&result); getUserShellFromEnv(instance, &result); - getShellVersion(&result.shellExe, result.shellExeName, &result.shellVersion); - if(strcasecmp(result.shellExeName, result.userShellExeName) != 0) - getShellVersion(&result.userShellExe, result.userShellExeName, &result.userShellVersion); - else - ffStrbufSet(&result.userShellVersion, &result.shellVersion); + ffStrbufClear(&result.shellVersion); + if(instance->config.shellVersion) + { + getShellVersion(&result.shellExe, result.shellExeName, &result.shellVersion); + + if(strcasecmp(result.shellExeName, result.userShellExeName) != 0) + getShellVersion(&result.userShellExe, result.userShellExeName, &result.userShellVersion); + else + ffStrbufSet(&result.userShellVersion, &result.shellVersion); + } if(ffStrbufEqualS(&result.shellProcessName, "pwsh")) ffStrbufInitS(&result.shellPrettyName, "PowerShell"); @@ -383,7 +388,9 @@ const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance) ffStrbufInitCopy(&result.terminalPrettyName, &result.terminalProcessName); ffStrbufInit(&result.terminalVersion); - fftsGetTerminalVersion(&result.terminalProcessName, &result.terminalExe, &result.terminalVersion); + + if(instance->config.terminalVersion) + fftsGetTerminalVersion(&result.terminalProcessName, &result.terminalExe, &result.terminalVersion); ffThreadMutexUnlock(&mutex); return &result; diff --git a/src/detection/terminalshell/terminalshell_windows.cpp b/src/detection/terminalshell/terminalshell_windows.cpp index e4355666e..8dd59c70d 100644 --- a/src/detection/terminalshell/terminalshell_windows.cpp +++ b/src/detection/terminalshell/terminalshell_windows.cpp @@ -132,7 +132,8 @@ static uint32_t getShellInfo(FFTerminalShellResult* result, uint32_t pid) } ffStrbufClear(&result->shellVersion); - fftsGetShellVersion(&result->shellExe, result->shellPrettyName.chars, &result->shellVersion); + if(instance->config.shellVersion) + fftsGetShellVersion(&result->shellExe, result->shellPrettyName.chars, &result->shellVersion); if(ffStrbufIgnCaseEqualS(&result->shellPrettyName, "pwsh")) ffStrbufSetS(&result->shellPrettyName, "PowerShell"); @@ -305,7 +306,8 @@ const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance) getTerminalFromEnv(&result); ffStrbufInit(&result.terminalVersion); - fftsGetTerminalVersion(&result.terminalProcessName, &result.terminalExe, &result.terminalVersion); + if(instance->config.terminalVersion) + fftsGetTerminalVersion(&result.terminalProcessName, &result.terminalExe, &result.terminalVersion); exit: ffThreadMutexUnlock(&mutex); diff --git a/src/fastfetch.c b/src/fastfetch.c index 62935fc73..6013a6daa 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -1248,6 +1248,10 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con instance->config.batteryTemp = optionParseBoolean(value); else if(strcasecmp(key, "--title-fqdn") == 0) instance->config.titleFQDN = optionParseBoolean(value); + else if(strcasecmp(key, "--shell-version") == 0) + instance->config.shellVersion = optionParseBoolean(value); + else if(strcasecmp(key, "--terminal-version") == 0) + instance->config.terminalVersion = optionParseBoolean(value); else if(strcasecmp(key, "--disk-folders") == 0) optionParseString(key, value, &instance->config.diskFolders); else if(strcasecmp(key, "--disk-show-removable") == 0) diff --git a/src/fastfetch.h b/src/fastfetch.h index af9496c8d..a12182435 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -177,6 +177,9 @@ typedef struct FFconfig bool titleFQDN; + bool shellVersion; + bool terminalVersion; + FFstrbuf diskFolders; bool diskShowRemovable; bool diskShowHidden; From 99fc4e76ecbd12cc588af5d39d0ffd0275d1b2cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 11 Jan 2023 17:27:34 +0800 Subject: [PATCH 064/142] TerminalShell: fix build on Windows --- .../terminalshell/terminalshell_windows.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/detection/terminalshell/terminalshell_windows.cpp b/src/detection/terminalshell/terminalshell_windows.cpp index 8dd59c70d..8541f37f3 100644 --- a/src/detection/terminalshell/terminalshell_windows.cpp +++ b/src/detection/terminalshell/terminalshell_windows.cpp @@ -99,7 +99,7 @@ static bool getProcessInfo(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFstrb extern "C" bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version); -static uint32_t getShellInfo(FFTerminalShellResult* result, uint32_t pid) +static uint32_t getShellInfo(const FFinstance* instance, FFTerminalShellResult* result, uint32_t pid) { uint32_t ppid; @@ -128,7 +128,7 @@ static uint32_t getShellInfo(FFTerminalShellResult* result, uint32_t pid) ffStrbufClear(&result->shellPrettyName); ffStrbufClear(&result->shellExe); result->shellExeName = nullptr; - return getShellInfo(result, ppid); + return getShellInfo(instance, result, ppid); } ffStrbufClear(&result->shellVersion); @@ -176,7 +176,7 @@ static uint32_t getShellInfo(FFTerminalShellResult* result, uint32_t pid) return ppid; } -static uint32_t getTerminalInfo(FFTerminalShellResult* result, uint32_t pid) +static uint32_t getTerminalInfo(const FFinstance* instance, FFTerminalShellResult* result, uint32_t pid) { uint32_t ppid; @@ -202,7 +202,7 @@ static uint32_t getTerminalInfo(FFTerminalShellResult* result, uint32_t pid) ffStrbufClear(&result->terminalPrettyName); ffStrbufClear(&result->terminalExe); result->terminalExeName = ""; - return getTerminalInfo(result, ppid); + return getTerminalInfo(instance, result, ppid); } if(ffStrbufIgnCaseEqualS(&result->terminalPrettyName, "WindowsTerminal")) @@ -300,8 +300,8 @@ const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance) if(!getProcessInfo(0, &ppid, nullptr, nullptr, nullptr)) goto exit; - ppid = getShellInfo(&result, ppid); - getTerminalInfo(&result, ppid); + ppid = getShellInfo(instance, &result, ppid); + getTerminalInfo(instance, &result, ppid); if(result.terminalProcessName.length == 0) getTerminalFromEnv(&result); From a74f813df12bd3f6172f58420535ac0731345942 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 11 Jan 2023 17:33:31 +0800 Subject: [PATCH 065/142] CHANGLOG: remove a duplicated entry oops --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 983db0620..0f0fd7867 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,6 @@ Features: * Add `Brightness` module support * Add `Battery` module support for FreeBSD * Add `--disk-show-unknown` option for Disk module -* Add `--disk-show-unknown` option for Disk module * Detect terminal version when available * Support `WezTerm` terminal font detection (requires [`wezterm` executable](https://wezfurlong.org/wezterm/cli/general.html) being available) * Add `--shell-version` and `--terminal-version` options to disable shell / terminal version detection From 84a03e80def159cd338fadcfcf20114caa603ed5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 11 Jan 2023 17:35:44 +0800 Subject: [PATCH 066/142] README: clarify that fastfetch isn't written in pure C Ref: https://github.com/ScoopInstaller/Main/pull/4334#discussion_r1066502517 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 78312f6a8..147977a0d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Fastfetch -Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying them in a pretty way. It is written in pure c, with performance and customizability in mind. Currently, Linux, Android, FreeBSD, MacOS and Windows 7+ are supported. +Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying them in a pretty way. It is written in C-family languages, with performance and customizability in mind. Currently, Linux, Android, FreeBSD, MacOS and Windows 7+ are supported. From 6ca3b76a424eac963a96f2cc11096f31f799ee5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 11 Jan 2023 18:07:58 +0800 Subject: [PATCH 067/142] Update README --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 147977a0d..ed848668c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Fastfetch -Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying them in a pretty way. It is written in C-family languages, with performance and customizability in mind. Currently, Linux, Android, FreeBSD, MacOS and Windows 7+ are supported. +Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying them in a pretty way. It is written mainly in C, with performance and customizability in mind. Currently, Linux, Android, FreeBSD, MacOS and Windows 7+ are supported. @@ -112,7 +112,7 @@ KDE Plasma, Gnome, Cinnamon, Mate, XFCE4, LXQt ##### Terminal fonts ``` -Konsole, Gnome Terminal, Tilix, XFCE4 Terminal, Alacritty, Kitty, LXTerminal, Deepin Terminal, iTerm2, Apple Terminal, Warp, TTY, Windows Terminal, Termux, mintty, ConEmu +Konsole, Gnome Terminal, Tilix, XFCE4 Terminal, Alacritty, Kitty, LXTerminal, Deepin Terminal, iTerm2, Apple Terminal, Warp, TTY, Windows Terminal, Termux, mintty, ConEmu, WezTerm ``` ## Building @@ -132,12 +132,13 @@ If the build process fails to find the headers for a library listed in [dependen Currently GCC or clang is required (MSVC is not supported). MSYS2 with CLANG64 subsystem (or CLANGARM64 if needed) is suggested (and tested) to build fastfetch. If you need Windows 7 / 8.x support, using MINGW64 is suggested. 1. Install [MSYS2](https://www.msys2.org/#installation) -1. Open `MSYS2 CLANG64` (not `MSYS2 / MSYS`, which targets cygwin C runtime) +1. Open `MSYS2 / CLANG64` (not `MSYS2 / MSYS`, which targets cygwin C runtime) 1. Install dependencies ```bash pacman -Syu mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-pkgconf mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-cjson mingw-w64-clang-x86_64-vulkan-loader mingw-w64-clang-x86_64-opencl-icd ``` -1. Follow building instructions of Linux + +Follow the building instructions of Linux next. ## Packaging From cd0b74b0de5a4231e816caad29cfe47cd3ce994d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 11 Jan 2023 18:12:36 +0800 Subject: [PATCH 068/142] TerminalShell: support deepin-terminal version detection --- src/detection/terminalshell/terminalshell.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index 133a6281b..2684d04f3 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -206,6 +206,9 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe if(ffStrbufIgnCaseEqualS(processName, "xfce4-terminal")) return getExeVersionGeneral(exe, version);//xfce4-terminal 1.0.4 (Xfce 4.18)... + if(ffStrbufIgnCaseEqualS(processName, "deepin-terminal")) + return getExeVersionGeneral(exe, version);//deepin-terminal 5.4.36 + #endif #ifndef _WIN32 From eb02206c05512e80a8b7ab1b35b455d0555a76ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 11 Jan 2023 22:01:37 +0800 Subject: [PATCH 069/142] TerminalShell: support Windows Terminal version detection --- src/detection/terminalshell/terminalshell.c | 28 +++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index 2684d04f3..818e7d640 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -1,5 +1,7 @@ #include "fastfetch.h" +#include "common/io.h" #include "common/processing.h" +#include "common/properties.h" #ifdef _WIN32 @@ -186,6 +188,25 @@ FF_MAYBE_UNUSED static bool getTerminalVersionKonsole(FFstrbuf* exe, FFstrbuf* v return getExeVersionGeneral(exe, version); } +#ifdef _WIN32 + +static bool getTerminalVersionWindowsTerminal(FFstrbuf* exe, FFstrbuf* version) +{ + FF_STRBUF_AUTO_DESTROY buildInfoPath; + ffStrbufInitNS(&buildInfoPath, ffStrbufLastIndexC(exe, '\\') + 1, exe->chars); + ffStrbufAppendS(&buildInfoPath, "BuildInfo.xml"); + + if(ffParsePropFile(buildInfoPath.chars, "StoreVersion=\"", version)) + { + ffStrbufTrimRight(version, '"'); + return true; + } + + return getFileVersion(exe->chars, version); +} + +#endif + bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe, FFstrbuf* version) { #ifdef __ANDROID__ @@ -211,6 +232,13 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe #endif + #ifdef _WIN32 + + if(ffStrbufIgnCaseEqualS(processName, "WindowsTerminal.exe")) + return getTerminalVersionWindowsTerminal(exe, version); + + #endif + #ifndef _WIN32 if(ffStrbufIgnCaseEqualS(processName, "kitty")) From 66ed9adcda59f3d87e2f97ab0678f4464455b58c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 11 Jan 2023 22:14:47 +0800 Subject: [PATCH 070/142] TerminalShell: support ConEmu version detection --- src/detection/terminalshell/terminalshell.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index 818e7d640..6965ae0a3 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -205,6 +205,16 @@ static bool getTerminalVersionWindowsTerminal(FFstrbuf* exe, FFstrbuf* version) return getFileVersion(exe->chars, version); } +static bool getTerminalVersionConEmu(FFstrbuf* exe, FFstrbuf* version) +{ + ffStrbufSetS(version, getenv("ConEmuBuild")); + + if(version->length) + return true; + + return getFileVersion(exe->chars, version); +} + #endif bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe, FFstrbuf* version) @@ -237,6 +247,9 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe if(ffStrbufIgnCaseEqualS(processName, "WindowsTerminal.exe")) return getTerminalVersionWindowsTerminal(exe, version); + if(ffStrbufStartsWithIgnCaseS(processName, "ConEmuC")) + return getTerminalVersionConEmu(exe, version); + #endif #ifndef _WIN32 From ebfbf108a277d35c1cc4ad4caa2189cee9098651 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 11 Jan 2023 23:46:15 +0800 Subject: [PATCH 071/142] TerminalShell: support Alacritty terminal version detection --- src/detection/terminalshell/terminalshell.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index 6965ae0a3..aa9d221f3 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -259,6 +259,9 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe #endif + if(ffStrbufStartsWithIgnCaseS(processName, "alacritty")) + return getExeVersionGeneral(exe, version); + const char* termProgramVersion = getenv("TERM_PROGRAM_VERSION"); if(termProgramVersion) { From c3861954dc76ba3d66b7c8e829ddc7c0a8b701f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 11 Jan 2023 23:46:37 +0800 Subject: [PATCH 072/142] TerminalFont: support Alacritty on Windows --- src/detection/terminalfont/terminalfont.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index 1dde994bf..b08e39565 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -352,7 +352,7 @@ void ffDetectTerminalFontPlatform(const FFinstance* instance, const FFTerminalSh static bool detectTerminalFontCommon(const FFinstance* instance, const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont) { - if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "alacritty") == 0) + if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalProcessName, "alacritty")) detectAlacritty(instance, terminalFont); else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "kitty") == 0) detectKitty(instance, terminalFont); From c4aa55d5223a7c9fa4ce87bcd8db81da99fa15ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 12 Jan 2023 00:09:21 +0800 Subject: [PATCH 073/142] TerminalFont: support WezTerm on Windows --- src/detection/terminalfont/terminalfont.c | 2 +- src/detection/terminalshell/terminalshell_windows.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index b08e39565..9e9996304 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -356,7 +356,7 @@ static bool detectTerminalFontCommon(const FFinstance* instance, const FFTermina detectAlacritty(instance, terminalFont); else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "kitty") == 0) detectKitty(instance, terminalFont); - else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "wezterm-gui") == 0) + else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalProcessName, "wezterm-gui")) detectWezterm(instance, terminalFont); else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalExe, "/dev/tty")) detectTTY(terminalFont); diff --git a/src/detection/terminalshell/terminalshell_windows.cpp b/src/detection/terminalshell/terminalshell_windows.cpp index 8541f37f3..b800228fa 100644 --- a/src/detection/terminalshell/terminalshell_windows.cpp +++ b/src/detection/terminalshell/terminalshell_windows.cpp @@ -218,6 +218,8 @@ static uint32_t getTerminalInfo(const FFinstance* instance, FFTerminalShellResul ffStrbufSetS(&result->terminalPrettyName, "Windows Explorer"); else if(ffStrbufStartsWithIgnCaseS(&result->terminalPrettyName, "ConEmuC")) ffStrbufSetS(&result->terminalPrettyName, "ConEmu"); + else if(ffStrbufEqualS(&result->terminalPrettyName, "wezterm-gui")) + ffStrbufInitS(&result->terminalPrettyName, "WezTerm"); return ppid; } From 387b8298bd57505a15d2a4a540b32541b846f30a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 12 Jan 2023 00:11:25 +0800 Subject: [PATCH 074/142] Windows: fix bug that line buffering doesn't work properly --- CHANGELOG.md | 1 + CMakeLists.txt | 6 +++++- src/fastfetch.c | 4 ++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f0fd7867..c082fa0c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ Logos: Bugfixes: * `--logo-type` now does accept `iterm` too (@CarterLi, #374) * Fix mintty terminal font detection +* Fix bug that line buffering doesn't work properly (Windows) Other: * Fixed a Typo in iterm error message (@jessebot, #376) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4abd15ffb..fc0451893 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -645,7 +645,6 @@ if(ENABLE_THREADS) endif() endif() - if(ENABLE_BUFFER) target_compile_definitions(libfastfetch PRIVATE FF_ENABLE_BUFFER) endif() @@ -720,6 +719,11 @@ target_link_libraries(flashfetch PRIVATE libfastfetch ) +if(ENABLE_BUFFER) # FF_ENABLE_BUFFER is used in fastfetch.c + target_compile_definitions(fastfetch PRIVATE FF_ENABLE_BUFFER) + target_compile_definitions(flashfetch PRIVATE FF_ENABLE_BUFFER) +endif() + if(WIN32) set(TARGET_NAME fastfetch) target_sources(fastfetch diff --git a/src/fastfetch.c b/src/fastfetch.c index 6013a6daa..0e8fb855c 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -1482,6 +1482,10 @@ int main(int argc, const char** argv) ffStart(&instance); + #if defined(_WIN32) && defined(FF_ENABLE_BUFFER) + fflush(stdout); + #endif + //Parse the structure and call the modules uint32_t startIndex = 0; while (startIndex < data.structure.length) From 46ed8aa87cdc47623e8da7b273d1ff39ed9b6c54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 12 Jan 2023 00:18:02 +0800 Subject: [PATCH 075/142] TerminalFont: don't try to detecting kitty and tty fonts on Windows --- src/detection/terminalfont/terminalfont.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index 9e9996304..41ff5428b 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -37,7 +37,7 @@ static void detectAlacritty(const FFinstance* instance, FFTerminalFontResult* te ffStrbufDestroy(&fontSize); } -static void detectTTY(FFTerminalFontResult* terminalFont) +FF_MAYBE_UNUSED static void detectTTY(FFTerminalFontResult* terminalFont) { FFstrbuf fontName; ffStrbufInit(&fontName); @@ -291,7 +291,7 @@ static void detectFromWindowsTeriminal(const FFinstance* instance, const FFstrbu #endif #endif //defined(_WIN32) || defined(__linux__) -static bool detectKitty(const FFinstance* instance, FFTerminalFontResult* result) +FF_MAYBE_UNUSED static bool detectKitty(const FFinstance* instance, FFTerminalFontResult* result) { FFstrbuf fontName; ffStrbufInit(&fontName); @@ -354,17 +354,20 @@ static bool detectTerminalFontCommon(const FFinstance* instance, const FFTermina { if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalProcessName, "alacritty")) detectAlacritty(instance, terminalFont); - else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "kitty") == 0) - detectKitty(instance, terminalFont); else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalProcessName, "wezterm-gui")) detectWezterm(instance, terminalFont); + + #ifndef _WIN32 + else if(ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "kitty")) + detectKitty(instance, terminalFont); else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalExe, "/dev/tty")) detectTTY(terminalFont); + #endif #if defined(_WIN32) || defined(__linux__) //Used by both Linux (WSL) and Windows - else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "Windows Terminal") == 0 || - ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "WindowsTerminal.exe") == 0) + else if(ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "Windows Terminal") || + ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "WindowsTerminal.exe")) detectFromWindowsTeriminal(instance, &terminalShell->terminalExe, terminalFont); #endif From 670cf6fe900a2f5ac656f9a2dd4408afd1d37e6e Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Thu, 12 Jan 2023 11:41:07 +0100 Subject: [PATCH 076/142] GPU selection options #379 --- CHANGELOG.md | 2 ++ completions/bash | 2 ++ src/common/init.c | 3 +++ src/data/config_user.txt | 7 ++++++ src/data/help.txt | 2 ++ src/detection/gpu/gpu.h | 8 ++++++ src/detection/gpu/gpu_apple.c | 2 ++ src/detection/gpu/gpu_linux.c | 24 +++++++++++++++++- src/detection/gpu/gpu_windows.cpp | 4 +++ src/detection/vulkan.c | 5 ++++ src/fastfetch.c | 9 +++++-- src/fastfetch.h | 3 +++ src/modules/gpu.c | 42 +++++++++++++++++++++++++------ 13 files changed, 102 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44402b68a..097671066 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ Features: * Add `Brightness` module support * Add `Battery` module support for FreeBSD * Add `--disk-show-unknown` option for Disk module +* Add `--gpu-hide-integrated` option (#379) +* Add `--gpu-hide-discrete` option (#379) Logos: * Raspbian (@IamNoRobot, #373) diff --git a/completions/bash b/completions/bash index 5dedf5f6f..d71e6c83b 100644 --- a/completions/bash +++ b/completions/bash @@ -191,6 +191,8 @@ __fastfetch_completion() "--escape-bedrock" "--disk-show-removable" "--disk-show-hidden" + "--gpu-hide-integrated" + "--gpu-hide-discrete" ) local FF_OPTIONS_STRING=( diff --git a/src/common/init.c b/src/common/init.c index c333e03b6..85ef35668 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -315,6 +315,9 @@ static void defaultConfig(FFinstance* instance) instance->config.gpuTemp = false; instance->config.batteryTemp = false; + instance->config.gpuHideIntegrated = false; + instance->config.gpuHideDiscrete = false; + instance->config.titleFQDN = false; ffStrbufInitA(&instance->config.diskFolders, 0); diff --git a/src/data/config_user.txt b/src/data/config_user.txt index d2faddb78..859267bcc 100644 --- a/src/data/config_user.txt +++ b/src/data/config_user.txt @@ -212,6 +212,13 @@ # Default is auto. #--gl auto +# GPU hide options +# Sets weather to hide certain gpu types +# Must be either true or false +# Default is false. +#--gpu-hide-integrated +#--gpu-hide-discrete + # Disk option # Sets if removable volume should be printed # Must be either true or false diff --git a/src/data/help.txt b/src/data/help.txt index 5fb36821a..9cd91fd9f 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -110,6 +110,8 @@ Module specific options: --battery-dir : The directory where the battery folders are. Standard: /sys/class/power_supply/ --cpu-temp : Detect and display CPU temperature if supported. Default is false --gpu-temp : Detect and display GPU temperature if supported. Default is false + --gpu-hide-integrated : Hide integrated GPU if supported. Default is false + --gpu-hide-discrete : Hide discrete GPU if supported. Default is false --battery-temp : Detect and display Battery temperature if supported. Default is false --localip-show-ipv4 : Show IPv4 addresses in local ip module. Default is true --localip-show-ipv6 : Show IPv6 addresses in local ip module. Default is false diff --git a/src/detection/gpu/gpu.h b/src/detection/gpu/gpu.h index 16bd2ff53..e36e1d5ea 100644 --- a/src/detection/gpu/gpu.h +++ b/src/detection/gpu/gpu.h @@ -12,8 +12,16 @@ #define FF_GPU_VENDOR_NAME_INTEL "Intel" #define FF_GPU_VENDOR_NAME_NVIDIA "NVIDIA" +typedef enum FFGpuType +{ + FF_GPU_TYPE_INTEGRATED, + FF_GPU_TYPE_DISCRETE, + FF_GPU_TYPE_UNKNOWN +} FFGpuType; + typedef struct FFGPUResult { + FFGpuType type; FFstrbuf vendor; FFstrbuf name; FFstrbuf driver; diff --git a/src/detection/gpu/gpu_apple.c b/src/detection/gpu/gpu_apple.c index 52292d83e..d8867207f 100644 --- a/src/detection/gpu/gpu_apple.c +++ b/src/detection/gpu/gpu_apple.c @@ -59,6 +59,8 @@ const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance) FFGPUResult* gpu = ffListAdd(gpus); + gpu->type = FF_GPU_TYPE_UNKNOWN; + ffStrbufInitA(&gpu->vendor, 0); ffStrbufInit(&gpu->driver); diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 5877f6176..0fb0dc061 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -61,7 +61,7 @@ static void pciDetectVendorName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* static void drmDetectDeviceName(const FFinstance* instance, FFGPUResult* gpu, PCIData* pci, struct pci_dev* device) { u8 revId; - bool revIdSet = false;; + bool revIdSet = false; #if PCI_LIB_VERSION >= 0x030800 revIdSet = pci->ffpci_fill_info(device, PCI_FILL_CLASS_EXT) & PCI_FILL_CLASS_EXT; @@ -167,6 +167,24 @@ static void pciDetectTemperatur(const FFinstance* instance, FFGPUResult* gpu, st } } +static void detectType(FFGPUResult* gpu, const PCIData* pci, struct pci_dev* device) +{ + //There is no straightforward way to detect the type of a GPU. + //The approach taken here is to look at the memory sizes of the device. + //Since integrated GPUs usually use the system ram, they don't have expansive ROMs + + if(!(pci->ffpci_fill_info(device, PCI_FILL_SIZES) & PCI_FILL_SIZES)) + { + gpu->type = FF_GPU_TYPE_UNKNOWN; + return; + } + + if(device->rom_size > 0) + gpu->type = FF_GPU_TYPE_DISCRETE; + else + gpu->type = FF_GPU_TYPE_INTEGRATED; +} + static void pciHandleDevice(const FFinstance* instance, FFlist* results, PCIData* pci, struct pci_dev* device) { pci->ffpci_fill_info(device, PCI_FILL_CLASS); @@ -175,7 +193,9 @@ static void pciHandleDevice(const FFinstance* instance, FFlist* results, PCIData pci->ffpci_lookup_name(pci->access, class, sizeof(class) - 1, PCI_LOOKUP_CLASS, device->device_class); if( + //https://pci-ids.ucw.cz/read/PD/03 strcasecmp("VGA compatible controller", class) != 0 && + strcasecmp("XGA compatible controller", class) != 0 && strcasecmp("3D controller", class) != 0 && strcasecmp("Display controller", class) != 0 ) return; @@ -193,6 +213,8 @@ static void pciHandleDevice(const FFinstance* instance, FFlist* results, PCIData ffStrbufInit(&gpu->driver); pciDetectDriverName(gpu, pci, device); + detectType(gpu, pci, device); + gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->temperature = FF_GPU_TEMP_UNSET; diff --git a/src/detection/gpu/gpu_windows.cpp b/src/detection/gpu/gpu_windows.cpp index f5d0f4946..41eab75cc 100644 --- a/src/detection/gpu/gpu_windows.cpp +++ b/src/detection/gpu/gpu_windows.cpp @@ -26,6 +26,8 @@ static const char* detectWithDxgi(FFlist* gpus) FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); + gpu->type = FF_GPU_TYPE_UNKNOWN; + if(wmemchr((const wchar_t[]) {0x1002, 0x1022}, (wchar_t)desc.VendorId, 2)) ffStrbufInitS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD); else if(wmemchr((const wchar_t[]) {0x03e7, 0x8086, 0x8087}, (wchar_t)desc.VendorId, 3)) @@ -65,6 +67,8 @@ static const char* detectWithWmi(FFlist* gpus) { FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); + gpu->type = FF_GPU_TYPE_UNKNOWN; + ffStrbufInit(&gpu->vendor); record.getString(L"AdapterCompatibility", &gpu->vendor); if(ffStrbufStartsWithS(&gpu->vendor, "Intel ")) diff --git a/src/detection/vulkan.c b/src/detection/vulkan.c index 4119280a7..dbda127bb 100644 --- a/src/detection/vulkan.c +++ b/src/detection/vulkan.c @@ -190,6 +190,11 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu ffStrbufInit(&gpu->name); ffStrbufAppendS(&gpu->name, physicalDeviceProperties.properties.deviceName); + if(physicalDeviceProperties.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) + gpu->type = FF_GPU_TYPE_INTEGRATED; + else + gpu->type = FF_GPU_TYPE_DISCRETE; + //No way to detect those using vulkan ffStrbufInit(&gpu->vendor); ffStrbufInit(&gpu->driver); diff --git a/src/fastfetch.c b/src/fastfetch.c index 62935fc73..543aea831 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -288,12 +288,13 @@ static inline void printCommandHelp(const char* command) } else if(strcasecmp(command, "gpu-format") == 0) { - constructAndPrintCommandHelpFormat("gpu", "{} {}", 5, + constructAndPrintCommandHelpFormat("gpu", "{} {}", 6, "GPU vendor", "GPU name", "GPU driver", "GPU temperature", - "GPU core count" + "GPU core count", + "GPU type" ); } else if(strcasecmp(command, "memory-format") == 0) @@ -1246,6 +1247,10 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con instance->config.gpuTemp = optionParseBoolean(value); else if(strcasecmp(key, "--battery-temp") == 0) instance->config.batteryTemp = optionParseBoolean(value); + else if(strcasecmp(key, "--gpu-hide-integrated") == 0) + instance->config.gpuHideIntegrated = optionParseBoolean(value); + else if(strcasecmp(key, "--gpu-hide-discrete") == 0) + instance->config.gpuHideDiscrete = optionParseBoolean(value); else if(strcasecmp(key, "--title-fqdn") == 0) instance->config.titleFQDN = optionParseBoolean(value); else if(strcasecmp(key, "--disk-folders") == 0) diff --git a/src/fastfetch.h b/src/fastfetch.h index e215d3e3f..1c6316957 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -175,6 +175,9 @@ typedef struct FFconfig bool gpuTemp; bool batteryTemp; + bool gpuHideIntegrated; + bool gpuHideDiscrete; + bool titleFQDN; FFstrbuf diskFolders; diff --git a/src/modules/gpu.c b/src/modules/gpu.c index 0d0ae8266..a2daad515 100644 --- a/src/modules/gpu.c +++ b/src/modules/gpu.c @@ -6,13 +6,13 @@ #include #define FF_GPU_MODULE_NAME "GPU" -#define FF_GPU_NUM_FORMAT_ARGS 5 +#define FF_GPU_NUM_FORMAT_ARGS 6 -static void printGPUResult(FFinstance* instance, uint8_t index, FFGPUResult* gpu) +static void printGPUResult(FFinstance* instance, uint8_t index, const FFGPUResult* gpu) { if(instance->config.gpu.outputFormat.length == 0) { - ffPrintLogoAndKey(instance, FF_GPU_MODULE_NAME, 0, &instance->config.gpu.key); + ffPrintLogoAndKey(instance, FF_GPU_MODULE_NAME, index, &instance->config.gpu.key); FFstrbuf output; ffStrbufInitA(&output, gpu->vendor.length + 1 + gpu->name.length); @@ -37,13 +37,24 @@ static void printGPUResult(FFinstance* instance, uint8_t index, FFGPUResult* gpu } else { + FFstrbuf type; + if(gpu->type == FF_GPU_TYPE_INTEGRATED) + ffStrbufInitS(&type, "Integrated"); + else if(gpu->type == FF_GPU_TYPE_DISCRETE) + ffStrbufInitS(&type, "Discrete"); + else + ffStrbufInitS(&type, "Unknown"); + ffPrintFormat(instance, FF_GPU_MODULE_NAME, index, &instance->config.gpu, FF_GPU_NUM_FORMAT_ARGS, (FFformatarg[]){ {FF_FORMAT_ARG_TYPE_STRBUF, &gpu->vendor}, {FF_FORMAT_ARG_TYPE_STRBUF, &gpu->name}, {FF_FORMAT_ARG_TYPE_STRBUF, &gpu->driver}, {FF_FORMAT_ARG_TYPE_DOUBLE, &gpu->temperature}, {FF_FORMAT_ARG_TYPE_INT, &gpu->coreCount}, + {FF_FORMAT_ARG_TYPE_STRBUF, &type}, }); + + ffStrbufDestroy(&type); } } @@ -51,12 +62,27 @@ void ffPrintGPU(FFinstance* instance) { const FFlist* gpus = ffDetectGPU(instance); - if(gpus->length == 0) + FFlist selectedGpus; + ffListInitA(&selectedGpus, sizeof(const FFGPUResult*), gpus->length); + + for(uint32_t i = 0; i < gpus->length; i++) { - ffPrintError(instance, FF_GPU_MODULE_NAME, 0, &instance->config.gpu, "No GPUs found"); - return; + const FFGPUResult* gpu = ffListGet(gpus, i); + + if(gpu->type == FF_GPU_TYPE_INTEGRATED && instance->config.gpuHideIntegrated) + continue; + + if(gpu->type == FF_GPU_TYPE_DISCRETE && instance->config.gpuHideDiscrete) + continue; + + * (const FFGPUResult**) ffListAdd(&selectedGpus) = gpu; } - for(uint8_t i = 0; i < (uint8_t) gpus->length; i++) - printGPUResult(instance, gpus->length == 1 ? 0 : (uint8_t) (i + 1), ffListGet(gpus, i)); + for(uint32_t i = 0; i < selectedGpus.length; i++) + printGPUResult(instance, selectedGpus.length == 1 ? 0 : (uint8_t) (i + 1), * (const FFGPUResult**) ffListGet(&selectedGpus, i)); + + if(selectedGpus.length == 0) + ffPrintError(instance, FF_GPU_MODULE_NAME, 0, &instance->config.gpu, "No GPUs found"); + + ffListDestroy(&selectedGpus); } From 5a90d8b5459a8291f0a5bd308f53a135261dbf43 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Thu, 12 Jan 2023 12:54:04 +0100 Subject: [PATCH 077/142] Better GPU type detection #379 --- src/detection/gpu/gpu_linux.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 0fb0dc061..106b53861 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -172,6 +172,7 @@ static void detectType(FFGPUResult* gpu, const PCIData* pci, struct pci_dev* dev //There is no straightforward way to detect the type of a GPU. //The approach taken here is to look at the memory sizes of the device. //Since integrated GPUs usually use the system ram, they don't have expansive ROMs + //and their memory sizes are usually smaller than 1GB. if(!(pci->ffpci_fill_info(device, PCI_FILL_SIZES) & PCI_FILL_SIZES)) { @@ -180,9 +181,22 @@ static void detectType(FFGPUResult* gpu, const PCIData* pci, struct pci_dev* dev } if(device->rom_size > 0) + { gpu->type = FF_GPU_TYPE_DISCRETE; - else - gpu->type = FF_GPU_TYPE_INTEGRATED; + return; + } + + uint32_t numSizes = sizeof(device->size) / sizeof(device->size[0]); + for(uint32_t i = 0; i < numSizes; i++) + { + if(device->size[i] > 1024 * 1024 * 1024) //1GB + { + gpu->type = FF_GPU_TYPE_INTEGRATED; + return; + } + } + + gpu->type = FF_GPU_TYPE_INTEGRATED; } static void pciHandleDevice(const FFinstance* instance, FFlist* results, PCIData* pci, struct pci_dev* device) From 1a710e409478e5f940f2818f4717c23ef4292ad1 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Thu, 12 Jan 2023 12:56:17 +0100 Subject: [PATCH 078/142] Better GPU type detection nr2 #379 --- src/detection/gpu/gpu_linux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 106b53861..21e71668f 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -189,9 +189,9 @@ static void detectType(FFGPUResult* gpu, const PCIData* pci, struct pci_dev* dev uint32_t numSizes = sizeof(device->size) / sizeof(device->size[0]); for(uint32_t i = 0; i < numSizes; i++) { - if(device->size[i] > 1024 * 1024 * 1024) //1GB + if(device->size[i] >= 1024 * 1024 * 1024) //1GB { - gpu->type = FF_GPU_TYPE_INTEGRATED; + gpu->type = FF_GPU_TYPE_DISCRETE; return; } } From 53c6a0ec9fc1781aa16bcd9ba4ec67f485ee0f77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 12 Jan 2023 22:19:14 +0800 Subject: [PATCH 079/142] GPU: apply GPU type selection logic to Windows --- src/detection/gpu/gpu_windows.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/detection/gpu/gpu_windows.cpp b/src/detection/gpu/gpu_windows.cpp index 41eab75cc..07b711205 100644 --- a/src/detection/gpu/gpu_windows.cpp +++ b/src/detection/gpu/gpu_windows.cpp @@ -26,8 +26,6 @@ static const char* detectWithDxgi(FFlist* gpus) FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); - gpu->type = FF_GPU_TYPE_UNKNOWN; - if(wmemchr((const wchar_t[]) {0x1002, 0x1022}, (wchar_t)desc.VendorId, 2)) ffStrbufInitS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD); else if(wmemchr((const wchar_t[]) {0x03e7, 0x8086, 0x8087}, (wchar_t)desc.VendorId, 3)) @@ -42,6 +40,8 @@ static const char* detectWithDxgi(FFlist* gpus) ffStrbufInit(&gpu->driver); + gpu->type = desc.DedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED; + adapter->Release(); gpu->temperature = FF_GPU_TEMP_UNSET; From 2b5511997cee9c9107d1c78ce09fd5fbd36777a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 12 Jan 2023 22:41:11 +0800 Subject: [PATCH 080/142] Global: support hiding other texts when printing percentage values --- CHANGELOG.md | 1 + src/common/bar.h | 1 + src/data/config_user.txt | 2 +- src/data/help.txt | 2 +- src/modules/battery.c | 3 ++- src/modules/disk.c | 15 ++++++++++----- src/modules/memory.c | 6 ++++-- 7 files changed, 20 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dcbc706da..737092a23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ Features: * Detect terminal version when available * Support `WezTerm` terminal font detection (requires [`wezterm` executable](https://wezfurlong.org/wezterm/cli/general.html) being available) * Add `--shell-version` and `--terminal-version` options to disable shell / terminal version detection +* Enhance `--percent-type` to allow hiding other texts (#387) Logos: * Raspbian (@IamNoRobot, #373) diff --git a/src/common/bar.h b/src/common/bar.h index a6c2be234..575adc01d 100644 --- a/src/common/bar.h +++ b/src/common/bar.h @@ -9,6 +9,7 @@ enum { FF_PERCENTAGE_TYPE_NUM_BIT = 1, FF_PERCENTAGE_TYPE_BAR_BIT = 2, + FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT = 4, }; void ffAppendPercentBar(FFinstance* instance, FFstrbuf* buffer, uint8_t percent, uint8_t green, uint8_t yellow, uint8_t red); diff --git a/src/data/config_user.txt b/src/data/config_user.txt index b68b845ca..435143dc4 100644 --- a/src/data/config_user.txt +++ b/src/data/config_user.txt @@ -259,7 +259,7 @@ # Percentage output type option # Applies to all modules that prints percentage values. Currently memory, swap, disk, battery and CPU usage are supported. # Only works with default format ( without --module-format option ). -# 0: prints none; 1: prints percent number only; 2: prints bar only; 3: prints both percent number and bar +# 0: prints none; 1: prints percent number only; 2: prints bar only; 3: prints both percent number and bar; 6: prints bar and hide other texts #--percent-type 1 # Key options: diff --git a/src/data/help.txt b/src/data/help.txt index c83dec794..81b52dd7f 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -125,7 +125,7 @@ Module specific options: --weather-output-format: The output weather format to be used. It must be URI encoded. --player-name: The name of the player to use --gl : Set the OpenGL context creation library to use. Must be auto, egl, glx or osmesa. Default is auto - --percent-type : Set the percentage output type. 1 for percentage number, 2 for bar, 3 for both. Default is 1 + --percent-type : Set the percentage output type. 1 for percentage number, 2 for bar, 3 for both, 6 for bar only. Default is 1 Parsing is not case sensitive. E.g. "--lib-PCI" is equal to "--Lib-Pci" If a value starts with a ?, it is optional. "true" will be used if not set. diff --git a/src/modules/battery.c b/src/modules/battery.c index 97c603d9a..79cdf4c79 100644 --- a/src/modules/battery.c +++ b/src/modules/battery.c @@ -13,6 +13,7 @@ static void printBattery(FFinstance* instance, BatteryResult* result, uint8_t in ffPrintLogoAndKey(instance, FF_BATTERY_MODULE_NAME, index, &instance->config.battery.key); bool showStatus = + !(instance->config.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT) && result->status.length > 0 && ffStrbufIgnCaseCompS(&result->status, "Unknown") != 0; @@ -35,7 +36,7 @@ static void printBattery(FFinstance* instance, BatteryResult* result, uint8_t in { if(str.length > 0) ffStrbufAppendC(&str, ' '); - ffStrbufAppendF(&str, "%.0f%%", result->capacity); + ffStrbufAppendF(&str, str.length > 0 ? "(%u%%)" : "%u%%", (unsigned) result->capacity); } } diff --git a/src/modules/disk.c b/src/modules/disk.c index ba07fb823..df7614d5c 100644 --- a/src/modules/disk.c +++ b/src/modules/disk.c @@ -47,17 +47,22 @@ static void printDisk(FFinstance* instance, const FFDisk* disk) ffAppendPercentBar(instance, &str, bytesPercentage, 0, 5, 8); ffStrbufAppendC(&str, ' '); } - ffStrbufAppendF(&str, "%s / %s", usedPretty.chars, totalPretty.chars); + + if(!(instance->config.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) + ffStrbufAppendF(&str, "%s / %s ", usedPretty.chars, totalPretty.chars); if(instance->config.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) - ffStrbufAppendF(&str, " (%u%%)", bytesPercentage); + { + ffStrbufAppendF(&str, str.length > 0 ? "(%u%%) " : "%u%% ", bytesPercentage); + } } else - ffStrbufAppendS(&str, "Unknown"); + ffStrbufAppendS(&str, "Unknown "); - if(disk->type == FF_DISK_TYPE_EXTERNAL) - ffStrbufAppendS(&str, " [Removable]"); + if(disk->type == FF_DISK_TYPE_EXTERNAL && !(instance->config.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) + ffStrbufAppendS(&str, "[Removable]"); + ffStrbufTrimRight(&str, ' '); ffStrbufPutTo(&str, stdout); ffStrbufDestroy(&str); } diff --git a/src/modules/memory.c b/src/modules/memory.c index 149eef45b..fbb893f02 100644 --- a/src/modules/memory.c +++ b/src/modules/memory.c @@ -52,11 +52,13 @@ static void printMemory(FFinstance* instance, const char* name, const FFModuleAr ffStrbufAppendC(&str, ' '); } - ffStrbufAppendF(&str, "%s / %s", usedPretty.chars, totalPretty.chars); + if(!(instance->config.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) + ffStrbufAppendF(&str, "%s / %s ", usedPretty.chars, totalPretty.chars); if(instance->config.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) - ffStrbufAppendF(&str, " (%u%%)", percentage); + ffStrbufAppendF(&str, str.length > 0 ? "(%u%%)" : "%u%%", percentage); + ffStrbufTrimRight(&str, ' '); ffStrbufPutTo(&str, stdout); ffStrbufDestroy(&str); } From 67ab7c07796122a1cca07e50dd0c34d2bf9e3d56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 13 Jan 2023 10:43:33 +0800 Subject: [PATCH 081/142] GPU: support vendor detection --- src/detection/gpu/gpu.h | 1 + src/detection/gpu/gpu_apple.c | 15 ++++++++++++++- src/util/apple/cf_helpers.c | 29 ++++++++++++++++++++++------- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/src/detection/gpu/gpu.h b/src/detection/gpu/gpu.h index e36e1d5ea..e14feb9d8 100644 --- a/src/detection/gpu/gpu.h +++ b/src/detection/gpu/gpu.h @@ -8,6 +8,7 @@ #define FF_GPU_TEMP_UNSET (0/0.0) #define FF_GPU_CORE_COUNT_UNSET -1 +#define FF_GPU_VENDOR_NAME_APPLE "Apple" #define FF_GPU_VENDOR_NAME_AMD "AMD" #define FF_GPU_VENDOR_NAME_INTEL "Intel" #define FF_GPU_VENDOR_NAME_NVIDIA "NVIDIA" diff --git a/src/detection/gpu/gpu_apple.c b/src/detection/gpu/gpu_apple.c index d8867207f..5d4d05eae 100644 --- a/src/detection/gpu/gpu_apple.c +++ b/src/detection/gpu/gpu_apple.c @@ -5,6 +5,7 @@ #include "util/apple/cf_helpers.h" #include +#include static double detectGpuTemp(const FFstrbuf* gpuName) { @@ -61,7 +62,19 @@ const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance) gpu->type = FF_GPU_TYPE_UNKNOWN; - ffStrbufInitA(&gpu->vendor, 0); + ffStrbufInit(&gpu->vendor); + int vendorId; + if(!ffCfDictGetInt(properties, CFSTR("vendor-id"), &vendorId)) + { + if(vendorId == 0x106b) + ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE); + else if(wmemchr((const wchar_t[]) {0x1002, 0x1022}, (wchar_t)vendorId, 2)) + ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD); + else if(wmemchr((const wchar_t[]) {0x03e7, 0x8086, 0x8087}, (wchar_t)vendorId, 3)) + ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL); + else if(wmemchr((const wchar_t[]) {0x0955, 0x10de, 0x12d2}, (wchar_t)vendorId, 3)) + ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA); + } ffStrbufInit(&gpu->driver); ffCfDictGetString(properties, CFSTR("CFBundleIdentifier"), &gpu->driver); diff --git a/src/util/apple/cf_helpers.c b/src/util/apple/cf_helpers.c index 65dcd7248..f5c37b7ad 100644 --- a/src/util/apple/cf_helpers.c +++ b/src/util/apple/cf_helpers.c @@ -44,7 +44,10 @@ const char* ffCfDictGetString(CFDictionaryRef dict, CFStringRef key, FFstrbuf* r const char* ffCfDictGetBool(CFDictionaryRef dict, CFStringRef key, bool* result) { CFBooleanRef cf = (CFBooleanRef)CFDictionaryGetValue(dict, key); - if(cf == NULL || CFGetTypeID(cf) != CFBooleanGetTypeID()) + if(cf == NULL) + return "CFDictionaryGetValue() failed"; + + if(CFGetTypeID(cf) != CFBooleanGetTypeID()) return "TypeID is not 'CFBoolean'"; *result = CFBooleanGetValue(cf); @@ -53,13 +56,25 @@ const char* ffCfDictGetBool(CFDictionaryRef dict, CFStringRef key, bool* result) const char* ffCfDictGetInt(CFDictionaryRef dict, CFStringRef key, int* result) { - CFNumberRef cf = (CFNumberRef)CFDictionaryGetValue(dict, key); - if (cf == NULL || CFGetTypeID(cf) != CFNumberGetTypeID()) - return "TypeID is not 'CFNumber'"; + CFTypeRef cf = (CFTypeRef)CFDictionaryGetValue(dict, key); + if(cf == NULL) + return "CFDictionaryGetValue() failed"; - if(!CFNumberGetValue(cf, kCFNumberSInt32Type, result)) - return "Number type is not SInt32"; - return NULL; + if(CFGetTypeID(cf) == CFNumberGetTypeID()) + { + if(!CFNumberGetValue((CFNumberRef)cf, kCFNumberSInt32Type, result)) + return "Number type is not SInt32"; + return NULL; + } + else if(CFGetTypeID(cf) == CFDataGetTypeID()) + { + if(CFDataGetLength((CFDataRef)cf) != sizeof(int)) + return "Data length is not sizeof(int)"; + CFDataGetBytes((CFDataRef)cf, CFRangeMake(0, sizeof(int)), (uint8_t*)result); + return NULL; + } + + return "TypeID is neither 'CFNumber' nor 'CFData'"; } const char* ffCfDictGetDict(CFDictionaryRef dict, CFStringRef key, CFDictionaryRef* result) From dcf04aa4fe0d113a344ca09301f66f3aa7745762 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 13 Jan 2023 15:44:52 +0800 Subject: [PATCH 082/142] GPU: detect type based on vendor --- src/detection/gpu/gpu_apple.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/detection/gpu/gpu_apple.c b/src/detection/gpu/gpu_apple.c index 5d4d05eae..413e65746 100644 --- a/src/detection/gpu/gpu_apple.c +++ b/src/detection/gpu/gpu_apple.c @@ -67,13 +67,25 @@ const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance) if(!ffCfDictGetInt(properties, CFSTR("vendor-id"), &vendorId)) { if(vendorId == 0x106b) + { ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE); + gpu->type = FF_GPU_TYPE_INTEGRATED; + } else if(wmemchr((const wchar_t[]) {0x1002, 0x1022}, (wchar_t)vendorId, 2)) + { ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD); + gpu->type = FF_GPU_TYPE_DISCRETE; // Apple never used AMD CPUs + } else if(wmemchr((const wchar_t[]) {0x03e7, 0x8086, 0x8087}, (wchar_t)vendorId, 3)) + { ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL); + gpu->type = FF_GPU_TYPE_INTEGRATED; + } else if(wmemchr((const wchar_t[]) {0x0955, 0x10de, 0x12d2}, (wchar_t)vendorId, 3)) + { ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA); + gpu->type = FF_GPU_TYPE_DISCRETE; + } } ffStrbufInit(&gpu->driver); From 83ea189d81287dd0b60ef9e7e3ae8d39e3bcb022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 13 Jan 2023 15:46:29 +0800 Subject: [PATCH 083/142] GPU: simplify code --- src/modules/gpu.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/modules/gpu.c b/src/modules/gpu.c index a2daad515..6c673df36 100644 --- a/src/modules/gpu.c +++ b/src/modules/gpu.c @@ -37,13 +37,13 @@ static void printGPUResult(FFinstance* instance, uint8_t index, const FFGPUResul } else { - FFstrbuf type; + const char* type; if(gpu->type == FF_GPU_TYPE_INTEGRATED) - ffStrbufInitS(&type, "Integrated"); + type = "Integrated"; else if(gpu->type == FF_GPU_TYPE_DISCRETE) - ffStrbufInitS(&type, "Discrete"); + type = "Discrete"; else - ffStrbufInitS(&type, "Unknown"); + type = "Unknown"; ffPrintFormat(instance, FF_GPU_MODULE_NAME, index, &instance->config.gpu, FF_GPU_NUM_FORMAT_ARGS, (FFformatarg[]){ {FF_FORMAT_ARG_TYPE_STRBUF, &gpu->vendor}, @@ -51,10 +51,8 @@ static void printGPUResult(FFinstance* instance, uint8_t index, const FFGPUResul {FF_FORMAT_ARG_TYPE_STRBUF, &gpu->driver}, {FF_FORMAT_ARG_TYPE_DOUBLE, &gpu->temperature}, {FF_FORMAT_ARG_TYPE_INT, &gpu->coreCount}, - {FF_FORMAT_ARG_TYPE_STRBUF, &type}, + {FF_FORMAT_ARG_TYPE_STRING, type}, }); - - ffStrbufDestroy(&type); } } From 3cee8f5475d5708b52b5c8179259a14156ba7caf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 13 Jan 2023 19:03:09 +0800 Subject: [PATCH 084/142] FFlist: add new functions to make it be able to work as a queue --- src/util/FFlist.c | 22 ++++++++++++++++++++++ src/util/FFlist.h | 5 +++++ tests/list.c | 26 +++++++++++++++++++++++++- 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/util/FFlist.c b/src/util/FFlist.c index d01353ffb..40ed90816 100644 --- a/src/util/FFlist.c +++ b/src/util/FFlist.c @@ -1,6 +1,7 @@ #include "FFlist.h" #include +#include void ffListInitA(FFlist* list, uint32_t elementSize, uint32_t capacity) { @@ -34,6 +35,27 @@ uint32_t ffListFirstIndexComp(const FFlist* list, void* compElement, bool(*compF return list->length; } +bool ffListShift(FFlist* list, void* result) +{ + if(list->length == 0) + return false; + + memcpy(result, list->data, list->elementSize); + memmove(list->data, list->data + list->elementSize, list->elementSize * (list->length - 1)); + --list->length; + return true; +} + +bool ffListPop(FFlist* list, void* result) +{ + if(list->length == 0) + return false; + + memcpy(result, ffListGet(list, list->length - 1), list->elementSize); + --list->length; + return result; +} + void ffListDestroy(FFlist* list) { //Avoid free-after-use. These 3 assignments are cheap so don't remove them diff --git a/src/util/FFlist.h b/src/util/FFlist.h index e65180d3a..5b42add89 100644 --- a/src/util/FFlist.h +++ b/src/util/FFlist.h @@ -26,6 +26,11 @@ void* ffListAdd(FFlist* list); FF_C_NODISCARD uint32_t ffListFirstIndexComp(const FFlist* list, void* compElement, bool(*compFunc)(const void*, const void*)); +// Removes the first element, and copy its value to `*result` +bool ffListShift(FFlist* list, void* result); +// Removes the last element, and copy its value to `*result` +bool ffListPop(FFlist* list, void* result); + void ffListDestroy(FFlist* list); static inline void ffListInit(FFlist* list, uint32_t elementSize) diff --git a/tests/list.c b/tests/list.c index b42ef4b18..db4db544a 100644 --- a/tests/list.c +++ b/tests/list.c @@ -31,6 +31,7 @@ static bool numEqualsAdapter(const void* first, const void* second) int main(void) { FFlist list; + uint32_t n = 0; //initA @@ -44,6 +45,14 @@ int main(void) FF_LIST_FOR_EACH(uint32_t, item, list) VERIFY(false); + //shift + VERIFY(!ffListShift(&list, &n)); + VERIFY(list.length == 0); + + //pop + VERIFY(!ffListPop(&list, &n)); + VERIFY(list.length == 0); + //add for (uint32_t i = 1; i <= FF_LIST_DEFAULT_ALLOC + 1; ++i) { @@ -64,6 +73,7 @@ int main(void) VERIFY(*(uint32_t*)ffListGet(&list, 0) == 1); VERIFY(*(uint32_t*)ffListGet(&list, i - 1) == i); } + VERIFY(list.length == FF_LIST_DEFAULT_ALLOC + 1); uint32_t sum = 0; //forEach @@ -72,11 +82,25 @@ int main(void) VERIFY(sum == (1 + FF_LIST_DEFAULT_ALLOC + 1) * (FF_LIST_DEFAULT_ALLOC + 1) / 2); // ffListFirstIndexComp - uint32_t n = 10; + n = 10; VERIFY(ffListFirstIndexComp(&list, &n, numEqualsAdapter) == 9); n = 999; VERIFY(ffListFirstIndexComp(&list, &n, numEqualsAdapter) == list.length); + //shift + VERIFY(ffListShift(&list, &n)); + VERIFY(n == 1); + VERIFY(list.length == FF_LIST_DEFAULT_ALLOC); + VERIFY(*(uint32_t*) ffListGet(&list, 0) == 2); + VERIFY(*(uint32_t*) ffListGet(&list, list.length - 1) == FF_LIST_DEFAULT_ALLOC + 1); + + //pop + VERIFY(ffListPop(&list, &n)); + VERIFY(n == FF_LIST_DEFAULT_ALLOC + 1); + VERIFY(list.length == FF_LIST_DEFAULT_ALLOC - 1); + VERIFY(*(uint32_t*) ffListGet(&list, 0) == 2); + VERIFY(*(uint32_t*) ffListGet(&list, list.length - 1) == FF_LIST_DEFAULT_ALLOC); + //Destroy ffListDestroy(&list); From e076097a7c7cde11415fb3bbc3d292c11213bf4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 14 Jan 2023 00:19:55 +0800 Subject: [PATCH 085/142] FFlist: fix compiler warnings --- src/util/FFlist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/FFlist.c b/src/util/FFlist.c index 40ed90816..d2151b803 100644 --- a/src/util/FFlist.c +++ b/src/util/FFlist.c @@ -1,7 +1,7 @@ #include "FFlist.h" #include -#include +#include void ffListInitA(FFlist* list, uint32_t elementSize, uint32_t capacity) { From b739d94f23f23a1e35eb8d67c5a7e7c311c999dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 13 Jan 2023 19:26:00 +0800 Subject: [PATCH 086/142] Command: an attempt to add a new module which can run custom shell scripts --- CMakeLists.txt | 1 + src/common/init.c | 20 +++++++++++ src/common/processing_linux.c | 4 +-- src/data/help.txt | 3 ++ src/fastfetch.c | 16 +++++++++ src/fastfetch.h | 5 +++ src/modules/command.c | 67 +++++++++++++++++++++++++++++++++++ 7 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 src/modules/command.c diff --git a/CMakeLists.txt b/CMakeLists.txt index fc0451893..2b7ed8b72 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -263,6 +263,7 @@ set(LIBFASTFETCH_SRC src/modules/cpuUsage.c src/modules/cursor.c src/modules/custom.c + src/modules/command.c src/modules/date.c src/modules/datetime.c src/modules/de.c diff --git a/src/common/init.c b/src/common/init.c index 97184f345..06c657708 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -348,6 +348,18 @@ static void defaultConfig(FFinstance* instance) ffStrbufInitA(&instance->config.playerName, 0); instance->config.percentType = 1; + + ffStrbufInitS(&instance->config.commandShell, + #ifdef _WIN32 + "cmd" + #elif defined(__FreeBSD__) + "csh" + #else + "bash" + #endif + ); + ffListInit(&instance->config.commandKeys, sizeof(FFstrbuf)); + ffListInit(&instance->config.commandTexts, sizeof(FFstrbuf)); } void ffInitInstance(FFinstance* instance) @@ -558,6 +570,14 @@ static void destroyConfig(FFinstance* instance) ffStrbufDestroy(&instance->config.weatherOutputFormat); ffStrbufDestroy(&instance->config.osFile); ffStrbufDestroy(&instance->config.playerName); + + ffStrbufDestroy(&instance->config.commandShell); + FF_LIST_FOR_EACH(FFstrbuf, item, instance->config.commandKeys) + ffStrbufDestroy(item); + ffListDestroy(&instance->config.commandKeys); + FF_LIST_FOR_EACH(FFstrbuf, item, instance->config.commandTexts) + ffStrbufDestroy(item); + ffListDestroy(&instance->config.commandTexts); } static void destroyState(FFinstance* instance) diff --git a/src/common/processing_linux.c b/src/common/processing_linux.c index d8bb4e0bd..a628aeb3d 100644 --- a/src/common/processing_linux.c +++ b/src/common/processing_linux.c @@ -31,8 +31,8 @@ const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[]) //Parent close(pipes[1]); waitpid(childPid, NULL, 0); - ffAppendFDBuffer(pipes[0], buffer); + bool ok = ffAppendFDBuffer(pipes[0], buffer); close(pipes[0]); - return NULL; + return ok ? NULL : "ffAppendFDBuffer() failed"; } diff --git a/src/data/help.txt b/src/data/help.txt index 81b52dd7f..441c1c6cf 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -126,6 +126,9 @@ Module specific options: --player-name: The name of the player to use --gl : Set the OpenGL context creation library to use. Must be auto, egl, glx or osmesa. Default is auto --percent-type : Set the percentage output type. 1 for percentage number, 2 for bar, 3 for both, 6 for bar only. Default is 1 + --command-shell : Set the shell program to execute the command text. Default is cmd for Windows, csh for FreeBSD, bash for others + --command-key : Set the module key to display, can be specified mulitple times + --command-text : Set the command text to be executed, can be specified mulitple times Parsing is not case sensitive. E.g. "--lib-PCI" is equal to "--Lib-Pci" If a value starts with a ?, it is optional. "true" will be used if not set. diff --git a/src/fastfetch.c b/src/fastfetch.c index a18e3256e..e732422c3 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -1301,6 +1301,20 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con } else if(strcasecmp(key, "--percent-type") == 0) instance->config.percentType = optionParseUInt32(key, value); + else if(strcasecmp(key, "--command-shell") == 0) + optionParseString(key, value, &instance->config.commandShell); + else if(strcasecmp(key, "--command-key") == 0) + { + FFstrbuf* result = (FFstrbuf*) ffListAdd(&instance->config.commandKeys); + ffStrbufInit(result); + optionParseString(key, value, result); + } + else if(strcasecmp(key, "--command-text") == 0) + { + FFstrbuf* result = (FFstrbuf*) ffListAdd(&instance->config.commandTexts); + ffStrbufInit(result); + optionParseString(key, value, result); + } ////////////////// //Unknown option// @@ -1454,6 +1468,8 @@ static void parseStructureCommand(FFinstance* instance, FFdata* data, const char ffPrintOpenCL(instance); else if(strcasecmp(line, "users") == 0) ffPrintUsers(instance); + else if(strcasecmp(line, "command") == 0) + ffPrintCommand(instance); else ffPrintErrorString(instance, line, 0, NULL, NULL, ""); } diff --git a/src/fastfetch.h b/src/fastfetch.h index 8ee5cd356..c793b3c0e 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -208,6 +208,10 @@ typedef struct FFconfig FFstrbuf playerName; uint32_t percentType; + + FFstrbuf commandShell; + FFlist commandKeys; + FFlist commandTexts; } FFconfig; typedef struct FFstate @@ -314,5 +318,6 @@ void ffPrintVulkan(FFinstance* instance); void ffPrintOpenGL(FFinstance* instance); void ffPrintOpenCL(FFinstance* instance); void ffPrintUsers(FFinstance* instance); +void ffPrintCommand(FFinstance* instance); #endif diff --git a/src/modules/command.c b/src/modules/command.c new file mode 100644 index 000000000..1b767013b --- /dev/null +++ b/src/modules/command.c @@ -0,0 +1,67 @@ +#include "fastfetch.h" + +#include "common/printing.h" +#include "common/processing.h" +#include "util/textModifier.h" + +#define FF_COMMAND_MODULE_NAME "Command" + +static void printError(FFinstance* instance, const char* key, const char* error) +{ + ffPrintLogoAndKey(instance, key, 0, NULL); + + if(instance->config.pipe) + fputs(FASTFETCH_TEXT_MODIFIER_ERROR, stdout); + + fputs(error, stdout); + + if(!instance->config.pipe) + fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout); + + putchar('\n'); +} + +void ffPrintCommand(FFinstance* instance) +{ + FF_STRBUF_AUTO_DESTROY key; + ffStrbufInit(&key); + + if(!ffListShift(&instance->config.commandKeys, &key)) + ffStrbufInitS(&key, FF_COMMAND_MODULE_NAME); + + FF_STRBUF_AUTO_DESTROY text; + ffStrbufInit(&text); + if(!ffListShift(&instance->config.commandTexts, &text)) + { + printError(instance, key.chars, "No command text left"); + return; + } + + FF_STRBUF_AUTO_DESTROY result; + ffStrbufInit(&result); + const char* error = ffProcessAppendStdOut(&result, (char* const[]){ + instance->config.commandShell.chars, + #ifdef _WIN32 + "/c", + #else + "-c", + #endif + text.chars, + NULL + }); + + if(error) + { + printError(instance, key.chars, error); + return; + } + + if(!result.length) + { + printError(instance, key.chars, "No result printed"); + return; + } + + ffPrintLogoAndKey(instance, key.chars, 0, NULL); + puts(result.chars); +} From cdff99339e108756e02bafd942c9e81ec8c6bba8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 14 Jan 2023 17:31:04 +0800 Subject: [PATCH 087/142] Windows: fix the last issue that breaks Win10- --- src/common/init.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/common/init.c b/src/common/init.c index 97184f345..05827dd31 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -400,6 +400,10 @@ static void resetConsole() if(ffHideCursor) fputs("\033[?25h", stdout); + + #if defined(_WIN32) && defined(FF_ENABLE_BUFFER) + fflush(stdout); + #endif } #ifdef _WIN32 From 9c0fc63ee9a02d567457717cb80ee6220cb75109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 14 Jan 2023 17:46:11 +0800 Subject: [PATCH 088/142] Windows: with cdff99, the special build for Win7 is no longer needed. Drop it. --- .github/workflows/push.yml | 77 +------------------------------------- README.md | 5 +-- 2 files changed, 2 insertions(+), 80 deletions(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 006e26d22..05e721183 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -197,80 +197,6 @@ jobs: name: fastfetch-windows path: ./fastfetch-*-Windows.zip - win7: - name: Win7 - runs-on: windows-latest - permissions: - security-events: write - contents: read - defaults: - run: - shell: msys2 {0} - steps: - - name: checkout repository - uses: actions/checkout@v3 - - - name: setup-msys2 - uses: msys2/setup-msys2@v2 - with: - msystem: MINGW64 - update: true - install: git zip mingw-w64-x86_64-cmake mingw-w64-x86_64-gcc mingw-w64-x86_64-cjson mingw-w64-x86_64-vulkan-loader mingw-w64-x86_64-opencl-icd - - - name: print msys version - run: uname -a - - # https://github.com/msys2/MINGW-packages/issues/13524#event-7555720785 - - name: create OpenCL.pc - run: | - cat > /mingw64/lib/pkgconfig/OpenCL.pc << EOF - prefix=/mingw64 - exec_prefix=${prefix} - libdir=${exec_prefix}/lib - includedir=${prefix}/include - - Name: OpenCL - Description: Open Computing Language generic Installable Client Driver Loader - Version: 2022.09.30-1 - Libs: -L${libdir} -lOpenCL.dll - Cflags: -I${includedir} - EOF - - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: c, cpp - - - name: configure project - run: env PKG_CONFIG_PATH=/mingw64/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_BUFFER=Off . - - - name: build project - run: cmake --build . - - - name: perform CodeQL analysis - uses: github/codeql-action/analyze@v2 - - - name: copy necessary dlls - run: cp /mingw64/bin/{libcjson,libOpenCL,vulkan-1}.dll . - - - name: run fastfetch - run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all - - - name: run flashfetch - run: time ./flashfetch - - - name: run tests - run: ctest - - - name: create zip archive - run: zip fastfetch-$(./fastfetch --version-raw)-Win7.zip *.dll fastfetch.exe flashfetch.exe - - - name: upload artifacts - uses: actions/upload-artifact@v3 - with: - name: fastfetch-win7 - path: ./fastfetch-*-Win7.zip - release: if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'LinusDierheimer/fastfetch' name: Release @@ -280,7 +206,6 @@ jobs: - macos - freebsd - windows - - win7 permissions: contents: write steps: @@ -300,4 +225,4 @@ jobs: tag: ${{ needs.linux.outputs.ffversion }} commit: ${{ github.sha }} artifactErrorsFailBuild: true - artifacts: fastfetch-linux/*,fastfetch-macos/*,fastfetch-freebsd/*,fastfetch-windows/*,fastfetch-win7/* + artifacts: fastfetch-linux/*,fastfetch-macos/*,fastfetch-freebsd/*,fastfetch-windows/* diff --git a/README.md b/README.md index ed848668c..8c7ad6f70 100644 --- a/README.md +++ b/README.md @@ -70,10 +70,7 @@ For the image logo, iTerm with iterm image protocol should work. Apple Terminal * [`libvulkan`](https://www.vulkan.org/): Vulkan module. Usually has been provided by GPU drivers. [`vulkan-loader`](https://github.com/msys2/MINGW-packages/tree/master/mingw-w64-vulkan-loader) [`vulkan-headers`](https://github.com/msys2/MINGW-packages/tree/master/mingw-w64-vulkan-headers) * [`libOpenCL`](https://www.khronos.org/opencl/): OpenCL module. [`opencl-icd`](https://github.com/msys2/MINGW-packages/tree/master/mingw-w64-opencl-icd) -Note: In Windows 7, 8 and 8.1, [ConEmu](https://conemu.github.io/en/AnsiEscapeCodes.html) is required to run fastfetch due to [the lack of ASCII escape code native support](https://en.wikipedia.org/wiki/ANSI_escape_code#DOS,_OS/2,_and_Windows). In addition, special build `fastfetch-win7` is provided to support these old systems, which - -1. Build with the ancient [MSVCRT](https://en.wikipedia.org/wiki/Microsoft_Windows_library_files#MSVCRT.DLL,_MSVCP*.DLL_and_CRTDLL.DLL) C runtime library, instead of the modern [UCRT](https://learn.microsoft.com/en-us/cpp/windows/universal-crt-deployment) C runtime library -2. Disable stdout application buffer, which seems to problematic for ConEmu. +Note: In Windows 7, 8 and 8.1, [ConEmu](https://conemu.github.io/en/AnsiEscapeCodes.html) is required to run fastfetch due to [the lack of ASCII escape code native support](https://en.wikipedia.org/wiki/ANSI_escape_code#DOS,_OS/2,_and_Windows). In addition, as fastfetch for Windows targets [UCRT](https://learn.microsoft.com/en-us/cpp/windows/universal-crt-deployment) C runtime library, [it must be installed manually](https://support.microsoft.com/en-us/topic/update-for-universal-c-runtime-in-windows-c0514201-7fe6-95a3-b0a5-287930f3560c) as UCRT is only pre-installed in Windows 10 and later. For the image logo, only chafa is supported due to [the design flaw of ConPTY](https://github.com/microsoft/terminal/issues/1173). In addition, chafa support is not built by default due to the massive dependencies of imagemagick. You must built it yourself. From 026424ab8c1618ece1e15fbe679c906989de0954 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Sat, 14 Jan 2023 16:38:34 +0100 Subject: [PATCH 089/142] Don't crash when uname fails #385 --- src/common/init.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/common/init.c b/src/common/init.c index 97184f345..261c293c0 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -192,7 +192,9 @@ static void initState(FFstate* state) #else state->passwd = ffGetPasswd(); #endif - uname(&state->utsname); + + if(uname(&state->utsname) != 0) + memset(&state->utsname, 0, sizeof(struct utsname)); initConfigDirs(state); initDataDirs(state); From 6e1d656a601b2506b07270fc064a1b518fbee62b Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Sat, 14 Jan 2023 16:58:09 +0100 Subject: [PATCH 090/142] Fix budgie detection #382 --- src/detection/displayserver/linux/wmde.c | 14 ++++++++++++++ src/detection/gtk.c | 9 ++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/detection/displayserver/linux/wmde.c b/src/detection/displayserver/linux/wmde.c index 3f564bfb6..4d9d79b6a 100644 --- a/src/detection/displayserver/linux/wmde.c +++ b/src/detection/displayserver/linux/wmde.c @@ -239,6 +239,13 @@ static void getLXQt(const FFinstance* instance, FFDisplayServerResult* result) ffStrbufDestroy(&wmProcessNameBuffer); } +static void getBudgie(const FFinstance* instance, FFDisplayServerResult* result) +{ + ffStrbufSetS(&result->dePrettyName, "Budgie"); + ffStrbufSetS(&result->deProcessName, "budgie-desktop"); + ffParsePropFileData(instance, "budgie/budgie-version.xml", "", &result->deVersion); +} + static void applyPrettyNameIfDE(const FFinstance* instance, FFDisplayServerResult* result, const char* name) { if(!ffStrSet(name)) @@ -282,6 +289,13 @@ static void applyPrettyNameIfDE(const FFinstance* instance, FFDisplayServerResul strcasecmp(name, "X-LXQT") == 0 || strcasecmp(name, "lxqt-session") == 0 ) getLXQt(instance, result); + + else if( + strcasecmp(name, "Budgie") == 0 || + strcasecmp(name, "X-Budgie") == 0 || + strcasecmp(name, "budgie-desktop") == 0 || + strcasecmp(name, "Budgie:GNOME") == 0 + ) getBudgie(instance, result); } static void getWMProtocolNameFromEnv(FFDisplayServerResult* result) diff --git a/src/detection/gtk.c b/src/detection/gtk.c index ad24c9c4e..71f8ac972 100644 --- a/src/detection/gtk.c +++ b/src/detection/gtk.c @@ -80,8 +80,11 @@ static void detectGTKFromSettings(const FFinstance* instance, FFGTKResult* resul cursorTheme = ffSettingsGet(instance, "/org/mate/peripherals-mouse/cursor-theme", "org.mate.peripherals-mouse", NULL, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue; cursorSize = ffSettingsGet(instance, "/org/mate/peripherals-mouse/cursor-size", "org.mate.peripherals-mouse", NULL, "cursor-size", FF_VARIANT_TYPE_INT).intValue; } - else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Gnome") == 0 || ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Unity") == 0 || ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Budgie") == 0) - { + else if( + ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Gnome") == 0 || + ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Unity") == 0 || + fStrbufIgnCaseCompS(&wmde->dePrettyName, "Budgie") == 0 + ) { themeName = ffSettingsGet(instance, "/org/gnome/desktop/interface/gtk-theme", "org.gnome.desktop.interface", NULL, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue; iconsName = ffSettingsGet(instance, "/org/gnome/desktop/interface/icon-theme", "org.gnome.desktop.interface", NULL, "icon-theme", FF_VARIANT_TYPE_STRING).strValue; fontName = ffSettingsGet(instance, "/org/gnome/desktop/interface/font-name", "org.gnome.desktop.interface", NULL, "font-name", FF_VARIANT_TYPE_STRING).strValue; @@ -145,7 +148,7 @@ static void detectGTKFromConfigDir(FFstrbuf* configDir, const char* version, FFG static void detectGTK(const FFinstance* instance, const char* version, FFGTKResult* result) { - //Mate, Cinnamon and Gnome use dconf to save theme config + //Mate, Cinnamon, Gnome, Unity, Budgie use dconf to save theme config //On other DEs, this will do nothing detectGTKFromSettings(instance, result); if(allPropertiesSet(result)) From 8a054706b5efd6d50db4cf92388d62a94d50f4ca Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Sat, 14 Jan 2023 17:00:56 +0100 Subject: [PATCH 091/142] Fix build on linux --- src/detection/gtk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/gtk.c b/src/detection/gtk.c index 71f8ac972..2e3c807d0 100644 --- a/src/detection/gtk.c +++ b/src/detection/gtk.c @@ -83,7 +83,7 @@ static void detectGTKFromSettings(const FFinstance* instance, FFGTKResult* resul else if( ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Gnome") == 0 || ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Unity") == 0 || - fStrbufIgnCaseCompS(&wmde->dePrettyName, "Budgie") == 0 + ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Budgie") == 0 ) { themeName = ffSettingsGet(instance, "/org/gnome/desktop/interface/gtk-theme", "org.gnome.desktop.interface", NULL, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue; iconsName = ffSettingsGet(instance, "/org/gnome/desktop/interface/icon-theme", "org.gnome.desktop.interface", NULL, "icon-theme", FF_VARIANT_TYPE_STRING).strValue; From f77f617bc2b8a021bb37c1eb27846d0353a9072a Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Sat, 14 Jan 2023 17:20:36 +0100 Subject: [PATCH 092/142] Update Support Status --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 8c7ad6f70..339993501 100644 --- a/README.md +++ b/README.md @@ -84,32 +84,32 @@ All categories not listed here should work without needing a specific implementa ##### Available Modules ``` -Title, Separator, OS, Host, Bios, Board, Kernel, Uptime, Processes, Packages, Shell, Resolution, Brightness, DE, WM, WMTheme, Theme, Icons, Font, Cursor, Terminal, Terminal Font, CPU, CPUUsage, GPU, Memory, Swap, Disk, Battery, Power Adapter, Player, Media, Vulkan, OpenGL, OpenCL, LocalIP, PublicIP, Wifi, DateTime, Date, Time, Locale, Colors, Break, Custom +Battery, Bios, Board, Break, Brightness, Colors, Command, CPU, CPUUsage, Cursor, Custom, Date, DateTime, DE, Disk, Font, GPU, Host, Icons, Kernel, Locale, LocalIP, Media, Memory, OpenCL, OpenGL, Packages, Player, Power Adapter, Processes, PublicIP, Resolution, Separator OS, Shell, Swap, Terminal, Terminal Font, Theme, Time, Title, Uptime, Vulkan, Wifi, WM, WMTheme ``` ##### Builtin logos ``` -AlmaLinux, Alpine, Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, CRUX, Crystal, Debian, Devuan, Deepin, Endeavour, Enso, Fedora, FreeBSD, Garuda, Gentoo, KDE Neon, KISS, Kubuntu, LangitKetujuh, Linux, MacOS, Manjaro, Mint, MSYS2, NixOS, Nobara, OpenSUSE, OpenSUSE Tumbleweed, OpenSUSE LEAP, Parabola, Raspbian, Pop!_OS, RebornOS, RedstarOS, Rocky, Rosa, Slackware, Solus, Ubuntu, Vanilla, Void, Windows 11, Windows 8, Windows, Zorin +AlmaLinux, Alpine, Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, CRUX, Crystal, Debian, Deepin, Devuan, Endeavour, Enso, Fedora, FreeBSD, Garuda, Gentoo, KDE Neon, KISS, Kubuntu, LangitKetujuh, Linux, MacOS, Manjaro, Mint, MSYS2, NixOS, Nobara, OpenSUSE, OpenSUSE LEAP, OpenSUSE Tumbleweed, Parabola, Pop!_OS, Raspbian, RebornOS, RedstarOS, Rocky, Rosa, Slackware, Solus, Ubuntu, Vanilla, Void, Windows, Windows 11, Windows 8, Zorin ``` ##### Package managers ``` -Pacman, dpkg, rpm, emerge, eopkg, xbps, nix, Flatpak, Snap, apk, pkg, brew, MacPorts, scoop, Chocolatey +apk, brew, Chocolatey, dpkg, emerge, eopkg, Flatpak, MacPorts, nix, Pacman, pkg, rpm, scoop, Snap, xbps ``` ##### WM themes ``` -KWin, Mutter, Muffin, Marco, XFWM, Openbox (LXDE, LXQT & without DE), Quartz Compositor (macOS), DWM (Windows) +DWM (Windows), KWin, Marco, Muffin, Mutter, Openbox (LXDE, LXQT & without DE), Quartz Compositor (macOS), XFWM ``` ##### DE versions ``` -KDE Plasma, Gnome, Cinnamon, Mate, XFCE4, LXQt +Budgie, Cinnamon, Gnome, KDE Plasma, LXQt, Mate, XFCE4 ``` ##### Terminal fonts ``` -Konsole, Gnome Terminal, Tilix, XFCE4 Terminal, Alacritty, Kitty, LXTerminal, Deepin Terminal, iTerm2, Apple Terminal, Warp, TTY, Windows Terminal, Termux, mintty, ConEmu, WezTerm +Alacritty, Apple Terminal, ConEmu, Deepin Terminal, Gnome Terminal, iTerm2, Kitty, Konsole, LXTerminal, mintty, Termux, Tilix, TTY, Warp, WezTerm, Windows Terminal, XFCE4 Terminal ``` ## Building From f13a502123ddebd223b68e0233e51e3703c17d0a Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Sat, 14 Jan 2023 17:50:14 +0100 Subject: [PATCH 093/142] Update logo doc --- doc/logo.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/logo.md b/doc/logo.md index c24cae948..504bd4902 100644 --- a/doc/logo.md +++ b/doc/logo.md @@ -14,6 +14,12 @@ | `--logo-padding-right` | `4` | Sets the padding right of the logo | | `--logo-padding-top` | `0` | Sets the padding top of the logo | +All filesytem paths can be: +* Absolute +* Relative to the current working directory +* Relative to any of the directories listed by `fastfetch --list-data-paths` + `/logos` + For example, the file `~/.local/share/fastfetch/logos/shrek` can simply be referenced as `shrek`. + ### Text | Option | Default | Description | From b6abc6e32657bf93c4ebc3c183f712e5580a5e32 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Sat, 14 Jan 2023 17:54:21 +0100 Subject: [PATCH 094/142] Update logo doc --- doc/logo.md | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/doc/logo.md b/doc/logo.md index 504bd4902..69d13e8ef 100644 --- a/doc/logo.md +++ b/doc/logo.md @@ -1,8 +1,6 @@ -# Logo Documentation +# Logo options -## Logo options - -### General +## General | Option | Default | Description | |--------|---------|-------------| @@ -20,7 +18,7 @@ All filesytem paths can be: * Relative to any of the directories listed by `fastfetch --list-data-paths` + `/logos` For example, the file `~/.local/share/fastfetch/logos/shrek` can simply be referenced as `shrek`. -### Text +## Text | Option | Default | Description | |--------|---------|-------------| @@ -30,7 +28,7 @@ All filesytem paths can be: * Color placeholders are in the form `$[1-9]`. To print a `$`, use `$$`. * If a color placeholder value is not set, the placeholder is simply discarded. -### Image +## Image | Option | Default | Description | |--------|---------|-------------| @@ -40,9 +38,9 @@ All filesytem paths can be: * If one of the height / width options is set, but the other not, the aspect ratio is preserved. * If neither height nor width is set, the original size is used. -## Logo types +# Logo types -### auto +## auto Trys to detect the logo type depending on the value of `--logo`, in the following order: * If the value is empty / not set, an autodected builtin logo is displayed. @@ -51,7 +49,7 @@ Trys to detect the logo type depending on the value of `--logo`, in the followin * If the value is the path to a text file, the content is displayed. * The autodetected builtin logo is displayed. -### builtin +## builtin The value of `--logo` is interpreted as the name of a builtin logo. * If the value is empty / not set, it is autodetected. @@ -60,45 +58,45 @@ The value of `--logo` is interpreted as the name of a builtin logo. * All builtin logos set default values for `--logo-color-[1-9]`. * Use `none` to disable the logo, but keep key colors from the detected logo. -### file +## file The value of `--logo` is interpreted as the path to a file. The content of the file is displayed. * If the file can't be read, the autodetected builtin logo is displayed. -### file-raw +## file-raw The value of `--logo` is interpreted as the path to a file. The content of the file is displayed. * No color placeholder replacement is done. * If the file can't be read, the autodetected builtin logo is displayed. -### data +## data The value of `--logo` is interpreted as the logo and directly displayed. * If the value is empty / not set, the autodetected builtin logo is displayed. -### data-raw +## data-raw The value of `--logo` is interpreted as the logo and directly displayed. * No color placeholder replacement is done. * If the value is empty / not set, the autodetected builtin logo is displayed. -### sixel +## sixel The value of `--logo` is interpreted as the path to an image file. It is displayed using the sixel graphics protocol. * `fastfetch` must be compiled with the `imagemagick6` or `imagemagick7` feature. -### kitty +## kitty The value of `--logo` is interpreted as the path to an image file. It is displayed using the kitty graphics protocol. * If the file is a png file, and both `--logo-width` and `--logo-height` are specified, the image is directly send to the terminal emulator. * Otherwise `fastfetch` must be compiled with the `imagemagick6` or `imagemagick7` feature. -### iterm +## iterm The value of `--logo` is interpreted as the path to an image file. It is displayed using the iTerm graphics protocol. * Both `--logo-width` and `--logo-height` must be specified. -### chafa +## chafa The value of `--logo` is interpreted as the path to an image file. It is converted to an ascii logo using `libchafa`. * `fastfetch` must be compiled with the `chafa` feature. @@ -110,7 +108,7 @@ The value of `--logo` is interpreted as the path to an image file. It is convert * Use `--chafa-dither-mode` to set the dither mode. * See the [chafa documentation](https://hpjansson.org/chafa/man/) for more information. -### raw +## raw The value of `--logo` is interpreted as the path to a binary file. It is printed as-is. * Both `--logo-width` and `--logo-height` must be specified. From 27efc94b0950433d600a94274bbb0cf5b73b36a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 15 Jan 2023 00:59:33 +0800 Subject: [PATCH 095/142] FFlist: silence compiler warnings when compiling with -m32 --- src/util/FFlist.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/FFlist.h b/src/util/FFlist.h index 5b42add89..58612e347 100644 --- a/src/util/FFlist.h +++ b/src/util/FFlist.h @@ -53,7 +53,7 @@ static inline void ffListSort(FFlist* list, int(*compar)(const void*, const void #define FF_LIST_FOR_EACH(itemType, itemVarName, listVar) \ assert(sizeof(itemType) == (listVar).elementSize); \ for(itemType* itemVarName = (itemType*)(listVar).data; \ - itemVarName - (itemType*)(listVar).data < (listVar).length; \ + itemVarName - (itemType*)(listVar).data < (intptr_t)(listVar).length; \ ++itemVarName) #define FF_LIST_AUTO_DESTROY FFlist __attribute__((__cleanup__(ffListDestroy))) From dd77ebe11e78cb7ee8eabce35a72ad9ec89beddc Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Sat, 14 Jan 2023 19:59:54 +0100 Subject: [PATCH 096/142] Fix GitHub code scanning alert --- src/util/FFlist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/FFlist.c b/src/util/FFlist.c index d2151b803..bd643014a 100644 --- a/src/util/FFlist.c +++ b/src/util/FFlist.c @@ -41,7 +41,7 @@ bool ffListShift(FFlist* list, void* result) return false; memcpy(result, list->data, list->elementSize); - memmove(list->data, list->data + list->elementSize, list->elementSize * (list->length - 1)); + memmove(list->data, list->data + list->elementSize, (size_t) list->elementSize * (list->length - 1)); --list->length; return true; } From a1d8e3e598ec5081353c41d39bab05fb0e4a2dee Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Sun, 15 Jan 2023 15:57:26 +0100 Subject: [PATCH 097/142] Introduce FFPlatform --- CMakeLists.txt | 7 +- src/common/init.c | 188 +-------------- src/common/parsing.c | 11 - src/common/parsing.h | 1 - src/common/properties.c | 2 +- src/common/properties.h | 4 +- src/detection/gtk.c | 4 +- src/detection/os/os.h | 2 - src/detection/os/os_android.c | 4 - src/detection/os/os_apple.m | 4 - src/detection/os/os_linux.c | 5 - src/detection/os/os_windows.cpp | 5 - src/detection/packages/packages_linux.c | 2 +- src/detection/qt.c | 4 +- .../terminalfont/terminalfont_linux.c | 4 +- .../terminalshell/terminalshell_linux.c | 5 +- src/detection/title.c | 66 ----- src/detection/title.h | 17 -- src/detection/wmtheme/wmtheme_linux.c | 4 +- src/fastfetch.c | 14 +- src/fastfetch.h | 15 +- src/logo/image/image.c | 16 +- src/logo/logo.c | 6 +- src/modules/kernel.c | 20 +- src/modules/os.c | 24 +- src/modules/separator.c | 8 +- src/modules/title.c | 10 +- src/util/FFstrbuf.c | 11 + src/util/FFstrbuf.h | 2 + src/util/platform/FFPlatform.c | 118 +++++++++ src/util/platform/FFPlatform.h | 29 +++ src/util/platform/FFPlatform_private.h | 21 ++ src/util/platform/FFPlatform_unix.c | 138 +++++++++++ src/util/platform/FFPlatform_windows.c | 228 ++++++++++++++++++ src/util/windows/pwd.c | 22 -- src/util/windows/pwd.h | 22 -- src/util/windows/unicode.h | 4 +- src/util/windows/utsname.c | 116 --------- src/util/windows/utsname.h | 19 -- 39 files changed, 622 insertions(+), 560 deletions(-) delete mode 100644 src/detection/title.c delete mode 100644 src/detection/title.h create mode 100644 src/util/platform/FFPlatform.c create mode 100644 src/util/platform/FFPlatform.h create mode 100644 src/util/platform/FFPlatform_private.h create mode 100644 src/util/platform/FFPlatform_unix.c create mode 100644 src/util/platform/FFPlatform_windows.c delete mode 100644 src/util/windows/pwd.c delete mode 100644 src/util/windows/pwd.h delete mode 100644 src/util/windows/utsname.c delete mode 100644 src/util/windows/utsname.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2b7ed8b72..87c9c6b7b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -245,7 +245,6 @@ set(LIBFASTFETCH_SRC src/detection/packages/packages.c src/detection/terminalfont/terminalfont.c src/detection/terminalshell/terminalshell.c - src/detection/title.c src/detection/vulkan.c src/logo/builtin.c src/logo/image/im6.c @@ -303,6 +302,7 @@ set(LIBFASTFETCH_SRC src/util/FFlist.c src/util/FFstrbuf.c src/util/FFvaluestore.c + src/util/platform/FFPlatform.c ) if(LINUX) @@ -344,6 +344,7 @@ if(LINUX) src/detection/users/users_linux.c src/detection/wifi/wifi_linux.c src/detection/wmtheme/wmtheme_linux.c + src/util/platform/FFPlatform_unix.c ) elseif(ANDROID) list(APPEND LIBFASTFETCH_SRC @@ -378,6 +379,7 @@ elseif(ANDROID) src/detection/users/users_linux.c src/detection/wifi/wifi_nosupport.c src/detection/wmtheme/wmtheme_nosupport.c + src/util/platform/FFPlatform_unix.c ) elseif(BSD) list(APPEND LIBFASTFETCH_SRC @@ -419,6 +421,7 @@ elseif(BSD) src/detection/users/users_linux.c src/detection/wifi/wifi_nosupport.c src/detection/wmtheme/wmtheme_linux.c + src/util/platform/FFPlatform_unix.c ) elseif(APPLE) list(APPEND LIBFASTFETCH_SRC @@ -457,6 +460,7 @@ elseif(APPLE) src/detection/wmtheme/wmtheme_apple.m src/util/apple/cf_helpers.c src/util/apple/osascript.m + src/util/platform/FFPlatform_unix.c ) elseif(WIN32) list(APPEND LIBFASTFETCH_SRC @@ -496,6 +500,7 @@ elseif(WIN32) src/util/windows/unicode.c src/util/windows/utsname.c src/util/windows/wmi.cpp + src/util/platform/FFPlatform_windows.c ) endif() diff --git a/src/common/init.c b/src/common/init.c index e2c32c3c0..d08cbaf09 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -18,186 +18,13 @@ #include #endif -#define FF_ENSURE_ONLY_ONCE_IN_LIST(list, element) \ - if(ffListFirstIndexComp(list, element, (bool(*)(const void*, const void*))ffStrbufEqual) < list->length - 1) \ - { \ - ffStrbufDestroy(ffListGet(list, list->length - 1)); \ - --list->length; \ - } - -static void pathsAddHome(FFlist* dirs, FFstate* state, const char* suffix) -{ - FFstrbuf* buffer = (FFstrbuf*) ffListAdd(dirs); - ffStrbufInitA(buffer, 64); - ffStrbufAppendS(buffer, state->passwd->pw_dir); - ffStrbufAppendS(buffer, suffix); - ffStrbufEnsureEndsWithC(buffer, '/'); - FF_ENSURE_ONLY_ONCE_IN_LIST(dirs, buffer); -} - -static void pathsAddAbsolute(FFlist* dirs, const char* path) -{ - FFstrbuf* buffer = (FFstrbuf*) ffListAdd(dirs); - ffStrbufInitA(buffer, 64); - ffStrbufAppendS(buffer, path); - ffStrbufEnsureEndsWithC(buffer, '/'); - FF_ENSURE_ONLY_ONCE_IN_LIST(dirs, buffer); -} - -static void pathsAddEnv(FFlist* dirs, const char* env) -{ - const char* envValue = getenv(env); - if(!ffStrSet(envValue)) - return; - - FFstrbuf value; - ffStrbufInitA(&value, 64); - ffStrbufAppendS(&value, envValue); - - uint32_t startIndex = 0; - while (startIndex < value.length) - { - uint32_t colonIndex = ffStrbufNextIndexC(&value, startIndex, ':'); - value.chars[colonIndex] = '\0'; - - if(!ffStrSet(value.chars + startIndex)) - { - startIndex = colonIndex + 1; - continue; - } - - pathsAddAbsolute(dirs, value.chars + startIndex); - - startIndex = colonIndex + 1; - } - - ffStrbufDestroy(&value); -} - -#ifdef _WIN32 -static void pathsAddKnownFolder(FFlist* dirs, REFKNOWNFOLDERID folderId) -{ - PWSTR pPath; - if(SUCCEEDED(SHGetKnownFolderPath(folderId, 0, NULL, &pPath))) - { - FFstrbuf* buffer = (FFstrbuf*) ffListAdd(dirs); - ffStrbufInit(buffer); - ffStrbufSetWS(buffer, pPath); - ffStrbufReplaceAllC(buffer, '\\', '/'); - ffStrbufEnsureEndsWithC(buffer, '/'); - FF_ENSURE_ONLY_ONCE_IN_LIST(dirs, buffer); - } - CoTaskMemFree(pPath); -} - -static void pathsAddEnvSuffix(FFlist* dirs, const char* env, const char* suffix) -{ - const char* value = getenv(env); - if(!ffStrSet(value)) - return; - - FFstrbuf* buffer = ffListAdd(dirs); - ffStrbufInitA(buffer, 64); - ffStrbufAppendS(buffer, value); - ffStrbufReplaceAllC(buffer, '\\', '/'); - ffStrbufEnsureEndsWithC(buffer, '/'); - ffStrbufAppendS(buffer, suffix); - ffStrbufEnsureEndsWithC(buffer, '/'); - FF_ENSURE_ONLY_ONCE_IN_LIST(dirs, buffer); -} -#endif - -static void initConfigDirs(FFstate* state) -{ - ffListInit(&state->configDirs, sizeof(FFstrbuf)); - - pathsAddEnv(&state->configDirs, "XDG_CONFIG_HOME"); // On systems where this is not set (Windows & Apple presumably), this wil do nothing - pathsAddHome(&state->configDirs, state, "/.config/"); - - #ifdef _WIN32 - pathsAddKnownFolder(&state->configDirs, &FOLDERID_RoamingAppData); - pathsAddKnownFolder(&state->configDirs, &FOLDERID_LocalAppData); - #elif defined(__APPLE__) - pathsAddHome(&state->configDirs, state, "/Library/Preferences/"); - #endif - - pathsAddHome(&state->configDirs, state, ""); - - #ifdef _WIN32 - if(getenv("MSYSTEM") && getenv("HOME")) - { - // We are in MSYS2 / Git Bash - pathsAddEnvSuffix(&state->configDirs, "HOME", ".config/"); - pathsAddEnvSuffix(&state->configDirs, "HOME", ""); - } - #endif - - pathsAddEnv(&state->configDirs, "XDG_CONFIG_DIRS"); - - #if !defined(_WIN32) && !defined(__APPLE__) - pathsAddAbsolute(&state->configDirs, FASTFETCH_TARGET_DIR_ETC"/xdg/"); - #endif - - #if !defined(_WIN32) - pathsAddAbsolute(&state->configDirs, FASTFETCH_TARGET_DIR_ETC"/"); - pathsAddAbsolute(&state->configDirs, FASTFETCH_TARGET_DIR_INSTALL_SYSCONF"/"); - #endif -} - -static void initDataDirs(FFstate* state) -{ - ffListInit(&state->dataDirs, sizeof(FFstrbuf)); - - pathsAddEnv(&state->dataDirs, "XDG_DATA_HOME"); // On systems where this is not set (Windows & Apple presumably), this wil do nothing - pathsAddHome(&state->dataDirs, state, "/.local/share/"); - - #ifdef _WIN32 - pathsAddKnownFolder(&state->dataDirs, &FOLDERID_RoamingAppData); - pathsAddKnownFolder(&state->dataDirs, &FOLDERID_LocalAppData); - #elif defined(__APPLE__) - pathsAddHome(&state->dataDirs, state, "/Library/Application Support/"); - #endif - - pathsAddHome(&state->dataDirs, state, ""); - - #ifdef _WIN32 - if(getenv("MSYSTEM") && getenv("HOME")) - { - // We are in MSYS2 / Git Bash - pathsAddEnvSuffix(&state->dataDirs, "HOME", ".local/share/"); - pathsAddEnvSuffix(&state->dataDirs, "HOME", ""); - } - #endif - - pathsAddEnv(&state->dataDirs, "XDG_DATA_DIRS"); - - #if !defined(_WIN32) - pathsAddAbsolute(&state->dataDirs, FASTFETCH_TARGET_DIR_USR"/local/share/"); - pathsAddAbsolute(&state->dataDirs, FASTFETCH_TARGET_DIR_USR"/share/"); - #endif -} - static void initState(FFstate* state) { - #ifdef WIN32 - //https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/setlocale-wsetlocale?source=recommendations&view=msvc-170#utf-8-support - setlocale(LC_ALL, ".UTF8"); - #endif - state->logoWidth = 0; state->logoHeight = 0; state->keysHeight = 0; - #ifndef WIN32 - state->passwd = getpwuid(getuid()); - #else - state->passwd = ffGetPasswd(); - #endif - if(uname(&state->utsname) != 0) - memset(&state->utsname, 0, sizeof(struct utsname)); - - initConfigDirs(state); - initDataDirs(state); + ffPlatformInit(&state->platform); } static void initModuleArg(FFModuleArgs* args) @@ -366,6 +193,11 @@ static void defaultConfig(FFinstance* instance) void ffInitInstance(FFinstance* instance) { + #ifdef WIN32 + //https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/setlocale-wsetlocale?source=recommendations&view=msvc-170#utf-8-support + setlocale(LC_ALL, ".UTF8"); + #endif + initState(&instance->state); defaultConfig(instance); } @@ -588,13 +420,7 @@ static void destroyConfig(FFinstance* instance) static void destroyState(FFinstance* instance) { - FF_LIST_FOR_EACH(FFstrbuf, configDir, instance->state.configDirs) - ffStrbufDestroy(configDir); - ffListDestroy(&instance->state.configDirs); - - FF_LIST_FOR_EACH(FFstrbuf, dataDir, instance->state.dataDirs) - ffStrbufDestroy(dataDir); - ffListDestroy(&instance->state.dataDirs); + ffPlatformDestroy(&instance->state.platform); } void ffDestroyInstance(FFinstance* instance) diff --git a/src/common/parsing.c b/src/common/parsing.c index 015235952..95bba4720 100644 --- a/src/common/parsing.c +++ b/src/common/parsing.c @@ -3,17 +3,6 @@ #include #include -bool ffStrSet(const char* str) -{ - if(str == NULL) - return false; - - while(isspace(*str)) - str++; - - return *str != '\0'; -} - void ffParseSemver(FFstrbuf* buffer, const FFstrbuf* major, const FFstrbuf* minor, const FFstrbuf* patch) { if(major->length > 0) diff --git a/src/common/parsing.h b/src/common/parsing.h index 239caa42f..613e20bb5 100644 --- a/src/common/parsing.h +++ b/src/common/parsing.h @@ -14,7 +14,6 @@ typedef struct FFVersion #define FF_VERSION_INIT ((FFVersion) {0}) -bool ffStrSet(const char* str); void ffParseSemver(FFstrbuf* buffer, const FFstrbuf* major, const FFstrbuf* minor, const FFstrbuf* patch); void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, const FFstrbuf* gtk4); diff --git a/src/common/properties.c b/src/common/properties.c index c2038be6b..2e3246517 100644 --- a/src/common/properties.c +++ b/src/common/properties.c @@ -148,7 +148,7 @@ bool ffParsePropFileHomeValues(const FFinstance* instance, const char* relativeF { FFstrbuf absolutePath; ffStrbufInitA(&absolutePath, 64); - ffStrbufAppendS(&absolutePath, instance->state.passwd->pw_dir); + ffStrbufAppend(&absolutePath, &instance->state.platform.homeDir); ffStrbufAppendC(&absolutePath, '/'); ffStrbufAppendS(&absolutePath, relativeFile); diff --git a/src/common/properties.h b/src/common/properties.h index f10f7caaf..ea78ed903 100644 --- a/src/common/properties.h +++ b/src/common/properties.h @@ -34,7 +34,7 @@ static inline bool ffParsePropFileList(const FFlist* list, const char* relativeF static inline bool ffParsePropFileConfigValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries) { - return ffParsePropFileListValues(&instance->state.configDirs, relativeFile, numQueries, queries); + return ffParsePropFileListValues(&instance->state.platform.configDirs, relativeFile, numQueries, queries); } static inline bool ffParsePropFileConfig(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer) @@ -44,7 +44,7 @@ static inline bool ffParsePropFileConfig(const FFinstance* instance, const char* static inline bool ffParsePropFileDataValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries) { - return ffParsePropFileListValues(&instance->state.dataDirs, relativeFile, numQueries, queries); + return ffParsePropFileListValues(&instance->state.platform.dataDirs, relativeFile, numQueries, queries); } static inline bool ffParsePropFileData(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer) diff --git a/src/detection/gtk.c b/src/detection/gtk.c index 2e3c807d0..1db344edd 100644 --- a/src/detection/gtk.c +++ b/src/detection/gtk.c @@ -158,9 +158,9 @@ static void detectGTK(const FFinstance* instance, const char* version, FFGTKResu FFstrbuf baseDir; ffStrbufInitA(&baseDir, 64); - for(uint32_t i = 0; i < instance->state.configDirs.length; i++) + FF_LIST_FOR_EACH(FFstrbuf, configDir, instance->state.platform.configDirs) { - ffStrbufSet(&baseDir, ffListGet(&instance->state.configDirs, i)); + ffStrbufSet(&baseDir, configDir); detectGTKFromConfigDir(&baseDir, version, result); if(allPropertiesSet(result)) break; diff --git a/src/detection/os/os.h b/src/detection/os/os.h index 688d6f63b..80fb6b2af 100644 --- a/src/detection/os/os.h +++ b/src/detection/os/os.h @@ -17,8 +17,6 @@ typedef struct FFOSResult FFstrbuf versionID; FFstrbuf codename; FFstrbuf buildID; - FFstrbuf systemName; - FFstrbuf architecture; } FFOSResult; const FFOSResult* ffDetectOS(const FFinstance* instance); diff --git a/src/detection/os/os_android.c b/src/detection/os/os_android.c index eb4bf97d5..890486ab7 100644 --- a/src/detection/os/os_android.c +++ b/src/detection/os/os_android.c @@ -23,10 +23,6 @@ void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance) ffStrbufInit(&os->buildID); ffSettingsGetAndroidProperty("ro.build.id", &os->buildID); - ffStrbufInitS(&os->systemName, instance->state.utsname.sysname); - - ffStrbufInitS(&os->architecture, instance->state.utsname.machine); - ffStrbufInit(&os->idLike); ffStrbufInit(&os->variant); ffStrbufInit(&os->variantID); diff --git a/src/detection/os/os_apple.m b/src/detection/os/os_apple.m index d6a410506..8f8174387 100644 --- a/src/detection/os/os_apple.m +++ b/src/detection/os/os_apple.m @@ -61,8 +61,6 @@ void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance) ffStrbufInit(&os->id); ffStrbufInit(&os->prettyName); ffStrbufInit(&os->versionID); - ffStrbufInit(&os->systemName); - ffStrbufInit(&os->architecture); ffStrbufInitA(&os->codename, 0); ffStrbufInitA(&os->idLike, 0); @@ -82,8 +80,6 @@ void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance) ffStrbufAppend(&os->prettyName, &os->name); ffStrbufAppend(&os->versionID, &os->version); - ffSysctlGetString("kern.ostype", &os->systemName); - ffSysctlGetString("hw.machine", &os->architecture); parseOSXSoftwareLicense(os); } diff --git a/src/detection/os/os_linux.c b/src/detection/os/os_linux.c index 73c513922..45a0f5cec 100644 --- a/src/detection/os/os_linux.c +++ b/src/detection/os/os_linux.c @@ -138,11 +138,6 @@ void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance) ffStrbufInit(&os->versionID); ffStrbufInit(&os->codename); ffStrbufInit(&os->buildID); - ffStrbufInit(&os->systemName); - ffStrbufInit(&os->architecture); - - ffStrbufSetS(&os->systemName, instance->state.utsname.sysname); - ffStrbufSetS(&os->architecture, instance->state.utsname.machine); detectOS(os, instance); diff --git a/src/detection/os/os_windows.cpp b/src/detection/os/os_windows.cpp index fdda72c89..2dee095a0 100644 --- a/src/detection/os/os_windows.cpp +++ b/src/detection/os/os_windows.cpp @@ -56,8 +56,6 @@ void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance) ffStrbufInit(&os->versionID); ffStrbufInit(&os->codename); ffStrbufInit(&os->buildID); - ffStrbufInit(&os->systemName); - ffStrbufInit(&os->architecture); if(getOsNameByWinbrand(&os->variant) && getOsNameByWmi(&os->variant)) return; @@ -106,7 +104,4 @@ void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance) } ffStrbufAppendF(&os->id, "%*s %*s", os->prettyName.length, os->prettyName.chars, os->version.length, os->version.chars); - - ffStrbufSetS(&os->architecture, instance->state.utsname.machine); - ffStrbufSetS(&os->systemName, instance->state.utsname.sysname); } diff --git a/src/detection/packages/packages_linux.c b/src/detection/packages/packages_linux.c index a44d586f0..2c448f9a9 100644 --- a/src/detection/packages/packages_linux.c +++ b/src/detection/packages/packages_linux.c @@ -339,7 +339,7 @@ void ffDetectPackagesImpl(const FFinstance* instance, FFPackagesResult* result) result->rpm = getRpmFromLibrpm(instance); #endif - ffStrbufSetS(&baseDir, instance->state.passwd->pw_dir); + ffStrbufSet(&baseDir, &instance->state.platform.homeDir); result->nixUser = getNixPackages(&baseDir, "/.nix-profile"); ffStrbufDestroy(&baseDir); diff --git a/src/detection/qt.c b/src/detection/qt.c index 6a7794c8e..5ac1d943e 100644 --- a/src/detection/qt.c +++ b/src/detection/qt.c @@ -88,9 +88,9 @@ static void detectPlasma(const FFinstance* instance, FFQtResult* result) FFstrbuf baseDir; ffStrbufInitA(&baseDir, 64); - for(uint32_t i = 0; i < instance->state.configDirs.length; i++) + FF_LIST_FOR_EACH(FFstrbuf, configDir, instance->state.platform.configDirs) { - ffStrbufSet(&baseDir, ffListGet(&instance->state.configDirs, i)); + ffStrbufSet(&baseDir, configDir); ffStrbufAppendS(&baseDir, "kdeglobals"); if(detectPlasmaFromFile(baseDir.chars, result)) diff --git a/src/detection/terminalfont/terminalfont_linux.c b/src/detection/terminalfont/terminalfont_linux.c index 8eb90e7c5..1d06d09c1 100644 --- a/src/detection/terminalfont/terminalfont_linux.c +++ b/src/detection/terminalfont/terminalfont_linux.c @@ -149,7 +149,9 @@ static void detectDeepinTerminal(const FFinstance* instance, FFTerminalFontResul ffStrbufInit(&fontSize); FFstrbuf profile; - ffStrbufInitF(&profile, "%s/.config/deepin/deepin-terminal/config.conf", instance->state.passwd->pw_dir); + ffStrbufInit(&profile); + ffStrbufAppend(&profile, &instance->state.platform.homeDir); + ffStrbufAppendS(&profile, ".config/deepin/deepin-terminal/config.conf"); //TODO: Use config dirs FILE* file = fopen(profile.chars, "r"); if(file) diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index 07b902dac..1f30866c2 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -261,10 +261,7 @@ static void getTerminalFromEnv(FFTerminalShellResult* result) static void getUserShellFromEnv(const FFinstance* instance, FFTerminalShellResult* result) { - if(instance->state.passwd->pw_shell[0] != '\0') - ffStrbufAppendS(&result->userShellExe, instance->state.passwd->pw_shell); - else - ffStrbufAppendS(&result->userShellExe, getenv("SHELL")); + ffStrbufSet(&result->userShellExe, &instance->state.platform.userShell); if(result->userShellExe.length == 0) return; diff --git a/src/detection/title.c b/src/detection/title.c deleted file mode 100644 index df9367ba0..000000000 --- a/src/detection/title.c +++ /dev/null @@ -1,66 +0,0 @@ -#include "fastfetch.h" -#include "detection/title.h" -#include "common/thread.h" - -#include -#include - -#ifndef HOST_NAME_MAX - #define HOST_NAME_MAX 64 -#endif - -#ifdef __linux__ -#include - -static void detectFQDN(FFTitleResult* title) -{ - struct addrinfo hints = {0}; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_CANONNAME; - - struct addrinfo* info = NULL; - - if(getaddrinfo(title->hostname.chars, "80", &hints, &info) == 0) - { - struct addrinfo* current = info; - while(title->fqdn.length == 0 && current != NULL) - { - ffStrbufAppendS(&title->fqdn, current->ai_canonname); - current = current->ai_next; - } - - freeaddrinfo(info); - } -} -#endif - -const FFTitleResult* ffDetectTitle(const FFinstance* instance) -{ - static FFTitleResult result; - - static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER; - static bool init = false; - ffThreadMutexLock(&mutex); - if(init) - { - ffThreadMutexUnlock(&mutex); - return &result; - } - init = true; - - ffStrbufInit(&result.userName); - ffStrbufAppendS(&result.userName, instance->state.passwd->pw_name); - - ffStrbufInitA(&result.hostname, HOST_NAME_MAX); - ffStrbufAppendS(&result.hostname, instance->state.utsname.nodename); - - ffStrbufInitA(&result.fqdn, HOST_NAME_MAX); - #ifdef __linux__ - detectFQDN(&result); - #endif - if(result.fqdn.length == 0) - ffStrbufAppend(&result.fqdn, &result.hostname); - - ffThreadMutexUnlock(&mutex); - return &result; -} diff --git a/src/detection/title.h b/src/detection/title.h deleted file mode 100644 index 9dc31d312..000000000 --- a/src/detection/title.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#ifndef FF_INCLUDED_detection_title -#define FF_INCLUDED_detection_title - -#include "fastfetch.h" - -typedef struct FFTitleResult -{ - FFstrbuf userName; - FFstrbuf hostname; - FFstrbuf fqdn; //Fully qualified domain name -} FFTitleResult; - -const FFTitleResult* ffDetectTitle(const FFinstance* instance); - -#endif diff --git a/src/detection/wmtheme/wmtheme_linux.c b/src/detection/wmtheme/wmtheme_linux.c index 19765c79a..6efba12c5 100644 --- a/src/detection/wmtheme/wmtheme_linux.c +++ b/src/detection/wmtheme/wmtheme_linux.c @@ -131,9 +131,9 @@ static bool detectOpenbox(FFinstance* instance, const FFstrbuf* dePrettyName, FF { FFstrbuf absolutePath; ffStrbufInitA(&absolutePath, 64); - ffStrbufAppendS(&absolutePath, instance->state.passwd->pw_dir); - ffStrbufAppendC(&absolutePath, '/'); + ffStrbufAppend(&absolutePath, &instance->state.platform.homeDir); + //TODO: use config dirs if(ffStrbufIgnCaseCompS(dePrettyName, "LXQT") == 0) ffStrbufAppendS(&absolutePath, ".config/openbox/lxqt-rc.xml"); else if(ffStrbufIgnCaseCompS(dePrettyName, "LXDE") == 0) diff --git a/src/fastfetch.c b/src/fastfetch.c index e732422c3..8df75819f 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -527,7 +527,7 @@ static inline void listAvailablePresetsFromFolder(FFstrbuf* folder, uint8_t inde static inline void listAvailablePresets(FFinstance* instance) { - FF_LIST_FOR_EACH(FFstrbuf, path, instance->state.dataDirs) + FF_LIST_FOR_EACH(FFstrbuf, path, instance->state.platform.dataDirs) { ffStrbufAppendS(path, "fastfetch/presets/"); listAvailablePresetsFromFolder(path, 0, NULL); @@ -536,7 +536,7 @@ static inline void listAvailablePresets(FFinstance* instance) static void listConfigPaths(FFinstance* instance) { - FF_LIST_FOR_EACH(FFstrbuf, folder, instance->state.configDirs) + FF_LIST_FOR_EACH(FFstrbuf, folder, instance->state.platform.configDirs) { ffStrbufAppendS(folder, "fastfetch/config.conf"); printf("%s%s\n", folder->chars, ffFileExists(folder->chars, S_IFREG) ? " (*)" : ""); @@ -545,7 +545,7 @@ static void listConfigPaths(FFinstance* instance) static void listDataPaths(FFinstance* instance) { - FF_LIST_FOR_EACH(FFstrbuf, folder, instance->state.dataDirs) + FF_LIST_FOR_EACH(FFstrbuf, folder, instance->state.platform.dataDirs) { ffStrbufAppendS(folder, "fastfetch/"); puts(folder->chars); @@ -619,7 +619,7 @@ static bool parseConfigFile(FFinstance* instance, FFdata* data, const char* path static void generateConfigFile(FFinstance* instance, bool force) { - FFstrbuf* filename = (FFstrbuf*) ffListGet(&instance->state.configDirs, 0); + FFstrbuf* filename = (FFstrbuf*) ffListGet(&instance->state.platform.configDirs, 0); // Paths generated in `init.c/initConfigDirs` end with `/` ffStrbufAppendS(filename, "fastfetch/config.conf"); @@ -651,7 +651,7 @@ static void optionParseConfigFile(FFinstance* instance, FFdata* data, const char //Try to load as a relative path - FF_LIST_FOR_EACH(FFstrbuf, path, instance->state.dataDirs) + FF_LIST_FOR_EACH(FFstrbuf, path, instance->state.platform.dataDirs) { uint32_t pathLength = path->length; @@ -1330,12 +1330,12 @@ error: static void parseConfigFiles(FFinstance* instance, FFdata* data) { - for(uint32_t i = instance->state.configDirs.length; i > 0; --i) + for(uint32_t i = instance->state.platform.configDirs.length; i > 0; --i) { if(!data->loadUserConfig) return; - FFstrbuf* dir = ffListGet(&instance->state.configDirs, i - 1); + FFstrbuf* dir = ffListGet(&instance->state.platform.configDirs, i - 1); uint32_t dirLength = dir->length; ffStrbufAppendS(dir, "fastfetch/config.conf"); diff --git a/src/fastfetch.h b/src/fastfetch.h index c793b3c0e..93be159df 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -8,16 +8,9 @@ #include #include -#ifndef _WIN32 - #include - #include -#else - #include "util/windows/pwd.h" - #include "util/windows/utsname.h" -#endif - #include "util/FFstrbuf.h" #include "util/FFlist.h" +#include "util/platform/FFPlatform.h" static inline void ffUnused(int dummy, ...) { (void) dummy; } #define FF_UNUSED(...) ffUnused(0, __VA_ARGS__); @@ -220,11 +213,7 @@ typedef struct FFstate uint32_t logoHeight; uint32_t keysHeight; - struct passwd* passwd; - struct utsname utsname; - - FFlist configDirs; // List of FFstrbuf, trailing slash included - FFlist dataDirs; // List of FFstrbuf, trailing slash included + FFPlatform platform; } FFstate; typedef struct FFinstance diff --git a/src/logo/image/image.c b/src/logo/image/image.c index 171809278..b2bfff6b5 100644 --- a/src/logo/image/image.c +++ b/src/logo/image/image.c @@ -691,20 +691,8 @@ static bool printImageIfExistsSlowPath(FFinstance* instance, FFLogoType type) requestData.logoPixelWidth = simpleCeil((double) instance->config.logo.width * requestData.characterPixelWidth); requestData.logoPixelHeight = simpleCeil((double) instance->config.logo.height * requestData.characterPixelHeight); - ffStrbufInitA(&requestData.cacheDir, PATH_MAX * 2); - - #if !(defined(_WIN32) || defined(__APPLE__) || defined(__ANDROID__)) - ffStrbufAppendS(&requestData.cacheDir, getenv("XDG_CACHE_HOME")); - #endif - - if(requestData.cacheDir.length == 0) - { - ffStrbufAppendS(&requestData.cacheDir, instance->state.passwd->pw_dir); - ffStrbufAppendS(&requestData.cacheDir, "/.cache/"); - } - else - ffStrbufEnsureEndsWithC(&requestData.cacheDir, '/'); - + ffStrbufInit(&requestData.cacheDir); + ffStrbufAppend(&requestData.cacheDir, &instance->state.platform.cacheDir); ffStrbufAppendS(&requestData.cacheDir, "fastfetch"); ffStrbufEnsureFree(&requestData.cacheDir, PATH_MAX); diff --git a/src/logo/logo.c b/src/logo/logo.c index dd9f7ddd5..60cbdf8bb 100644 --- a/src/logo/logo.c +++ b/src/logo/logo.c @@ -205,7 +205,7 @@ static const FFlogo* logoGetBuiltin(const char* name) return NULL; } -static const FFlogo* logoGetBuiltinDetected(FFinstance* instance) +static const FFlogo* logoGetBuiltinDetected(const FFinstance* instance) { const FFOSResult* os = ffDetectOS(instance); @@ -225,7 +225,7 @@ static const FFlogo* logoGetBuiltinDetected(FFinstance* instance) if(logo != NULL) return logo; - logo = logoGetBuiltin(os->systemName.chars); + logo = logoGetBuiltin(instance->state.platform.systemName.chars); if(logo != NULL) return logo; @@ -293,7 +293,7 @@ static bool loadLogoFile(const FFinstance* instance, FFstrbuf* buffer) FFstrbuf fullPath; ffStrbufInit(&fullPath); - FF_LIST_FOR_EACH(FFstrbuf, dataDir, instance->state.dataDirs) + FF_LIST_FOR_EACH(FFstrbuf, dataDir, instance->state.platform.dataDirs) { //We need to copy it, because multiple threads might be using dataDirs at the same time ffStrbufSet(&fullPath, dataDir); diff --git a/src/modules/kernel.c b/src/modules/kernel.c index 72096ce55..bc1139833 100644 --- a/src/modules/kernel.c +++ b/src/modules/kernel.c @@ -2,29 +2,29 @@ #include "common/printing.h" #define FF_KERNEL_MODULE_NAME "Kernel" -#define FF_KERNEL_NUM_FORMAT_ARGS 3 +#define FF_KERNEL_NUM_FORMAT_ARGS 4 void ffPrintKernel(FFinstance* instance) { if(instance->config.kernel.outputFormat.length == 0) { ffPrintLogoAndKey(instance, FF_KERNEL_MODULE_NAME, 0, &instance->config.kernel.key); + ffStrbufWriteTo(&instance->state.platform.systemRelease, stdout); #ifdef _WIN32 - if(instance->state.utsname.version[0] != '\0') - printf("%s (%s)\n", instance->state.utsname.release, instance->state.utsname.version); - else - puts(instance->state.utsname.release); - #else - puts(instance->state.utsname.release); + if(instance->state.platform.systemVersion.length > 0) + printf(" (%s)", instance->state.platform.systemVersion.chars); #endif + + putchar('\n'); } else { ffPrintFormat(instance, FF_KERNEL_MODULE_NAME, 0, &instance->config.kernel, FF_KERNEL_NUM_FORMAT_ARGS, (FFformatarg[]){ - {FF_FORMAT_ARG_TYPE_STRING, instance->state.utsname.sysname}, - {FF_FORMAT_ARG_TYPE_STRING, instance->state.utsname.release}, - {FF_FORMAT_ARG_TYPE_STRING, instance->state.utsname.version} + {FF_FORMAT_ARG_TYPE_STRBUF, &instance->state.platform.systemName}, + {FF_FORMAT_ARG_TYPE_STRBUF, &instance->state.platform.systemRelease}, + {FF_FORMAT_ARG_TYPE_STRBUF, &instance->state.platform.systemVersion}, + {FF_FORMAT_ARG_TYPE_STRBUF, &instance->state.platform.systemArchitecture} }); } } diff --git a/src/modules/os.c b/src/modules/os.c index 7d5a15842..140cfdbbe 100644 --- a/src/modules/os.c +++ b/src/modules/os.c @@ -7,7 +7,7 @@ #define FF_OS_MODULE_NAME "OS" #define FF_OS_NUM_FORMAT_ARGS 12 -static void buildOutputDefault(const FFOSResult* os, FFstrbuf* result) +static void buildOutputDefault(const FFinstance* instance, const FFOSResult* os, FFstrbuf* result) { //Create the basic output if(os->name.length > 0) @@ -17,7 +17,7 @@ static void buildOutputDefault(const FFOSResult* os, FFstrbuf* result) else if(os->id.length > 0) ffStrbufAppend(result, &os->id); else - ffStrbufAppend(result, &os->systemName); + ffStrbufAppend(result, &instance->state.platform.systemName); #ifdef __APPLE__ if(os->codename.length > 0) @@ -62,14 +62,14 @@ static void buildOutputDefault(const FFOSResult* os, FFstrbuf* result) } //Append architecture if it is missing - if(ffStrbufFirstIndex(result, &os->architecture) == result->length) + if(ffStrbufFirstIndex(result, &instance->state.platform.systemArchitecture) == result->length) { ffStrbufAppendC(result, ' '); - ffStrbufAppend(result, &os->architecture); + ffStrbufAppend(result, &instance->state.platform.systemArchitecture); } } -static void buildOutputNixOS(const FFOSResult* os, FFstrbuf* result) +static void buildOutputNixOS(const FFinstance* instance, const FFOSResult* os, FFstrbuf* result) { ffStrbufAppendS(result, "NixOS"); @@ -87,10 +87,10 @@ static void buildOutputNixOS(const FFOSResult* os, FFstrbuf* result) ffStrbufAppendC(result, ')'); } - if(os->architecture.length > 0) + if(instance->state.platform.systemArchitecture.length > 0) { ffStrbufAppendC(result, ' '); - ffStrbufAppend(result, &os->architecture); + ffStrbufAppend(result, &instance->state.platform.systemArchitecture); } } @@ -98,7 +98,7 @@ void ffPrintOS(FFinstance* instance) { const FFOSResult* os = ffDetectOS(instance); - if(os->name.length == 0 && os->prettyName.length == 0 && os->id.length == 0 && os->systemName.length == 0) + if(os->name.length == 0 && os->prettyName.length == 0 && os->id.length == 0) { ffPrintError(instance, FF_OS_MODULE_NAME, 0, &instance->config.os, "Could not detect OS"); return; @@ -110,9 +110,9 @@ void ffPrintOS(FFinstance* instance) ffStrbufInit(&result); if(ffStrbufIgnCaseCompS(&os->id, "nixos") == 0) - buildOutputNixOS(os, &result); + buildOutputNixOS(instance, os, &result); else - buildOutputDefault(os, &result); + buildOutputDefault(instance, os, &result); ffPrintLogoAndKey(instance, FF_OS_MODULE_NAME, 0, &instance->config.os.key); ffStrbufPutTo(&result, stdout); @@ -121,7 +121,7 @@ void ffPrintOS(FFinstance* instance) else { ffPrintFormat(instance, FF_OS_MODULE_NAME, 0, &instance->config.os, FF_OS_NUM_FORMAT_ARGS, (FFformatarg[]){ - {FF_FORMAT_ARG_TYPE_STRBUF, &os->systemName}, + {FF_FORMAT_ARG_TYPE_STRBUF, &instance->state.platform.systemName}, {FF_FORMAT_ARG_TYPE_STRBUF, &os->name}, {FF_FORMAT_ARG_TYPE_STRBUF, &os->prettyName}, {FF_FORMAT_ARG_TYPE_STRBUF, &os->id}, @@ -132,7 +132,7 @@ void ffPrintOS(FFinstance* instance) {FF_FORMAT_ARG_TYPE_STRBUF, &os->versionID}, {FF_FORMAT_ARG_TYPE_STRBUF, &os->codename}, {FF_FORMAT_ARG_TYPE_STRBUF, &os->buildID}, - {FF_FORMAT_ARG_TYPE_STRBUF, &os->architecture} + {FF_FORMAT_ARG_TYPE_STRBUF, &instance->state.platform.systemArchitecture} }); } } diff --git a/src/modules/separator.c b/src/modules/separator.c index 7227f9ae4..879bc5bb8 100644 --- a/src/modules/separator.c +++ b/src/modules/separator.c @@ -1,12 +1,12 @@ #include "fastfetch.h" #include "common/printing.h" -#include "detection/title.h" void ffPrintSeparator(FFinstance* instance) { - const FFTitleResult* result = ffDetectTitle(instance); - uint32_t titleLength = result->userName.length + 1 + - (instance->config.titleFQDN ? result->fqdn.length : result->hostname.length); + uint32_t titleLength = instance->state.platform.userName.length + 1 + (instance->config.titleFQDN ? + instance->state.platform.domainName.length : + instance->state.platform.hostName.length + ); ffLogoPrintLine(instance); diff --git a/src/modules/title.c b/src/modules/title.c index cef00d146..4e509fbe5 100644 --- a/src/modules/title.c +++ b/src/modules/title.c @@ -1,6 +1,5 @@ #include "fastfetch.h" #include "common/printing.h" -#include "detection/title.h" #include "util/textModifier.h" static inline void printTitlePart(FFinstance* instance, const FFstrbuf* content) @@ -19,12 +18,13 @@ static inline void printTitlePart(FFinstance* instance, const FFstrbuf* content) void ffPrintTitle(FFinstance* instance) { - const FFTitleResult* result = ffDetectTitle(instance); - ffLogoPrintLine(instance); - printTitlePart(instance, &result->userName); + printTitlePart(instance, &instance->state.platform.userName); putchar('@'); - printTitlePart(instance, instance->config.titleFQDN ? &result->fqdn : &result->hostname); + printTitlePart(instance, instance->config.titleFQDN ? + &instance->state.platform.domainName : + &instance->state.platform.hostName + ); putchar('\n'); } diff --git a/src/util/FFstrbuf.c b/src/util/FFstrbuf.c index 94f436d51..375c53aaa 100644 --- a/src/util/FFstrbuf.c +++ b/src/util/FFstrbuf.c @@ -3,6 +3,17 @@ #include #include +bool ffStrSet(const char* str) +{ + if(str == NULL) + return false; + + while(isspace(*str)) + str++; + + return *str != '\0'; +} + static char* CHAR_NULL_PTR = ""; void ffStrbufInitA(FFstrbuf* strbuf, uint32_t allocate) diff --git a/src/util/FFstrbuf.h b/src/util/FFstrbuf.h index 7755225a7..7342cb607 100644 --- a/src/util/FFstrbuf.h +++ b/src/util/FFstrbuf.h @@ -18,6 +18,8 @@ #define strcasestr StrStrIA #endif +bool ffStrSet(const char* str); + #define FASTFETCH_STRBUF_DEFAULT_ALLOC 32 typedef struct FFstrbuf diff --git a/src/util/platform/FFPlatform.c b/src/util/platform/FFPlatform.c new file mode 100644 index 000000000..9ea045736 --- /dev/null +++ b/src/util/platform/FFPlatform.c @@ -0,0 +1,118 @@ +#include "FFPlatform_private.h" + +void ffPlatformInit(FFPlatform* platform) +{ + ffStrbufInit(&platform->homeDir); + ffStrbufInit(&platform->cacheDir); + ffListInit(&platform->configDirs, sizeof(FFstrbuf)); + ffListInit(&platform->dataDirs, sizeof(FFstrbuf)); + + ffStrbufInit(&platform->userName); + ffStrbufInit(&platform->hostName); + ffStrbufInit(&platform->domainName); + ffStrbufInit(&platform->userShell); + + ffStrbufInit(&platform->systemName); + ffStrbufInit(&platform->systemRelease); + ffStrbufInit(&platform->systemVersion); + ffStrbufInit(&platform->systemArchitecture); + + ffPlatformInitÎmpl(platform); + + if(platform->domainName.length == 0) + ffStrbufAppend(&platform->domainName, &platform->hostName); + + if(platform->systemName.length == 0) + { + #if defined(__linux__) + ffStrbufAppendS(&platform->systemName, "Linux"); + #elif defined(__FreeBSD__) + ffStrbufAppendS(&platform->systemName, "FreeBSD"); + #elif defined(__APPLE__) + ffStrbufAppendS(&platform->systemName, "Darwin"); + #elif defined(__WIN32__) || defined(__WIN64__) + ffStrbufAppendS(&platform->systemName, "Windows_NT"); + #endif + } + + if(platform->systemArchitecture.length == 0) + { + #if defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) || defined(__amd64) + ffStrbufAppendS(&platform->systemArchitecture, "x86_64"); + #elif defined(__i386__) || defined(__i386) || defined(__i486__) || defined(__i486) || defined(__i586__) || defined(__i586) || defined(__i686__) || defined(__i686) + ffStrbufAppendS(&platform->systemArchitecture, "i386"); + #elif defined(__aarch64__) + ffStrbufAppendS(&platform->systemArchitecture, "aarch64"); + #elif defined(__arm__) + ffStrbufAppendS(&platform->systemArchitecture, "arm"); + #endif + } +} + +void ffPlatformDestroy(FFPlatform* platform) +{ + ffStrbufDestroy(&platform->homeDir); + ffStrbufDestroy(&platform->cacheDir); + + FF_LIST_FOR_EACH(FFstrbuf, dir, platform->configDirs) + ffStrbufDestroy(dir); + ffListDestroy(&platform->configDirs); + + FF_LIST_FOR_EACH(FFstrbuf, dir, platform->dataDirs) + ffStrbufDestroy(dir); + ffListDestroy(&platform->dataDirs); + + ffStrbufDestroy(&platform->userName); + ffStrbufDestroy(&platform->hostName); + ffStrbufDestroy(&platform->domainName); + ffStrbufDestroy(&platform->userShell); +} + +void ffPlatformPathAddAbsolute(FFlist* dirs, const char* path) +{ + FFstrbuf* buffer = (FFstrbuf*) ffListAdd(dirs); + ffStrbufInitA(buffer, 64); + ffStrbufAppendS(buffer, path); + ffStrbufEnsureEndsWithC(buffer, '/'); + FF_PLATFORM_PATH_UNIQUE(dirs, buffer); +} + +void ffPlatformPathAddHome(FFlist* dirs, const FFPlatform* platform, const char* suffix) +{ + FFstrbuf* buffer = (FFstrbuf*) ffListAdd(dirs); + ffStrbufInitA(buffer, 64); + ffStrbufAppend(buffer, &platform->homeDir); + ffStrbufAppendS(buffer, suffix); + ffStrbufEnsureEndsWithC(buffer, '/'); + FF_PLATFORM_PATH_UNIQUE(dirs, buffer); +} + +void ffPlatformPathAddEnv(FFlist* dirs, const char* env) +{ + const char* envValue = getenv(env); + if(!ffStrSet(envValue)) + return; + + FFstrbuf value; + ffStrbufInitA(&value, 64); + ffStrbufAppendS(&value, envValue); + + uint32_t startIndex = 0; + while (startIndex < value.length) + { + uint32_t colonIndex = ffStrbufNextIndexC(&value, startIndex, ':'); + value.chars[colonIndex] = '\0'; + + if(!ffStrSet(value.chars + startIndex)) + { + startIndex = colonIndex + 1; + continue; + } + + ffPlatformPathAddAbsolute(dirs, value.chars + startIndex); + + startIndex = colonIndex + 1; + } + + ffStrbufDestroy(&value); +} diff --git a/src/util/platform/FFPlatform.h b/src/util/platform/FFPlatform.h new file mode 100644 index 000000000..caebc7c6f --- /dev/null +++ b/src/util/platform/FFPlatform.h @@ -0,0 +1,29 @@ +#pragma once + +#ifndef FF_INCLUDED_util_platform_FFPlatform +#define FF_INCLUDED_util_platform_FFPlatform + +#include "util/FFstrbuf.h" +#include "util/FFlist.h" + +typedef struct FFPlatform { + FFstrbuf homeDir; // Trailing slash included + FFstrbuf cacheDir; // Trailing slash included + FFlist configDirs; // List of FFstrbuf, trailing slash included + FFlist dataDirs; // List of FFstrbuf, trailing slash included + + FFstrbuf userName; + FFstrbuf hostName; + FFstrbuf domainName; + FFstrbuf userShell; + + FFstrbuf systemName; + FFstrbuf systemRelease; + FFstrbuf systemVersion; + FFstrbuf systemArchitecture; +} FFPlatform; + +void ffPlatformInit(FFPlatform* platform); +void ffPlatformDestroy(FFPlatform* platform); + +#endif diff --git a/src/util/platform/FFPlatform_private.h b/src/util/platform/FFPlatform_private.h new file mode 100644 index 000000000..c51d01d80 --- /dev/null +++ b/src/util/platform/FFPlatform_private.h @@ -0,0 +1,21 @@ +#pragma once + +#ifndef FF_INCLUDED_util_platform_FFPlatform_private +#define FF_INCLUDED_util_platform_FFPlatform_private + +#include "FFPlatform.h" + +void ffPlatformInitÎmpl(FFPlatform* platform); + +#define FF_PLATFORM_PATH_UNIQUE(list, element) \ + if(ffListFirstIndexComp(list, element, (bool(*)(const void*, const void*))ffStrbufEqual) < list->length - 1) \ + { \ + ffStrbufDestroy(ffListGet(list, list->length - 1)); \ + --list->length; \ + } + +void ffPlatformPathAddAbsolute(FFlist* dirs, const char* path); +void ffPlatformPathAddHome(FFlist* dirs, const FFPlatform* platform, const char* suffix); +void ffPlatformPathAddEnv(FFlist* dirs, const char* env); + +#endif diff --git a/src/util/platform/FFPlatform_unix.c b/src/util/platform/FFPlatform_unix.c new file mode 100644 index 000000000..e5adaac95 --- /dev/null +++ b/src/util/platform/FFPlatform_unix.c @@ -0,0 +1,138 @@ +#include "FFPlatform_private.h" + +#include "fastfetch_config.h" + +#include +#include +#include +#include + +static void getHomeDir(FFPlatform* platform, const struct passwd* pwd) +{ + const char* home = getenv("HOME"); + if(!ffStrSet(home) && pwd) + home = pwd->pw_dir; + + ffStrbufAppendS(&platform->homeDir, home); + ffStrbufEnsureEndsWithC(&platform->homeDir, '/'); +} + +static void getCacheDir(FFPlatform* platform) +{ + const char* cache = getenv("XDG_CACHE_HOME"); + if(ffStrSet(cache)) + { + ffStrbufAppendS(&platform->cacheDir, cache); + ffStrbufEnsureEndsWithC(&platform->cacheDir, '/'); + } + else + { + ffStrbufAppend(&platform->cacheDir, &platform->homeDir); + ffStrbufAppendS(&platform->cacheDir, ".cache/"); + } + + ffStrbufAppendS(&platform->cacheDir, "fastfetch/"); +} + +static void getConfigDirs(FFPlatform* platform) +{ + ffPlatformPathAddEnv(&platform->configDirs, "XDG_CONFIG_HOME"); + ffPlatformPathAddHome(&platform->configDirs, platform, ".config/"); + + #if defined(__APPLE__) + pathsAddHome(&state->configDirs, state, "/Library/Preferences/"); + #endif + + ffPlatformPathAddHome(&platform->configDirs, platform, ""); + ffPlatformPathAddEnv(&platform->configDirs, "XDG_CONFIG_DIRS"); + + #if !defined(__APPLE__) + ffPlatformPathAddAbsolute(&platform->configDirs, FASTFETCH_TARGET_DIR_ETC"/xdg/"); + #endif + + ffPlatformPathAddAbsolute(&platform->configDirs, FASTFETCH_TARGET_DIR_ETC"/"); + ffPlatformPathAddAbsolute(&platform->configDirs, FASTFETCH_TARGET_DIR_INSTALL_SYSCONF"/"); +} + +static void getDataDirs(FFPlatform* platform) +{ + ffPlatformPathAddEnv(&platform->dataDirs, "XDG_DATA_HOME"); + ffPlatformPathAddHome(&platform->dataDirs, platform, ".local/share/"); + ffPlatformPathAddHome(&platform->dataDirs, platform, ""); + ffPlatformPathAddEnv(&platform->dataDirs, "XDG_DATA_DIRS"); + ffPlatformPathAddAbsolute(&platform->dataDirs, FASTFETCH_TARGET_DIR_USR"/local/share/"); + ffPlatformPathAddAbsolute(&platform->dataDirs, FASTFETCH_TARGET_DIR_USR"/share/"); +} + +static void getUserName(FFPlatform* platform, const struct passwd* pwd) +{ + const char* user = getenv("USER"); + if(!ffStrSet(user) && pwd) + user = pwd->pw_name; + + ffStrbufAppendS(&platform->userName, user); +} + +static void getHostName(FFPlatform* platform, const struct utsname* uts) +{ + char hostname[256]; + if(gethostname(hostname, sizeof(hostname)) == 0) + ffStrbufAppendS(&platform->hostName, hostname); + + if(platform->hostName.length == 0) + ffStrbufAppendS(&platform->hostName, uts->nodename); +} + +static void getDomainName(FFPlatform* platform) +{ + struct addrinfo hints = {0}; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_CANONNAME; + + struct addrinfo* info = NULL; + + if(getaddrinfo(platform->hostName.chars, "80", &hints, &info) != 0) + return; + + struct addrinfo* current = info; + while(platform->domainName.length == 0 && current != NULL) + { + ffStrbufAppendS(&platform->domainName, current->ai_canonname); + current = current->ai_next; + } + + freeaddrinfo(info); +} + +static void getUserShell(FFPlatform* platform, const struct passwd* pwd) +{ + const char* shell = getenv("SHELL"); + if(!ffStrSet(shell) && pwd) + shell = pwd->pw_shell; + + ffStrbufAppendS(&platform->userShell, shell); +} + +void ffPlatformInitÎmpl(FFPlatform* platform) +{ + struct passwd* pwd = getpwuid(getuid()); + + struct utsname uts; + if(uname(&uts) != 0) + memset(&uts, 0, sizeof(uts)); + + getHomeDir(platform, pwd); + getCacheDir(platform); + getConfigDirs(platform); + getDataDirs(platform); + + getUserName(platform, pwd); + getHostName(platform, &uts); + getDomainName(platform); + getUserShell(platform, pwd); + + ffStrbufAppendS(&platform->systemName, uts.sysname); + ffStrbufAppendS(&platform->systemRelease, uts.release); + ffStrbufAppendS(&platform->systemVersion, uts.version); + ffStrbufAppendS(&platform->systemArchitecture, uts.machine); +} diff --git a/src/util/platform/FFPlatform_windows.c b/src/util/platform/FFPlatform_windows.c new file mode 100644 index 000000000..ade0087fc --- /dev/null +++ b/src/util/platform/FFPlatform_windows.c @@ -0,0 +1,228 @@ +#include "FFPlatform_private.h" + +#define WIN32_LEAN_AND_MEAN +#include +#include + +#include "util/windows/unicode.h" + +static void getHomeDir(FFPlatform* platform) +{ + PWSTR pPath; + if(SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_Profile, KF_FLAG_DEFAULT, NULL, &pPath))) + { + ffStrbufSetWS(&platform->home_dir, pPath); + ffStrbufReplaceAllC(&platform->home_dir, '\\', '/'); + ffStrbufEnsureEndsWithC(&platform->home_dir, '/'); + } + CoTaskMemFree(pPath); +} + +static void getCacheDir(FFPlatform* platform) +{ + PWSTR pPath; + if(SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_LocalAppData, KF_FLAG_DEFAULT, NULL, &pPath))) + { + ffStrbufSetWS(&platform->cache_dir, pPath); + ffStrbufReplaceAllC(&platform->cache_dir, '\\', '/'); + ffStrbufEnsureEndsWithC(&platform->cache_dir, '/'); + } + else + { + ffStrbufAppend(&platform->cache_dir, &platform->home_dir); + ffStrbufAppendS(&platform->cache_dir, "AppData/Local/"); + } + CoTaskMemFree(pPath); + + ffStrbufAppendS(&platform->cache_dir, "fastfetch/"); +} + +static void platformPathAddKnownFolder(FFlist* dirs, REFKNOWNFOLDERID folderId) +{ + PWSTR pPath; + if(SUCCEEDED(SHGetKnownFolderPath(folderId, 0, NULL, &pPath))) + { + FFstrbuf* buffer = (FFstrbuf*) ffListAdd(dirs); + ffStrbufInit(buffer); + ffStrbufSetWS(buffer, pPath); + ffStrbufReplaceAllC(buffer, '\\', '/'); + ffStrbufEnsureEndsWithC(buffer, '/'); + FF_PLATFORM_PATH_UNIQUE(dirs, buffer); + } + CoTaskMemFree(pPath); +} + +static void platformPathAddEnvSuffix(FFlist* dirs, const char* env, const char* suffix) +{ + const char* value = getenv(env); + if(!ffStrSet(value)) + return; + + FFstrbuf* buffer = ffListAdd(dirs); + ffStrbufInitA(buffer, 64); + ffStrbufAppendS(buffer, value); + ffStrbufReplaceAllC(buffer, '\\', '/'); + ffStrbufEnsureEndsWithC(buffer, '/'); + ffStrbufAppendS(buffer, suffix); + ffStrbufEnsureEndsWithC(buffer, '/'); + FF_PLATFORM_PATH_UNIQUE(dirs, buffer); +} + +static void getConfigDirs(FFPlatform* platform) +{ + ffListInit(&platform->configDirs, sizeof(FFstrbuf)); + + ffPlatformPathAddEnv(&platform->configDirs, "XDG_CONFIG_HOME"); + ffPlatformPathAddHome(&platform->configDirs, platform, "/.config/"); + platformPathAddKnownFolder(&platform->configDirs, &FOLDERID_RoamingAppData); + platformPathAddKnownFolder(&platform->configDirs, &FOLDERID_LocalAppData); + ffPlatformPathAddHome(&platform->configDirs, platform, ""); + + if(getenv("MSYSTEM") && getenv("HOME")) + { + // We are in MSYS2 / Git Bash + platformPathAddEnvSuffix(&platform->configDirs, "HOME", ".config/"); + platformPathAddEnvSuffix(&platform->configDirs, "HOME", ""); + } + + ffPlatformPathAddEnv(&platform->configDirs, "XDG_CONFIG_DIRS"); +} + +static void getConfigDirs(FFPlatform* platform) +{ + ffPlatformPathAddEnv(&platform->dataDirs, "XDG_DATA_HOME"); + ffPlatformPathAddHome(&platform->dataDirs, platform, "/.local/share/"); + platformPathAddKnownFolder(&platform->dataDirs, &FOLDERID_RoamingAppData); + platformPathAddKnownFolder(&platform->dataDirs, &FOLDERID_LocalAppData); + ffPlatformPathAddHome(&platform->dataDirs, platform, ""); + + if(getenv("MSYSTEM") && getenv("HOME")) + { + // We are in MSYS2 / Git Bash + platformPathAddEnvSuffix(&platform->dataDirs, "HOME", ".local/share/"); + platformPathAddEnvSuffix(&platform->dataDirs, "HOME", ""); + } + + ffPlatformPathAddEnv(&platform->dataDirs, "XDG_DATA_DIRS"); +} + +static void getUserName(FFPlatform* platform) +{ + ffStrbufEnsureFree(&platform->userName, 64); + GetUserNameA(platform->userName.chars, (LPDWORD) ffStrbufGetFree(&platform->userName)); + ffStrbufRecalculateLength(&platform->userName); +} + +static void getHostName(FFPlatform* platform) +{ + ffStrbufEnsureFree(&platform->hostName, 64); + GetComputerNameA(platform->hostName.chars, (LPDWORD) ffStrbufGetFree(&platform->hostName)); + ffStrbufRecalculateLength(&platform->hostName); +} + +static void getDomainName(FFPlatform* platform) +{ + ffStrbufEnsureFree(&platform->domainName, 64); + GetComputerNameExA(ComputerNameDnsDomain, platform->domainName.chars, (LPDWORD) ffStrbufGetFree(&platform->domainName)); + ffStrbufRecalculateLength(&platform->domainName); +} + +static void getSystemName(FFPlatform* platform) +{ + ffStrbufAppendS(&platform->systemName, "Windows_NT"); +} + +static void getSystemReleaseAndVersion(FFPlatform* platform) +{ + HKEY hKey; + if(RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS) + return; + + DWORD bufSize; + + char currentVersion[32]; + + { + DWORD currentMajorVersionNumber; + DWORD currentMinorVersionNumber; + bufSize = sizeof(currentMajorVersionNumber); + if(RegGetValueW(hKey, NULL, L"CurrentMajorVersionNumber", RRF_RT_REG_DWORD, NULL, ¤tMajorVersionNumber, &bufSize) == ERROR_SUCCESS && + RegGetValueW(hKey, NULL, L"CurrentMinorVersionNumber", RRF_RT_REG_DWORD, NULL, ¤tMinorVersionNumber, &bufSize) == ERROR_SUCCESS + ) + snprintf(currentVersion, sizeof(currentVersion), "%u.%u", (unsigned)currentMajorVersionNumber, (unsigned)currentMinorVersionNumber); + else + { + bufSize = sizeof(currentVersion); + if(RegGetValueA(hKey, NULL, "CurrentVersion", RRF_RT_REG_SZ, NULL, currentVersion, &bufSize) != ERROR_SUCCESS) + strcpy(currentVersion, "0.0"); + } + } + + char currentBuildNumber[32]; + bufSize = sizeof(currentBuildNumber); + if(RegGetValueA(hKey, NULL, "CurrentBuildNumber", RRF_RT_REG_SZ, NULL, currentBuildNumber, &bufSize) != ERROR_SUCCESS) + strcpy(currentBuildNumber, "0"); + + DWORD ubr; + bufSize = sizeof(ubr); + if(RegGetValueA(hKey, NULL, "UBR", RRF_RT_REG_DWORD, NULL, &ubr, &bufSize) != ERROR_SUCCESS || bufSize != sizeof(ubr)) + ubr = 0; + + ffStrbufAppendF(&platform->systemRelease, "%s.%s.%u", currentVersion, currentBuildNumber, (unsigned)ubr); + + ffStrbufEnsureFree(&platform->systemVersion, 256); + RegGetValueA(hKey, NULL, "DisplayVersion", RRF_RT_REG_SZ, NULL, platform->systemVersion.chars, (LPDWORD) ffStrbufGetFree(&platform->systemVersion)); + ffStrbufRecalculateLength(&platform->systemVersion); + + RegCloseKey(hKey); +} + +static void getSystemArchitecture(FFPlatform* platform) +{ + SYSTEM_INFO sysInfo = {0}; + GetNativeSystemInfo(&sysInfo); + + switch(sysInfo.wProcessorArchitecture) + { + case PROCESSOR_ARCHITECTURE_AMD64: + strcpy(name->machine, "x86_64"); + break; + case PROCESSOR_ARCHITECTURE_IA64: + strcpy(name->machine, "ia64"); + break; + case PROCESSOR_ARCHITECTURE_INTEL: + strcpy(name->machine, "x86"); + break; + case PROCESSOR_ARCHITECTURE_ARM64: + strcpy(name->machine, "aarch64"); + break; + case PROCESSOR_ARCHITECTURE_ARM: + strcpy(name->machine, "arm"); + break; + case PROCESSOR_ARCHITECTURE_PPC: + strcpy(name->machine, "ppc"); + break; + case PROCESSOR_ARCHITECTURE_MIPS: + strcpy(name->machine, "mips"); + break; + case PROCESSOR_ARCHITECTURE_UNKNOWN: + default: + break; + } +} + +void ffPlatformInitÎmpl(FFPlatform* platform) +{ + getHomeDir(platform); + getCacheDir(platform); + getConfigDirs(platform); + getDataDirs(platform); + + getUserName(platform); + getHostName(platform); + getDomainName(platform); + + getSystemName(platform); + getSystemReleaseAndVersion(platform); + getSystemArchitecture(platform); +} diff --git a/src/util/windows/pwd.c b/src/util/windows/pwd.c deleted file mode 100644 index ce37aabc7..000000000 --- a/src/util/windows/pwd.c +++ /dev/null @@ -1,22 +0,0 @@ -#include "pwd.h" - -#define WIN32_LEAN_AND_MEAN -#include -#include - -struct passwd* ffGetPasswd() -{ - static struct passwd res; - - DWORD len = sizeof(res.pw_name); - GetUserNameA(res.pw_name, &len); - - PWSTR pPath; - if(SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_Profile, KF_FLAG_DEFAULT, NULL, &pPath))) - WideCharToMultiByte(CP_UTF8, 0, pPath, -1, res.pw_dir, sizeof(res.pw_dir), NULL, NULL); //res has been NULL inited - CoTaskMemFree(pPath); - for (char *current_pos = strchr(res.pw_dir, '\\'); current_pos; current_pos = strchr(current_pos + 1, '\\')) - *current_pos = '/'; - - return &res; -} diff --git a/src/util/windows/pwd.h b/src/util/windows/pwd.h deleted file mode 100644 index 29d4c883b..000000000 --- a/src/util/windows/pwd.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#ifndef FASTFETCH_INCLUDED_UTIL_PWD -#define FASTFETCH_INCLUDED_UTIL_PWD - -#include -#include - -struct passwd -{ - char pw_name[UNLEN + 1]; /* username */ - // char *pw_passwd[1]; /* user password */ - // int pw_uid; /* user ID */ - // int pw_gid; /* group ID */ - // char *pw_gecos; /* user information */ - char pw_dir[MAX_PATH]; /* home directory */ - // char *pw_shell; /* shell program */ -}; - -struct passwd* ffGetPasswd(); - -#endif diff --git a/src/util/windows/unicode.h b/src/util/windows/unicode.h index d70fbb22e..f01080b0a 100644 --- a/src/util/windows/unicode.h +++ b/src/util/windows/unicode.h @@ -3,16 +3,18 @@ #ifndef FASTFETCH_INCLUDED_UNICODE_H #define FASTFETCH_INCLUDED_UNICODE_H -#include "fastfetch.h" +#include "util/FFstrbuf.h" #include void ffStrbufSetNWS(FFstrbuf* result, uint32_t length, const wchar_t* source); + static inline void ffStrbufSetWS(FFstrbuf* result, const wchar_t* source) { return ffStrbufSetNWS(result, (uint32_t)wcslen(source), source); } FFstrbuf ffStrbufCreateNWS(uint32_t length, const wchar_t* source); + static inline FFstrbuf ffStrbufCreateWS(const wchar_t* source) { return ffStrbufCreateNWS((uint32_t)wcslen(source), source); diff --git a/src/util/windows/utsname.c b/src/util/windows/utsname.c deleted file mode 100644 index c21389f19..000000000 --- a/src/util/windows/utsname.c +++ /dev/null @@ -1,116 +0,0 @@ -#include "fastfetch.h" -#include "utsname.h" - -#define WIN32_LEAN_AND_MEAN 1 -#include - -static int detectSysname(struct utsname *name) -{ - strncpy(name->sysname, "Windows_NT", UTSNAME_MAXLENGTH); - return 0; -} - -static int detectNodename(struct utsname *name) -{ - DWORD bufSize = UTSNAME_MAXLENGTH - 1; - if(!GetComputerNameExA(ComputerNameDnsFullyQualified, name->nodename, &bufSize)) - return 1; - name->nodename[bufSize] = '\0'; - return 0; -} - -static int detectVersion(struct utsname *name) -{ - HKEY hKey; - if(RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS) - return 1; - - DWORD bufSize; - - char currentVersion[32]; - - { - DWORD currentMajorVersionNumber; - DWORD currentMinorVersionNumber; - bufSize = sizeof(currentMajorVersionNumber); - if(RegGetValueW(hKey, NULL, L"CurrentMajorVersionNumber", RRF_RT_REG_DWORD, NULL, ¤tMajorVersionNumber, &bufSize) == ERROR_SUCCESS && - RegGetValueW(hKey, NULL, L"CurrentMinorVersionNumber", RRF_RT_REG_DWORD, NULL, ¤tMinorVersionNumber, &bufSize) == ERROR_SUCCESS - ) - snprintf(currentVersion, sizeof(currentVersion), "%u.%u", (unsigned)currentMajorVersionNumber, (unsigned)currentMinorVersionNumber); - else - { - bufSize = sizeof(currentVersion); - if(RegGetValueA(hKey, NULL, "CurrentVersion", RRF_RT_REG_SZ, NULL, currentVersion, &bufSize) != ERROR_SUCCESS) - strcpy(currentVersion, "0.0"); - } - } - - char currentBuildNumber[32]; - bufSize = sizeof(currentBuildNumber); - if(RegGetValueA(hKey, NULL, "CurrentBuildNumber", RRF_RT_REG_SZ, NULL, currentBuildNumber, &bufSize) != ERROR_SUCCESS) - strcpy(currentBuildNumber, "0"); - - DWORD ubr; - bufSize = sizeof(ubr); - if(RegGetValueA(hKey, NULL, "UBR", RRF_RT_REG_DWORD, NULL, &ubr, &bufSize) != ERROR_SUCCESS || bufSize != sizeof(ubr)) - ubr = 0; - - snprintf(name->release, sizeof(name->release), "%s.%s.%u", currentVersion, currentBuildNumber, (unsigned)ubr); - - bufSize = sizeof(name->version); - RegGetValueA(hKey, NULL, "DisplayVersion", RRF_RT_REG_SZ, NULL, name->version, &bufSize); - - RegCloseKey(hKey); - return 0; -} - -static int detectMachine(struct utsname *name) -{ - // Get hardware info - SYSTEM_INFO sysInfo = {0}; - GetNativeSystemInfo(&sysInfo); - - // Set processor architecture - switch(sysInfo.wProcessorArchitecture) - { - case PROCESSOR_ARCHITECTURE_AMD64: - strcpy(name->machine, "x86_64"); - break; - case PROCESSOR_ARCHITECTURE_IA64: - strcpy(name->machine, "ia64"); - break; - case PROCESSOR_ARCHITECTURE_INTEL: - strcpy(name->machine, "x86"); - break; - case PROCESSOR_ARCHITECTURE_ARM64: - strcpy(name->machine, "aarch64"); - break; - case PROCESSOR_ARCHITECTURE_ARM: - strcpy(name->machine, "arm"); - break; - case PROCESSOR_ARCHITECTURE_PPC: - strcpy(name->machine, "ppc"); - break; - case PROCESSOR_ARCHITECTURE_MIPS: - strcpy(name->machine, "mips"); - break; - case PROCESSOR_ARCHITECTURE_UNKNOWN: - default: - strcpy(name->machine, "unknown"); - break; - } - - return 0; -} - -int uname(struct utsname *name) -{ - memset(name, 0, sizeof(*name)); - - int sysnameResult = detectSysname(name); - int nodenameResult = detectNodename(name); - int versionResult = detectVersion(name); - int machineResult = detectMachine(name); - - return sysnameResult || nodenameResult || versionResult || machineResult; -} diff --git a/src/util/windows/utsname.h b/src/util/windows/utsname.h deleted file mode 100644 index 96bc53adc..000000000 --- a/src/util/windows/utsname.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#ifndef FASTFETCH_INCLUDED_UTSNAME_H -#define FASTFETCH_INCLUDED_UTSNAME_H - -#define UTSNAME_MAXLENGTH 256 - -struct utsname -{ - char sysname[UTSNAME_MAXLENGTH]; // name of this implementation of the operating system - char nodename[UTSNAME_MAXLENGTH]; // name of this node within an implementation - dependent communications network - char release[UTSNAME_MAXLENGTH]; // current release level of this implementation - char version[UTSNAME_MAXLENGTH]; // current version level of this release - char machine[UTSNAME_MAXLENGTH]; // name of the hardware type on which the system is running -}; - -int uname(struct utsname *name); - -#endif From 3ef3cca76b62cbffe49c231212bac3d43e31c427 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Sun, 15 Jan 2023 16:06:50 +0100 Subject: [PATCH 098/142] First round of fixes for FFPlatform --- CMakeLists.txt | 2 -- src/detection/packages/packages_windows.c | 2 +- src/detection/terminalfont/terminalfont_apple.m | 4 ++-- src/detection/wmtheme/wmtheme_apple.m | 2 +- src/util/platform/FFPlatform.c | 2 +- src/util/platform/FFPlatform_private.h | 2 +- src/util/platform/FFPlatform_unix.c | 2 +- src/util/platform/FFPlatform_windows.c | 2 +- 8 files changed, 8 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 87c9c6b7b..2aeeef888 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -495,10 +495,8 @@ elseif(WIN32) src/detection/wifi/wifi_windows.c src/detection/wmtheme/wmtheme_windows.c src/util/windows/getline.c - src/util/windows/pwd.c src/util/windows/registry.c src/util/windows/unicode.c - src/util/windows/utsname.c src/util/windows/wmi.cpp src/util/platform/FFPlatform_windows.c ) diff --git a/src/detection/packages/packages_windows.c b/src/detection/packages/packages_windows.c index 93739e9bf..fa50bdd5b 100644 --- a/src/detection/packages/packages_windows.c +++ b/src/detection/packages/packages_windows.c @@ -28,7 +28,7 @@ static uint32_t getNumElements(const char* searchPath /* including `\*` suffix * static void detectScoop(const FFinstance* instance, FFPackagesResult* result) { char scoopPath[MAX_PATH + 3]; - strcpy(scoopPath, instance->state.passwd->pw_dir); + strcpy(scoopPath, instance->state.platform.homeDir.chars); strncat(scoopPath, "/scoop/apps/*", sizeof(scoopPath) - 1 - strlen(scoopPath)); result->scoop = getNumElements(scoopPath, FILE_ATTRIBUTE_DIRECTORY); if(result->scoop > 0) diff --git a/src/detection/terminalfont/terminalfont_apple.m b/src/detection/terminalfont/terminalfont_apple.m index 1ee387aa2..71ecc8b22 100644 --- a/src/detection/terminalfont/terminalfont_apple.m +++ b/src/detection/terminalfont/terminalfont_apple.m @@ -17,7 +17,7 @@ static void detectIterm2(const FFinstance* instance, FFTerminalFontResult* termi } NSError* error; - NSString* fileName = [NSString stringWithFormat:@"file://%s/Library/Preferences/com.googlecode.iterm2.plist", instance->state.passwd->pw_dir]; + NSString* fileName = [NSString stringWithFormat:@"file://%s/Library/Preferences/com.googlecode.iterm2.plist", instance->state.platform.homeDir.chars]; NSDictionary* dict = [NSDictionary dictionaryWithContentsOfURL:[NSURL URLWithString:fileName] error:&error]; if(error) @@ -62,7 +62,7 @@ static void detectAppleTerminal(FFTerminalFontResult* terminalFont) static void detectWarpTerminal(const FFinstance* instance, FFTerminalFontResult* terminalFont) { NSError* error; - NSString* fileName = [NSString stringWithFormat:@"file://%s/Library/Preferences/dev.warp.Warp-Stable.plist", instance->state.passwd->pw_dir]; + NSString* fileName = [NSString stringWithFormat:@"file://%s/Library/Preferences/dev.warp.Warp-Stable.plist", instance->state.platform.homeDir.chars]; NSDictionary* dict = [NSDictionary dictionaryWithContentsOfURL:[NSURL URLWithString:fileName] error:&error]; if(error) diff --git a/src/detection/wmtheme/wmtheme_apple.m b/src/detection/wmtheme/wmtheme_apple.m index d0b099790..437d6ed97 100644 --- a/src/detection/wmtheme/wmtheme_apple.m +++ b/src/detection/wmtheme/wmtheme_apple.m @@ -9,7 +9,7 @@ static bool detectQuartzCompositor(FFinstance* instance, FFstrbuf* themeOrError) FF_UNUSED(instance); NSError* error; - NSString* fileName = [NSString stringWithFormat:@"file://%s/Library/Preferences/.GlobalPreferences.plist", instance->state.passwd->pw_dir]; + NSString* fileName = [NSString stringWithFormat:@"file://%s/Library/Preferences/.GlobalPreferences.plist", instance->state.platform.homeDir.chars]; NSDictionary* dict = [NSDictionary dictionaryWithContentsOfURL:[NSURL URLWithString:fileName] error:&error]; if(error) diff --git a/src/util/platform/FFPlatform.c b/src/util/platform/FFPlatform.c index 9ea045736..aa59feda9 100644 --- a/src/util/platform/FFPlatform.c +++ b/src/util/platform/FFPlatform.c @@ -17,7 +17,7 @@ void ffPlatformInit(FFPlatform* platform) ffStrbufInit(&platform->systemVersion); ffStrbufInit(&platform->systemArchitecture); - ffPlatformInitÎmpl(platform); + ffPlatformInitImpl(platform); if(platform->domainName.length == 0) ffStrbufAppend(&platform->domainName, &platform->hostName); diff --git a/src/util/platform/FFPlatform_private.h b/src/util/platform/FFPlatform_private.h index c51d01d80..698f07609 100644 --- a/src/util/platform/FFPlatform_private.h +++ b/src/util/platform/FFPlatform_private.h @@ -5,7 +5,7 @@ #include "FFPlatform.h" -void ffPlatformInitÎmpl(FFPlatform* platform); +void ffPlatformInitImpl(FFPlatform* platform); #define FF_PLATFORM_PATH_UNIQUE(list, element) \ if(ffListFirstIndexComp(list, element, (bool(*)(const void*, const void*))ffStrbufEqual) < list->length - 1) \ diff --git a/src/util/platform/FFPlatform_unix.c b/src/util/platform/FFPlatform_unix.c index e5adaac95..e8025c49e 100644 --- a/src/util/platform/FFPlatform_unix.c +++ b/src/util/platform/FFPlatform_unix.c @@ -113,7 +113,7 @@ static void getUserShell(FFPlatform* platform, const struct passwd* pwd) ffStrbufAppendS(&platform->userShell, shell); } -void ffPlatformInitÎmpl(FFPlatform* platform) +void ffPlatformInitImpl(FFPlatform* platform) { struct passwd* pwd = getpwuid(getuid()); diff --git a/src/util/platform/FFPlatform_windows.c b/src/util/platform/FFPlatform_windows.c index ade0087fc..6175cb3c2 100644 --- a/src/util/platform/FFPlatform_windows.c +++ b/src/util/platform/FFPlatform_windows.c @@ -211,7 +211,7 @@ static void getSystemArchitecture(FFPlatform* platform) } } -void ffPlatformInitÎmpl(FFPlatform* platform) +void ffPlatformInitImpl(FFPlatform* platform) { getHomeDir(platform); getCacheDir(platform); From 7bef5008c2045bc69468d06a05286da5bfb2d8bf Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Sun, 15 Jan 2023 16:26:08 +0100 Subject: [PATCH 099/142] Second round of fixes for FFPlatform --- src/detection/os/os_windows.cpp | 2 ++ src/util/platform/FFPlatform_unix.c | 11 +++++++++-- src/util/platform/FFPlatform_windows.c | 18 +++++++++--------- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/detection/os/os_windows.cpp b/src/detection/os/os_windows.cpp index 2dee095a0..7b4c6ea2f 100644 --- a/src/detection/os/os_windows.cpp +++ b/src/detection/os/os_windows.cpp @@ -46,6 +46,8 @@ static const char* getOsNameByWinbrand(FFstrbuf* osName) extern "C" void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance) { + FF_UNUSED(instance); + ffStrbufInit(&os->name); ffStrbufInit(&os->prettyName); ffStrbufInit(&os->id); diff --git a/src/util/platform/FFPlatform_unix.c b/src/util/platform/FFPlatform_unix.c index e8025c49e..aa019acb0 100644 --- a/src/util/platform/FFPlatform_unix.c +++ b/src/util/platform/FFPlatform_unix.c @@ -5,7 +5,6 @@ #include #include #include -#include static void getHomeDir(FFPlatform* platform, const struct passwd* pwd) { @@ -40,7 +39,7 @@ static void getConfigDirs(FFPlatform* platform) ffPlatformPathAddHome(&platform->configDirs, platform, ".config/"); #if defined(__APPLE__) - pathsAddHome(&state->configDirs, state, "/Library/Preferences/"); + ffPlatformPathAddHome(&state->configDirs, platform, "/Library/Preferences/"); #endif ffPlatformPathAddHome(&platform->configDirs, platform, ""); @@ -58,6 +57,11 @@ static void getDataDirs(FFPlatform* platform) { ffPlatformPathAddEnv(&platform->dataDirs, "XDG_DATA_HOME"); ffPlatformPathAddHome(&platform->dataDirs, platform, ".local/share/"); + + #if defined(__APPLE__) + ffPlatformPathAddHome(&platform->dataDirs, platform, "/Library/Application Support/"); + #endif + ffPlatformPathAddHome(&platform->dataDirs, platform, ""); ffPlatformPathAddEnv(&platform->dataDirs, "XDG_DATA_DIRS"); ffPlatformPathAddAbsolute(&platform->dataDirs, FASTFETCH_TARGET_DIR_USR"/local/share/"); @@ -83,6 +87,8 @@ static void getHostName(FFPlatform* platform, const struct utsname* uts) ffStrbufAppendS(&platform->hostName, uts->nodename); } +#ifdef __linux__ +#include static void getDomainName(FFPlatform* platform) { struct addrinfo hints = {0}; @@ -103,6 +109,7 @@ static void getDomainName(FFPlatform* platform) freeaddrinfo(info); } +#endif static void getUserShell(FFPlatform* platform, const struct passwd* pwd) { diff --git a/src/util/platform/FFPlatform_windows.c b/src/util/platform/FFPlatform_windows.c index 6175cb3c2..4f09b89f1 100644 --- a/src/util/platform/FFPlatform_windows.c +++ b/src/util/platform/FFPlatform_windows.c @@ -11,9 +11,9 @@ static void getHomeDir(FFPlatform* platform) PWSTR pPath; if(SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_Profile, KF_FLAG_DEFAULT, NULL, &pPath))) { - ffStrbufSetWS(&platform->home_dir, pPath); - ffStrbufReplaceAllC(&platform->home_dir, '\\', '/'); - ffStrbufEnsureEndsWithC(&platform->home_dir, '/'); + ffStrbufSetWS(&platform->homeDir, pPath); + ffStrbufReplaceAllC(&platform->homeDir, '\\', '/'); + ffStrbufEnsureEndsWithC(&platform->homeDir, '/'); } CoTaskMemFree(pPath); } @@ -23,18 +23,18 @@ static void getCacheDir(FFPlatform* platform) PWSTR pPath; if(SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_LocalAppData, KF_FLAG_DEFAULT, NULL, &pPath))) { - ffStrbufSetWS(&platform->cache_dir, pPath); - ffStrbufReplaceAllC(&platform->cache_dir, '\\', '/'); - ffStrbufEnsureEndsWithC(&platform->cache_dir, '/'); + ffStrbufSetWS(&platform->cacheDir, pPath); + ffStrbufReplaceAllC(&platform->cacheDir, '\\', '/'); + ffStrbufEnsureEndsWithC(&platform->cacheDir, '/'); } else { - ffStrbufAppend(&platform->cache_dir, &platform->home_dir); - ffStrbufAppendS(&platform->cache_dir, "AppData/Local/"); + ffStrbufAppend(&platform->cacheDir, &platform->homeDir); + ffStrbufAppendS(&platform->cacheDir, "AppData/Local/"); } CoTaskMemFree(pPath); - ffStrbufAppendS(&platform->cache_dir, "fastfetch/"); + ffStrbufAppendS(&platform->cacheDir, "fastfetch/"); } static void platformPathAddKnownFolder(FFlist* dirs, REFKNOWNFOLDERID folderId) From c1d92206f50bbbd0bf3f39786d66642a447f3b8e Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Sun, 15 Jan 2023 16:45:16 +0100 Subject: [PATCH 100/142] Third round of fixes for FFPlatform --- src/util/platform/FFPlatform_unix.c | 8 ++++++-- src/util/platform/FFPlatform_windows.c | 16 ++++++++-------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/util/platform/FFPlatform_unix.c b/src/util/platform/FFPlatform_unix.c index aa019acb0..3d13042fc 100644 --- a/src/util/platform/FFPlatform_unix.c +++ b/src/util/platform/FFPlatform_unix.c @@ -39,7 +39,7 @@ static void getConfigDirs(FFPlatform* platform) ffPlatformPathAddHome(&platform->configDirs, platform, ".config/"); #if defined(__APPLE__) - ffPlatformPathAddHome(&state->configDirs, platform, "/Library/Preferences/"); + ffPlatformPathAddHome(&platform->configDirs, platform, "/Library/Preferences/"); #endif ffPlatformPathAddHome(&platform->configDirs, platform, ""); @@ -135,7 +135,11 @@ void ffPlatformInitImpl(FFPlatform* platform) getUserName(platform, pwd); getHostName(platform, &uts); - getDomainName(platform); + + #ifdef __linux__ + getDomainName(platform); + #endif + getUserShell(platform, pwd); ffStrbufAppendS(&platform->systemName, uts.sysname); diff --git a/src/util/platform/FFPlatform_windows.c b/src/util/platform/FFPlatform_windows.c index 4f09b89f1..b1ad2bef8 100644 --- a/src/util/platform/FFPlatform_windows.c +++ b/src/util/platform/FFPlatform_windows.c @@ -88,7 +88,7 @@ static void getConfigDirs(FFPlatform* platform) ffPlatformPathAddEnv(&platform->configDirs, "XDG_CONFIG_DIRS"); } -static void getConfigDirs(FFPlatform* platform) +static void getDataDirs(FFPlatform* platform) { ffPlatformPathAddEnv(&platform->dataDirs, "XDG_DATA_HOME"); ffPlatformPathAddHome(&platform->dataDirs, platform, "/.local/share/"); @@ -185,25 +185,25 @@ static void getSystemArchitecture(FFPlatform* platform) switch(sysInfo.wProcessorArchitecture) { case PROCESSOR_ARCHITECTURE_AMD64: - strcpy(name->machine, "x86_64"); + ffStrbufAppendS(&platform->systemArchitecture, "x86_64"); break; case PROCESSOR_ARCHITECTURE_IA64: - strcpy(name->machine, "ia64"); + ffStrbufAppendS(&platform->systemArchitecture, "ia64"); break; case PROCESSOR_ARCHITECTURE_INTEL: - strcpy(name->machine, "x86"); + ffStrbufAppendS(&platform->systemArchitecture, "i686"); break; case PROCESSOR_ARCHITECTURE_ARM64: - strcpy(name->machine, "aarch64"); + ffStrbufAppendS(&platform->systemArchitecture, "aarch64"); break; case PROCESSOR_ARCHITECTURE_ARM: - strcpy(name->machine, "arm"); + ffStrbufAppendS(&platform->systemArchitecture, "arm"); break; case PROCESSOR_ARCHITECTURE_PPC: - strcpy(name->machine, "ppc"); + ffStrbufAppendS(&platform->systemArchitecture, "ppc"); break; case PROCESSOR_ARCHITECTURE_MIPS: - strcpy(name->machine, "mips"); + ffStrbufAppendS(&platform->systemArchitecture, "mips"); break; case PROCESSOR_ARCHITECTURE_UNKNOWN: default: From 1c93d68e7b70b48cdf68e9896d3c5175b13d317b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 16 Jan 2023 00:33:22 +0800 Subject: [PATCH 101/142] Wifi: add basic Linux support using `iw` --- src/detection/wifi/wifi_linux.c | 60 ++++++++++++++++++++++++++++----- src/modules/wifi.c | 2 +- 2 files changed, 52 insertions(+), 10 deletions(-) diff --git a/src/detection/wifi/wifi_linux.c b/src/detection/wifi/wifi_linux.c index 985ba6f74..32bc40d00 100644 --- a/src/detection/wifi/wifi_linux.c +++ b/src/detection/wifi/wifi_linux.c @@ -1,14 +1,59 @@ #include "wifi.h" #include "common/io.h" -#include +#include "common/processing.h" +#include "common/properties.h" + #include -static const char* detectInf(uint32_t ifIndex, FFWifiResult* wifi) +static const char* detectInf(char* ifName, FFWifiResult* wifi) { - //TODO: play with netlink - FF_UNUSED(ifIndex, wifi); - return "Unimplemented"; + const char* error = NULL; + FF_STRBUF_AUTO_DESTROY output; + ffStrbufInit(&output); + if((error = ffProcessAppendStdOut(&output, (char* const[]){ + "iw", + "dev", + ifName, + "link", + NULL + }))) + return error; + + if(output.length == 0) + return "iw command execution failed"; + + if(!ffParsePropLines(output.chars, "Connected to ", &wifi->conn.macAddress)) + { + ffStrbufAppendS(&wifi->conn.status, "Disconnected"); + return NULL; + } + + FF_STRBUF_AUTO_DESTROY temp; + ffStrbufInit(&temp); + + ffStrbufAppendS(&wifi->conn.status, "Connected"); + ffStrbufSubstrBefore(&wifi->conn.macAddress, ' '); + ffParsePropLines(output.chars, "SSID: ", &wifi->conn.ssid); + + if(ffParsePropLines(output.chars, "signal: ", &temp)) + wifi->conn.signalQuality = ffStrbufToDouble(&temp); + + if(ffParsePropLines(output.chars, "tx bitrate: ", &temp)) + { + if(ffStrbufContainS(&temp, " HE-MCS ")) + ffStrbufAppendS(&wifi->conn.phyType, "802.11ax (Wi-Fi 6)"); + else if(ffStrbufContainS(&temp, " VHT-MCS ")) + ffStrbufAppendS(&wifi->conn.phyType, "802.11ac (Wi-Fi 5)"); + else if(ffStrbufContainS(&temp, " MCS ")) + ffStrbufAppendS(&wifi->conn.phyType, "802.11n (Wi-Fi 4)"); + else + ffStrbufAppendS(&wifi->conn.phyType, "802.11a/b/g"); + } + + wifi->security.enabled = true; //FIXME: Unable to find this info. Set it true so that fastfetch won't print `insecure` + + return NULL; } const char* ffDetectWifi(const FFinstance* instance, FFlist* result) @@ -46,10 +91,7 @@ const char* ffDetectWifi(const FFinstance* instance, FFlist* result) if(!ffAppendFileBuffer(path.chars, &item->inf.status) || !ffStrbufEqualS(&item->inf.status, "up")) continue; - ffStrbufSetF(&path, "/sys/class/net/%s/address", i->if_name); - ffAppendFileBuffer(path.chars, &item->conn.macAddress); - - detectInf(i->if_index, item); + detectInf(i->if_name, item); } if_freenameindex(infs); ffStrbufDestroy(&path); diff --git a/src/modules/wifi.c b/src/modules/wifi.c index 596c18baa..5a791e4fd 100644 --- a/src/modules/wifi.c +++ b/src/modules/wifi.c @@ -7,7 +7,7 @@ void ffPrintWifi(FFinstance* instance) { - FFlist result; + FF_LIST_AUTO_DESTROY result; ffListInit(&result, sizeof(FFWifiResult)); const char* error = ffDetectWifi(instance, &result); From d4ecbc6638f40c8f167a616d1767e71c891923aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 16 Jan 2023 00:35:48 +0800 Subject: [PATCH 102/142] FFPlatform: fix memleaks --- src/util/platform/FFPlatform.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/util/platform/FFPlatform.c b/src/util/platform/FFPlatform.c index aa59feda9..5b4f246c4 100644 --- a/src/util/platform/FFPlatform.c +++ b/src/util/platform/FFPlatform.c @@ -66,6 +66,11 @@ void ffPlatformDestroy(FFPlatform* platform) ffStrbufDestroy(&platform->hostName); ffStrbufDestroy(&platform->domainName); ffStrbufDestroy(&platform->userShell); + + ffStrbufDestroy(&platform->systemArchitecture); + ffStrbufDestroy(&platform->systemName); + ffStrbufDestroy(&platform->systemRelease); + ffStrbufDestroy(&platform->systemVersion); } void ffPlatformPathAddAbsolute(FFlist* dirs, const char* path) From 9b6dafe715b98146da4766504a966bcb4daf3c2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 16 Jan 2023 00:41:35 +0800 Subject: [PATCH 103/142] Packages: fix rpm count detection Can't believe that this bug has existed for more than 3 months and no one found it --- src/detection/packages/packages_linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/packages/packages_linux.c b/src/detection/packages/packages_linux.c index 2c448f9a9..ace7d637e 100644 --- a/src/detection/packages/packages_linux.c +++ b/src/detection/packages/packages_linux.c @@ -271,7 +271,7 @@ static void getPackageCounts(const FFinstance* instance, FFstrbuf* baseDir, FFPa packageCounts->nixSystem += getNixPackages(baseDir, "/run/current-system"); packageCounts->pacman += getNumElements(baseDir, "/var/lib/pacman/local", DT_DIR); packageCounts->pkg += getSQLite3Int(instance, baseDir, "/var/db/pkg/local.sqlite", "SELECT count(id) FROM packages"); - packageCounts->rpm += getSQLite3Int(instance, baseDir, "/var/lib/rpm/rmpdb.sqlite", "SELECT count(blob) FROM Packages"); + packageCounts->rpm += getSQLite3Int(instance, baseDir, "/var/lib/rpm/rpmdb.sqlite", "SELECT count(blob) FROM Packages"); packageCounts->snap += getSnap(baseDir); packageCounts->xbps += getXBPS(baseDir, "/var/db/xbps"); } From 52f36d29dc084d22f8ae0a0fae65b1fac980405f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 16 Jan 2023 00:41:56 +0800 Subject: [PATCH 104/142] Doc: update CHANGELOG --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 737092a23..f9d32ee7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,14 +21,16 @@ Features: * Support `WezTerm` terminal font detection (requires [`wezterm` executable](https://wezfurlong.org/wezterm/cli/general.html) being available) * Add `--shell-version` and `--terminal-version` options to disable shell / terminal version detection * Enhance `--percent-type` to allow hiding other texts (#387) +* Add Wifi module basic support for Linux Logos: * Raspbian (@IamNoRobot, #373) Bugfixes: * `--logo-type` now does accept `iterm` too (@CarterLi, #374) -* Fix mintty terminal font detection +* Fix mintty terminal font detection (Windows) * Fix bug that line buffering doesn't work properly (Windows) +* Fix rpm package count detection (Linux) Other: * Fixed a Typo in iterm error message (@jessebot, #376) From c832c7d79455d360662d9d8c8272a238df284cac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 14 Jan 2023 20:35:08 +0800 Subject: [PATCH 105/142] Host: don't print None as product version --- src/modules/host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/host.c b/src/modules/host.c index e8d8e6044..9fa3bafee 100644 --- a/src/modules/host.c +++ b/src/modules/host.c @@ -33,7 +33,7 @@ void ffPrintHost(FFinstance* instance) else ffStrbufAppend(&output, &host->productFamily); - if(host->productVersion.length > 0) + if(host->productVersion.length > 0 && !ffStrbufIgnCaseEqualS(&host->productVersion, "none")) { ffStrbufAppendF(&output, " (%s)", host->productVersion.chars); } From cc7724dec444e4ffb591a31c6bb8e36986fa5c6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 15 Jan 2023 17:00:36 +0800 Subject: [PATCH 106/142] FFPlatform: don't use target platform as running platform --- src/util/platform/FFPlatform.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/util/platform/FFPlatform.c b/src/util/platform/FFPlatform.c index 5b4f246c4..ed39e9fe0 100644 --- a/src/util/platform/FFPlatform.c +++ b/src/util/platform/FFPlatform.c @@ -30,23 +30,15 @@ void ffPlatformInit(FFPlatform* platform) ffStrbufAppendS(&platform->systemName, "FreeBSD"); #elif defined(__APPLE__) ffStrbufAppendS(&platform->systemName, "Darwin"); - #elif defined(__WIN32__) || defined(__WIN64__) + #elif defined(_WIN32) ffStrbufAppendS(&platform->systemName, "Windows_NT"); + #else + ffStrbufAppendS(&platform->systemName, "Unknown"); #endif } if(platform->systemArchitecture.length == 0) - { - #if defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) || defined(__amd64) - ffStrbufAppendS(&platform->systemArchitecture, "x86_64"); - #elif defined(__i386__) || defined(__i386) || defined(__i486__) || defined(__i486) || defined(__i586__) || defined(__i586) || defined(__i686__) || defined(__i686) - ffStrbufAppendS(&platform->systemArchitecture, "i386"); - #elif defined(__aarch64__) - ffStrbufAppendS(&platform->systemArchitecture, "aarch64"); - #elif defined(__arm__) - ffStrbufAppendS(&platform->systemArchitecture, "arm"); - #endif - } + ffStrbufAppendS(&platform->systemName, "Unknown"); } void ffPlatformDestroy(FFPlatform* platform) From 6b41b85d4d5f1a5679b0138ff468efc2fd12ca39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 16 Jan 2023 01:18:13 +0800 Subject: [PATCH 107/142] Windows: fix sigfault --- src/util/platform/FFPlatform_windows.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/util/platform/FFPlatform_windows.c b/src/util/platform/FFPlatform_windows.c index b1ad2bef8..2fff50ef5 100644 --- a/src/util/platform/FFPlatform_windows.c +++ b/src/util/platform/FFPlatform_windows.c @@ -109,22 +109,25 @@ static void getDataDirs(FFPlatform* platform) static void getUserName(FFPlatform* platform) { ffStrbufEnsureFree(&platform->userName, 64); - GetUserNameA(platform->userName.chars, (LPDWORD) ffStrbufGetFree(&platform->userName)); - ffStrbufRecalculateLength(&platform->userName); + DWORD len = (DWORD) ffStrbufGetFree(&platform->userName); + if(GetUserNameA(platform->userName.chars, &len)) + platform->userName.length = (uint32_t) len; } static void getHostName(FFPlatform* platform) { ffStrbufEnsureFree(&platform->hostName, 64); - GetComputerNameA(platform->hostName.chars, (LPDWORD) ffStrbufGetFree(&platform->hostName)); - ffStrbufRecalculateLength(&platform->hostName); + DWORD len = (DWORD) ffStrbufGetFree(&platform->hostName); + if(GetComputerNameExA(ComputerNameDnsHostname, platform->hostName.chars, &len)) + platform->hostName.length = (uint32_t) len; } static void getDomainName(FFPlatform* platform) { ffStrbufEnsureFree(&platform->domainName, 64); - GetComputerNameExA(ComputerNameDnsDomain, platform->domainName.chars, (LPDWORD) ffStrbufGetFree(&platform->domainName)); - ffStrbufRecalculateLength(&platform->domainName); + DWORD len = (DWORD) ffStrbufGetFree(&platform->domainName); + if(GetComputerNameExA(ComputerNameDnsDomain, platform->domainName.chars, &len)) + platform->domainName.length = (uint32_t) len; } static void getSystemName(FFPlatform* platform) @@ -171,8 +174,9 @@ static void getSystemReleaseAndVersion(FFPlatform* platform) ffStrbufAppendF(&platform->systemRelease, "%s.%s.%u", currentVersion, currentBuildNumber, (unsigned)ubr); ffStrbufEnsureFree(&platform->systemVersion, 256); - RegGetValueA(hKey, NULL, "DisplayVersion", RRF_RT_REG_SZ, NULL, platform->systemVersion.chars, (LPDWORD) ffStrbufGetFree(&platform->systemVersion)); - ffStrbufRecalculateLength(&platform->systemVersion); + bufSize = (DWORD) ffStrbufGetFree(&platform->systemVersion); + if(RegGetValueA(hKey, NULL, "DisplayVersion", RRF_RT_REG_SZ, NULL, platform->systemVersion.chars, &bufSize) == ERROR_SUCCESS) + platform->systemVersion.length = (uint32_t) bufSize; RegCloseKey(hKey); } From 14286e8c0fb33f29fbc3e5162b1b2b1d7f2d61f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 16 Jan 2023 01:20:10 +0800 Subject: [PATCH 108/142] Fix typo --- src/util/platform/FFPlatform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/platform/FFPlatform.c b/src/util/platform/FFPlatform.c index ed39e9fe0..d549b6501 100644 --- a/src/util/platform/FFPlatform.c +++ b/src/util/platform/FFPlatform.c @@ -38,7 +38,7 @@ void ffPlatformInit(FFPlatform* platform) } if(platform->systemArchitecture.length == 0) - ffStrbufAppendS(&platform->systemName, "Unknown"); + ffStrbufAppendS(&platform->systemArchitecture, "Unknown"); } void ffPlatformDestroy(FFPlatform* platform) From ab7b0571f35bc0e40a4eaba0da68bcc26d96a56d Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Sun, 15 Jan 2023 20:03:28 +0100 Subject: [PATCH 109/142] Fix config files loading other config files --- src/fastfetch.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/fastfetch.c b/src/fastfetch.c index 8df75819f..d80537e41 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -651,21 +651,24 @@ static void optionParseConfigFile(FFinstance* instance, FFdata* data, const char //Try to load as a relative path + FFstrbuf absolutePath; + ffStrbufInitA(&absolutePath, 128); + FF_LIST_FOR_EACH(FFstrbuf, path, instance->state.platform.dataDirs) { - uint32_t pathLength = path->length; + //We need to copy it, because if a config file loads a config file, the value of path must be unchanged + ffStrbufSet(&absolutePath, path); + ffStrbufAppendS(&absolutePath, "fastfetch/presets/"); + ffStrbufAppendS(&absolutePath, value); - ffStrbufAppendS(path, "fastfetch/presets/"); - ffStrbufAppendS(path, value); - - bool success = parseConfigFile(instance, data, path->chars); - - ffStrbufSubstrBefore(path, pathLength); + bool success = parseConfigFile(instance, data, absolutePath.chars); if(success) return; } + ffStrbufDestroy(&absolutePath); + //File not found fprintf(stderr, "Error: couldn't find config: %s\n", value); From 9a2687768f7f2db3de1d63575fa69172ec48c1fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 16 Jan 2023 18:23:54 +0800 Subject: [PATCH 110/142] FFPlatform: remove extra `/` --- src/util/platform/FFPlatform_unix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/platform/FFPlatform_unix.c b/src/util/platform/FFPlatform_unix.c index 3d13042fc..393d2290b 100644 --- a/src/util/platform/FFPlatform_unix.c +++ b/src/util/platform/FFPlatform_unix.c @@ -39,7 +39,7 @@ static void getConfigDirs(FFPlatform* platform) ffPlatformPathAddHome(&platform->configDirs, platform, ".config/"); #if defined(__APPLE__) - ffPlatformPathAddHome(&platform->configDirs, platform, "/Library/Preferences/"); + ffPlatformPathAddHome(&platform->configDirs, platform, "Library/Preferences/"); #endif ffPlatformPathAddHome(&platform->configDirs, platform, ""); From b1ccd2e2c03c5f798998ceac8e870956b2d0d892 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Mon, 16 Jan 2023 11:52:54 +0100 Subject: [PATCH 111/142] Don't show subvolumes by default --- CHANGELOG.md | 1 + completions/bash | 1 + src/common/init.c | 1 + src/data/config_user.txt | 17 +++------- src/data/help.txt | 59 +++++++++++++++++---------------- src/detection/disk/disk.h | 3 +- src/detection/disk/disk_linux.c | 41 ++++++++++++++++------- src/fastfetch.c | 2 ++ src/fastfetch.h | 1 + src/modules/disk.c | 3 ++ 10 files changed, 74 insertions(+), 55 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f9d32ee7a..9d5ebd2b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ Features: * Add `Brightness` module support * Add `Battery` module support for FreeBSD * Add `--disk-show-unknown` option for Disk module +* Add `--disk-show-subvolumes` option for Disk module * Add `--gpu-hide-integrated` option (#379) * Add `--gpu-hide-discrete` option (#379) * Detect terminal version when available diff --git a/completions/bash b/completions/bash index 66649337a..b4f1548f7 100644 --- a/completions/bash +++ b/completions/bash @@ -194,6 +194,7 @@ __fastfetch_completion() "--disk-folders" "--disk-show-removable" "--disk-show-hidden" + "--disk-show-subvolumes" "--gpu-hide-integrated" "--gpu-hide-discrete" "--disk-show-unknown" diff --git a/src/common/init.c b/src/common/init.c index d08cbaf09..efef9190a 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -156,6 +156,7 @@ static void defaultConfig(FFinstance* instance) instance->config.diskShowRemovable = true; instance->config.diskShowHidden = false; instance->config.diskShowUnknown = false; + instance->config.diskShowSubvolumes = false; ffStrbufInitA(&instance->config.batteryDir, 0); diff --git a/src/data/config_user.txt b/src/data/config_user.txt index 435143dc4..0ea7b3973 100644 --- a/src/data/config_user.txt +++ b/src/data/config_user.txt @@ -231,22 +231,13 @@ # Default is true. #--terminal-version true -# Disk option -# Sets if removable volume should be printed +# Disk show options +# Sets if certain types of disk should be printed # Must be either true or false -# Default is true. +# Default is false except for --disk-show-removable. #--disk-show-removable true - -# Disk option -# Sets if hidden volume should be printed -# Must be either true or false -# Default is false. #--disk-show-hidden false - -# Disk option -# Sets if unknown (unable to detect sizes) volume should be printed -# Must be either true or false -# Default is false. +#--disk-show-subvolumes false #--disk-show-unknown false # Disk option diff --git a/src/data/help.txt b/src/data/help.txt index 441c1c6cf..b8a546c9c 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -100,35 +100,36 @@ Library options: Set the path of a library to load --lib-cjson Module specific options: - --title-fqdn : Set if the title should use fully qualified domain name. Default is false - --separator-string : Set the string printed by the separator module - --os-file : Set the path to the file containing OS information - --shell-version : Set if shell version should be detected and printed - --terminal-version : Set if terminal version should be detected and printed - --disk-folders : A colon (semicolon on Windows) separated list of folder paths for the disk output. Default is "/:/home" ("C:\\;D:\\ ..." on Windows) - --disk-show-removable : Set if removable volume should be printed. Default is true - --disk-show-hidden : Set if hidden volumes should be printed. Default is false - --disk-show-unknown : Set if unknown (unable to detect sizes) volumes should be printed. Default is false - --battery-dir : The directory where the battery folders are. Standard: /sys/class/power_supply/ - --cpu-temp : Detect and display CPU temperature if supported. Default is false - --gpu-temp : Detect and display GPU temperature if supported. Default is false - --gpu-hide-integrated : Hide integrated GPU if supported. Default is false - --gpu-hide-discrete : Hide discrete GPU if supported. Default is false - --battery-temp : Detect and display Battery temperature if supported. Default is false - --localip-show-ipv4 : Show IPv4 addresses in local ip module. Default is true - --localip-show-ipv6 : Show IPv6 addresses in local ip module. Default is false - --localip-show-loop : Show loop back addresses (127.0.0.1) in local ip module. Default is false - --localip-name-prefix : Show IPs with given name prefix only. Default is empty - --public-ip-timeout: Time in milliseconds to wait for the public ip server to respond. Default is disabled (0) - --public-ip-url: The URL of public IP detection server to be used. - --weather-timeout: Time in milliseconds to wait for the weather server to respond. Default is disabled (0) - --weather-output-format: The output weather format to be used. It must be URI encoded. - --player-name: The name of the player to use - --gl : Set the OpenGL context creation library to use. Must be auto, egl, glx or osmesa. Default is auto - --percent-type : Set the percentage output type. 1 for percentage number, 2 for bar, 3 for both, 6 for bar only. Default is 1 - --command-shell : Set the shell program to execute the command text. Default is cmd for Windows, csh for FreeBSD, bash for others - --command-key : Set the module key to display, can be specified mulitple times - --command-text : Set the command text to be executed, can be specified mulitple times + --title-fqdn : Set if the title should use fully qualified domain name. Default is false + --separator-string : Set the string printed by the separator module + --os-file : Set the path to the file containing OS information + --shell-version : Set if shell version should be detected and printed + --terminal-version : Set if terminal version should be detected and printed + --disk-folders : A colon (semicolon on Windows) separated list of folder paths for the disk output. Default is "/:/home" ("C:\\;D:\\ ..." on Windows) + --disk-show-removable : Set if removable volume should be printed. Default is true + --disk-show-hidden : Set if hidden volumes should be printed. Default is false + --disk-show-subvolumes : Set if subvolumes should be printed. Default is false + --disk-show-unknown : Set if unknown (unable to detect sizes) volumes should be printed. Default is false + --battery-dir : The directory where the battery folders are. Standard: /sys/class/power_supply/ + --cpu-temp : Detect and display CPU temperature if supported. Default is false + --gpu-temp : Detect and display GPU temperature if supported. Default is false + --gpu-hide-integrated : Hide integrated GPU if supported. Default is false + --gpu-hide-discrete : Hide discrete GPU if supported. Default is false + --battery-temp : Detect and display Battery temperature if supported. Default is false + --localip-show-ipv4 : Show IPv4 addresses in local ip module. Default is true + --localip-show-ipv6 : Show IPv6 addresses in local ip module. Default is false + --localip-show-loop : Show loop back addresses (127.0.0.1) in local ip module. Default is false + --localip-name-prefix : Show IPs with given name prefix only. Default is empty + --public-ip-timeout: Time in milliseconds to wait for the public ip server to respond. Default is disabled (0) + --public-ip-url: The URL of public IP detection server to be used. + --weather-timeout: Time in milliseconds to wait for the weather server to respond. Default is disabled (0) + --weather-output-format: The output weather format to be used. It must be URI encoded. + --player-name: The name of the player to use + --gl : Set the OpenGL context creation library to use. Must be auto, egl, glx or osmesa. Default is auto + --percent-type : Set the percentage output type. 1 for percentage number, 2 for bar, 3 for both, 6 for bar only. Default is 1 + --command-shell : Set the shell program to execute the command text. Default is cmd for Windows, csh for FreeBSD, bash for others + --command-key : Set the module key to display, can be specified mulitple times + --command-text : Set the command text to be executed, can be specified mulitple times Parsing is not case sensitive. E.g. "--lib-PCI" is equal to "--Lib-Pci" If a value starts with a ?, it is optional. "true" will be used if not set. diff --git a/src/detection/disk/disk.h b/src/detection/disk/disk.h index c061ce6c9..f4230ce46 100644 --- a/src/detection/disk/disk.h +++ b/src/detection/disk/disk.h @@ -9,7 +9,8 @@ typedef enum FFDiskType { FF_DISK_TYPE_REGULAR, FF_DISK_TYPE_HIDDEN, - FF_DISK_TYPE_EXTERNAL + FF_DISK_TYPE_EXTERNAL, + FF_DISK_TYPE_SUBVOLUME } FFDiskType; typedef struct FFDisk diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index 72d6c3f27..1907657d7 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -28,6 +28,21 @@ static void strbufAppendMountPoint(FFstrbuf* mountpoint, const char* source) } } +#ifndef __ANDROID__ +static bool isSubvolume(const char* options) +{ + const char* prefix = "subvol=/@"; //Btrfs subvolume + const char* subvolume = strstr(options, prefix); + if(subvolume == NULL) + return false; + + subvolume += strlen(prefix); + + //If there is no space or comma after the @, it is a btrfs subvolume + return *subvolume != ' ' && *subvolume != ','; +} +#endif + void ffDetectDisksImpl(FFDiskResult* disks) { FILE* mountsFile = fopen("/proc/mounts", "r"); @@ -82,19 +97,21 @@ void ffDetectDisksImpl(FFDiskResult* disks) ++currentPos; #ifdef __ANDROID__ - if(ffStrbufEqualS(&disk->mountpoint, "/") || ffStrbufEqualS(&disk->mountpoint, "/storage/emulated")) - disk->type = FF_DISK_TYPE_REGULAR; - else if(ffStrbufStartsWithS(&disk->mountpoint, "/mnt/media_rw/")) - disk->type = FF_DISK_TYPE_EXTERNAL; - else - disk->type = FF_DISK_TYPE_HIDDEN; + if(ffStrbufEqualS(&disk->mountpoint, "/") || ffStrbufEqualS(&disk->mountpoint, "/storage/emulated")) + disk->type = FF_DISK_TYPE_REGULAR; + else if(ffStrbufStartsWithS(&disk->mountpoint, "/mnt/media_rw/")) + disk->type = FF_DISK_TYPE_EXTERNAL; + else + disk->type = FF_DISK_TYPE_HIDDEN; #else - if(strstr(currentPos, "nosuid") != NULL || strstr(currentPos, "nodev") != NULL) - disk->type = FF_DISK_TYPE_EXTERNAL; - else if(ffStrbufStartsWithS(&disk->mountpoint, "/boot") || ffStrbufStartsWithS(&disk->mountpoint, "/efi")) - disk->type = FF_DISK_TYPE_HIDDEN; - else - disk->type = FF_DISK_TYPE_REGULAR; + if(isSubvolume(currentPos)) + disk->type = FF_DISK_TYPE_SUBVOLUME; + else if(strstr(currentPos, "nosuid") != NULL || strstr(currentPos, "nodev") != NULL) + disk->type = FF_DISK_TYPE_EXTERNAL; + else if(ffStrbufStartsWithS(&disk->mountpoint, "/boot") || ffStrbufStartsWithS(&disk->mountpoint, "/efi")) + disk->type = FF_DISK_TYPE_HIDDEN; + else + disk->type = FF_DISK_TYPE_REGULAR; #endif //Detects stats diff --git a/src/fastfetch.c b/src/fastfetch.c index d80537e41..486245dd2 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -1266,6 +1266,8 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con instance->config.diskShowRemovable = optionParseBoolean(value); else if(strcasecmp(key, "--disk-show-hidden") == 0) instance->config.diskShowHidden = optionParseBoolean(value); + else if(strcasecmp(key, "--disk-show-subvolumes") == 0) + instance->config.diskShowSubvolumes = optionParseBoolean(value); else if(strcasecmp(key, "--disk-show-unknown") == 0) instance->config.diskShowUnknown = optionParseBoolean(value); else if(strcasecmp(key, "--battery-dir") == 0) diff --git a/src/fastfetch.h b/src/fastfetch.h index 93be159df..084ec26f3 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -180,6 +180,7 @@ typedef struct FFconfig bool diskShowRemovable; bool diskShowHidden; bool diskShowUnknown; + bool diskShowSubvolumes; FFstrbuf batteryDir; diff --git a/src/modules/disk.c b/src/modules/disk.c index df7614d5c..c1e074812 100644 --- a/src/modules/disk.c +++ b/src/modules/disk.c @@ -137,6 +137,9 @@ static void printAutodetected(FFinstance* instance, const FFlist* disks) if(disk->type == FF_DISK_TYPE_EXTERNAL && !instance->config.diskShowRemovable) continue; + if(disk->type == FF_DISK_TYPE_SUBVOLUME && !instance->config.diskShowSubvolumes) + continue; + if(disk->type == FF_DISK_TYPE_HIDDEN && !instance->config.diskShowHidden) continue; From df793c20fd1073b35820536810f1e2c0be55f1de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 16 Jan 2023 16:58:19 +0800 Subject: [PATCH 112/142] Wifi: use ioctls instead of `iw` (Linux) --- src/detection/wifi/wifi.h | 9 ++- src/detection/wifi/wifi_apple.m | 4 +- src/detection/wifi/wifi_linux.c | 107 ++++++++++++++++++------------ src/detection/wifi/wifi_windows.c | 4 +- src/modules/wifi.c | 4 +- 5 files changed, 80 insertions(+), 48 deletions(-) diff --git a/src/detection/wifi/wifi.h b/src/detection/wifi/wifi.h index 375299a76..5db32a009 100644 --- a/src/detection/wifi/wifi.h +++ b/src/detection/wifi/wifi.h @@ -22,9 +22,16 @@ struct FFWifiConnection double txRate; }; +enum FFWifiSecurityType +{ + FF_WIFI_SECURITY_UNKNOWN, + FF_WIFI_SECURITY_ENABLED, + FF_WIFI_SECURITY_DISABLED, +}; + struct FFWifiSecurity { - bool enabled; + enum FFWifiSecurityType type; bool oneXEnabled; FFstrbuf algorithm; }; diff --git a/src/detection/wifi/wifi_apple.m b/src/detection/wifi/wifi_apple.m index 4f09ae1a7..4c8906dee 100644 --- a/src/detection/wifi/wifi_apple.m +++ b/src/detection/wifi/wifi_apple.m @@ -25,7 +25,7 @@ const char* ffDetectWifi(const FFinstance* instance, FFlist* result) item->conn.signalQuality = 0.0/0.0; item->conn.rxRate = 0.0/0.0; item->conn.txRate = 0.0/0.0; - item->security.enabled = false; + item->security.type = FF_WIFI_SECURITY_UNKNOWN; item->security.oneXEnabled = false; ffStrbufInit(&item->security.algorithm); @@ -72,7 +72,7 @@ const char* ffDetectWifi(const FFinstance* instance, FFlist* result) } item->conn.signalQuality = inf.rssiValue >= -50 ? 100 : inf.rssiValue <= -100 ? 0 : (inf.rssiValue + 100) * 2; item->conn.txRate = inf.transmitRate; - item->security.enabled = inf.security != kCWSecurityNone; + item->security.type = inf.security != kCWSecurityNone ? FF_WIFI_SECURITY_ENABLED : FF_WIFI_SECURITY_DISABLED; switch(inf.security) { case kCWSecurityNone: diff --git a/src/detection/wifi/wifi_linux.c b/src/detection/wifi/wifi_linux.c index 32bc40d00..905581682 100644 --- a/src/detection/wifi/wifi_linux.c +++ b/src/detection/wifi/wifi_linux.c @@ -1,57 +1,82 @@ #include "wifi.h" #include "common/io.h" -#include "common/processing.h" -#include "common/properties.h" #include +#include +#include +#include static const char* detectInf(char* ifName, FFWifiResult* wifi) { - const char* error = NULL; - FF_STRBUF_AUTO_DESTROY output; - ffStrbufInit(&output); - if((error = ffProcessAppendStdOut(&output, (char* const[]){ - "iw", - "dev", - ifName, - "link", - NULL - }))) - return error; + int sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if(sock < 0) + return "socket() failed"; - if(output.length == 0) - return "iw command execution failed"; + struct iwreq iwr; - if(!ffParsePropLines(output.chars, "Connected to ", &wifi->conn.macAddress)) + strncpy(iwr.ifr_name, ifName, IFNAMSIZ); + ffStrbufEnsureFree(&wifi->conn.ssid, IW_ESSID_MAX_SIZE); + iwr.u.essid.pointer = (caddr_t) wifi->conn.ssid.chars; + iwr.u.essid.length = IW_ESSID_MAX_SIZE + 1; + iwr.u.essid.flags = 0; + if(ioctl(sock, SIOCGIWESSID, &iwr) >= 0) + ffStrbufRecalculateLength(&wifi->conn.ssid); + + if(ioctl(sock, SIOCGIWNAME, &iwr) >= 0) { - ffStrbufAppendS(&wifi->conn.status, "Disconnected"); - return NULL; - } - - FF_STRBUF_AUTO_DESTROY temp; - ffStrbufInit(&temp); - - ffStrbufAppendS(&wifi->conn.status, "Connected"); - ffStrbufSubstrBefore(&wifi->conn.macAddress, ' '); - ffParsePropLines(output.chars, "SSID: ", &wifi->conn.ssid); - - if(ffParsePropLines(output.chars, "signal: ", &temp)) - wifi->conn.signalQuality = ffStrbufToDouble(&temp); - - if(ffParsePropLines(output.chars, "tx bitrate: ", &temp)) - { - if(ffStrbufContainS(&temp, " HE-MCS ")) - ffStrbufAppendS(&wifi->conn.phyType, "802.11ax (Wi-Fi 6)"); - else if(ffStrbufContainS(&temp, " VHT-MCS ")) - ffStrbufAppendS(&wifi->conn.phyType, "802.11ac (Wi-Fi 5)"); - else if(ffStrbufContainS(&temp, " MCS ")) - ffStrbufAppendS(&wifi->conn.phyType, "802.11n (Wi-Fi 4)"); + if(strncasecmp(iwr.u.name, "IEEE ", 5) == 0) + ffStrbufSetS(&wifi->conn.phyType, iwr.u.name + 5); else - ffStrbufAppendS(&wifi->conn.phyType, "802.11a/b/g"); + ffStrbufSetS(&wifi->conn.phyType, iwr.u.name); } - wifi->security.enabled = true; //FIXME: Unable to find this info. Set it true so that fastfetch won't print `insecure` + if(ioctl(sock, SIOCGIWAP, &iwr) >= 0) + { + for(int i = 0; i < 6; ++i) + ffStrbufAppendF(&wifi->conn.macAddress, "%.2X-", (uint8_t) iwr.u.ap_addr.sa_data[i]); + ffStrbufTrimRight(&wifi->conn.macAddress, '-'); + } + + //FIXME: doesn't work + if(ioctl(sock, SIOCGIWSPY, &iwr) >= 0) + wifi->conn.signalQuality = iwr.u.qual.level; + + //FIXME: doesn't work + struct iw_encode_ext iwe; + iwr.u.data.pointer = &iwe; + iwr.u.data.length = sizeof(iwe); + iwr.u.data.flags = 0; + if(ioctl(sock, SIOCGIWENCODEEXT, &iwr) >= 0) + { + struct iw_encode_ext* iwe = iwr.u.data.pointer; + if(iwe->alg == IW_ENCODE_ALG_NONE) + wifi->security.type = FF_WIFI_SECURITY_DISABLED; + else + { + wifi->security.type = FF_WIFI_SECURITY_ENABLED; + switch(iwe->alg) + { + case IW_ENCODE_ALG_WEP: + ffStrbufAppendS(&wifi->security.algorithm, "WEP"); + break; + case IW_ENCODE_ALG_TKIP: + ffStrbufAppendS(&wifi->security.algorithm, "TKIP"); + break; + case IW_ENCODE_ALG_CCMP: + ffStrbufAppendS(&wifi->security.algorithm, "CCMP"); + break; + case IW_ENCODE_ALG_PMK: + ffStrbufAppendS(&wifi->security.algorithm, "PMK"); + break; + case IW_ENCODE_ALG_AES_CMAC: + ffStrbufAppendS(&wifi->security.algorithm, "CMAC"); + break; + } + } + } + + close(sock); return NULL; } @@ -83,7 +108,7 @@ const char* ffDetectWifi(const FFinstance* instance, FFlist* result) item->conn.signalQuality = 0.0/0.0; item->conn.rxRate = 0.0/0.0; item->conn.txRate = 0.0/0.0; - item->security.enabled = false; + item->security.type = FF_WIFI_SECURITY_UNKNOWN; item->security.oneXEnabled = false; ffStrbufInit(&item->security.algorithm); diff --git a/src/detection/wifi/wifi_windows.c b/src/detection/wifi/wifi_windows.c index a972939d7..c59375419 100644 --- a/src/detection/wifi/wifi_windows.c +++ b/src/detection/wifi/wifi_windows.c @@ -86,7 +86,7 @@ const char* ffDetectWifi(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* res item->conn.signalQuality = 0.0/0.0; item->conn.rxRate = 0.0/0.0; item->conn.txRate = 0.0/0.0; - item->security.enabled = false; + item->security.type = FF_WIFI_SECURITY_UNKNOWN; item->security.oneXEnabled = false; ffStrbufInit(&item->security.algorithm); @@ -162,7 +162,7 @@ const char* ffDetectWifi(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* res item->conn.rxRate = connInfo->wlanAssociationAttributes.ulRxRate; item->conn.txRate = connInfo->wlanAssociationAttributes.ulTxRate; - item->security.enabled = connInfo->wlanSecurityAttributes.bSecurityEnabled; + item->security.type = connInfo->wlanSecurityAttributes.bSecurityEnabled ? FF_WIFI_SECURITY_ENABLED : FF_WIFI_SECURITY_DISABLED; item->security.oneXEnabled = connInfo->wlanSecurityAttributes.bOneXEnabled; switch (connInfo->wlanSecurityAttributes.dot11AuthAlgorithm) { diff --git a/src/modules/wifi.c b/src/modules/wifi.c index 5a791e4fd..ef3d4cfb5 100644 --- a/src/modules/wifi.c +++ b/src/modules/wifi.c @@ -25,7 +25,7 @@ void ffPrintWifi(FFinstance* instance) if(item->conn.ssid.length) { printf("%s - %s", item->conn.ssid.chars, item->conn.phyType.chars); - if(!item->security.enabled) + if(item->security.type == FF_WIFI_SECURITY_DISABLED) puts(" - insecure"); else putchar('\n'); @@ -47,7 +47,7 @@ void ffPrintWifi(FFinstance* instance) {FF_FORMAT_ARG_TYPE_DOUBLE, &item->conn.signalQuality}, {FF_FORMAT_ARG_TYPE_DOUBLE, &item->conn.rxRate}, {FF_FORMAT_ARG_TYPE_DOUBLE, &item->conn.txRate}, - {FF_FORMAT_ARG_TYPE_BOOL, &item->security.enabled}, + {FF_FORMAT_ARG_TYPE_STRING, item->security.type == FF_WIFI_SECURITY_UNKNOWN ? "Unknown" : item->security.type == FF_WIFI_SECURITY_ENABLED ? "Secure" : "Insecure"}, {FF_FORMAT_ARG_TYPE_BOOL, &item->security.oneXEnabled}, {FF_FORMAT_ARG_TYPE_STRBUF, &item->security.algorithm}, }); From f28805fb940b6be10784372989c06fb6c754a6d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 17 Jan 2023 12:45:26 +0800 Subject: [PATCH 113/142] Wifi: detect more information using libnm (Linux) --- CHANGELOG.md | 2 +- CMakeLists.txt | 5 + README.md | 1 + src/common/init.c | 2 + src/detection/wifi/wifi.h | 18 +-- src/detection/wifi/wifi_apple.m | 61 ++++---- src/detection/wifi/wifi_linux.c | 251 ++++++++++++++++++++++++++---- src/detection/wifi/wifi_windows.c | 158 +++++++------------ src/fastfetch.c | 8 +- src/fastfetch.h | 1 + src/modules/wifi.c | 22 ++- 11 files changed, 334 insertions(+), 195 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d5ebd2b8..558a90dcb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,7 @@ Features: * Support `WezTerm` terminal font detection (requires [`wezterm` executable](https://wezfurlong.org/wezterm/cli/general.html) being available) * Add `--shell-version` and `--terminal-version` options to disable shell / terminal version detection * Enhance `--percent-type` to allow hiding other texts (#387) -* Add Wifi module basic support for Linux +* Add Wifi module support for Linux Logos: * Raspbian (@IamNoRobot, #373) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2aeeef888..be70a5e01 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,6 +68,7 @@ cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR BSD" OFF) cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX OR BSD" OFF) cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR BSD OR WIN32" OFF) cmake_dependent_option(ENABLE_LIBCJSON "Enable libcjson" ON "LINUX OR WIN32" OFF) +cmake_dependent_option(ENABLE_LIBNM "Enable libnm" ON "LINUX" OFF) cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF) cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND AND NOT ANDROID" OFF) cmake_dependent_option(ENABLE_BUFFER "Enable stdout buffer" ON "LINUX OR APPLE OR BSD OR WIN32 OR ANDROID" OFF) @@ -637,6 +638,10 @@ ff_lib_enable(LIBCJSON "libcjson" "CJson" ) +ff_lib_enable(LIBNM + "libnm" + "libnm" +) ff_lib_enable(FREETYPE "freetype2" "FreeType2" diff --git a/README.md b/README.md index 339993501..a7bc7b580 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,7 @@ The following libraries are used if present at runtime: * [`libsqlite3`](https://www.sqlite.org/index.html): Needed for pkg & rpm package count. * [`librpm`](http://rpm.org/): Slower fallback for rpm package count. Needed on openSUSE. * [`libcJSON`](https://github.com/DaveGamble/cJSON): Needed for Windows Terminal font ( WSL ). +* [`libnm`](https://networkmanager.dev/docs/libnm/latest/): Used for Wifi detection on Linux. ### macOS diff --git a/src/common/init.c b/src/common/init.c index efef9190a..de797fe82 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -139,6 +139,7 @@ static void defaultConfig(FFinstance* instance) ffStrbufInitA(&instance->config.libcJSON, 0); ffStrbufInitA(&instance->config.libfreetype, 0); ffStrbufInit(&instance->config.libwlanapi); + ffStrbufInit(&instance->config.libnm); instance->config.cpuTemp = false; instance->config.gpuTemp = false; @@ -400,6 +401,7 @@ static void destroyConfig(FFinstance* instance) ffStrbufDestroy(&instance->config.libcJSON); ffStrbufDestroy(&instance->config.libfreetype); ffStrbufDestroy(&instance->config.libwlanapi); + ffStrbufDestroy(&instance->config.libnm); ffStrbufDestroy(&instance->config.diskFolders); ffStrbufDestroy(&instance->config.batteryDir); diff --git a/src/detection/wifi/wifi.h b/src/detection/wifi/wifi.h index 5db32a009..fae5c46ce 100644 --- a/src/detection/wifi/wifi.h +++ b/src/detection/wifi/wifi.h @@ -16,31 +16,17 @@ struct FFWifiConnection FFstrbuf status; FFstrbuf ssid; FFstrbuf macAddress; - FFstrbuf phyType; + FFstrbuf protocol; + FFstrbuf security; double signalQuality; // Percentage double rxRate; double txRate; }; -enum FFWifiSecurityType -{ - FF_WIFI_SECURITY_UNKNOWN, - FF_WIFI_SECURITY_ENABLED, - FF_WIFI_SECURITY_DISABLED, -}; - -struct FFWifiSecurity -{ - enum FFWifiSecurityType type; - bool oneXEnabled; - FFstrbuf algorithm; -}; - typedef struct FFWifiResult { struct FFWifiInterface inf; struct FFWifiConnection conn; - struct FFWifiSecurity security; } FFWifiResult; const char* ffDetectWifi(const FFinstance* instance, FFlist* result /*list of FFWifiItem*/); diff --git a/src/detection/wifi/wifi_apple.m b/src/detection/wifi/wifi_apple.m index 4c8906dee..0616130e6 100644 --- a/src/detection/wifi/wifi_apple.m +++ b/src/detection/wifi/wifi_apple.m @@ -21,13 +21,11 @@ const char* ffDetectWifi(const FFinstance* instance, FFlist* result) ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); ffStrbufInit(&item->conn.macAddress); - ffStrbufInit(&item->conn.phyType); + ffStrbufInit(&item->conn.protocol); + ffStrbufInit(&item->conn.security); item->conn.signalQuality = 0.0/0.0; item->conn.rxRate = 0.0/0.0; item->conn.txRate = 0.0/0.0; - item->security.type = FF_WIFI_SECURITY_UNKNOWN; - item->security.oneXEnabled = false; - ffStrbufInit(&item->security.algorithm); ffStrbufAppendS(&item->inf.description, inf.interfaceName.UTF8String); ffStrbufAppendS(&item->inf.status, inf.powerOn ? "Power On" : "Power Off"); @@ -43,88 +41,85 @@ const char* ffDetectWifi(const FFinstance* instance, FFlist* result) switch(inf.activePHYMode) { case kCWPHYModeNone: - ffStrbufAppendS(&item->conn.phyType, "none"); + ffStrbufAppendS(&item->conn.protocol, "none"); break; case kCWPHYMode11a: - ffStrbufAppendS(&item->conn.phyType, "802.11a"); + ffStrbufAppendS(&item->conn.protocol, "802.11a"); break; case kCWPHYMode11b: - ffStrbufAppendS(&item->conn.phyType, "802.11b"); + ffStrbufAppendS(&item->conn.protocol, "802.11b"); break; case kCWPHYMode11g: - ffStrbufAppendS(&item->conn.phyType, "802.11g"); + ffStrbufAppendS(&item->conn.protocol, "802.11g"); break; case kCWPHYMode11n: - ffStrbufAppendS(&item->conn.phyType, "802.11n (Wi-Fi 4)"); + ffStrbufAppendS(&item->conn.protocol, "802.11n (Wi-Fi 4)"); break; case kCWPHYMode11ac: - ffStrbufAppendS(&item->conn.phyType, "802.11ac (Wi-Fi 5)"); + ffStrbufAppendS(&item->conn.protocol, "802.11ac (Wi-Fi 5)"); break; case 6 /*kCWPHYMode11ax*/: - ffStrbufAppendS(&item->conn.phyType, "802.11ax (Wi-Fi 6)"); + ffStrbufAppendS(&item->conn.protocol, "802.11ax (Wi-Fi 6)"); break; case 7 /*kCWPHYMode11be?*/: - ffStrbufAppendS(&item->conn.phyType, "802.11be (Wi-Fi 7)"); + ffStrbufAppendS(&item->conn.protocol, "802.11be (Wi-Fi 7)"); break; default: - ffStrbufAppendF(&item->conn.phyType, "Unknown (%ld)", inf.activePHYMode); + ffStrbufAppendF(&item->conn.protocol, "Unknown (%ld)", inf.activePHYMode); break; } item->conn.signalQuality = inf.rssiValue >= -50 ? 100 : inf.rssiValue <= -100 ? 0 : (inf.rssiValue + 100) * 2; item->conn.txRate = inf.transmitRate; - item->security.type = inf.security != kCWSecurityNone ? FF_WIFI_SECURITY_ENABLED : FF_WIFI_SECURITY_DISABLED; + switch(inf.security) { - case kCWSecurityNone: - ffStrbufAppendS(&item->security.algorithm, "None"); - break; case kCWSecurityWEP: - ffStrbufAppendS(&item->security.algorithm, "WEP"); + ffStrbufAppendS(&item->conn.security, "WEP"); break; case kCWSecurityWPAPersonal: - ffStrbufAppendS(&item->security.algorithm, "WPA Personal"); + ffStrbufAppendS(&item->conn.security, "WPA Personal"); break; case kCWSecurityWPAPersonalMixed: - ffStrbufAppendS(&item->security.algorithm, "WPA Persional Mixed"); + ffStrbufAppendS(&item->conn.security, "WPA Persional Mixed"); break; case kCWSecurityWPA2Personal: - ffStrbufAppendS(&item->security.algorithm, "WPA2 Personal"); + ffStrbufAppendS(&item->conn.security, "WPA2 Personal"); break; case kCWSecurityPersonal: - ffStrbufAppendS(&item->security.algorithm, "Personal"); + ffStrbufAppendS(&item->conn.security, "Personal"); break; case kCWSecurityDynamicWEP: - ffStrbufAppendS(&item->security.algorithm, "Dynamic WEP"); + ffStrbufAppendS(&item->conn.security, "Dynamic WEP"); break; case kCWSecurityWPAEnterprise: - ffStrbufAppendS(&item->security.algorithm, "WPA Enterprise"); + ffStrbufAppendS(&item->conn.security, "WPA Enterprise"); break; case kCWSecurityWPAEnterpriseMixed: - ffStrbufAppendS(&item->security.algorithm, "WPA Enterprise Mixed"); + ffStrbufAppendS(&item->conn.security, "WPA Enterprise Mixed"); break; case kCWSecurityWPA2Enterprise: - ffStrbufAppendS(&item->security.algorithm, "WPA2 Enterprise"); + ffStrbufAppendS(&item->conn.security, "WPA2 Enterprise"); break; case kCWSecurityEnterprise: - ffStrbufAppendS(&item->security.algorithm, "Enterprise"); + ffStrbufAppendS(&item->conn.security, "Enterprise"); break; case kCWSecurityWPA3Personal: - ffStrbufAppendS(&item->security.algorithm, "WPA3 Personal"); + ffStrbufAppendS(&item->conn.security, "WPA3 Personal"); break; case kCWSecurityWPA3Enterprise: - ffStrbufAppendS(&item->security.algorithm, "WPA3 Enterprise"); + ffStrbufAppendS(&item->conn.security, "WPA3 Enterprise"); break; case kCWSecurityWPA3Transition: - ffStrbufAppendS(&item->security.algorithm, "WPA3 Transition"); + ffStrbufAppendS(&item->conn.security, "WPA3 Transition"); break; case 14 /*kCWSecurityOWE*/: - ffStrbufAppendS(&item->security.algorithm, "OWE"); + ffStrbufAppendS(&item->conn.security, "OWE"); break; case 15 /*kCWSecurityOWETransition*/: - ffStrbufAppendS(&item->security.algorithm, "OWE Transition"); + ffStrbufAppendS(&item->conn.security, "OWE Transition"); break; default: - ffStrbufAppendF(&item->security.algorithm, "Unknown (%ld)", inf.security); + ffStrbufAppendF(&item->conn.security, "Unknown (%ld)", inf.security); break; } } diff --git a/src/detection/wifi/wifi_linux.c b/src/detection/wifi/wifi_linux.c index 905581682..65487218b 100644 --- a/src/detection/wifi/wifi_linux.c +++ b/src/detection/wifi/wifi_linux.c @@ -1,5 +1,204 @@ #include "wifi.h" +#include "common/processing.h" +#include "common/properties.h" +#include "common/library.h" + +#include +#include + +#ifdef FF_HAVE_LIBNM + +#include +#define NM_NO_INCLUDE_EXTRA_HEADERS 1 +#include + +const char* ffDetectWifi(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* result) +{ + FF_LIBRARY_LOAD(nm, &instance->config.libnm, "dlopen libnm failed", "libnm" FF_LIBRARY_EXTENSION, 0); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_client_new); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_client_get_devices); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_device_get_iface); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_device_get_state); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_device_wifi_get_type); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_device_wifi_get_active_access_point); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_ssid); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_utils_ssid_to_utf8); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_bssid); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_strength); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_max_bitrate); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_flags); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_wpa_flags); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_rsn_flags); + + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, g_type_check_instance_is_a); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, g_bytes_get_size); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, g_bytes_get_data); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, g_free); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, g_object_unref); + + NMClient* client = ffnm_client_new(NULL, NULL); + if(!client) + { + dlclose(nm); + return "Could not create NMClient"; + } + + /* Get all devices managed by NetworkManager */ + const GPtrArray* devices = ffnm_client_get_devices(client); + + /* Go through the array and process Wi-Fi devices */ + for (guint i = 0; i < devices->len; i++) + { + NMDevice *device = g_ptr_array_index(devices, i); + if (!({ + GTypeInstance *__inst = (GTypeInstance*) device; GType __t = ffnm_device_wifi_get_type(); gboolean __r; + if (!__inst) + __r = FALSE; + else if (__inst->g_class && __inst->g_class->g_type == __t) + __r = TRUE; + else + __r = ffg_type_check_instance_is_a (__inst, __t); + __r; + }) //NM_IS_DEVICE_WIFI(device) + ) + continue; + + FFWifiResult* item = (FFWifiResult*) ffListAdd(result); + ffStrbufInit(&item->inf.description); + ffStrbufInit(&item->inf.status); + ffStrbufInit(&item->conn.status); + ffStrbufInit(&item->conn.ssid); + ffStrbufInit(&item->conn.macAddress); + ffStrbufInit(&item->conn.protocol); + ffStrbufInit(&item->conn.security); + item->conn.signalQuality = 0.0/0.0; + item->conn.rxRate = 0.0/0.0; + item->conn.txRate = 0.0/0.0; + + ffStrbufAppendS(&item->inf.description, ffnm_device_get_iface(device)); + NMDeviceState state = ffnm_device_get_state(device); + switch(state) + { + case NM_DEVICE_STATE_UNKNOWN: + ffStrbufAppendS(&item->inf.status, "Unknown"); + break; + case NM_DEVICE_STATE_UNMANAGED: + ffStrbufAppendS(&item->inf.status, "Unmanaged"); + break; + case NM_DEVICE_STATE_UNAVAILABLE: + ffStrbufAppendS(&item->inf.status, "Unavailable"); + break; + case NM_DEVICE_STATE_DISCONNECTED: + ffStrbufAppendS(&item->inf.status, "Disconnected"); + break; + case NM_DEVICE_STATE_PREPARE: + ffStrbufAppendS(&item->inf.status, "Prepare"); + break; + case NM_DEVICE_STATE_CONFIG: + ffStrbufAppendS(&item->inf.status, "Config"); + break; + case NM_DEVICE_STATE_NEED_AUTH: + ffStrbufAppendS(&item->inf.status, "Need auth"); + break; + case NM_DEVICE_STATE_IP_CONFIG: + ffStrbufAppendS(&item->inf.status, "IP config"); + break; + case NM_DEVICE_STATE_IP_CHECK: + ffStrbufAppendS(&item->inf.status, "IP check"); + break; + case NM_DEVICE_STATE_SECONDARIES: + ffStrbufAppendS(&item->inf.status, "Secondaries"); + break; + case NM_DEVICE_STATE_ACTIVATED: + ffStrbufAppendS(&item->inf.status, "Activated"); + break; + case NM_DEVICE_STATE_DEACTIVATING: + ffStrbufAppendS(&item->inf.status, "Deactivating"); + break; + case NM_DEVICE_STATE_FAILED: + ffStrbufAppendS(&item->inf.status, "Failed"); + break; + } + if(state != NM_DEVICE_STATE_ACTIVATED) + continue; + + NMAccessPoint* ap = ffnm_device_wifi_get_active_access_point((NMDeviceWifi *) device); + if (!ap) + continue; + + GBytes* activeSsid = ffnm_access_point_get_ssid(ap); + if (activeSsid) + { + char* ssid = ffnm_utils_ssid_to_utf8(ffg_bytes_get_data(activeSsid, NULL), ffg_bytes_get_size(activeSsid)); + ffStrbufAppendS(&item->conn.ssid, ssid); + ffg_free(ssid); + } + + ffStrbufAppendS(&item->conn.macAddress, ffnm_access_point_get_bssid(ap)); + item->conn.signalQuality = ffnm_access_point_get_strength(ap); + item->conn.rxRate = ffnm_access_point_get_max_bitrate(ap); + + if(instance->config.allowSlowOperations) + { + FF_STRBUF_AUTO_DESTROY output; + ffStrbufInit(&output); + if(!ffProcessAppendStdOut(&output, (char* const[]){ + "iw", + "dev", + item->inf.description.chars, + "link", + NULL + }) && ffParsePropLines(output.chars, "tx bitrate: ", &item->conn.protocol)) + { + if(ffStrbufContainS(&item->conn.protocol, " HE-MCS ")) + ffStrbufSetS(&item->conn.protocol, "802.11ax (Wi-Fi 6)"); + else if(ffStrbufContainS(&item->conn.protocol, " VHT-MCS ")) + ffStrbufSetS(&item->conn.protocol, "802.11ac (Wi-Fi 5)"); + else if(ffStrbufContainS(&item->conn.protocol, " MCS ")) + ffStrbufSetS(&item->conn.protocol, "802.11n (Wi-Fi 4)"); + else + ffStrbufSetS(&item->conn.protocol, "802.11a/b/g"); + } + } + if(!item->conn.protocol.length) + ffStrbufAppendS(&item->conn.protocol, "802.11"); + + NM80211ApFlags flags = ffnm_access_point_get_flags(ap); + NM80211ApSecurityFlags wpaFlags = ffnm_access_point_get_wpa_flags(ap); + NM80211ApSecurityFlags rsnFlags = ffnm_access_point_get_rsn_flags(ap); + + if ((flags & NM_802_11_AP_FLAGS_PRIVACY) && (wpaFlags == NM_802_11_AP_SEC_NONE) + && (rsnFlags == NM_802_11_AP_SEC_NONE)) + ffStrbufAppendS(&item->conn.security, "WEP "); + if (wpaFlags != NM_802_11_AP_SEC_NONE) + ffStrbufAppendS(&item->conn.security, "WPA "); + if ((rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_PSK) + || (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) { + ffStrbufAppendS(&item->conn.security, "WPA2 "); + } + if (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_SAE) { + ffStrbufAppendS(&item->conn.security, "WPA3 "); + } + if ((rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_OWE) + || (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_OWE_TM)) { + ffStrbufAppendS(&item->conn.security, "OWE "); + } + if ((wpaFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) + || (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) { + ffStrbufAppendS(&item->conn.security, "802.1X "); + } + ffStrbufTrimRight(&item->conn.security, ' '); + } + + ffg_object_unref(client); + dlclose(nm); + + return NULL; +} + +#else + #include "common/io.h" #include @@ -26,9 +225,9 @@ static const char* detectInf(char* ifName, FFWifiResult* wifi) if(ioctl(sock, SIOCGIWNAME, &iwr) >= 0) { if(strncasecmp(iwr.u.name, "IEEE ", 5) == 0) - ffStrbufSetS(&wifi->conn.phyType, iwr.u.name + 5); + ffStrbufSetS(&wifi->conn.protocol, iwr.u.name + 5); else - ffStrbufSetS(&wifi->conn.phyType, iwr.u.name); + ffStrbufSetS(&wifi->conn.protocol, iwr.u.name); } if(ioctl(sock, SIOCGIWAP, &iwr) >= 0) @@ -50,30 +249,26 @@ static const char* detectInf(char* ifName, FFWifiResult* wifi) if(ioctl(sock, SIOCGIWENCODEEXT, &iwr) >= 0) { struct iw_encode_ext* iwe = iwr.u.data.pointer; - if(iwe->alg == IW_ENCODE_ALG_NONE) - wifi->security.type = FF_WIFI_SECURITY_DISABLED; - else + switch(iwe->alg) { - wifi->security.type = FF_WIFI_SECURITY_ENABLED; - switch(iwe->alg) - { - case IW_ENCODE_ALG_WEP: - ffStrbufAppendS(&wifi->security.algorithm, "WEP"); - break; - case IW_ENCODE_ALG_TKIP: - ffStrbufAppendS(&wifi->security.algorithm, "TKIP"); - break; - case IW_ENCODE_ALG_CCMP: - ffStrbufAppendS(&wifi->security.algorithm, "CCMP"); - break; - case IW_ENCODE_ALG_PMK: - ffStrbufAppendS(&wifi->security.algorithm, "PMK"); - break; - case IW_ENCODE_ALG_AES_CMAC: - ffStrbufAppendS(&wifi->security.algorithm, "CMAC"); - break; - } + case IW_ENCODE_ALG_WEP: + ffStrbufAppendS(&wifi->conn.security, "WEP"); + break; + case IW_ENCODE_ALG_TKIP: + ffStrbufAppendS(&wifi->conn.security, "TKIP"); + break; + case IW_ENCODE_ALG_CCMP: + ffStrbufAppendS(&wifi->conn.security, "CCMP"); + break; + case IW_ENCODE_ALG_PMK: + ffStrbufAppendS(&wifi->conn.security, "PMK"); + break; + case IW_ENCODE_ALG_AES_CMAC: + ffStrbufAppendS(&wifi->conn.security, "CMAC"); + break; } + } else { + ffStrbufAppendS(&wifi->conn.security, "unknown"); } close(sock); @@ -104,13 +299,11 @@ const char* ffDetectWifi(const FFinstance* instance, FFlist* result) ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); ffStrbufInit(&item->conn.macAddress); - ffStrbufInit(&item->conn.phyType); + ffStrbufInit(&item->conn.protocol); + ffStrbufInit(&item->conn.security); item->conn.signalQuality = 0.0/0.0; item->conn.rxRate = 0.0/0.0; item->conn.txRate = 0.0/0.0; - item->security.type = FF_WIFI_SECURITY_UNKNOWN; - item->security.oneXEnabled = false; - ffStrbufInit(&item->security.algorithm); ffStrbufSetF(&path, "/sys/class/net/%s/operstate", i->if_name); if(!ffAppendFileBuffer(path.chars, &item->inf.status) || !ffStrbufEqualS(&item->inf.status, "up")) @@ -126,3 +319,5 @@ const char* ffDetectWifi(const FFinstance* instance, FFlist* result) return NULL; } + +#endif diff --git a/src/detection/wifi/wifi_windows.c b/src/detection/wifi/wifi_windows.c index c59375419..143c1845a 100644 --- a/src/detection/wifi/wifi_windows.c +++ b/src/detection/wifi/wifi_windows.c @@ -82,13 +82,11 @@ const char* ffDetectWifi(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* res ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); ffStrbufInit(&item->conn.macAddress); - ffStrbufInit(&item->conn.phyType); + ffStrbufInit(&item->conn.protocol); + ffStrbufInit(&item->conn.security); item->conn.signalQuality = 0.0/0.0; item->conn.rxRate = 0.0/0.0; item->conn.txRate = 0.0/0.0; - item->security.type = FF_WIFI_SECURITY_UNKNOWN; - item->security.oneXEnabled = false; - ffStrbufInit(&item->security.algorithm); ffStrbufSetWS(&item->inf.description, ifInfo->strInterfaceDescription); convertIfStateToString(ifInfo->isState, &item->inf.status); @@ -121,40 +119,40 @@ const char* ffDetectWifi(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* res switch (connInfo->wlanAssociationAttributes.dot11PhyType) { case dot11_phy_type_fhss: - ffStrbufAppendS(&item->conn.phyType, "802.11 (FHSS)"); + ffStrbufAppendS(&item->conn.protocol, "802.11 (FHSS)"); break; case dot11_phy_type_dsss: - ffStrbufAppendS(&item->conn.phyType, "802.11 (DSSS)"); + ffStrbufAppendS(&item->conn.protocol, "802.11 (DSSS)"); break; case dot11_phy_type_irbaseband: - ffStrbufAppendS(&item->conn.phyType, "802.11 (IR)"); + ffStrbufAppendS(&item->conn.protocol, "802.11 (IR)"); break; case dot11_phy_type_ofdm: - ffStrbufAppendS(&item->conn.phyType, "802.11a"); + ffStrbufAppendS(&item->conn.protocol, "802.11a"); break; case dot11_phy_type_hrdsss: - ffStrbufAppendS(&item->conn.phyType, "802.11b"); + ffStrbufAppendS(&item->conn.protocol, "802.11b"); break; case dot11_phy_type_erp: - ffStrbufAppendS(&item->conn.phyType, "802.11g"); + ffStrbufAppendS(&item->conn.protocol, "802.11g"); break; case dot11_phy_type_ht: - ffStrbufAppendS(&item->conn.phyType, "802.11n (Wi-Fi 4)"); + ffStrbufAppendS(&item->conn.protocol, "802.11n (Wi-Fi 4)"); break; case 8 /*dot11_phy_type_vht*/: - ffStrbufAppendS(&item->conn.phyType, "802.11ac (Wi-Fi 5)"); + ffStrbufAppendS(&item->conn.protocol, "802.11ac (Wi-Fi 5)"); break; case 9 /*dot11_phy_type_dmg*/: - ffStrbufAppendS(&item->conn.phyType, "802.11ad (WiGig)"); + ffStrbufAppendS(&item->conn.protocol, "802.11ad (WiGig)"); break; case 10 /*dot11_phy_type_he*/: - ffStrbufAppendS(&item->conn.phyType, "802.11ax (Wi-Fi 6)"); + ffStrbufAppendS(&item->conn.protocol, "802.11ax (Wi-Fi 6)"); break; case 11 /*dot11_phy_type_eht*/: - ffStrbufAppendS(&item->conn.phyType, "802.11be (Wi-Fi 7)"); + ffStrbufAppendS(&item->conn.protocol, "802.11be (Wi-Fi 7)"); break; default: - ffStrbufAppendF(&item->conn.phyType, "Unknown (%u)", (unsigned)connInfo->wlanAssociationAttributes.dot11PhyType); + ffStrbufAppendF(&item->conn.protocol, "Unknown (%u)", (unsigned)connInfo->wlanAssociationAttributes.dot11PhyType); break; } @@ -162,93 +160,51 @@ const char* ffDetectWifi(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* res item->conn.rxRate = connInfo->wlanAssociationAttributes.ulRxRate; item->conn.txRate = connInfo->wlanAssociationAttributes.ulTxRate; - item->security.type = connInfo->wlanSecurityAttributes.bSecurityEnabled ? FF_WIFI_SECURITY_ENABLED : FF_WIFI_SECURITY_DISABLED; - item->security.oneXEnabled = connInfo->wlanSecurityAttributes.bOneXEnabled; - switch (connInfo->wlanSecurityAttributes.dot11AuthAlgorithm) + if(connInfo->wlanSecurityAttributes.bSecurityEnabled) { - case DOT11_AUTH_ALGO_80211_OPEN: - ffStrbufAppendS(&item->security.algorithm, "802.11 Open"); - break; - case DOT11_AUTH_ALGO_80211_SHARED_KEY: - ffStrbufAppendS(&item->security.algorithm, "802.11 Shared"); - break; - case DOT11_AUTH_ALGO_WPA: - ffStrbufAppendS(&item->security.algorithm, "WPA"); - break; - case DOT11_AUTH_ALGO_WPA_PSK: - ffStrbufAppendS(&item->security.algorithm, "WPA-PSK"); - break; - case DOT11_AUTH_ALGO_WPA_NONE: - ffStrbufAppendS(&item->security.algorithm, "WPA-None"); - break; - case DOT11_AUTH_ALGO_RSNA: - ffStrbufAppendS(&item->security.algorithm, "RSNA"); - break; - case DOT11_AUTH_ALGO_RSNA_PSK: - ffStrbufAppendS(&item->security.algorithm, "RSNA with PSK"); - break; - case 8 /* DOT11_AUTH_ALGO_WPA3 */: - ffStrbufAppendS(&item->security.algorithm, "WPA3"); - break; - case 9 /* DOT11_AUTH_ALGO_WPA3_SAE */: - ffStrbufAppendS(&item->security.algorithm, "WPA3-SAE"); - break; - case 10 /* DOT11_AUTH_ALGO_OWE */: - ffStrbufAppendS(&item->security.algorithm, "OWE"); - break; - case 11 /* DOT11_AUTH_ALGO_WPA3_ENT */: - ffStrbufAppendS(&item->security.algorithm, "OWE-ENT"); - break; - default: - ffStrbufAppendF(&item->security.algorithm, "Unknown (%u)", (unsigned)connInfo->wlanSecurityAttributes.dot11AuthAlgorithm); - break; - } - ffStrbufAppendS(&item->security.algorithm, " - "); - switch (connInfo->wlanSecurityAttributes.dot11CipherAlgorithm) - { - case DOT11_CIPHER_ALGO_NONE: - ffStrbufAppendS(&item->security.algorithm, "None"); - break; - case DOT11_CIPHER_ALGO_WEP40: - ffStrbufAppendS(&item->security.algorithm, "WEP-40"); - break; - case DOT11_CIPHER_ALGO_TKIP: - ffStrbufAppendS(&item->security.algorithm, "TKIP"); - break; - case DOT11_CIPHER_ALGO_CCMP: - ffStrbufAppendS(&item->security.algorithm, "CCMP"); - break; - case DOT11_CIPHER_ALGO_WEP104: - ffStrbufAppendS(&item->security.algorithm, "WEP-104"); - break; - case 0x06 /* DOT11_CIPHER_ALGO_BIP */: - ffStrbufAppendS(&item->security.algorithm, "BIP-CMAC-128"); - break; - case 0x08 /* DOT11_CIPHER_ALGO_GCMP */: - ffStrbufAppendS(&item->security.algorithm, "GCMP-128"); - break; - case 0x09 /* DOT11_CIPHER_ALGO_GCMP_256 */: - ffStrbufAppendS(&item->security.algorithm, "GCMP-256"); - break; - case 0x0a /* DOT11_CIPHER_ALGO_CCMP_256 */: - ffStrbufAppendS(&item->security.algorithm, "CCMP-256"); - break; - case 0x0b /* DOT11_CIPHER_ALGO_BIP_GMAC_128 */: - ffStrbufAppendS(&item->security.algorithm, "BIP-GMAC-128"); - break; - case 0x0c /* DOT11_CIPHER_ALGO_BIP_GMAC_256 */: - ffStrbufAppendS(&item->security.algorithm, "BIP-GMAC-256"); - break; - case 0x0d /* DOT11_CIPHER_ALGO_BIP_CMAC_256 */: - ffStrbufAppendS(&item->security.algorithm, "BIP-CMAC-256"); - break; - case DOT11_CIPHER_ALGO_WEP: - ffStrbufAppendS(&item->security.algorithm, "WEP"); - break; - default: - ffStrbufAppendF(&item->security.algorithm, "Unknown (%u)", (unsigned)connInfo->wlanSecurityAttributes.dot11CipherAlgorithm); - break; + switch (connInfo->wlanSecurityAttributes.dot11AuthAlgorithm) + { + case DOT11_AUTH_ALGO_80211_OPEN: + ffStrbufAppendS(&item->conn.security, "802.11 Open"); + break; + case DOT11_AUTH_ALGO_80211_SHARED_KEY: + ffStrbufAppendS(&item->conn.security, "802.11 Shared"); + break; + case DOT11_AUTH_ALGO_WPA: + ffStrbufAppendS(&item->conn.security, "WPA"); + break; + case DOT11_AUTH_ALGO_WPA_PSK: + ffStrbufAppendS(&item->conn.security, "WPA-PSK"); + break; + case DOT11_AUTH_ALGO_WPA_NONE: + ffStrbufAppendS(&item->conn.security, "WPA-None"); + break; + case DOT11_AUTH_ALGO_RSNA: + ffStrbufAppendS(&item->conn.security, "WPA2"); + break; + case DOT11_AUTH_ALGO_RSNA_PSK: + ffStrbufAppendS(&item->conn.security, "WPA2-PSK"); + break; + case 8 /* DOT11_AUTH_ALGO_WPA3 */: + ffStrbufAppendS(&item->conn.security, "WPA3"); + break; + case 9 /* DOT11_AUTH_ALGO_WPA3_SAE */: + ffStrbufAppendS(&item->conn.security, "WPA3-SAE"); + break; + case 10 /* DOT11_AUTH_ALGO_OWE */: + ffStrbufAppendS(&item->conn.security, "OWE"); + break; + case 11 /* DOT11_AUTH_ALGO_WPA3_ENT */: + ffStrbufAppendS(&item->conn.security, "OWE-ENT"); + break; + default: + ffStrbufAppendF(&item->conn.security, "Unknown (%u)", (unsigned)connInfo->wlanSecurityAttributes.dot11AuthAlgorithm); + break; + } + if(connInfo->wlanSecurityAttributes.bOneXEnabled) + ffStrbufAppendS(&item->conn.security, " 802.11X"); } + ffWlanFreeMemory(connInfo); } diff --git a/src/fastfetch.c b/src/fastfetch.c index 486245dd2..d31fbf7e2 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -373,13 +373,11 @@ static inline void printCommandHelp(const char* command) "Connection status", "Connection SSID", "Connection mac address", - "Connection PHY type", + "Connection protocol", "Connection signal quality (percentage)", "Connection RX rate", "Connection TX rate", - "Security enabled", - "Security 802.1X enabled", - "Security algorithm" + "Connection Security algorithm" ); } else if(strcasecmp(command, "player-format") == 0) @@ -1236,6 +1234,8 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con optionParseString(key, value, &instance->config.libcJSON); else if(strcasecmp(subkey, "-wlanapi") == 0) optionParseString(key, value, &instance->config.libwlanapi); + else if(strcasecmp(subkey, "-nm") == 0) + optionParseString(key, value, &instance->config.libnm); else goto error; } diff --git a/src/fastfetch.h b/src/fastfetch.h index 084ec26f3..2f3b20753 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -163,6 +163,7 @@ typedef struct FFconfig FFstrbuf libcJSON; FFstrbuf libfreetype; FFstrbuf libwlanapi; + FFstrbuf libnm; bool cpuTemp; bool gpuTemp; diff --git a/src/modules/wifi.c b/src/modules/wifi.c index ef3d4cfb5..95c59a3b5 100644 --- a/src/modules/wifi.c +++ b/src/modules/wifi.c @@ -3,7 +3,7 @@ #include "detection/wifi/wifi.h" #define FF_WIFI_MODULE_NAME "Wifi" -#define FF_WIFI_NUM_FORMAT_ARGS 12 +#define FF_WIFI_NUM_FORMAT_ARGS 10 void ffPrintWifi(FFinstance* instance) { @@ -24,11 +24,11 @@ void ffPrintWifi(FFinstance* instance) ffPrintLogoAndKey(instance, FF_WIFI_MODULE_NAME, moduleIndex, &instance->config.wifi.key); if(item->conn.ssid.length) { - printf("%s - %s", item->conn.ssid.chars, item->conn.phyType.chars); - if(item->security.type == FF_WIFI_SECURITY_DISABLED) - puts(" - insecure"); - else - putchar('\n'); + printf("%s - %s - %s\n", + item->conn.ssid.chars, + item->conn.protocol.chars, + item->conn.security.length > 0 ? item->conn.security.chars : "insecure" + ); } else { @@ -43,13 +43,11 @@ void ffPrintWifi(FFinstance* instance) {FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.status}, {FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.ssid}, {FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.macAddress}, - {FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.phyType}, + {FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.protocol}, {FF_FORMAT_ARG_TYPE_DOUBLE, &item->conn.signalQuality}, {FF_FORMAT_ARG_TYPE_DOUBLE, &item->conn.rxRate}, {FF_FORMAT_ARG_TYPE_DOUBLE, &item->conn.txRate}, - {FF_FORMAT_ARG_TYPE_STRING, item->security.type == FF_WIFI_SECURITY_UNKNOWN ? "Unknown" : item->security.type == FF_WIFI_SECURITY_ENABLED ? "Secure" : "Insecure"}, - {FF_FORMAT_ARG_TYPE_BOOL, &item->security.oneXEnabled}, - {FF_FORMAT_ARG_TYPE_STRBUF, &item->security.algorithm}, + {FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.security}, }); } @@ -58,8 +56,8 @@ void ffPrintWifi(FFinstance* instance) ffStrbufDestroy(&item->conn.status); ffStrbufDestroy(&item->conn.ssid); ffStrbufDestroy(&item->conn.macAddress); - ffStrbufDestroy(&item->conn.phyType); - ffStrbufDestroy(&item->security.algorithm); + ffStrbufDestroy(&item->conn.protocol); + ffStrbufDestroy(&item->conn.security); } } else From 68977be256497a762f6b5be143641f3229a811cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 17 Jan 2023 05:40:10 +0800 Subject: [PATCH 114/142] CI: build with `libnm` support; print supported features --- .github/workflows/push.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 05e721183..3fefdb776 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@v3 - name: install required packages - run: sudo apt-get update && sudo apt-get install -y libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libcjson-dev + run: sudo apt-get update && sudo apt-get install -y libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libcjson-dev libnm-dev - name: Initialize CodeQL uses: github/codeql-action/init@v2 @@ -34,6 +34,9 @@ jobs: - name: perform CodeQL analysis uses: github/codeql-action/analyze@v2 + - name: list features + run: ./fastfetch --list-features + - name: run fastfetch run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all @@ -80,6 +83,9 @@ jobs: - name: perform CodeQL analysis uses: github/codeql-action/analyze@v2 + - name: list features + run: ./fastfetch --list-features + - name: run fastfetch run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all @@ -113,6 +119,7 @@ jobs: run: | cmake -DSET_TWEAK=Off -DBUILD_TESTS=On . cmake --build . --target package + ./fastfetch --list-features time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all time ./flashfetch ctest @@ -179,6 +186,9 @@ jobs: - name: copy necessary dlls run: cp /clang64/bin/{libcjson,libOpenCL,vulkan-1}.dll . + - name: list features + run: ./fastfetch --list-features + - name: run fastfetch run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all From c746cde61e58dd883092f9e7157a03daf0d8fef4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 17 Jan 2023 15:52:51 +0800 Subject: [PATCH 115/142] Wifi: code refactor; fix a silly copy & paste error --- src/detection/wifi/wifi_apple.m | 3 - src/detection/wifi/wifi_windows.c | 6 -- src/modules/wifi.c | 91 ++++++++++++++++--------------- 3 files changed, 47 insertions(+), 53 deletions(-) diff --git a/src/detection/wifi/wifi_apple.m b/src/detection/wifi/wifi_apple.m index 0616130e6..417a4e3de 100644 --- a/src/detection/wifi/wifi_apple.m +++ b/src/detection/wifi/wifi_apple.m @@ -10,9 +10,6 @@ const char* ffDetectWifi(const FFinstance* instance, FFlist* result) if(!interfaces) return "CWWiFiClient.sharedWiFiClient.interfaces is nil"; - if(interfaces.count == 0) - return "No wifi interfaces found"; - for(CWInterface* inf in interfaces) { FFWifiResult* item = (FFWifiResult*)ffListAdd(result); diff --git a/src/detection/wifi/wifi_windows.c b/src/detection/wifi/wifi_windows.c index 143c1845a..2f275061e 100644 --- a/src/detection/wifi/wifi_windows.c +++ b/src/detection/wifi/wifi_windows.c @@ -66,12 +66,6 @@ const char* ffDetectWifi(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* res goto exit; } - if(ifList->dwNumberOfItems == 0) - { - error = "No wifi interfaces found"; - goto exit; - } - for(uint32_t index = 0; index < ifList->dwNumberOfItems; ++index) { WLAN_INTERFACE_INFO* ifInfo = (WLAN_INTERFACE_INFO*)&ifList->InterfaceInfo[index]; diff --git a/src/modules/wifi.c b/src/modules/wifi.c index 95c59a3b5..bc1bbacbf 100644 --- a/src/modules/wifi.c +++ b/src/modules/wifi.c @@ -11,57 +11,60 @@ void ffPrintWifi(FFinstance* instance) ffListInit(&result, sizeof(FFWifiResult)); const char* error = ffDetectWifi(instance, &result); - - if(!error) + if(error) { - for(uint32_t index = 0; index < result.length; ++index) - { - FFWifiResult* item = (FFWifiResult*)ffListGet(&result, index); - uint8_t moduleIndex = result.length == 1 ? 0 : (uint8_t)(index + 1); + ffPrintError(instance, FF_WIFI_MODULE_NAME, 0, &instance->config.wifi, "%s", error); + return; + } + if(!result.length) + { + ffPrintError(instance, FF_WIFI_MODULE_NAME, 0, &instance->config.wifi, "No Wifi interfaces found"); + return; + } - if(instance->config.wifi.outputFormat.length == 0) + for(uint32_t index = 0; index < result.length; ++index) + { + FFWifiResult* item = (FFWifiResult*)ffListGet(&result, index); + uint8_t moduleIndex = result.length == 1 ? 0 : (uint8_t)(index + 1); + + if(instance->config.wifi.outputFormat.length == 0) + { + ffPrintLogoAndKey(instance, FF_WIFI_MODULE_NAME, moduleIndex, &instance->config.wifi.key); + if(item->conn.ssid.length) { - ffPrintLogoAndKey(instance, FF_WIFI_MODULE_NAME, moduleIndex, &instance->config.wifi.key); - if(item->conn.ssid.length) - { - printf("%s - %s - %s\n", - item->conn.ssid.chars, - item->conn.protocol.chars, - item->conn.security.length > 0 ? item->conn.security.chars : "insecure" - ); - } - else - { - puts(item->inf.status.chars); - } + printf("%s - %s - %s\n", + item->conn.ssid.chars, + item->conn.protocol.chars, + item->conn.security.length > 0 ? item->conn.security.chars : "insecure" + ); } else { - ffPrintFormat(instance, FF_WIFI_MODULE_NAME, moduleIndex, &instance->config.wifi, FF_WIFI_NUM_FORMAT_ARGS, (FFformatarg[]){ - {FF_FORMAT_ARG_TYPE_STRBUF, &item->inf.description}, - {FF_FORMAT_ARG_TYPE_STRBUF, &item->inf.status}, - {FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.status}, - {FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.ssid}, - {FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.macAddress}, - {FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.protocol}, - {FF_FORMAT_ARG_TYPE_DOUBLE, &item->conn.signalQuality}, - {FF_FORMAT_ARG_TYPE_DOUBLE, &item->conn.rxRate}, - {FF_FORMAT_ARG_TYPE_DOUBLE, &item->conn.txRate}, - {FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.security}, - }); + puts(item->inf.status.chars); } - - ffStrbufDestroy(&item->inf.description); - ffStrbufDestroy(&item->inf.status); - ffStrbufDestroy(&item->conn.status); - ffStrbufDestroy(&item->conn.ssid); - ffStrbufDestroy(&item->conn.macAddress); - ffStrbufDestroy(&item->conn.protocol); - ffStrbufDestroy(&item->conn.security); } - } - else - { - ffPrintError(instance, FF_WIFI_MODULE_NAME, 0, &instance->config.wmTheme, "%s", error); + else + { + ffPrintFormat(instance, FF_WIFI_MODULE_NAME, moduleIndex, &instance->config.wifi, FF_WIFI_NUM_FORMAT_ARGS, (FFformatarg[]){ + {FF_FORMAT_ARG_TYPE_STRBUF, &item->inf.description}, + {FF_FORMAT_ARG_TYPE_STRBUF, &item->inf.status}, + {FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.status}, + {FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.ssid}, + {FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.macAddress}, + {FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.protocol}, + {FF_FORMAT_ARG_TYPE_DOUBLE, &item->conn.signalQuality}, + {FF_FORMAT_ARG_TYPE_DOUBLE, &item->conn.rxRate}, + {FF_FORMAT_ARG_TYPE_DOUBLE, &item->conn.txRate}, + {FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.security}, + }); + } + + ffStrbufDestroy(&item->inf.description); + ffStrbufDestroy(&item->inf.status); + ffStrbufDestroy(&item->conn.status); + ffStrbufDestroy(&item->conn.ssid); + ffStrbufDestroy(&item->conn.macAddress); + ffStrbufDestroy(&item->conn.protocol); + ffStrbufDestroy(&item->conn.security); } } From 622a5c267b06d7207b26b7e7158a03436135729c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 17 Jan 2023 15:54:06 +0800 Subject: [PATCH 116/142] Wifi: fall back to ioctls if fail to loading libnm libs --- src/common/init.c | 5 +- src/detection/wifi/wifi_linux.c | 163 ++++++++++++++++---------------- 2 files changed, 83 insertions(+), 85 deletions(-) diff --git a/src/common/init.c b/src/common/init.c index de797fe82..368a42677 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -503,7 +503,10 @@ void ffListFeatures() "libcjson\n" #endif #ifdef FF_HAVE_FREETYPE - "freetype" + "freetype\n" + #endif + #ifdef FF_HAVE_LIBNM + "libnm\n" #endif "" , stdout); diff --git a/src/detection/wifi/wifi_linux.c b/src/detection/wifi/wifi_linux.c index 65487218b..4459b3e5a 100644 --- a/src/detection/wifi/wifi_linux.c +++ b/src/detection/wifi/wifi_linux.c @@ -1,19 +1,19 @@ #include "wifi.h" -#include "common/processing.h" -#include "common/properties.h" -#include "common/library.h" - #include #include #ifdef FF_HAVE_LIBNM +#include "common/processing.h" +#include "common/properties.h" +#include "common/library.h" + #include #define NM_NO_INCLUDE_EXTRA_HEADERS 1 #include -const char* ffDetectWifi(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* result) +static const char* detectWifiWithLibnm(const FFinstance* instance, FFlist* result) { FF_LIBRARY_LOAD(nm, &instance->config.libnm, "dlopen libnm failed", "libnm" FF_LIBRARY_EXTENSION, 0); FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_client_new); @@ -197,7 +197,7 @@ const char* ffDetectWifi(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* res return NULL; } -#else +#endif #include "common/io.h" @@ -206,80 +206,8 @@ const char* ffDetectWifi(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* res #include #include -static const char* detectInf(char* ifName, FFWifiResult* wifi) +static const char* detectWifiWithIoctls(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* result) { - int sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); - if(sock < 0) - return "socket() failed"; - - struct iwreq iwr; - - strncpy(iwr.ifr_name, ifName, IFNAMSIZ); - ffStrbufEnsureFree(&wifi->conn.ssid, IW_ESSID_MAX_SIZE); - iwr.u.essid.pointer = (caddr_t) wifi->conn.ssid.chars; - iwr.u.essid.length = IW_ESSID_MAX_SIZE + 1; - iwr.u.essid.flags = 0; - if(ioctl(sock, SIOCGIWESSID, &iwr) >= 0) - ffStrbufRecalculateLength(&wifi->conn.ssid); - - if(ioctl(sock, SIOCGIWNAME, &iwr) >= 0) - { - if(strncasecmp(iwr.u.name, "IEEE ", 5) == 0) - ffStrbufSetS(&wifi->conn.protocol, iwr.u.name + 5); - else - ffStrbufSetS(&wifi->conn.protocol, iwr.u.name); - } - - if(ioctl(sock, SIOCGIWAP, &iwr) >= 0) - { - for(int i = 0; i < 6; ++i) - ffStrbufAppendF(&wifi->conn.macAddress, "%.2X-", (uint8_t) iwr.u.ap_addr.sa_data[i]); - ffStrbufTrimRight(&wifi->conn.macAddress, '-'); - } - - //FIXME: doesn't work - if(ioctl(sock, SIOCGIWSPY, &iwr) >= 0) - wifi->conn.signalQuality = iwr.u.qual.level; - - //FIXME: doesn't work - struct iw_encode_ext iwe; - iwr.u.data.pointer = &iwe; - iwr.u.data.length = sizeof(iwe); - iwr.u.data.flags = 0; - if(ioctl(sock, SIOCGIWENCODEEXT, &iwr) >= 0) - { - struct iw_encode_ext* iwe = iwr.u.data.pointer; - switch(iwe->alg) - { - case IW_ENCODE_ALG_WEP: - ffStrbufAppendS(&wifi->conn.security, "WEP"); - break; - case IW_ENCODE_ALG_TKIP: - ffStrbufAppendS(&wifi->conn.security, "TKIP"); - break; - case IW_ENCODE_ALG_CCMP: - ffStrbufAppendS(&wifi->conn.security, "CCMP"); - break; - case IW_ENCODE_ALG_PMK: - ffStrbufAppendS(&wifi->conn.security, "PMK"); - break; - case IW_ENCODE_ALG_AES_CMAC: - ffStrbufAppendS(&wifi->conn.security, "CMAC"); - break; - } - } else { - ffStrbufAppendS(&wifi->conn.security, "unknown"); - } - - close(sock); - - return NULL; -} - -const char* ffDetectWifi(const FFinstance* instance, FFlist* result) -{ - FF_UNUSED(instance); - struct if_nameindex* infs = if_nameindex(); if(!infs) return "if_nameindex() failed"; @@ -309,15 +237,82 @@ const char* ffDetectWifi(const FFinstance* instance, FFlist* result) if(!ffAppendFileBuffer(path.chars, &item->inf.status) || !ffStrbufEqualS(&item->inf.status, "up")) continue; - detectInf(i->if_name, item); + int sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if(sock < 0) + continue; + + struct iwreq iwr; + strncpy(iwr.ifr_name, i->if_name, 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; + iwr.u.essid.flags = 0; + if(ioctl(sock, SIOCGIWESSID, &iwr) >= 0) + ffStrbufRecalculateLength(&item->conn.ssid); + + if(ioctl(sock, SIOCGIWNAME, &iwr) >= 0) + { + if(strncasecmp(iwr.u.name, "IEEE ", 5) == 0) + ffStrbufSetS(&item->conn.protocol, iwr.u.name + 5); + else + ffStrbufSetS(&item->conn.protocol, iwr.u.name); + } + + if(ioctl(sock, SIOCGIWAP, &iwr) >= 0) + { + for(int i = 0; i < 6; ++i) + ffStrbufAppendF(&item->conn.macAddress, "%.2X-", (uint8_t) iwr.u.ap_addr.sa_data[i]); + ffStrbufTrimRight(&item->conn.macAddress, '-'); + } + + //FIXME: doesn't work + if(ioctl(sock, SIOCGIWSPY, &iwr) >= 0) + item->conn.signalQuality = iwr.u.qual.level; + + //FIXME: doesn't work + struct iw_encode_ext iwe; + iwr.u.data.pointer = &iwe; + iwr.u.data.length = sizeof(iwe); + iwr.u.data.flags = 0; + if(ioctl(sock, SIOCGIWENCODEEXT, &iwr) >= 0) + { + struct iw_encode_ext* iwe = iwr.u.data.pointer; + switch(iwe->alg) + { + case IW_ENCODE_ALG_WEP: + ffStrbufAppendS(&item->conn.security, "WEP"); + break; + case IW_ENCODE_ALG_TKIP: + ffStrbufAppendS(&item->conn.security, "TKIP"); + break; + case IW_ENCODE_ALG_CCMP: + ffStrbufAppendS(&item->conn.security, "CCMP"); + break; + case IW_ENCODE_ALG_PMK: + ffStrbufAppendS(&item->conn.security, "PMK"); + break; + case IW_ENCODE_ALG_AES_CMAC: + ffStrbufAppendS(&item->conn.security, "CMAC"); + break; + } + } else { + ffStrbufAppendS(&item->conn.security, "unknown"); + } + + close(sock); } if_freenameindex(infs); ffStrbufDestroy(&path); - if(result->length == 0) - return "No wifi interfaces found"; - return NULL; } -#endif +const char* ffDetectWifi(const FFinstance* instance, FFlist* result) +{ + #ifdef FF_HAVE_LIBNM + if(!detectWifiWithLibnm(instance, result)) + return NULL; + #endif + + return detectWifiWithIoctls(instance, result); +} From 65e2331979013bef18c7a13885aa92e028e57032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 18 Jan 2023 01:00:30 +0800 Subject: [PATCH 117/142] CI: print brightness --- presets/all | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/presets/all b/presets/all index 6f5fbb4d9..d89a50e90 100644 --- a/presets/all +++ b/presets/all @@ -1 +1 @@ ---structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Weather:Break:Colors +--structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Resolution:Brightness:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Weather:Break:Colors From f4a58036fa68e6efbba83ac142211f6f110721bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 18 Jan 2023 01:37:47 +0800 Subject: [PATCH 118/142] Resolution: rename to display --- CHANGELOG.md | 1 + CMakeLists.txt | 2 +- README.md | 6 ++-- completions/bash | 8 ++--- presets/all | 2 +- presets/hardware | 2 +- presets/neofetch | 6 ++-- presets/paleofetch | 4 +-- presets/verbose | 2 +- src/common/init.c | 4 +-- src/data/config_user.txt | 6 ++-- src/data/help_format.txt | 2 +- src/data/modules.txt | 2 +- src/data/structure.txt | 2 +- src/detection/displayserver/displayserver.c | 10 +++--- src/detection/displayserver/displayserver.h | 8 ++--- .../displayserver/displayserver_apple.c | 8 ++--- .../displayserver/displayserver_nosupport.c | 2 +- .../displayserver/displayserver_windows.c | 4 +-- .../displayserver/linux/displayserver_linux.c | 32 +++++++++---------- src/detection/displayserver/linux/wayland.c | 6 ++-- src/detection/displayserver/linux/xcb.c | 12 +++---- src/detection/displayserver/linux/xlib.c | 12 +++---- src/fastfetch.c | 10 +++--- src/fastfetch.h | 4 +-- src/flashfetch.c | 2 +- src/modules/{resolution.c => display.c} | 22 ++++++------- 27 files changed, 91 insertions(+), 90 deletions(-) rename src/modules/{resolution.c => display.c} (58%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 558a90dcb..53f43d5ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Notable Changes: * fastfetch no longer creates a sample config file silently. Use `--gen-config` to generate one. * fastfetch now search for user config file in the order of `fastfetch --list-config-paths` * Unknown disks are hidden by default. +* `Resolution` module is renamed to `Display`. (#393) Features: * `--logo-padding-top` option (@CarterLi, #372) diff --git a/CMakeLists.txt b/CMakeLists.txt index be70a5e01..2f07deeb2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -284,7 +284,7 @@ set(LIBFASTFETCH_SRC src/modules/poweradapter.c src/modules/processes.c src/modules/publicip.c - src/modules/resolution.c + src/modules/display.c src/modules/separator.c src/modules/shell.c src/modules/media.c diff --git a/README.md b/README.md index a7bc7b580..a87eee346 100644 --- a/README.md +++ b/README.md @@ -36,8 +36,8 @@ The following libraries are used if present at runtime: * [`libxcb-randr`](https://xcb.freedesktop.org/), [`libXrandr`](https://gitlab.freedesktop.org/xorg/lib/libxrandr), [`libxcb`](https://xcb.freedesktop.org/), - [`libX11`](https://gitlab.freedesktop.org/xorg/lib/libx11): At least one of them sould be present in X11 sessions for better resolution detection and faster WM detection. The `*randr` ones provide multi monitor support The `libxcb*` ones usually have better performance. -* [`libwayland-client`](https://wayland.freedesktop.org/): Better resolution performance and output in wayland sessions. Supports different refresh rates per monitor. + [`libX11`](https://gitlab.freedesktop.org/xorg/lib/libx11): At least one of them sould be present in X11 sessions for better display detection and faster WM detection. The `*randr` ones provide multi monitor support The `libxcb*` ones usually have better performance. +* [`libwayland-client`](https://wayland.freedesktop.org/): Better display performance and output in wayland sessions. Supports different refresh rates per monitor. * [`libGIO`](https://developer.gnome.org/gio/unstable/): Needed for values that are only stored GSettings. * [`libDConf`](https://developer.gnome.org/dconf/unstable/): Needed for values that are only stored in DConf + Fallback for GSettings. * [`libmagickcore` (ImageMagick)](https://www.imagemagick.org/): Images in terminal using sixel or kitty graphics protocol. @@ -85,7 +85,7 @@ All categories not listed here should work without needing a specific implementa ##### Available Modules ``` -Battery, Bios, Board, Break, Brightness, Colors, Command, CPU, CPUUsage, Cursor, Custom, Date, DateTime, DE, Disk, Font, GPU, Host, Icons, Kernel, Locale, LocalIP, Media, Memory, OpenCL, OpenGL, Packages, Player, Power Adapter, Processes, PublicIP, Resolution, Separator OS, Shell, Swap, Terminal, Terminal Font, Theme, Time, Title, Uptime, Vulkan, Wifi, WM, WMTheme +Battery, Bios, Board, Break, Brightness, Colors, Command, CPU, CPUUsage, Cursor, Custom, Date, DateTime, DE, Disk, Display, Font, GPU, Host, Icons, Kernel, Locale, LocalIP, Media, Memory, OpenCL, OpenGL, Packages, Player, Power Adapter, Processes, PublicIP, Separator OS, Shell, Swap, Terminal, Terminal Font, Theme, Time, Title, Uptime, Vulkan, Wifi, WM, WMTheme ``` ##### Builtin logos diff --git a/completions/bash b/completions/bash index b4f1548f7..7c32c4cc3 100644 --- a/completions/bash +++ b/completions/bash @@ -13,7 +13,7 @@ __fastfetch_complete_help() "processes-format" "packages-format" "shell-format" - "resolution-format" + "display-format" "de-format" "wm-format" "wm-theme-format" @@ -253,9 +253,9 @@ __fastfetch_completion() "--shell-key" "--shell-format" "--shell-error" - "--resolution-key" - "--resolution-format" - "--resolution-error" + "--display-key" + "--display-format" + "--display-error" "--de-key" "--de-format" "--de-error" diff --git a/presets/all b/presets/all index d89a50e90..85be11eef 100644 --- a/presets/all +++ b/presets/all @@ -1 +1 @@ ---structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Resolution:Brightness:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Weather:Break:Colors +--structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Display:Brightness:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Weather:Break:Colors diff --git a/presets/hardware b/presets/hardware index 3f3995d02..f93873197 100644 --- a/presets/hardware +++ b/presets/hardware @@ -1,4 +1,4 @@ ---structure Host:Resolution:CPU:GPU:Memory:Disk:Battery +--structure Host:Display:CPU:GPU:Memory:Disk:Battery --memory-format "{?2}{2}{?}" --disk-format "{?2}{2}{?}" --battery-format "{?1}{1} {?}{?2}{2} {?}{?3}({3}){?}" diff --git a/presets/neofetch b/presets/neofetch index 192abcf1a..9d42df956 100644 --- a/presets/neofetch +++ b/presets/neofetch @@ -1,10 +1,10 @@ ---structure "Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Terminal:TerminalFont:CPU:GPU:Memory:Break:Colors" +--structure "Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Display:DE:WM:WMTheme:Theme:Icons:Terminal:TerminalFont:CPU:GPU:Memory:Break:Colors" --host-format "{/2}{-}{/}{2}{?3} {3}{?}" --os-format "{3} {12}" ---resolution-format "{}x{}" +--display-format "{}x{}" --de-format "{2} {3}" --theme-format "{?1}{1}{?3} {3}{?} [Plasma], {?}{7}" --terminal-font-format "{/2}{-}{/}{2}{?3} {3}{?}" --memory-format "{/1}{-}{/}{/2}{-}{/}{} / {}" --gpu-key "GPU" ---resolution-key "Resolution" +--display-key "Display" diff --git a/presets/paleofetch b/presets/paleofetch index fbaa17848..66913e3dc 100644 --- a/presets/paleofetch +++ b/presets/paleofetch @@ -1,5 +1,5 @@ ---structure Title:Separator:OS:Host:Kernel:Uptime:Battery:Break:Packages:Shell:Resolution:Terminal:Break:CPU:GPU:Memory:Break:Colors +--structure Title:Separator:OS:Host:Kernel:Uptime:Battery:Break:Packages:Shell:Display:Terminal:Break:CPU:GPU:Memory:Break:Colors --host-format "{/2}{-}{/}{2}{?3} {3}{?}" --battery-format "{/4}{-}{/}{4}%{?5} [{5}]{?}" ---resolution-key "Resolution" +--display-key "Display" --gpu-key "GPU" diff --git a/presets/verbose b/presets/verbose index 5a9f2f0e5..57711c43d 100644 --- a/presets/verbose +++ b/presets/verbose @@ -5,7 +5,7 @@ --processes-format Count: {} --packages-format All: {}; pacman: {}; pacman branch: {}; dpkg: {}; rpm: {}; emerge: {}; eopkg: {}; xbps: {}; apk: {}; flatpak: {}; snap: {}; brew: {}; brew-cask: {}; port: {}; scoop: {}; choco: {} --shell-format Process name: {}; Process path: {}; Process exe: {}; Process version: {}; User path: {}; User exe: {}; User version: {} ---resolution-format Width: {}; Height: {}; Refresh rate: {} +--display-format Width: {}; Height: {}; Refresh rate: {} --de-format Process name: {}; Pretty name: {}; Version: {} --wm-format Process name: {}; Pretty name: {}; Protocol: {} --wm-theme-format Name: {} diff --git a/src/common/init.c b/src/common/init.c index 368a42677..e4f106e94 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -83,7 +83,7 @@ static void defaultConfig(FFinstance* instance) initModuleArg(&instance->config.processes); initModuleArg(&instance->config.packages); initModuleArg(&instance->config.shell); - initModuleArg(&instance->config.resolution); + initModuleArg(&instance->config.display); initModuleArg(&instance->config.de); initModuleArg(&instance->config.wm); initModuleArg(&instance->config.wmTheme); @@ -345,7 +345,7 @@ static void destroyConfig(FFinstance* instance) destroyModuleArg(&instance->config.processes); destroyModuleArg(&instance->config.packages); destroyModuleArg(&instance->config.shell); - destroyModuleArg(&instance->config.resolution); + destroyModuleArg(&instance->config.display); destroyModuleArg(&instance->config.de); destroyModuleArg(&instance->config.wm); destroyModuleArg(&instance->config.wmTheme); diff --git a/src/data/config_user.txt b/src/data/config_user.txt index 0ea7b3973..0e987509e 100644 --- a/src/data/config_user.txt +++ b/src/data/config_user.txt @@ -264,7 +264,7 @@ #--processes-key Processes #--packages-key Packages #--shell-key Shell -#--resolution-key Resolution {1} +#--display-key Display {1} #--brightness-key Brightness ({1}) #--de-key DE #--wm-key WM @@ -309,7 +309,7 @@ #--processes-format #--packages-format #--shell-format -#--resolution-format +#--display-format #--brightness-format #--de-format #--wm-format @@ -353,7 +353,7 @@ #--processes-error #--packages-error #--shell-error -#--resolution-error +#--display-error #--brightness-error #--de-error #--wm-error diff --git a/src/data/help_format.txt b/src/data/help_format.txt index 87a4b1cc2..106a7acdc 100644 --- a/src/data/help_format.txt +++ b/src/data/help_format.txt @@ -33,4 +33,4 @@ You can therefore use --host-format " " to disable host output. Note that --host-format "" would evaluate as not set, and therefore use the built-in host format Format string is also the way to go to set a fixed value - just use one without placeholders. -For example when running in headless mode, you could use "--resolution-format "Preferred". +For example when running in headless mode, you could use "--display-format Preferred". diff --git a/src/data/modules.txt b/src/data/modules.txt index a684c1b84..586c2de1d 100644 --- a/src/data/modules.txt +++ b/src/data/modules.txt @@ -11,6 +11,7 @@ Date Datetime DE Disk +Display Font GPU Host @@ -27,7 +28,6 @@ Player PowerAdapter Processes PublicIP -Resolution Separator Shell Swap diff --git a/src/data/structure.txt b/src/data/structure.txt index e47d27847..851657c6d 100644 --- a/src/data/structure.txt +++ b/src/data/structure.txt @@ -1 +1 @@ -Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Disk:Battery:PowerAdapter:Locale:Break:Colors +Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Display:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Disk:Battery:PowerAdapter:Locale:Break:Colors diff --git a/src/detection/displayserver/displayserver.c b/src/detection/displayserver/displayserver.c index 4a42a21a1..e7ab5c49e 100644 --- a/src/detection/displayserver/displayserver.c +++ b/src/detection/displayserver/displayserver.c @@ -19,15 +19,15 @@ uint32_t ffdsParseRefreshRate(int32_t refreshRate) return (uint32_t) refreshRate; } -bool ffdsAppendResolution(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate) +bool ffdsAppendDisplay(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate) { if(width == 0 || height == 0) return false; - FFResolutionResult* resolution = ffListAdd(&result->resolutions); - resolution->width = width; - resolution->height = height; - resolution->refreshRate = refreshRate; + FFDisplayResult* display = ffListAdd(&result->displays); + display->width = width; + display->height = height; + display->refreshRate = refreshRate; return true; } diff --git a/src/detection/displayserver/displayserver.h b/src/detection/displayserver/displayserver.h index d31d5edee..d100520b5 100644 --- a/src/detection/displayserver/displayserver.h +++ b/src/detection/displayserver/displayserver.h @@ -5,12 +5,12 @@ #include "fastfetch.h" -typedef struct FFResolutionResult +typedef struct FFDisplayResult { uint32_t width; uint32_t height; uint32_t refreshRate; -} FFResolutionResult; +} FFDisplayResult; typedef struct FFDisplayServerResult { @@ -20,13 +20,13 @@ typedef struct FFDisplayServerResult FFstrbuf deProcessName; FFstrbuf dePrettyName; FFstrbuf deVersion; - FFlist resolutions; //List of FFResolutionResult + FFlist displays; //List of FFDisplayResult } FFDisplayServerResult; const FFDisplayServerResult* ffConnectDisplayServer(const FFinstance* instance); //Used internal uint32_t ffdsParseRefreshRate(int32_t refreshRate); -bool ffdsAppendResolution(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate); +bool ffdsAppendDisplay(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate); #endif diff --git a/src/detection/displayserver/displayserver_apple.c b/src/detection/displayserver/displayserver_apple.c index 4d0d802c2..782453de9 100644 --- a/src/detection/displayserver/displayserver_apple.c +++ b/src/detection/displayserver/displayserver_apple.c @@ -7,7 +7,7 @@ #include #include -static void detectResolution(FFDisplayServerResult* ds) +static void detectDisplays(FFDisplayServerResult* ds) { CGDirectDisplayID screens[128]; uint32_t screenCount; @@ -20,7 +20,7 @@ static void detectResolution(FFDisplayServerResult* ds) CGDisplayModeRef mode = CGDisplayCopyDisplayMode(screen); if(mode) { - ffdsAppendResolution(ds, + ffdsAppendDisplay(ds, (uint32_t)CGDisplayModeGetWidth(mode), (uint32_t)CGDisplayModeGetHeight(mode), (uint32_t)CGDisplayModeGetRefreshRate(mode) @@ -84,6 +84,6 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* ins ffStrbufAppendS(&ds->deProcessName, "aqua"); ffStrbufAppendS(&ds->dePrettyName, "Aqua"); - ffListInitA(&ds->resolutions, sizeof(FFResolutionResult), 4); - detectResolution(ds); + ffListInitA(&ds->displays, sizeof(FFDisplayResult), 4); + detectDisplays(ds); } diff --git a/src/detection/displayserver/displayserver_nosupport.c b/src/detection/displayserver/displayserver_nosupport.c index 8427c7cb2..359ebc634 100644 --- a/src/detection/displayserver/displayserver_nosupport.c +++ b/src/detection/displayserver/displayserver_nosupport.c @@ -10,5 +10,5 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* ins ffStrbufInitA(&ds->deProcessName, 0); ffStrbufInitA(&ds->dePrettyName, 0); ffStrbufInitA(&ds->deVersion, 0); - ffListInitA(&ds->resolutions, sizeof(FFResolutionResult), 0); + ffListInitA(&ds->displays, sizeof(FFDisplayResult), 0); } diff --git a/src/detection/displayserver/displayserver_windows.c b/src/detection/displayserver/displayserver_windows.c index f39955b8b..439672571 100644 --- a/src/detection/displayserver/displayserver_windows.c +++ b/src/detection/displayserver/displayserver_windows.c @@ -23,7 +23,7 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* ins ffStrbufInit(&ds->deProcessName); ffStrbufInit(&ds->dePrettyName); ffStrbufInit(&ds->deVersion); - ffListInit(&ds->resolutions, sizeof(FFResolutionResult)); + ffListInit(&ds->displays, sizeof(FFDisplayResult)); DISPLAY_DEVICEW displayDevice = { .cb = sizeof(DISPLAY_DEVICEW) }; for(DWORD devNum = 0; EnumDisplayDevicesW(NULL, devNum, &displayDevice, 0) != 0; ++devNum) @@ -34,7 +34,7 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* ins if(EnumDisplaySettingsW(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &devMode) == 0) continue; - ffdsAppendResolution(ds, devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmDisplayFrequency); + ffdsAppendDisplay(ds, devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmDisplayFrequency); } //https://github.com/hykilpikonna/hyfetch/blob/master/neofetch#L2067 diff --git a/src/detection/displayserver/linux/displayserver_linux.c b/src/detection/displayserver/linux/displayserver_linux.c index 526670c9d..97d7f3c25 100644 --- a/src/detection/displayserver/linux/displayserver_linux.c +++ b/src/detection/displayserver/linux/displayserver_linux.c @@ -32,14 +32,14 @@ static void parseDRM(FFDisplayServerResult* result) continue; } - FFResolutionResult* resolution = ffListAdd(&result->resolutions); - resolution->width = 0; - resolution->height = 0; - resolution->refreshRate = 0; + FFDisplayResult* display = ffListAdd(&result->displays); + display->width = 0; + display->height = 0; + display->refreshRate = 0; - int scanned = fscanf(modeFile, "%ux%u", &resolution->width, &resolution->height); - if(scanned < 2 || resolution->width == 0 || resolution->height == 0) - --result->resolutions.length; + int scanned = fscanf(modeFile, "%ux%u", &display->width, &display->height); + if(scanned < 2 || display->width == 0 || display->height == 0) + --result->displays.length; fclose(modeFile); ffStrbufSubstrBefore(&drmDir, drmDirLength); @@ -57,31 +57,31 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* ins ffStrbufInit(&ds->deProcessName); ffStrbufInit(&ds->dePrettyName); ffStrbufInit(&ds->deVersion); - ffListInitA(&ds->resolutions, sizeof(FFResolutionResult), 4); + ffListInitA(&ds->displays, sizeof(FFDisplayResult), 4); //We try wayland as our prefered display server, as it supports the most features. //This method can't detect the name of our WM / DE ffdsConnectWayland(instance, ds); //Try the x11 libs, from most feature rich to least. - //We use the resolution list to detect if a connection is needed. - //They respect wmProtocolName, and only detect resolution if it is set. + //We use the display list to detect if a connection is needed. + //They respect wmProtocolName, and only detect display if it is set. - if(ds->resolutions.length == 0) + if(ds->displays.length == 0) ffdsConnectXcbRandr(instance, ds); - if(ds->resolutions.length == 0) + if(ds->displays.length == 0) ffdsConnectXrandr(instance, ds); - if(ds->resolutions.length == 0) + if(ds->displays.length == 0) ffdsConnectXcb(instance, ds); - if(ds->resolutions.length == 0) + if(ds->displays.length == 0) ffdsConnectXlib(instance, ds); - //This resolution detection method is display server independent. + //This display detection method is display server independent. //Use it if all connections failed - if(ds->resolutions.length == 0) + if(ds->displays.length == 0) parseDRM(ds); //This fills in missing information about WM / DE by using env vars and iterating processes diff --git a/src/detection/displayserver/linux/wayland.c b/src/detection/displayserver/linux/wayland.c index 37891149c..f95c82c6b 100644 --- a/src/detection/displayserver/linux/wayland.c +++ b/src/detection/displayserver/linux/wayland.c @@ -59,7 +59,7 @@ static void waylandOutputModeListener(void* data, struct wl_output* output, uint static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER; ffThreadMutexLock(&mutex); - FFResolutionResult* result = ffListAdd(wldata->results); + FFDisplayResult* result = ffListAdd(wldata->results); ffThreadMutexUnlock(&mutex); @@ -136,7 +136,7 @@ bool detectWayland(const FFinstance* instance, FFDisplayServerResult* result) return false; } - data.results = &result->resolutions; + data.results = &result->displays; struct wl_registry_listener registry_listener = { .global = waylandGlobalAddListener, @@ -151,7 +151,7 @@ bool detectWayland(const FFinstance* instance, FFDisplayServerResult* result) ffwl_display_disconnect(display); dlclose(wayland); - //We successfully connected to wayland and detected the resolution. + //We successfully connected to wayland and detected the display. //So we can set set the session type to wayland. //This is used as an indicator that we are running wayland by the x11 backends. ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_WAYLAND); diff --git a/src/detection/displayserver/linux/xcb.c b/src/detection/displayserver/linux/xcb.c index 692be7808..44b168a65 100644 --- a/src/detection/displayserver/linux/xcb.c +++ b/src/detection/displayserver/linux/xcb.c @@ -115,7 +115,7 @@ void ffdsConnectXcb(const FFinstance* instance, FFDisplayServerResult* result) while(iterator.rem > 0) { - ffdsAppendResolution( + ffdsAppendDisplay( result, (uint32_t) iterator.data->width_in_pixels, (uint32_t) iterator.data->height_in_pixels, @@ -180,7 +180,7 @@ static bool xcbRandrHandleModeInfo(XcbRandrData* data, xcb_randr_mode_info_t* mo modeInfo->dot_clock / (uint32_t) (modeInfo->htotal * modeInfo->vtotal) )); - return ffdsAppendResolution( + return ffdsAppendDisplay( data->result, (uint32_t) modeInfo->width, (uint32_t) modeInfo->height, @@ -190,7 +190,7 @@ static bool xcbRandrHandleModeInfo(XcbRandrData* data, xcb_randr_mode_info_t* mo static bool xcbRandrHandleMode(XcbRandrData* data, xcb_randr_mode_t mode) { - //We do the check here, because we want the best fallback resolution if this call failed + //We do the check here, because we want the best fallback display if this call failed if(data->screenResources == NULL) return false; @@ -215,7 +215,7 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc) return false; bool res = xcbRandrHandleMode(data, crtcInfoReply->mode); - res = res ? true : ffdsAppendResolution( + res = res ? true : ffdsAppendDisplay( data->result, (uint32_t) crtcInfoReply->width, (uint32_t) crtcInfoReply->height, @@ -258,7 +258,7 @@ static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t* data->ffxcb_randr_output_next(&outputIterator); }; - return foundOutput ? true : ffdsAppendResolution( + return foundOutput ? true : ffdsAppendDisplay( data->result, (uint32_t) monitor->width, (uint32_t) monitor->height, @@ -316,7 +316,7 @@ static void xcbRandrHandleScreen(XcbRandrData* data, xcb_screen_t* screen) return; //If detetction failed, fallback to screen = monitor, like in the libxcb.so implementation - ffdsAppendResolution( + ffdsAppendDisplay( data->result, (uint32_t) screen->width_in_pixels, (uint32_t) screen->height_in_pixels, diff --git a/src/detection/displayserver/linux/xlib.c b/src/detection/displayserver/linux/xlib.c index 108de5946..ef6d76b75 100644 --- a/src/detection/displayserver/linux/xlib.c +++ b/src/detection/displayserver/linux/xlib.c @@ -79,7 +79,7 @@ void ffdsConnectXlib(const FFinstance* instance, FFDisplayServerResult* result) for(int i = 0; i < ScreenCount(display); i++) { Screen* screen = ScreenOfDisplay(display, i); - ffdsAppendResolution( + ffdsAppendDisplay( result, (uint32_t) screen->width, (uint32_t) screen->height, @@ -138,7 +138,7 @@ static bool xrandrHandleModeInfo(XrandrData* data, XRRModeInfo* modeInfo) modeInfo->dotClock / (modeInfo->hTotal * modeInfo->vTotal) )); - return ffdsAppendResolution( + return ffdsAppendDisplay( data->result, (uint32_t) modeInfo->width, (uint32_t) modeInfo->height, @@ -158,7 +158,7 @@ static bool xrandrHandleMode(XrandrData* data, RRMode mode) static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc) { - //We do the check here, because we want the best fallback resolution if this call failed + //We do the check here, because we want the best fallback display if this call failed if(data->screenResources == NULL) return false; @@ -167,7 +167,7 @@ static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc) return false; bool res = xrandrHandleMode(data, crtcInfo->mode); - res = res ? true : ffdsAppendResolution( + res = res ? true : ffdsAppendDisplay( data->result, (uint32_t) crtcInfo->width, (uint32_t) crtcInfo->height, @@ -201,7 +201,7 @@ static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo) foundOutput = true; } - return foundOutput ? true : ffdsAppendResolution( + return foundOutput ? true : ffdsAppendDisplay( data->result, (uint32_t) monitorInfo->width, (uint32_t) monitorInfo->height, @@ -253,7 +253,7 @@ static void xrandrHandleScreen(XrandrData* data, Screen* screen) return; //Fallback to screen - ffdsAppendResolution( + ffdsAppendDisplay( data->result, (uint32_t) WidthOfScreen(screen), (uint32_t) HeightOfScreen(screen), diff --git a/src/fastfetch.c b/src/fastfetch.c index d31fbf7e2..37d473ee7 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -174,9 +174,9 @@ static inline void printCommandHelp(const char* command) "User shell version" ); } - else if(strcasecmp(command, "resolution-format") == 0) + else if(strcasecmp(command, "display-format") == 0) { - constructAndPrintCommandHelpFormat("resolution", "{}x{} @ {}Hz", 4, + constructAndPrintCommandHelpFormat("display", "{}x{} @ {}Hz", 4, "Screen width", "Screen height", "Screen refresh rate", @@ -1147,7 +1147,7 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con else if(optionParseModuleArgs(key, value, "processes", &instance->config.processes)) {} else if(optionParseModuleArgs(key, value, "packages", &instance->config.packages)) {} else if(optionParseModuleArgs(key, value, "shell", &instance->config.shell)) {} - else if(optionParseModuleArgs(key, value, "resolution", &instance->config.resolution)) {} + else if(optionParseModuleArgs(key, value, "display", &instance->config.display)) {} else if(optionParseModuleArgs(key, value, "brightness", &instance->config.brightness)) {} else if(optionParseModuleArgs(key, value, "de", &instance->config.de)) {} else if(optionParseModuleArgs(key, value, "wifi", &instance->config.wifi)) {} @@ -1407,8 +1407,8 @@ static void parseStructureCommand(FFinstance* instance, FFdata* data, const char ffPrintPackages(instance); else if(strcasecmp(line, "shell") == 0) ffPrintShell(instance); - else if(strcasecmp(line, "resolution") == 0) - ffPrintResolution(instance); + else if(strcasecmp(line, "display") == 0) + ffPrintDisplay(instance); else if(strcasecmp(line, "desktopenvironment") == 0 || strcasecmp(line, "de") == 0) ffPrintDesktopEnvironment(instance); else if(strcasecmp(line, "windowmanager") == 0 || strcasecmp(line, "wm") == 0) diff --git a/src/fastfetch.h b/src/fastfetch.h index 2f3b20753..69121e4c9 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -107,7 +107,7 @@ typedef struct FFconfig FFModuleArgs processes; FFModuleArgs packages; FFModuleArgs shell; - FFModuleArgs resolution; + FFModuleArgs display; FFModuleArgs de; FFModuleArgs wifi; FFModuleArgs wm; @@ -275,7 +275,7 @@ void ffPrintUptime(FFinstance* instance); void ffPrintProcesses(FFinstance* instance); void ffPrintPackages(FFinstance* instance); void ffPrintShell(FFinstance* instance); -void ffPrintResolution(FFinstance* instance); +void ffPrintDisplay(FFinstance* instance); void ffPrintBrightness(FFinstance* instance); void ffPrintDesktopEnvironment(FFinstance* instance); void ffPrintWM(FFinstance* instance); diff --git a/src/flashfetch.c b/src/flashfetch.c index 86729ace6..0c24732e3 100644 --- a/src/flashfetch.c +++ b/src/flashfetch.c @@ -30,7 +30,7 @@ int main(int argc, char** argv) //ffPrintProcesses(&instance); ffPrintPackages(&instance); ffPrintShell(&instance); - ffPrintResolution(&instance); + ffPrintDisplay(&instance); // ffPrintBrightness(&instance); ffPrintDesktopEnvironment(&instance); ffPrintWM(&instance); diff --git a/src/modules/resolution.c b/src/modules/display.c similarity index 58% rename from src/modules/resolution.c rename to src/modules/display.c index 396d435b1..beed373ba 100644 --- a/src/modules/resolution.c +++ b/src/modules/display.c @@ -2,26 +2,26 @@ #include "common/printing.h" #include "detection/displayserver/displayserver.h" -#define FF_RESOLUTION_MODULE_NAME "Resolution" +#define FF_RESOLUTION_MODULE_NAME "Display" #define FF_RESOLUTION_NUM_FORMAT_ARGS 3 -void ffPrintResolution(FFinstance* instance) +void ffPrintDisplay(FFinstance* instance) { #ifdef __ANDROID__ - ffPrintError(instance, FF_RESOLUTION_MODULE_NAME, 0, &instance->config.resolution, "Resolution detection is not supported on Android"); + ffPrintError(instance, FF_RESOLUTION_MODULE_NAME, 0, &instance->config.display, "Display detection is not supported on Android"); return; #endif const FFDisplayServerResult* dsResult = ffConnectDisplayServer(instance); - for(uint32_t i = 0; i < dsResult->resolutions.length; i++) + for(uint32_t i = 0; i < dsResult->displays.length; i++) { - FFResolutionResult* result = ffListGet(&dsResult->resolutions, i); - uint8_t moduleIndex = dsResult->resolutions.length == 1 ? 0 : (uint8_t) (i + 1); + FFDisplayResult* result = ffListGet(&dsResult->displays, i); + uint8_t moduleIndex = dsResult->displays.length == 1 ? 0 : (uint8_t) (i + 1); - if(instance->config.resolution.outputFormat.length == 0) + if(instance->config.display.outputFormat.length == 0) { - ffPrintLogoAndKey(instance, FF_RESOLUTION_MODULE_NAME, moduleIndex, &instance->config.resolution.key); + ffPrintLogoAndKey(instance, FF_RESOLUTION_MODULE_NAME, moduleIndex, &instance->config.display.key); printf("%ix%i", result->width, result->height); if(result->refreshRate > 0) @@ -31,7 +31,7 @@ void ffPrintResolution(FFinstance* instance) } else { - ffPrintFormat(instance, FF_RESOLUTION_MODULE_NAME, moduleIndex, &instance->config.resolution, FF_RESOLUTION_NUM_FORMAT_ARGS, (FFformatarg[]) { + ffPrintFormat(instance, FF_RESOLUTION_MODULE_NAME, moduleIndex, &instance->config.display, FF_RESOLUTION_NUM_FORMAT_ARGS, (FFformatarg[]) { {FF_FORMAT_ARG_TYPE_INT, &result->width}, {FF_FORMAT_ARG_TYPE_INT, &result->height}, {FF_FORMAT_ARG_TYPE_INT, &result->refreshRate} @@ -39,6 +39,6 @@ void ffPrintResolution(FFinstance* instance) } } - if(dsResult->resolutions.length == 0) - ffPrintError(instance, FF_RESOLUTION_MODULE_NAME, 0, &instance->config.resolution, "Couldn't detect resolution"); + if(dsResult->displays.length == 0) + ffPrintError(instance, FF_RESOLUTION_MODULE_NAME, 0, &instance->config.display, "Couldn't detect display"); } From 58999995f1fc0cb675a0abb371157c9b9f7d7119 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 17 Jan 2023 19:09:18 +0800 Subject: [PATCH 119/142] Display: split phycial resolution and scaled resolution --- src/detection/displayserver/displayserver.c | 4 +++- src/detection/displayserver/displayserver.h | 4 +++- .../displayserver/displayserver_apple.c | 6 ++++-- .../displayserver/displayserver_windows.c | 2 +- .../displayserver/linux/displayserver_linux.c | 2 ++ src/detection/displayserver/linux/wayland.c | 2 ++ src/detection/displayserver/linux/xcb.c | 18 ++++++++++++++---- src/detection/displayserver/linux/xlib.c | 18 ++++++++++++++---- src/modules/display.c | 5 +++++ 9 files changed, 48 insertions(+), 13 deletions(-) diff --git a/src/detection/displayserver/displayserver.c b/src/detection/displayserver/displayserver.c index e7ab5c49e..3bc47c345 100644 --- a/src/detection/displayserver/displayserver.c +++ b/src/detection/displayserver/displayserver.c @@ -19,7 +19,7 @@ uint32_t ffdsParseRefreshRate(int32_t refreshRate) return (uint32_t) refreshRate; } -bool ffdsAppendDisplay(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate) +bool ffdsAppendDisplay(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate, uint32_t scaledWidth, uint32_t scaledHeight) { if(width == 0 || height == 0) return false; @@ -28,6 +28,8 @@ bool ffdsAppendDisplay(FFDisplayServerResult* result, uint32_t width, uint32_t h display->width = width; display->height = height; display->refreshRate = refreshRate; + display->scaledWidth = scaledWidth; + display->scaledHeight = scaledHeight; return true; } diff --git a/src/detection/displayserver/displayserver.h b/src/detection/displayserver/displayserver.h index d100520b5..17fef3ba5 100644 --- a/src/detection/displayserver/displayserver.h +++ b/src/detection/displayserver/displayserver.h @@ -10,6 +10,8 @@ typedef struct FFDisplayResult uint32_t width; uint32_t height; uint32_t refreshRate; + uint32_t scaledWidth; + uint32_t scaledHeight; } FFDisplayResult; typedef struct FFDisplayServerResult @@ -27,6 +29,6 @@ const FFDisplayServerResult* ffConnectDisplayServer(const FFinstance* instance); //Used internal uint32_t ffdsParseRefreshRate(int32_t refreshRate); -bool ffdsAppendDisplay(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate); +bool ffdsAppendDisplay(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate, uint32_t scaledWidth, uint32_t scaledHeight); #endif diff --git a/src/detection/displayserver/displayserver_apple.c b/src/detection/displayserver/displayserver_apple.c index 782453de9..065e218b7 100644 --- a/src/detection/displayserver/displayserver_apple.c +++ b/src/detection/displayserver/displayserver_apple.c @@ -21,9 +21,11 @@ static void detectDisplays(FFDisplayServerResult* ds) if(mode) { ffdsAppendDisplay(ds, + (uint32_t)CGDisplayModeGetPixelWidth(mode), + (uint32_t)CGDisplayModeGetPixelHeight(mode), + (uint32_t)CGDisplayModeGetRefreshRate(mode), (uint32_t)CGDisplayModeGetWidth(mode), - (uint32_t)CGDisplayModeGetHeight(mode), - (uint32_t)CGDisplayModeGetRefreshRate(mode) + (uint32_t)CGDisplayModeGetHeight(mode) ); CGDisplayModeRelease(mode); } diff --git a/src/detection/displayserver/displayserver_windows.c b/src/detection/displayserver/displayserver_windows.c index 439672571..eb19469e8 100644 --- a/src/detection/displayserver/displayserver_windows.c +++ b/src/detection/displayserver/displayserver_windows.c @@ -34,7 +34,7 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* ins if(EnumDisplaySettingsW(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &devMode) == 0) continue; - ffdsAppendDisplay(ds, devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmDisplayFrequency); + ffdsAppendDisplay(ds, devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmDisplayFrequency, 0, 0); } //https://github.com/hykilpikonna/hyfetch/blob/master/neofetch#L2067 diff --git a/src/detection/displayserver/linux/displayserver_linux.c b/src/detection/displayserver/linux/displayserver_linux.c index 97d7f3c25..257c60cc1 100644 --- a/src/detection/displayserver/linux/displayserver_linux.c +++ b/src/detection/displayserver/linux/displayserver_linux.c @@ -36,6 +36,8 @@ static void parseDRM(FFDisplayServerResult* result) display->width = 0; display->height = 0; display->refreshRate = 0; + display->scaledWidth = 0; + display->scaledHeight = 0; int scanned = fscanf(modeFile, "%ux%u", &display->width, &display->height); if(scanned < 2 || display->width == 0 || display->height == 0) diff --git a/src/detection/displayserver/linux/wayland.c b/src/detection/displayserver/linux/wayland.c index f95c82c6b..27a5c09d3 100644 --- a/src/detection/displayserver/linux/wayland.c +++ b/src/detection/displayserver/linux/wayland.c @@ -66,6 +66,8 @@ static void waylandOutputModeListener(void* data, struct wl_output* output, uint result->width = (uint32_t) width; result->height = (uint32_t) height; result->refreshRate = ffdsParseRefreshRate(refreshRate / 1000); + result->scaledWidth = 0; + result->scaledHeight = 0; } static void waylandGlobalAddListener(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version) diff --git a/src/detection/displayserver/linux/xcb.c b/src/detection/displayserver/linux/xcb.c index 44b168a65..99a960894 100644 --- a/src/detection/displayserver/linux/xcb.c +++ b/src/detection/displayserver/linux/xcb.c @@ -119,6 +119,8 @@ void ffdsConnectXcb(const FFinstance* instance, FFDisplayServerResult* result) result, (uint32_t) iterator.data->width_in_pixels, (uint32_t) iterator.data->height_in_pixels, + 0, + 0, 0 ); ffxcb_screen_next(&iterator); @@ -184,7 +186,9 @@ static bool xcbRandrHandleModeInfo(XcbRandrData* data, xcb_randr_mode_info_t* mo data->result, (uint32_t) modeInfo->width, (uint32_t) modeInfo->height, - refreshRate == 0 ? data->defaultRefreshRate : refreshRate + refreshRate == 0 ? data->defaultRefreshRate : refreshRate, + 0, + 0 ); } @@ -219,7 +223,9 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc) data->result, (uint32_t) crtcInfoReply->width, (uint32_t) crtcInfoReply->height, - data->defaultRefreshRate + data->defaultRefreshRate, + 0, + 0 ); free(crtcInfoReply); @@ -262,7 +268,9 @@ static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t* data->result, (uint32_t) monitor->width, (uint32_t) monitor->height, - data->defaultRefreshRate + data->defaultRefreshRate, + 0, + 0 ); } @@ -320,7 +328,9 @@ static void xcbRandrHandleScreen(XcbRandrData* data, xcb_screen_t* screen) data->result, (uint32_t) screen->width_in_pixels, (uint32_t) screen->height_in_pixels, - data->defaultRefreshRate + data->defaultRefreshRate, + 0, + 0 ); } diff --git a/src/detection/displayserver/linux/xlib.c b/src/detection/displayserver/linux/xlib.c index ef6d76b75..12f87587c 100644 --- a/src/detection/displayserver/linux/xlib.c +++ b/src/detection/displayserver/linux/xlib.c @@ -83,6 +83,8 @@ void ffdsConnectXlib(const FFinstance* instance, FFDisplayServerResult* result) result, (uint32_t) screen->width, (uint32_t) screen->height, + 0, + 0, 0 ); } @@ -142,7 +144,9 @@ static bool xrandrHandleModeInfo(XrandrData* data, XRRModeInfo* modeInfo) data->result, (uint32_t) modeInfo->width, (uint32_t) modeInfo->height, - refreshRate == 0 ? data->defaultRefreshRate : refreshRate + refreshRate == 0 ? data->defaultRefreshRate : refreshRate, + 0, + 0 ); } @@ -171,7 +175,9 @@ static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc) data->result, (uint32_t) crtcInfo->width, (uint32_t) crtcInfo->height, - data->defaultRefreshRate + data->defaultRefreshRate, + 0, + 0 ); data->ffXRRFreeCrtcInfo(crtcInfo); @@ -205,7 +211,9 @@ static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo) data->result, (uint32_t) monitorInfo->width, (uint32_t) monitorInfo->height, - data->defaultRefreshRate + data->defaultRefreshRate, + 0, + 0 ); } @@ -257,7 +265,9 @@ static void xrandrHandleScreen(XrandrData* data, Screen* screen) data->result, (uint32_t) WidthOfScreen(screen), (uint32_t) HeightOfScreen(screen), - data->defaultRefreshRate + data->defaultRefreshRate, + 0, + 0 ); } diff --git a/src/modules/display.c b/src/modules/display.c index beed373ba..89496816b 100644 --- a/src/modules/display.c +++ b/src/modules/display.c @@ -27,6 +27,11 @@ void ffPrintDisplay(FFinstance* instance) if(result->refreshRate > 0) printf(" @ %iHz", result->refreshRate); + if( + result->scaledWidth > 0 && result->scaledWidth != result->width && + result->scaledHeight > 0 && result->scaledHeight != result->height) + printf(" (as %ix%i)", result->scaledWidth, result->scaledHeight); + putchar('\n'); } else From fdb0cfb4df8bab740b0f6250c50eca810be73cc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 17 Jan 2023 21:36:43 +0800 Subject: [PATCH 120/142] Display: detect scaled resolution (Windows) --- .../displayserver/displayserver_windows.c | 28 ++++++++++++++++++- src/util/windows/manifest.xml | 2 +- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/detection/displayserver/displayserver_windows.c b/src/detection/displayserver/displayserver_windows.c index eb19469e8..30c1def54 100644 --- a/src/detection/displayserver/displayserver_windows.c +++ b/src/detection/displayserver/displayserver_windows.c @@ -4,6 +4,26 @@ #include #include +typedef struct +{ + WCHAR* deviceName; + uint32_t width; + uint32_t height; +} DataBundle; + +static WINBOOL enumMonitorProc(HMONITOR hMonitor, FF_MAYBE_UNUSED HDC hDC, FF_MAYBE_UNUSED LPRECT rc, LPARAM lparam) +{ + MONITORINFOEXW mi = { .cbSize = sizeof(mi) }; + DataBundle* data = (DataBundle*) lparam; + if(GetMonitorInfoW(hMonitor, (MONITORINFO *)&mi) && wcscmp(mi.szDevice, data->deviceName) == 0) + { + data->width = (uint32_t) mi.rcMonitor.right; + data->height = (uint32_t) mi.rcMonitor.bottom; + return FALSE; + } + return TRUE; +} + void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* instance) { FF_UNUSED(instance); @@ -34,7 +54,13 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* ins if(EnumDisplaySettingsW(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &devMode) == 0) continue; - ffdsAppendDisplay(ds, devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmDisplayFrequency, 0, 0); + DataBundle data = { + .deviceName = displayDevice.DeviceName, + .width = 0, + .height = 0, + }; + EnumDisplayMonitors(NULL, NULL, enumMonitorProc, (LPARAM)&data); + ffdsAppendDisplay(ds, devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmDisplayFrequency, data.width, data.height); } //https://github.com/hykilpikonna/hyfetch/blob/master/neofetch#L2067 diff --git a/src/util/windows/manifest.xml b/src/util/windows/manifest.xml index 420545ded..86d623144 100644 --- a/src/util/windows/manifest.xml +++ b/src/util/windows/manifest.xml @@ -16,7 +16,7 @@ UTF-8 - true + false SegmentHeap From 6e904047f9f42cf8bdafc0301a5a19447e40fe65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 17 Jan 2023 23:07:20 +0800 Subject: [PATCH 121/142] Display: document scaled resolution support --- CHANGELOG.md | 1 + src/modules/display.c | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 53f43d5ba..0b81f8fca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ Features: * Add `--shell-version` and `--terminal-version` options to disable shell / terminal version detection * Enhance `--percent-type` to allow hiding other texts (#387) * Add Wifi module support for Linux +* Detect scaled resolutions (Windows, macOS) Logos: * Raspbian (@IamNoRobot, #373) diff --git a/src/modules/display.c b/src/modules/display.c index 89496816b..45d93234b 100644 --- a/src/modules/display.c +++ b/src/modules/display.c @@ -37,9 +37,11 @@ void ffPrintDisplay(FFinstance* instance) else { ffPrintFormat(instance, FF_RESOLUTION_MODULE_NAME, moduleIndex, &instance->config.display, FF_RESOLUTION_NUM_FORMAT_ARGS, (FFformatarg[]) { - {FF_FORMAT_ARG_TYPE_INT, &result->width}, - {FF_FORMAT_ARG_TYPE_INT, &result->height}, - {FF_FORMAT_ARG_TYPE_INT, &result->refreshRate} + {FF_FORMAT_ARG_TYPE_UINT, &result->width}, + {FF_FORMAT_ARG_TYPE_UINT, &result->height}, + {FF_FORMAT_ARG_TYPE_UINT, &result->refreshRate}, + {FF_FORMAT_ARG_TYPE_UINT, &result->scaledWidth}, + {FF_FORMAT_ARG_TYPE_UINT, &result->scaledHeight} }); } } From 5edab414d84a13cb311d9340151e8233c1234ede Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Tue, 17 Jan 2023 17:49:41 +0100 Subject: [PATCH 122/142] Cursor: prefer gtk over Xresources #382 --- src/detection/cursor/cursor_linux.c | 71 ++++++----------------------- 1 file changed, 15 insertions(+), 56 deletions(-) diff --git a/src/detection/cursor/cursor_linux.c b/src/detection/cursor/cursor_linux.c index 09db53ed4..63507e803 100644 --- a/src/detection/cursor/cursor_linux.c +++ b/src/detection/cursor/cursor_linux.c @@ -8,7 +8,7 @@ #include -static void detectCursorGTK(const FFinstance* instance, FFCursorResult* result) +static bool detectCursorGTK(const FFinstance* instance, FFCursorResult* result) { const FFGTKResult* gtk = ffDetectGTK4(instance); @@ -19,25 +19,11 @@ static void detectCursorGTK(const FFinstance* instance, FFCursorResult* result) gtk = ffDetectGTK2(instance); if(gtk->cursor.length == 0) - { - ffStrbufAppendS(&result->error, "Couldn't detect GTK Cursor"); - return; - } + return false; ffStrbufAppend(&result->theme, >k->cursor); ffStrbufAppend(&result->size, >k->cursorSize); -} - -static void detectCursorXFCE(const FFinstance* instance, FFCursorResult* result) -{ - ffStrbufAppendS(&result->theme, ffSettingsGetXFConf(instance, "xsettings", "/Gtk/CursorThemeName", FF_VARIANT_TYPE_STRING).strValue); - - if(result->theme.length == 0) - ffStrbufAppendS(&result->error, "Couldn't find xfce cursor in xfconf (xsettings::/Gtk/CursorThemeName)"); - - int cursorSizeVal = ffSettingsGetXFConf(instance, "xsettings", "/Gtk/CursorThemeSize", FF_VARIANT_TYPE_INT).intValue; - if(cursorSizeVal > 0) - ffStrbufAppendF(&result->size, "%i", cursorSizeVal); + return true; } static void detectCursorFromConfigFile(const FFinstance* instance, const char* relativeFilePath, const char* themeStart, const char* themeDefault, const char* sizeStart, const char* sizeDefault, FFCursorResult* result) @@ -68,16 +54,6 @@ static bool detectCursorFromXResources(const FFinstance* instance, FFCursorResul return result->theme.length > 0; } -static bool detectCursorFromXDG(const FFinstance* instance, bool user, FFCursorResult* result) -{ - if(user) - ffParsePropFileHome(instance, ".icons/default/index.theme", "Inherits =", &result->theme); - else - ffParsePropFileData(instance, "icons/default/index.theme", "Inherits =", &result->theme); - - return result->theme.length > 0; -} - static bool detectCursorFromEnv(const FFinstance* instance, FFCursorResult* result) { FF_UNUSED(instance); @@ -97,35 +73,18 @@ void ffDetectCursor(const FFinstance* instance, FFCursorResult* result) const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance); if(ffStrbufCompS(&wmde->wmPrettyName, "WSLg") == 0) - { ffStrbufAppendS(&result->error, "WSLg uses native windows cursor"); - return; - } - - if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, "TTY") == 0) - { + else if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, "TTY") == 0) ffStrbufAppendS(&result->error, "Cursor isn't supported in TTY"); - return; - } - - if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "KDE Plasma") == 0) - return detectCursorFromConfigFile(instance, "kcminputrc", "cursorTheme =", "Breeze", "cursorSize =", "24", result); - - if(ffStrbufStartsWithIgnCaseS(&wmde->dePrettyName, "XFCE")) - return detectCursorXFCE(instance, result); - - if(ffStrbufStartsWithIgnCaseS(&wmde->dePrettyName, "LXQt")) - return detectCursorFromConfigFile(instance, "lxqt/session.conf", "cursor_theme =", "Adwaita", "cursor_size =", "24", result); - - if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Gnome") == 0 || ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Cinnamon") == 0 || ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Mate") == 0) - return detectCursorGTK(instance, result); - - if( - detectCursorFromEnv(instance, result) || - detectCursorFromXDG(instance, true, result) || - detectCursorFromXResources(instance, result) || - detectCursorFromXDG(instance, false, result) - ) return; - - detectCursorGTK(instance, result); + else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "KDE Plasma") == 0) + detectCursorFromConfigFile(instance, "kcminputrc", "cursorTheme =", "Breeze", "cursorSize =", "24", result); + else if(ffStrbufStartsWithIgnCaseS(&wmde->dePrettyName, "LXQt")) + detectCursorFromConfigFile(instance, "lxqt/session.conf", "cursor_theme =", "Adwaita", "cursor_size =", "24", result); + else if( + !detectCursorGTK(instance, result) && + !detectCursorFromEnv(instance, result) && + !ffParsePropFileHome(instance, ".icons/default/index.theme", "Inherits =", &result->theme) && + !detectCursorFromXResources(instance, result) && + !ffParsePropFileData(instance, "icons/default/index.theme", "Inherits =", &result->theme) + ) ffStrbufAppendS(&result->error, "Couldn't find cursor"); } From 10b997608b6c9917c11bacaf82db1a2a53234276 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 18 Jan 2023 18:01:09 +0800 Subject: [PATCH 123/142] Font: optimise output for Windows --- CHANGELOG.md | 1 + src/modules/font.c | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b81f8fca..d55e32538 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ Features: * Enhance `--percent-type` to allow hiding other texts (#387) * Add Wifi module support for Linux * Detect scaled resolutions (Windows, macOS) +* Optimise font module printing (Windows) Logos: * Raspbian (@IamNoRobot, #373) diff --git a/src/modules/font.c b/src/modules/font.c index 25f394f61..0b2e05e16 100644 --- a/src/modules/font.c +++ b/src/modules/font.c @@ -48,12 +48,18 @@ static void printFont(const FFFontResult* font) const char* types[] = { "Caption", "Menu", "Message", "Status" }; for(uint32_t i = 0; i < sizeof(types) / sizeof(types[0]); ++i) { - if(font->fonts[i].length > 0) + if(i == 0 || !ffStrbufEqual(&font->fonts[i - 1], &font->fonts[i])) { - printf("%s [%s]", font->fonts[i].chars, types[i]); - break; + if(i > 0) + fputs("], ", stdout); + printf("%s [%s", font->fonts[i].chars, types[i]); + } + else + { + printf(" / %s", types[i]); } } + putchar(']'); } #else From 4ce618c33c1db4675429c804f801a3c3c10453f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 18 Jan 2023 22:44:24 +0800 Subject: [PATCH 124/142] DisplayServer: fix win32 compatibility --- src/detection/displayserver/displayserver_windows.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/displayserver/displayserver_windows.c b/src/detection/displayserver/displayserver_windows.c index 30c1def54..ba5f4e8b4 100644 --- a/src/detection/displayserver/displayserver_windows.c +++ b/src/detection/displayserver/displayserver_windows.c @@ -11,7 +11,7 @@ typedef struct uint32_t height; } DataBundle; -static WINBOOL enumMonitorProc(HMONITOR hMonitor, FF_MAYBE_UNUSED HDC hDC, FF_MAYBE_UNUSED LPRECT rc, LPARAM lparam) +static CALLBACK WINBOOL enumMonitorProc(HMONITOR hMonitor, FF_MAYBE_UNUSED HDC hDC, FF_MAYBE_UNUSED LPRECT rc, LPARAM lparam) { MONITORINFOEXW mi = { .cbSize = sizeof(mi) }; DataBundle* data = (DataBundle*) lparam; From 068cbafe3dfe847fa0c533d5b126f2ea30861418 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 18 Jan 2023 23:08:53 +0800 Subject: [PATCH 125/142] Packages: detect pacman package count inside MSYS2 env (Windows) --- CHANGELOG.md | 1 + src/detection/packages/packages_windows.c | 24 +++++++++++++++++------ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d55e32538..1d35baf7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ Features: * Add Wifi module support for Linux * Detect scaled resolutions (Windows, macOS) * Optimise font module printing (Windows) +* Detect pacman package count inside MSYS2 environment (Windows) Logos: * Raspbian (@IamNoRobot, #373) diff --git a/src/detection/packages/packages_windows.c b/src/detection/packages/packages_windows.c index fa50bdd5b..afd016c6d 100644 --- a/src/detection/packages/packages_windows.c +++ b/src/detection/packages/packages_windows.c @@ -17,10 +17,10 @@ static uint32_t getNumElements(const char* searchPath /* including `\*` suffix * counter++; } while (FindNextFileA(hFind, &wfd)); FindClose(hFind); - } - if(type == FILE_ATTRIBUTE_DIRECTORY && counter >= 2) - counter -= 2; // accounting for . and .. + if(type == FILE_ATTRIBUTE_DIRECTORY && counter >= 2) + counter -= 2; // accounting for . and .. + } return counter; } @@ -35,10 +35,8 @@ static void detectScoop(const FFinstance* instance, FFPackagesResult* result) result->scoop--; // scoop } -static void detectChoco(const FFinstance* instance, FFPackagesResult* result) +static void detectChoco(FF_MAYBE_UNUSED const FFinstance* instance, FFPackagesResult* result) { - FF_UNUSED(instance); - const char* chocoInstall = getenv("ChocolateyInstall"); if(!chocoInstall || chocoInstall[0] == '\0') return; @@ -51,8 +49,22 @@ static void detectChoco(const FFinstance* instance, FFPackagesResult* result) result->choco--; // choco } +static void detectPacman(FF_MAYBE_UNUSED const FFinstance* instance, FFPackagesResult* result) +{ + const char* msystemPrefix = getenv("MSYSTEM_PREFIX"); + if(!msystemPrefix) + return; + + // MSYS2 + char pacmanPath[MAX_PATH + 3]; + strcpy(pacmanPath, msystemPrefix); + strncat(pacmanPath, "/../var/lib/pacman/local/*", sizeof(pacmanPath) - 1 - strlen(pacmanPath)); + result->pacman = getNumElements(pacmanPath, FILE_ATTRIBUTE_DIRECTORY); +} + void ffDetectPackagesImpl(const FFinstance* instance, FFPackagesResult* result) { detectScoop(instance, result); detectChoco(instance, result); + detectPacman(instance, result); } From 1e9ec5424a638e30484f55fc9068e70e69eef71d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 20 Jan 2023 16:05:03 +0800 Subject: [PATCH 126/142] Global: add `NO_CONFIG` env variable to disable parsing config files, for debugging purpose. --- src/fastfetch.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/fastfetch.c b/src/fastfetch.c index 37d473ee7..e936237c6 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -1490,7 +1490,8 @@ int main(int argc, const char** argv) ffStrbufInitA(&data.structure, 256); data.loadUserConfig = true; - parseConfigFiles(&instance, &data); + if(!getenv("NO_CONFIG")) + parseConfigFiles(&instance, &data); parseArguments(&instance, &data, argc, argv); //If we don't have a custom structure, use the default one From a71f2142bb6db68503bbddacc3cb7c1a0b0b1bb3 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Fri, 20 Jan 2023 13:28:25 +0100 Subject: [PATCH 127/142] Disk(Linux): Better subvolume detection #396 --- src/detection/disk/disk_linux.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index 1907657d7..8d7fd1ee3 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -29,17 +29,18 @@ static void strbufAppendMountPoint(FFstrbuf* mountpoint, const char* source) } #ifndef __ANDROID__ -static bool isSubvolume(const char* options) +static bool isSubvolume(const FFlist* allDisks, const FFDisk* currentDisk) { - const char* prefix = "subvol=/@"; //Btrfs subvolume - const char* subvolume = strstr(options, prefix); - if(subvolume == NULL) - return false; + FF_LIST_FOR_EACH(FFDisk, disk, *allDisks) + { + if(disk == currentDisk) + continue; - subvolume += strlen(prefix); + if(ffStrbufEqual(&disk->mountpoint, ¤tDisk->mountpoint)) + return true; + } - //If there is no space or comma after the @, it is a btrfs subvolume - return *subvolume != ' ' && *subvolume != ','; + return false; } #endif @@ -104,7 +105,7 @@ void ffDetectDisksImpl(FFDiskResult* disks) else disk->type = FF_DISK_TYPE_HIDDEN; #else - if(isSubvolume(currentPos)) + if(isSubvolume(&disks->disks, disk)) disk->type = FF_DISK_TYPE_SUBVOLUME; else if(strstr(currentPos, "nosuid") != NULL || strstr(currentPos, "nodev") != NULL) disk->type = FF_DISK_TYPE_EXTERNAL; From 6f4bdafb0ce77cdb8c28d864a49659a1d88a115e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 21 Jan 2023 06:18:19 +0800 Subject: [PATCH 128/142] Temp: fix severial issues. Fixes #398 1. Temp detection has been gated behind of `--*-temp`. Don't make it a slow operation 2. According to [the kernel doc](https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface), `temp1_input` is millidegree Celsius, which should be divided by 1000 3. There is no `/sys/class/hwmon/hwmon3/device/class` on my laptop, but `/sys/class/hwmon/hwmon3/device/device/class`. Need to confirm with @LinusDierheimer 4. Small code optimizations --- src/detection/cpu/cpu_linux.c | 4 ++-- src/detection/gpu/gpu_linux.c | 12 ++++-------- src/detection/temps/temps_linux.c | 31 +++++++++++++------------------ src/detection/temps/temps_linux.h | 4 ++-- 4 files changed, 21 insertions(+), 30 deletions(-) diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index 47eaf6dc4..1b2bf28d6 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -67,9 +67,9 @@ static double getFrequency(const char* info, const char* scaling) return getGHz(scaling); } -static double detectCPUTemp(const FFinstance* instance) +static double detectCPUTemp() { - const FFTempsResult* temps = ffDetectTemps(instance); + const FFTempsResult* temps = ffDetectTemps(); for(uint32_t i = 0; i < temps->values.length; i++) { diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 21e71668f..d34807df9 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -146,20 +146,16 @@ static void pciDetectDriverName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* ffStrbufDestroy(&path); } -static void pciDetectTemperatur(const FFinstance* instance, FFGPUResult* gpu, struct pci_dev* device) +static void pciDetectTemperatur(FFGPUResult* gpu, struct pci_dev* device) { - const FFTempsResult* tempsResult = ffDetectTemps(instance); + const FFTempsResult* tempsResult = ffDetectTemps(); for(uint32_t i = 0; i < tempsResult->values.length; i++) { FFTempValue* tempValue = ffListGet(&tempsResult->values, i); - uint32_t tempClass; - if(sscanf(tempValue->deviceClass.chars, "%x", &tempClass) != 1) - continue; - //The kernel exposes the device class multiplied by 256 for some reason - if(tempClass == device->device_class * 256) + if(tempValue->deviceClass == device->device_class * 256) { gpu->temperature = tempValue->value; return; @@ -233,7 +229,7 @@ static void pciHandleDevice(const FFinstance* instance, FFlist* results, PCIData gpu->temperature = FF_GPU_TEMP_UNSET; if(instance->config.gpuTemp) - pciDetectTemperatur(instance, gpu, device); + pciDetectTemperatur(gpu, device); } static const char* pciDetectGPUs(const FFinstance* instance, FFlist* gpus) diff --git a/src/detection/temps/temps_linux.c b/src/detection/temps/temps_linux.c index cb342a9f8..5a1dc2bd4 100644 --- a/src/detection/temps/temps_linux.c +++ b/src/detection/temps/temps_linux.c @@ -8,18 +8,19 @@ static bool parseHwmonDir(FFstrbuf* dir, FFTempValue* value) { + //https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface uint32_t dirLength = dir->length; - FFstrbuf valueBuffer; + FF_STRBUF_AUTO_DESTROY valueBuffer; ffStrbufInit(&valueBuffer); ffStrbufAppendS(dir, "temp1_input"); - ffReadFileBuffer(dir->chars, &valueBuffer); + if(!ffReadFileBuffer(dir->chars, &valueBuffer)) + return false; + ffStrbufSubstrBefore(dir, dirLength); - value->value = ffStrbufToDouble(&valueBuffer); - - ffStrbufDestroy(&valueBuffer); + value->value = ffStrbufToDouble(&valueBuffer) / 1000; // valueBuffer is millidegree Celsius if(value->value != value->value) return false; @@ -28,14 +29,16 @@ static bool parseHwmonDir(FFstrbuf* dir, FFTempValue* value) ffReadFileBuffer(dir->chars, &value->name); ffStrbufSubstrBefore(dir, dirLength); - ffStrbufAppendS(dir, "device/class"); - ffReadFileBuffer(dir->chars, &value->deviceClass); + ffStrbufAppendS(dir, "device/device/class"); + + if(ffReadFileBuffer(dir->chars, &valueBuffer)) + value->deviceClass = (uint32_t) strtoul(valueBuffer.chars, NULL, 16); ffStrbufSubstrBefore(dir, dirLength); - return value->name.length > 0 || value->deviceClass.length > 0; + return value->name.length > 0 || value->deviceClass > 0; } -const FFTempsResult* ffDetectTemps(const FFinstance* instance) +const FFTempsResult* ffDetectTemps() { static FFTempsResult result; static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER; @@ -49,13 +52,6 @@ const FFTempsResult* ffDetectTemps(const FFinstance* instance) } init = true; - if(!instance->config.allowSlowOperations) - { - ffListInitA(&result.values, sizeof(FFTempValue), 0); - ffThreadMutexUnlock(&mutex); - return &result; - } - ffListInitA(&result.values, sizeof(FFTempValue), 16); FFstrbuf baseDir; @@ -83,11 +79,10 @@ const FFTempsResult* ffDetectTemps(const FFinstance* instance) FFTempValue* temp = ffListAdd(&result.values); ffStrbufInit(&temp->name); - ffStrbufInit(&temp->deviceClass); + temp->deviceClass = 0; if(!parseHwmonDir(&baseDir, temp)) { ffStrbufDestroy(&temp->name); - ffStrbufDestroy(&temp->deviceClass); --result.values.length; } diff --git a/src/detection/temps/temps_linux.h b/src/detection/temps/temps_linux.h index 6bece23ed..569bd0401 100644 --- a/src/detection/temps/temps_linux.h +++ b/src/detection/temps/temps_linux.h @@ -8,7 +8,7 @@ typedef struct FFTempValue { FFstrbuf name; - FFstrbuf deviceClass; + uint32_t deviceClass; double value; } FFTempValue; @@ -17,6 +17,6 @@ typedef struct FFTempsResult FFlist values; //List of FFTempValue } FFTempsResult; -const FFTempsResult* ffDetectTemps(const FFinstance* instance); +const FFTempsResult* ffDetectTemps(); #endif From 2af07fee4f8e152795fb20b5c1841f0dbf83a4e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 21 Jan 2023 06:26:24 +0800 Subject: [PATCH 129/142] Changelog: doc cpu temp fix --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d35baf7c..e313dceac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ Bugfixes: * Fix mintty terminal font detection (Windows) * Fix bug that line buffering doesn't work properly (Windows) * Fix rpm package count detection (Linux) +* Fix cpu temp detection (Linux) Other: * Fixed a Typo in iterm error message (@jessebot, #376) From 6d4bd06ffe6dded1dab8459f848cefdd9a457098 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 21 Jan 2023 06:27:39 +0800 Subject: [PATCH 130/142] Fastfetch: add missing `\n` when printing messages --- src/fastfetch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fastfetch.c b/src/fastfetch.c index e936237c6..2ab454993 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -629,7 +629,7 @@ static void generateConfigFile(FFinstance* instance, bool force) else { ffWriteFileData(filename->chars, sizeof(FASTFETCH_DATATEXT_CONFIG_USER), FASTFETCH_DATATEXT_CONFIG_USER); - printf("A sample config file has been written in `%s`", filename->chars); + printf("A sample config file has been written in `%s`\n", filename->chars); exit(0); } } From e651633c54451c3d8c98d93091927fe0d1a8ed4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 21 Jan 2023 06:54:51 +0800 Subject: [PATCH 131/142] Temp: detect both `device/class` and`device/device/class` --- src/detection/temps/temps_linux.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/detection/temps/temps_linux.c b/src/detection/temps/temps_linux.c index 5a1dc2bd4..913e6f037 100644 --- a/src/detection/temps/temps_linux.c +++ b/src/detection/temps/temps_linux.c @@ -29,11 +29,15 @@ static bool parseHwmonDir(FFstrbuf* dir, FFTempValue* value) ffReadFileBuffer(dir->chars, &value->name); ffStrbufSubstrBefore(dir, dirLength); - ffStrbufAppendS(dir, "device/device/class"); - - if(ffReadFileBuffer(dir->chars, &valueBuffer)) + ffStrbufAppendS(dir, "device/class"); + if(!ffReadFileBuffer(dir->chars, &valueBuffer)) + { + ffStrbufSubstrBefore(dir, dirLength); + ffStrbufAppendS(dir, "device/device/class"); + ffReadFileBuffer(dir->chars, &valueBuffer); + } + if(valueBuffer.length) value->deviceClass = (uint32_t) strtoul(valueBuffer.chars, NULL, 16); - ffStrbufSubstrBefore(dir, dirLength); return value->name.length > 0 || value->deviceClass > 0; } From 734ee386410af7355824c6ea6319a3403fc36e79 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Fri, 20 Jan 2023 20:25:22 +0100 Subject: [PATCH 132/142] Disk (Linux): partition name impl & general refactor --- src/detection/disk/disk_linux.c | 240 ++++++++++++++++++++++---------- 1 file changed, 165 insertions(+), 75 deletions(-) diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index 8d7fd1ee3..423b660cd 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -2,33 +2,137 @@ #include #include +#include +#include #include -static void strbufAppendMountPoint(FFstrbuf* mountpoint, const char* source) +#ifdef __USE_LARGEFILE64 + #define stat stat64 + #define statvfs statvfs64 + #define dirent dirent64 + #define readdir readdir64 +#endif + +static bool isPhysicalDevice(const char* device) { - while(*source != '\0' && !isspace(*source)) + //DrvFs is a filesystem plugin to WSL that was designed to support interop between WSL and the Windows filesystem. + if(strcmp(device, "drvfs") == 0) + return true; + + //Pseudo filesystems don't have a device in /dev + const char* devPrefix = "/dev/"; + if(strncmp(device, devPrefix, strlen(devPrefix)) != 0) + return false; + + //Skip /dev/ prefix + device += strlen(devPrefix); + + if( + strncmp(device, "loop", 4) == 0 || //Ignore loop devices + strncmp(device, "ram", 3) == 0 || //Ignore ram devices + strncmp(device, "fd", 2) == 0 //Ignore fd devices + ) return false; + + return true; +} + +static void appendNextEntry(FFstrbuf* buffer, char** source) +{ + //Read the current entry into the buffer + while(**source != '\0' && !isspace(**source)) { //After a backslash the next 3 characters are octal ascii codes - if(*source == '\\' && strnlen(source, 4) == 4) + if(**source == '\\' && strnlen(*source, 4) == 4) { char octal[4] = {0}; - strncpy(octal, source + 1, 3); + strncpy(octal, *source + 1, 3); long value = strtol(octal, NULL, 8); //Returns 0 on error, so no need to check endptr if(value > 0 && value < CHAR_MAX) { - ffStrbufAppendC(mountpoint, (char) value); - source += 4; + ffStrbufAppendC(buffer, (char) value); + *source += 4; continue; } } - ffStrbufAppendC(mountpoint, *source); - ++source; + ffStrbufAppendC(buffer, **source); + ++*source; } + + //Skip whitespace + while(isspace(**source)) + ++*source; } -#ifndef __ANDROID__ +static void detectNameFromPath(FFDisk* disk, const struct stat* deviceStat, FFstrbuf* basePath) +{ + DIR* dir = opendir(basePath->chars); + if(dir == NULL) + return; + + uint32_t basePathLength = basePath->length; + + struct dirent* entry; + while((entry = readdir(dir)) != NULL) + { + if(entry->d_name[0] == '.') + continue; + + ffStrbufAppendS(basePath, entry->d_name); + + struct stat entryStat; + bool ret = stat(basePath->chars, &entryStat) == 0; + + ffStrbufSubstrBefore(basePath, basePathLength); + + if(!ret || deviceStat->st_ino != entryStat.st_ino) + continue; + + ffStrbufAppendS(&disk->name, entry->d_name); + break; + } + + closedir(dir); +} + +static void detectName(FFDisk* disk, const FFstrbuf* device) +{ + struct stat deviceStat; + if(stat(device->chars, &deviceStat) != 0) + return; + + FFstrbuf basePath; + ffStrbufInit(&basePath); + + //Try partlabel first + ffStrbufSetS(&basePath, "/dev/disk/by-partlabel/"); + detectNameFromPath(disk, &deviceStat, &basePath); + + //Try label second + if(disk->name.length == 0) + { + ffStrbufSetS(&basePath, "/dev/disk/by-label/"); + detectNameFromPath(disk, &deviceStat, &basePath); + } + + ffStrbufDestroy(&basePath); +} + +#ifdef __ANDROID__ + +static void detectType(const FFlist* allDisks, FFDisk* currentDisk, const char* options) +{ + if(ffStrbufEqualS(&disk->mountpoint, "/") || ffStrbufEqualS(&disk->mountpoint, "/storage/emulated")) + disk->type = FF_DISK_TYPE_REGULAR; + else if(ffStrbufStartsWithS(&disk->mountpoint, "/mnt/media_rw/")) + disk->type = FF_DISK_TYPE_EXTERNAL; + else + disk->type = FF_DISK_TYPE_HIDDEN; +} + +#else + static bool isSubvolume(const FFlist* allDisks, const FFDisk* currentDisk) { FF_LIST_FOR_EACH(FFDisk, disk, *allDisks) @@ -42,8 +146,34 @@ static bool isSubvolume(const FFlist* allDisks, const FFDisk* currentDisk) return false; } + +static void detectType(const FFlist* allDisks, FFDisk* currentDisk, const char* options) +{ + if(isSubvolume(allDisks, currentDisk)) + currentDisk->type = FF_DISK_TYPE_SUBVOLUME; + else if(strstr(options, "nosuid") != NULL || strstr(options, "nodev") != NULL) + currentDisk->type = FF_DISK_TYPE_EXTERNAL; + else if(ffStrbufStartsWithS(¤tDisk->mountpoint, "/boot") || ffStrbufStartsWithS(¤tDisk->mountpoint, "/efi")) + currentDisk->type = FF_DISK_TYPE_HIDDEN; + else + currentDisk->type = FF_DISK_TYPE_REGULAR; +} + #endif +static void detectStats(FFDisk* disk) +{ + struct statvfs fs; + if(statvfs(disk->mountpoint.chars, &fs) != 0) + memset(&fs, 0, sizeof(struct statvfs)); //Set all values to 0, so our values get initialized to 0 too + + disk->bytesTotal = fs.f_blocks * fs.f_frsize; + disk->bytesUsed = disk->bytesTotal - (fs.f_bavail * fs.f_frsize); + + disk->filesTotal = (uint32_t) fs.f_files; + disk->filesUsed = (uint32_t) (disk->filesTotal - fs.f_ffree); +} + void ffDetectDisksImpl(FFDiskResult* disks) { FILE* mountsFile = fopen("/proc/mounts", "r"); @@ -53,90 +183,50 @@ void ffDetectDisksImpl(FFDiskResult* disks) return; } + FFstrbuf device; + ffStrbufInit(&device); + char* line = NULL; size_t len = 0; while(getline(&line, &len, mountsFile) != EOF) { + if(!isPhysicalDevice(line)) + continue; + + //We have a valid device, add it to the list + FFDisk* disk = ffListAdd(&disks->disks); + //Format of the file: " ..." (Same as fstab) char* currentPos = line; - //Non pseudo filesystems have their device in /dev/ - //DrvFs is a filesystem plugin to WSL that was designed to support interop between WSL and the Windows filesystem. - if(strncmp(currentPos, "/dev/", 5) != 0 && strncmp(currentPos, "drvfs", 5) != 0) - continue; + //detect device + ffStrbufClear(&device); + appendNextEntry(&device, ¤tPos); - //Skip /dev/ or drvfs - currentPos += 5; + //detect mountpoint + ffStrbufInit(&disk->mountpoint); + appendNextEntry(&disk->mountpoint, ¤tPos); - //Don't show loop file systems - if(strncasecmp(currentPos, "loop", 4) == 0) - continue; + //detect filesystem + ffStrbufInit(&disk->filesystem); + appendNextEntry(&disk->filesystem, ¤tPos); - FFDisk* disk = ffListAdd(&disks->disks); + //detect name + ffStrbufInit(&disk->name); + detectName(disk, &device); - //Go to mountpoint - while(!isspace(*currentPos) && *currentPos != '\0') - ++currentPos; - while(isspace(*currentPos)) - ++currentPos; - - ffStrbufInitA(&disk->mountpoint, 16); - strbufAppendMountPoint(&disk->mountpoint, currentPos); - - //Go to filesystem - currentPos += disk->mountpoint.length; - while(isspace(*currentPos)) - ++currentPos; - - ffStrbufInitA(&disk->filesystem, 16); - ffStrbufAppendSUntilC(&disk->filesystem, currentPos, ' '); - - //Go to options, detect type - currentPos += disk->filesystem.length; - while(isspace(*currentPos)) - ++currentPos; - - #ifdef __ANDROID__ - if(ffStrbufEqualS(&disk->mountpoint, "/") || ffStrbufEqualS(&disk->mountpoint, "/storage/emulated")) - disk->type = FF_DISK_TYPE_REGULAR; - else if(ffStrbufStartsWithS(&disk->mountpoint, "/mnt/media_rw/")) - disk->type = FF_DISK_TYPE_EXTERNAL; - else - disk->type = FF_DISK_TYPE_HIDDEN; - #else - if(isSubvolume(&disks->disks, disk)) - disk->type = FF_DISK_TYPE_SUBVOLUME; - else if(strstr(currentPos, "nosuid") != NULL || strstr(currentPos, "nodev") != NULL) - disk->type = FF_DISK_TYPE_EXTERNAL; - else if(ffStrbufStartsWithS(&disk->mountpoint, "/boot") || ffStrbufStartsWithS(&disk->mountpoint, "/efi")) - disk->type = FF_DISK_TYPE_HIDDEN; - else - disk->type = FF_DISK_TYPE_REGULAR; - #endif + //detect type + detectType(&disks->disks, disk, currentPos); //Detects stats - #ifdef __USE_LARGEFILE64 - struct statvfs64 fs; - if(statvfs64(disk->mountpoint.chars, &fs) != 0) - memset(&fs, 0, sizeof(struct statvfs64)); //Set all values to 0, so our values get initialized to 0 too - #else - struct statvfs fs; - if(statvfs(disk->mountpoint.chars, &fs) != 0) - memset(&fs, 0, sizeof(struct statvfs)); //Set all values to 0, so our values get initialized to 0 too - #endif - - disk->bytesTotal = fs.f_blocks * fs.f_frsize; - disk->bytesUsed = disk->bytesTotal - (fs.f_bavail * fs.f_frsize); - - disk->filesTotal = (uint32_t) fs.f_files; - disk->filesUsed = (uint32_t) (disk->filesTotal - fs.f_ffree); - - ffStrbufInit(&disk->name); //TODO: implement this + detectStats(disk); } if(line != NULL) free(line); + ffStrbufDestroy(&device); + fclose(mountsFile); } From d9e79a53768fb195dc563c2062fb7d5e4e008d0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 19 Jan 2023 14:57:54 +0800 Subject: [PATCH 133/142] Fastfetch: print more info with `-v` --- src/fastfetch.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/fastfetch.c b/src/fastfetch.c index 2ab454993..18c130ef2 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -859,7 +859,35 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con } else if(strcasecmp(key, "-v") == 0 || strcasecmp(key, "--version") == 0) { - puts("fastfetch "FASTFETCH_PROJECT_VERSION""FASTFETCH_PROJECT_VERSION_TWEAK); + #ifndef NDEBUG + #define FF_BUILD_TYPE "-debug" + #else + #define FF_BUILD_TYPE + #endif + + #if defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) || defined(__amd64) + #define FF_ARCHITECTURE "x86_64" + #elif defined(__i386__) || defined(__i386) || defined(__i486__) || defined(__i486) || defined(__i586__) || defined(__i586) || defined(__i686__) || defined(__i686) + #define FF_ARCHITECTURE "i386" + #elif defined(__aarch64__) + #define FF_ARCHITECTURE "aarch64" + #elif defined(__arm__) + #define FF_ARCHITECTURE "arm" + #elif defined(__mips__) + #define FF_ARCHITECTURE "mips" + #elif defined(__powerpc__) || defined(__powerpc) + #define FF_ARCHITECTURE "powerpc" + #elif defined(__riscv__) || defined(__riscv) + #define FF_ARCHITECTURE "riscv" + #elif + #define FF_ARCHITECTURE "unknown" + #endif + + puts("fastfetch " FASTFETCH_PROJECT_VERSION FASTFETCH_PROJECT_VERSION_TWEAK FF_BUILD_TYPE " (" FF_ARCHITECTURE ")"); + + #undef FF_ARCHITECTURE + #undef FF_BUILD_TYPE + exit(0); } else if(strcasecmp(key, "--version-raw") == 0) From f640102b0ee544032d333863b14824e6434e2834 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 21 Jan 2023 14:03:57 +0800 Subject: [PATCH 134/142] CPU (Linux): fix compiler warnings --- src/detection/cpu/cpu_linux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index 1b2bf28d6..73ce6eaca 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -67,7 +67,7 @@ static double getFrequency(const char* info, const char* scaling) return getGHz(scaling); } -static double detectCPUTemp() +static double detectCPUTemp(void) { const FFTempsResult* temps = ffDetectTemps(); @@ -107,7 +107,7 @@ static void parseIsa(FFstrbuf* cpuIsa) void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu) { if(instance->config.cpuTemp) - cpu->temperature = detectCPUTemp(instance); + cpu->temperature = detectCPUTemp(); else cpu->temperature = FF_CPU_TEMP_UNSET; From b424c525cc44cd2a525e4e844b11ee816a1b2c47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 21 Jan 2023 14:04:17 +0800 Subject: [PATCH 135/142] Disk (Android): fix compiling errors --- src/detection/disk/disk_linux.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index 423b660cd..dc3bc3f96 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -121,14 +121,14 @@ static void detectName(FFDisk* disk, const FFstrbuf* device) #ifdef __ANDROID__ -static void detectType(const FFlist* allDisks, FFDisk* currentDisk, const char* options) +static void detectType(FF_MAYBE_UNUSED const FFlist* allDisks, FFDisk* currentDisk, FF_MAYBE_UNUSED const char* options) { - if(ffStrbufEqualS(&disk->mountpoint, "/") || ffStrbufEqualS(&disk->mountpoint, "/storage/emulated")) - disk->type = FF_DISK_TYPE_REGULAR; - else if(ffStrbufStartsWithS(&disk->mountpoint, "/mnt/media_rw/")) - disk->type = FF_DISK_TYPE_EXTERNAL; + if(ffStrbufEqualS(¤tDisk->mountpoint, "/") || ffStrbufEqualS(¤tDisk->mountpoint, "/storage/emulated")) + currentDisk->type = FF_DISK_TYPE_REGULAR; + else if(ffStrbufStartsWithS(¤tDisk->mountpoint, "/mnt/media_rw/")) + currentDisk->type = FF_DISK_TYPE_EXTERNAL; else - disk->type = FF_DISK_TYPE_HIDDEN; + currentDisk->type = FF_DISK_TYPE_HIDDEN; } #else From c1444c082212b7bc29d5ef5707427d030ad0b4f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 21 Jan 2023 14:45:36 +0800 Subject: [PATCH 136/142] Android: support Wifi & Battery by using `termux-api` --- CMakeLists.txt | 4 +- src/detection/battery/battery_android.c | 38 +++++++++++++++ src/detection/wifi/wifi_android.c | 62 +++++++++++++++++++++++++ src/detection/wifi/wifi_apple.m | 2 + src/detection/wifi/wifi_linux.c | 12 +++-- src/detection/wifi/wifi_windows.c | 2 + src/modules/wifi.c | 11 +++-- 7 files changed, 119 insertions(+), 12 deletions(-) create mode 100644 src/detection/battery/battery_android.c create mode 100644 src/detection/wifi/wifi_android.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f07deeb2..453244774 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -351,7 +351,7 @@ elseif(ANDROID) list(APPEND LIBFASTFETCH_SRC src/common/networking_linux.c src/common/processing_linux.c - src/detection/battery/battery_nosupport.c + src/detection/battery/battery_android.c src/detection/bios/bios_nosupport.c src/detection/board/board_nosupport.c src/detection/brightness/brightness_nosupport.c @@ -378,7 +378,7 @@ elseif(ANDROID) src/detection/terminalshell/terminalshell_linux.c src/detection/uptime/uptime_linux.c src/detection/users/users_linux.c - src/detection/wifi/wifi_nosupport.c + src/detection/wifi/wifi_android.c src/detection/wmtheme/wmtheme_nosupport.c src/util/platform/FFPlatform_unix.c ) diff --git a/src/detection/battery/battery_android.c b/src/detection/battery/battery_android.c new file mode 100644 index 000000000..0c4772c3e --- /dev/null +++ b/src/detection/battery/battery_android.c @@ -0,0 +1,38 @@ +#include "fastfetch.h" +#include "battery.h" + +#include "common/processing.h" +#include "common/properties.h" + +const char* ffDetectBatteryImpl(FF_MAYBE_UNUSED FFinstance* instance, FFlist* results) +{ + FF_STRBUF_AUTO_DESTROY buffer; + ffStrbufInit(&buffer); + + if(ffProcessAppendStdOut(&buffer, (char* const[]){ + FASTFETCH_TARGET_DIR_ROOT "/libexec/termux-api", + "BatteryStatus" + })) + return "Starting `" FASTFETCH_TARGET_DIR_ROOT "/libexec/termux-api" " BatteryStatus` failed"; + + BatteryResult* battery = ffListAdd(results); + battery->temperature = FF_BATTERY_TEMP_UNSET; + ffStrbufInit(&battery->manufacturer); + ffStrbufInit(&battery->modelName); + ffStrbufInit(&battery->status); + ffStrbufInit(&battery->technology); + + if(ffParsePropLines(buffer.chars, "\"percentage\": ", &battery->status)) + { + battery->capacity = ffStrbufToDouble(&battery->status); + ffStrbufClear(&battery->status); + } + + if(ffParsePropLines(buffer.chars, "\"status\": ", &battery->status)) + { + ffStrbufTrimRight(&battery->status, ','); + ffStrbufTrim(&battery->status, '"'); + } + + return NULL; +} diff --git a/src/detection/wifi/wifi_android.c b/src/detection/wifi/wifi_android.c new file mode 100644 index 000000000..af1012fe7 --- /dev/null +++ b/src/detection/wifi/wifi_android.c @@ -0,0 +1,62 @@ +#include "wifi.h" + +#include "common/processing.h" +#include "common/properties.h" + +const char* ffDetectWifi(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* result) +{ + FF_STRBUF_AUTO_DESTROY buffer; + ffStrbufInit(&buffer); + + if(ffProcessAppendStdOut(&buffer, (char* const[]){ + FASTFETCH_TARGET_DIR_ROOT "/libexec/termux-api", + "WifiConnectionInfo" + })) + return "Starting `" FASTFETCH_TARGET_DIR_ROOT "/libexec/termux-api" " WifiConnectionInfo` failed"; + + FFWifiResult* item = (FFWifiResult*)ffListAdd(result); + ffStrbufInit(&item->inf.description); + ffStrbufInit(&item->inf.status); + ffStrbufInit(&item->conn.status); + ffStrbufInit(&item->conn.ssid); + ffStrbufInit(&item->conn.macAddress); + ffStrbufInit(&item->conn.protocol); + ffStrbufInit(&item->conn.security); + item->conn.signalQuality = 0.0/0.0; + item->conn.rxRate = 0.0/0.0; + item->conn.txRate = 0.0/0.0; + + if(!ffParsePropLines(buffer.chars, "\"supplicant_state\": ", &item->inf.status)) + ffStrbufAppendS(&item->inf.status, "Unknown"); + + { + ffStrbufTrimRight(&item->inf.status, ','); + ffStrbufTrim(&item->inf.status, '"'); + if(!ffStrbufEqualS(&item->inf.status, "COMPLETED")) + return NULL; + } + + if(ffParsePropLines(buffer.chars, "\"rssi\": ", &item->inf.description)) + { + double rssi = ffStrbufToDouble(&item->inf.description); + item->conn.signalQuality = rssi >= -50 ? 100 : rssi <= -100 ? 0 : (rssi + 100) * 2; + ffStrbufClear(&item->inf.description); + } + + if(ffParsePropLines(buffer.chars, "\"network_id\": ", &item->inf.description)) + ffStrbufTrimRight(&item->inf.description, ','); + + if(ffParsePropLines(buffer.chars, "\"bssid\": ", &item->conn.macAddress)) + { + ffStrbufTrimRight(&item->conn.macAddress, ','); + ffStrbufTrim(&item->conn.macAddress, '"'); + } + + if(ffParsePropLines(buffer.chars, "\"ssid\": ", &item->conn.ssid)) + { + ffStrbufTrimRight(&item->conn.ssid, ','); + ffStrbufTrim(&item->conn.ssid, '"'); + } + + return NULL; +} diff --git a/src/detection/wifi/wifi_apple.m b/src/detection/wifi/wifi_apple.m index 417a4e3de..fafaf22a0 100644 --- a/src/detection/wifi/wifi_apple.m +++ b/src/detection/wifi/wifi_apple.m @@ -119,6 +119,8 @@ const char* ffDetectWifi(const FFinstance* instance, FFlist* result) ffStrbufAppendF(&item->conn.security, "Unknown (%ld)", inf.security); break; } + else + ffStrbufAppendS(&item->conn.security, "Insecure"); } return NULL; } diff --git a/src/detection/wifi/wifi_linux.c b/src/detection/wifi/wifi_linux.c index 4459b3e5a..a8f70620d 100644 --- a/src/detection/wifi/wifi_linux.c +++ b/src/detection/wifi/wifi_linux.c @@ -161,8 +161,6 @@ static const char* detectWifiWithLibnm(const FFinstance* instance, FFlist* resul ffStrbufSetS(&item->conn.protocol, "802.11a/b/g"); } } - if(!item->conn.protocol.length) - ffStrbufAppendS(&item->conn.protocol, "802.11"); NM80211ApFlags flags = ffnm_access_point_get_flags(ap); NM80211ApSecurityFlags wpaFlags = ffnm_access_point_get_wpa_flags(ap); @@ -188,7 +186,10 @@ static const char* detectWifiWithLibnm(const FFinstance* instance, FFlist* resul || (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) { ffStrbufAppendS(&item->conn.security, "802.1X "); } - ffStrbufTrimRight(&item->conn.security, ' '); + if (!item->conn.security.length) + ffStrbufAppendS(&item->conn.security, "Insecure"); + else + ffStrbufTrimRight(&item->conn.security, ' '); } ffg_object_unref(client); @@ -294,9 +295,10 @@ static const char* detectWifiWithIoctls(FF_MAYBE_UNUSED const FFinstance* instan case IW_ENCODE_ALG_AES_CMAC: ffStrbufAppendS(&item->conn.security, "CMAC"); break; + default: + ffStrbufAppendF(&item->conn.security, "Unknown (%d)", (int) iwe->alg); + break; } - } else { - ffStrbufAppendS(&item->conn.security, "unknown"); } close(sock); diff --git a/src/detection/wifi/wifi_windows.c b/src/detection/wifi/wifi_windows.c index 2f275061e..70d7ea577 100644 --- a/src/detection/wifi/wifi_windows.c +++ b/src/detection/wifi/wifi_windows.c @@ -198,6 +198,8 @@ const char* ffDetectWifi(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* res if(connInfo->wlanSecurityAttributes.bOneXEnabled) ffStrbufAppendS(&item->conn.security, " 802.11X"); } + else + ffStrbufAppendS(&item->conn.security, "Insecure"); ffWlanFreeMemory(connInfo); } diff --git a/src/modules/wifi.c b/src/modules/wifi.c index bc1bbacbf..fa9d19caf 100644 --- a/src/modules/wifi.c +++ b/src/modules/wifi.c @@ -32,11 +32,12 @@ void ffPrintWifi(FFinstance* instance) ffPrintLogoAndKey(instance, FF_WIFI_MODULE_NAME, moduleIndex, &instance->config.wifi.key); if(item->conn.ssid.length) { - printf("%s - %s - %s\n", - item->conn.ssid.chars, - item->conn.protocol.chars, - item->conn.security.length > 0 ? item->conn.security.chars : "insecure" - ); + ffStrbufWriteTo(&item->conn.ssid, stdout); + if(item->conn.protocol.length) + printf("- %s", item->conn.protocol.chars); + if(item->conn.security.length) + printf("- %s", item->conn.security.chars); + putchar('\n'); } else { From 3b820f1145d8508393888c043a732bc1980a250b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 21 Jan 2023 16:02:40 +0800 Subject: [PATCH 137/142] Doc: document wifi / battery support on Android --- CHANGELOG.md | 1 + README.md | 3 +++ 2 files changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e313dceac..8d9a648c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ Features: * Detect scaled resolutions (Windows, macOS) * Optimise font module printing (Windows) * Detect pacman package count inside MSYS2 environment (Windows) +* Add Wifi / Battery module support for Android Logos: * Raspbian (@IamNoRobot, #373) diff --git a/README.md b/README.md index a87eee346..c1d5dbb99 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for +There are [screenshots on different platforms](https://github.com/LinusDierheimer/fastfetch/wiki) + ## Customization With customization and speed being two competing goals, this project actually builds two executables. @@ -79,6 +81,7 @@ For the image logo, only chafa is supported due to [the design flaw of ConPTY](h * [`freetype`](https://www.freetype.org/): Used for Termux font detection. [`freetype`](https://github.com/termux/termux-packages/tree/master/packages/freetype) * [`libvulkan`](https://www.vulkan.org/): Vulkan module, also used for GPU detection. Usually has been provided by Android system. [`vulkan-loader-android`](https://github.com/termux/termux-packages/tree/master/packages/vulkan-loader-android) [`vulkan-headers`](https://github.com/termux/termux-packages/tree/master/packages/vulkan-headers) +* [`termux-api`](https://github.com/termux/termux-api-package): Used for Wifi / Battery detection. Read [the official doc](https://wiki.termux.com/wiki/Termux:API) for detail or if you hang on these modules (IMPORTANT). [`termux-api`](https://github.com/termux/termux-packages/tree/master/packages/termux-api) ## Support status All categories not listed here should work without needing a specific implementation. From e8bde5a39492fef2815e69ddefdab31210526c9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 21 Jan 2023 16:23:28 +0800 Subject: [PATCH 138/142] Wifi: fix compiling on macOS --- src/detection/wifi/wifi_apple.m | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/detection/wifi/wifi_apple.m b/src/detection/wifi/wifi_apple.m index fafaf22a0..a83f79485 100644 --- a/src/detection/wifi/wifi_apple.m +++ b/src/detection/wifi/wifi_apple.m @@ -70,6 +70,9 @@ const char* ffDetectWifi(const FFinstance* instance, FFlist* result) switch(inf.security) { + case kCWSecurityNone: + ffStrbufAppendS(&item->conn.security, "Insecure"); + break; case kCWSecurityWEP: ffStrbufAppendS(&item->conn.security, "WEP"); break; @@ -119,8 +122,6 @@ const char* ffDetectWifi(const FFinstance* instance, FFlist* result) ffStrbufAppendF(&item->conn.security, "Unknown (%ld)", inf.security); break; } - else - ffStrbufAppendS(&item->conn.security, "Insecure"); } return NULL; } From 27f76599bc3f240502f993224b41a240d3dc43d4 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Sat, 21 Jan 2023 14:42:19 +0100 Subject: [PATCH 139/142] Fix subvolume detection #396 --- src/detection/disk/disk_linux.c | 44 ++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index 423b660cd..6b46a0af2 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -121,35 +121,36 @@ static void detectName(FFDisk* disk, const FFstrbuf* device) #ifdef __ANDROID__ -static void detectType(const FFlist* allDisks, FFDisk* currentDisk, const char* options) +static void detectType(const FFlist* devices, FFDisk* currentDisk, const char* options) { - if(ffStrbufEqualS(&disk->mountpoint, "/") || ffStrbufEqualS(&disk->mountpoint, "/storage/emulated")) - disk->type = FF_DISK_TYPE_REGULAR; + if(ffStrbufEqualS(¤tDisk->mountpoint, "/") || ffStrbufEqualS(¤tDisk->mountpoint, "/storage/emulated")) + currentDisk->type = FF_DISK_TYPE_REGULAR; else if(ffStrbufStartsWithS(&disk->mountpoint, "/mnt/media_rw/")) - disk->type = FF_DISK_TYPE_EXTERNAL; + currentDisk->type = FF_DISK_TYPE_EXTERNAL; else - disk->type = FF_DISK_TYPE_HIDDEN; + currentDisk->type = FF_DISK_TYPE_HIDDEN; } #else -static bool isSubvolume(const FFlist* allDisks, const FFDisk* currentDisk) +static bool isSubvolume(const FFlist* devices) { - FF_LIST_FOR_EACH(FFDisk, disk, *allDisks) - { - if(disk == currentDisk) - continue; + const FFstrbuf* currentDevie = ffListGet(devices, devices->length - 1); - if(ffStrbufEqual(&disk->mountpoint, ¤tDisk->mountpoint)) + for(uint32_t i = 0; i < devices->length - 1; i++) + { + const FFstrbuf* otherDevice = ffListGet(devices, i); + + if(ffStrbufEqual(currentDevie, otherDevice)) return true; } return false; } -static void detectType(const FFlist* allDisks, FFDisk* currentDisk, const char* options) +static void detectType(const FFlist* devices, FFDisk* currentDisk, const char* options) { - if(isSubvolume(allDisks, currentDisk)) + if(isSubvolume(devices)) currentDisk->type = FF_DISK_TYPE_SUBVOLUME; else if(strstr(options, "nosuid") != NULL || strstr(options, "nodev") != NULL) currentDisk->type = FF_DISK_TYPE_EXTERNAL; @@ -183,8 +184,8 @@ void ffDetectDisksImpl(FFDiskResult* disks) return; } - FFstrbuf device; - ffStrbufInit(&device); + FFlist devices; + ffListInit(&devices, sizeof(FFstrbuf)); char* line = NULL; size_t len = 0; @@ -201,8 +202,9 @@ void ffDetectDisksImpl(FFDiskResult* disks) char* currentPos = line; //detect device - ffStrbufClear(&device); - appendNextEntry(&device, ¤tPos); + FFstrbuf* device = ffListAdd(&devices); + ffStrbufInit(device); + appendNextEntry(device, ¤tPos); //detect mountpoint ffStrbufInit(&disk->mountpoint); @@ -214,10 +216,10 @@ void ffDetectDisksImpl(FFDiskResult* disks) //detect name ffStrbufInit(&disk->name); - detectName(disk, &device); + detectName(disk, device); //detect type - detectType(&disks->disks, disk, currentPos); + detectType(&devices, disk, currentPos); //Detects stats detectStats(disk); @@ -226,7 +228,9 @@ void ffDetectDisksImpl(FFDiskResult* disks) if(line != NULL) free(line); - ffStrbufDestroy(&device); + FF_LIST_FOR_EACH(FFstrbuf, device, devices) + ffStrbufDestroy(device); + ffListDestroy(&devices); fclose(mountsFile); } From c15f55762dd3d78f30af1606384bf4d79cf7745d Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Sat, 21 Jan 2023 14:57:30 +0100 Subject: [PATCH 140/142] Disk(Linux): Use mountpoint as last fallback for disk name --- CHANGELOG.md | 1 + src/detection/disk/disk_linux.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d9a648c7..c8546a6ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ Features: * Optimise font module printing (Windows) * Detect pacman package count inside MSYS2 environment (Windows) * Add Wifi / Battery module support for Android +* Disk name support for Linux Logos: * Raspbian (@IamNoRobot, #373) diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index edf42b8ab..ec7a26abf 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -116,6 +116,10 @@ static void detectName(FFDisk* disk, const FFstrbuf* device) detectNameFromPath(disk, &deviceStat, &basePath); } + //Use the mountpoint as a last resort + if(disk->name.length == 0) + ffStrbufAppend(&disk->name, &disk->mountpoint); + ffStrbufDestroy(&basePath); } From f360e10050c8ad89a5cc17bf2c5721f28240a012 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 22 Jan 2023 00:32:41 +0800 Subject: [PATCH 141/142] Release: 1.9.0 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 453244774..0d257dab7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url project(fastfetch - VERSION 1.8.2 + VERSION 1.9.0 LANGUAGES C DESCRIPTION "Fast system information tool" HOMEPAGE_URL "https://github.com/LinusDierheimer/fastfetch" From e0b2db17c2520b22b7a0a8e6e326eb34da9dd312 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 22 Jan 2023 00:39:45 +0800 Subject: [PATCH 142/142] Changelog: update version --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8546a6ca..b4fba05d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# dev +# 1.9.0 Notable Changes: * fastfetch no longer creates a sample config file silently. Use `--gen-config` to generate one.