Compare commits

...

41 Commits

Author SHA1 Message Date
Linus Dierheimer 60af0b9e39 Release 1.4.0
Feature: Display images converted to ascii art as logo, using chafa
Feature: Stretch images by using the --logo-height option
Logo: RedstarOS
Logo: Devuan
Logo: Rocky
Bugfix: Better calculation of image dimensions
Bugfix: Better rpm package detection
Bugfix: Format uptime right, when hours > 0 and minutes = 0
Bugfix: Only detect themes for installed gtk versions
2022-05-23 19:39:49 +02:00
Linus Dierheimer e4ecb9d069 Use sqlite to get rpm package count 2022-05-23 19:30:02 +02:00
Linus Dierheimer 3c648d84db Better GTK detection 2022-05-23 16:19:58 +02:00
Linus Dierheimer 45db4a5c3d Fix possible use after free 2022-05-23 15:50:25 +02:00
Linus Dierheimer caf976bec2 Fix building without chafa enabled 2022-05-23 15:36:19 +02:00
Linus Dierheimer b3d855355e Rewrote image dimension calculation 2022-05-23 15:32:10 +02:00
Linus Dierheimer 0a2eb49891 Merge pull request #164 from draumaz/master
Add Rocky Linux logo
2022-05-23 12:34:06 +02:00
draumaz ab2efa151a update readme 2022-05-23 03:29:04 -07:00
draumaz 1aee3f81c5 added Rocky Linux logo 2022-05-23 03:22:39 -07:00
Linus Dierheimer 4c7031cb12 Merge pull request #161 from Samisafool/patch-1
Typo
2022-05-16 11:51:08 +02:00
Samisafool 81c96d0f11 Typo 2022-05-16 09:54:48 +05:30
Linus Dierheimer 4d8680ec2d Merge pull request #160 from draumaz/master
Add Devuan logo
2022-05-15 23:46:56 +02:00
draumaz 039eb3a38a Fix alphabetical ordering 2022-05-15 13:48:10 -07:00
draumaz d07a653404 Update README.md 2022-05-15 13:45:31 -07:00
draumaz 76c0b7e457 Update README.md 2022-05-15 13:43:36 -07:00
draumaz 1c0e532b79 add Devuan 2022-05-15 06:22:28 -07:00
Linus Dierheimer c79a9f1bff Format uptime better 2022-05-14 14:13:10 +02:00
Linus Dierheimer 759069adfa Merge pull request #157 from Samisafool/patch-1
Fix bug_report.md
2022-05-14 14:03:04 +02:00
Samisafool 66ff6adfb0 Update bug_report.md 2022-05-13 14:06:05 +05:30
Samisafool 1dba19c49f Typo 2022-05-12 08:29:47 +05:30
Samisafool 2afd158d96 Fix bug_report.md 2022-05-12 08:28:24 +05:30
Linus Dierheimer 36c2ce6219 Look for newer versions of librpm 2022-05-05 15:48:01 +02:00
Linus Dierheimer 5f6432c150 RedstarOS logo 2022-05-04 18:11:32 +02:00
Linus Dierheimer e9f0eca3dd Add documentation about logo height option 2022-04-30 11:25:22 +02:00
Linus Dierheimer 998691847e logo-height option 2022-04-30 11:22:51 +02:00
Linus Dierheimer 64e5ef0df7 Fix output with no custom logo 2022-04-29 21:52:42 +02:00
Linus Dierheimer cc1e876faf Better automatic logo type detection 2022-04-29 21:44:32 +02:00
Linus Dierheimer 964a5aa8b4 Add chafa to feature list 2022-04-29 14:11:22 +02:00
Linus Dierheimer ad2601f097 Fix visual bug in README.md 2022-04-29 13:08:39 +02:00
Linus Dierheimer 7cae63ac05 Require chafa>=1.10 2022-04-29 13:07:20 +02:00
Linus Dierheimer 0d26cfb218 Dont try to build with ubuntu's outdated chafa enabled 2022-04-29 13:05:38 +02:00
Linus Dierheimer 3b6855b9da Build github packages with chafa support 2022-04-28 19:17:13 +02:00
Linus Dierheimer 51414c5511 Ascii image output using chafa 2022-04-28 19:15:46 +02:00
Linus Dierheimer 24f8ad7673 Release 1.3.4
* Bugfix: Using custom logos in terminals that don't support \033[14t or \033[18t once again works
* Feature: Ubuntu flavour detection
* Feature: Kubuntu logo
* Feature: Deepin logo
2022-04-27 08:03:15 +02:00
Linus Dierheimer e404dd62c0 Check for ubuntu flavours 2022-04-26 19:21:19 +02:00
Linus Dierheimer 21b315d548 Use a timeout when waiting for terminal responses 2022-04-26 17:17:16 +02:00
Linus Dierheimer 14fa052257 Use reasonable timeout for dbus 2022-04-25 18:42:05 +02:00
Linus Dierheimer 5861012d95 Deepin logo 2022-04-25 18:01:29 +02:00
Linus Dierheimer 4d9fbd93d2 Kubuntu logo 2022-04-25 17:51:51 +02:00
Linus Dierheimer 1d99bd2e08 Fix prebuild deb package for real this time 2022-04-23 11:28:46 +02:00
Linus Dierheimer 52eed51eb6 Fix prebuild deb package 2022-04-23 11:24:24 +02:00
25 changed files with 827 additions and 305 deletions
+10 -4
View File
@@ -7,6 +7,13 @@ assignees: ''
---
# General description of bug:
# Often helpful questions:
* Does the issue occur across multiple terminal emulators? [Y/N]
* Does the issue occur across multiple shells? (bash, zsh, fish, etc) [Y/N]
Output of `fastfetch --version`:
```
//paste here
@@ -27,9 +34,8 @@ Output of `fastfetch --list-features`:
//paste here
```
<!--
If you get the following error: `Error: couldn't find config: [...]`, copy the files in [presets](../../presets/) to `/usr/share/fastfetch/presets/` or `~/.local/share/fastfetch/presets/`.
If this isn't possible (or to much work) for you, post the output of `fastfetch --show-errors --recache --multithreading false --disable-linewrap false`.
If this isn't possible (or too much work) for you, post the output of `fastfetch --show-errors --recache --multithreading false --disable-linewrap false`.
-->
Often helpful questions:
* Does the issue occur across multiple terminal emulators?
* Does the issue occur across multiple shells? (bash, zsh, fish, etc)
+1 -1
View File
@@ -13,7 +13,7 @@ jobs:
uses: actions/checkout@v2
- 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 rpm librpm-dev libzstd-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
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
uses: actions/checkout@v2
- 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 rpm librpm-dev libzstd-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
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
+36 -25
View File
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.1.0) # Threads::Threads
project(fastfetch
VERSION 1.3.1
VERSION 1.4.0
LANGUAGES C
)
@@ -27,10 +27,11 @@ OPTION(ENABLE_GIO "Enable gio-2.0" ON)
OPTION(ENABLE_DCONF "Enable dconf" ON)
OPTION(ENABLE_DBUS "Enable dbus-1" ON)
OPTION(ENABLE_XFCONF "Enable libxfconf-0" ON)
OPTION(ENABLE_RPM "Enable rpm" ON)
OPTION(ENABLE_SQLITE3 "Enable sqlite3" ON)
OPTION(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON)
OPTION(ENABLE_IMAGEMAGICK6 "Enable imagemagick 6" ON)
OPTION(ENABLE_ZLIB "Enable zlib" ON)
OPTION(ENABLE_CHAFA "Enable chafa" ON)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
@@ -265,12 +266,12 @@ if(ENABLE_XFCONF)
endif()
endif()
if(ENABLE_RPM)
pkg_check_modules(RPM rpm)
if(RPM_FOUND)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_RPM=1)
if(ENABLE_SQLITE3)
pkg_check_modules(SQLITE3 sqlite3)
if(SQLITE3_FOUND)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_SQLITE3=1)
else()
message(WARNING "Package librpm not found. Building without support.")
message(WARNING "Package sqlite3 not found. Building without support.")
endif()
endif()
@@ -321,6 +322,15 @@ if(ENABLE_ZLIB)
endif()
endif()
if(ENABLE_CHAFA)
pkg_check_modules(CHAFA chafa>=1.10)
if(CHAFA_FOUND)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_CHAFA=1)
else()
message(WARNING "Package chafa>=1.10 not found. Building without support.")
endif()
endif()
target_include_directories(libfastfetch
PUBLIC ${PROJECT_BINARY_DIR}
PUBLIC ${PROJECT_SOURCE_DIR}/src
@@ -336,10 +346,11 @@ target_include_directories(libfastfetch
PRIVATE ${DCONF_INCLUDE_DIRS}
PRIVATE ${DBUS_INCLUDE_DIRS}
PRIVATE ${XFCONF_INCLUDE_DIRS}
PRIVATE ${RPM_INCLUDE_DIRS}
PRIVATE ${SQLITE3_INCLUDE_DIRS}
PRIVATE ${IMAGEMAGICK7_INCLUDE_DIRS}
PRIVATE ${IMAGEMAGICK6_INCLUDE_DIRS}
PRIVATE ${ZLIB_INCLUDE_DIRS}
PRIVATE ${CHAFA_INCLUDE_DIRS}
)
target_link_libraries(libfastfetch
@@ -420,29 +431,29 @@ set(CPACK_GENERATOR "DEB;RPM;TGZ;ZIP")
set(CPACK_PACKAGE_CONTACT "Linus Dierheimer <Linus@Dierheimer.de>")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Neofetch clone written in C")
set(CPACK_PACKAGE_DESCRIPTION "
fastfetch is a neofetch-like tool for fetching system information and displaying them in a pretty way.
It is written in c to achieve much better performance.
set(CPACK_PACKAGE_DESCRIPTION "\
fastfetch is a neofetch-like tool for fetching system information and displaying them in a pretty way. \
It is written in c to achieve much better performance.\
")
set(CPACK_PACKAGE_HOMEPAGE_URL "https://github.com/LinusDierheimer")
set(CPACK_DEBIAN_PACKAGE_SECTION, "utils")
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6")
set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "
libpci3
libvulkan1
libwayland-client0
libxcb-randr0
xcb
libxrandr2
libx11-6
libdconf1
libglib2.0-0
libdbus-1-3
libxfconf-0-3
libmagickcore-6.q16hdri-6
libmagickcore-6.q16-6
set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "\
libpci3, \
libvulkan1, \
libwayland-client0, \
libxcb-randr0, \
xcb, \
libxrandr2, \
libx11-6, \
libdconf1, \
libglib2.0-0, \
libdbus-1-3, \
libxfconf-0-3, \
libmagickcore-6.q16hdri-6, \
zlib1g \
")
set(CPACK_RPM_PACKAGE_LICENSE "MIT")
+3 -2
View File
@@ -29,10 +29,11 @@ The following libraries are used if present at runtime:
* [`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.
* [`libchafa`](https://github.com/hpjansson/chafa): Image output as ascii art.
* [`libZ`](https://www.zlib.net/): Faster image output when using kitty graphics protocol.
* [`libDBus`](https://www.freedesktop.org/wiki/Software/dbus): Needed for detecting current media player and song.
* [`libXFConf`](https://gitlab.xfce.org/xfce/xfconf): Needed for XFWM theme and XFCE Terminal font.
* [`librpm`](http://rpm.org/): Needed for rpm package count.
* [`libsqlite3`](https://www.sqlite.org/index.html): Needed for rpm package count.
## Support status
All categories not listed here should work without needing a specific implementation.
@@ -44,7 +45,7 @@ Title, Separator, OS, Host, Kernel, Uptime, Processes, Packages, Shell, Resoluti
##### Logos
```
Android, Arch, Arco, Artix, CachyOS, CentOS, Debian, Endeavour, Fedora, Garuda, Gentoo, KDE Neon, Linux, Manjaro, Mint, NixOS, OpenSUSE, OpenSUSE Tumbleweed, OpenSUSE LEAP, Pop!_OS, RebornOS, Ubuntu, Void, Zorin
Android, Arch, Arco, Artix, CachyOS, CentOS, Debian, Devuan, Deepin, Endeavour, Fedora, Garuda, Gentoo, KDE Neon, Kubuntu, Linux, Manjaro, Mint, NixOS, OpenSUSE, OpenSUSE Tumbleweed, OpenSUSE LEAP, Pop!_OS, RebornOS, RedstarOS, Rocky, Ubuntu, Void, 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.
+2 -1
View File
@@ -231,9 +231,10 @@ __fastfetch_completion()
"--lib-DConf"
"--lib-DBus"
"--lib-XFConf"
"--lib-RPM"
"--lib-sqlite3"
"--lib-imagemagick"
"--lib-z"
"--lib-chafa"
"--battery-dir"
"--load-config"
)
+9 -4
View File
@@ -108,7 +108,8 @@ static void defaultConfig(FFinstance* instance)
instance->config.logoType = FF_LOGO_TYPE_AUTO;
for(uint8_t i = 0; i < (uint8_t) FASTFETCH_LOGO_MAX_COLORS; ++i)
ffStrbufInit(&instance->config.logoColors[i]);
instance->config.logoWidth = 65;
instance->config.logoWidth = 0;
instance->config.logoHeight = 0; //preserve aspect ratio
instance->config.logoPaddingLeft = 0;
instance->config.logoPaddingRight = 4;
instance->config.logoPrintRemaining = true;
@@ -198,9 +199,10 @@ static void defaultConfig(FFinstance* instance)
ffStrbufInitA(&instance->config.libDConf, 0);
ffStrbufInitA(&instance->config.libDBus, 0);
ffStrbufInitA(&instance->config.libXFConf, 0);
ffStrbufInitA(&instance->config.librpm, 0);
ffStrbufInitA(&instance->config.libSQLite3, 0);
ffStrbufInitA(&instance->config.libImageMagick, 0);
ffStrbufInitA(&instance->config.libZ, 0);
ffStrbufInitA(&instance->config.libChafa, 0);
ffStrbufInitA(&instance->config.diskFolders, 0);
@@ -317,14 +319,17 @@ void ffListFeatures()
#ifdef FF_HAVE_IMAGEMAGICK6
"imagemagick6\n"
#endif
#ifdef FF_HAVE_CHAFA
"chafa\n"
#endif
#ifdef FF_HAVE_ZLIB
"zlib\n"
#endif
#ifdef FF_HAVE_XFCONF
"xfconf\n"
#endif
#ifdef FF_HAVE_RPM
"librpm\n"
#ifdef FF_HAVE_SQLITE3
"sqlite3\n"
#endif
""
, stdout);
+25 -15
View File
@@ -1,11 +1,11 @@
#include "fastfetch.h"
#include <stdio.h>
#include <malloc.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdarg.h>
#include <termios.h>
#include <poll.h>
bool ffWriteFDContent(int fd, const FFstrbuf* content)
{
@@ -128,32 +128,42 @@ bool ffFileExists(const char* fileName, mode_t mode)
return stat(fileName, &fileStat) == 0 && ((fileStat.st_mode & S_IFMT) == mode);
}
void ffGetTerminalResponse(const char* request, char end, const char* format, ...)
void ffGetTerminalResponse(const char* request, const char* format, ...)
{
struct termios oldTerm, newTerm;
tcgetattr(STDIN_FILENO, &oldTerm);
if(tcgetattr(STDIN_FILENO, &oldTerm) == -1)
return;
newTerm = oldTerm;
newTerm.c_lflag &= (tcflag_t) ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newTerm);
if(tcsetattr(STDIN_FILENO, TCSANOW, &newTerm) == -1)
return;
fputs(request, stdout);
fflush(stdout);
struct pollfd pfd;
pfd.fd = STDIN_FILENO;
pfd.events = POLLIN;
pfd.revents = 0;
//Give the terminal 35ms to respond
if(poll(&pfd, 1, 35) <= 0)
{
tcsetattr(STDIN_FILENO, TCSANOW, &oldTerm);
return;
}
char buffer[512];
int pos = 0;
while((size_t) pos < sizeof(buffer) - 1)
{
char c = (char) getc(stdin);
if(c == '\0')
break;
buffer[pos++] = c;
if(c == end)
break;
}
buffer[pos] = '\0';
ssize_t readed = read(STDIN_FILENO, buffer, sizeof(buffer) - 1);
tcsetattr(STDIN_FILENO, TCSANOW, &oldTerm);
if(readed <= 0)
return;
buffer[readed] = '\0';
va_list args;
va_start(args, format);
vsscanf(buffer, format, args);
+69
View File
@@ -1,6 +1,7 @@
#include "fastfetch.h"
#include <pthread.h>
#include <string.h>
#define FF_LIBRARY_DATA_LOAD_INIT(dataObject, userLibraryName, ...) \
static dataObject data; \
@@ -267,6 +268,74 @@ FFvariant ffSettingsGetXFConf(FFinstance* instance, const char* channelName, con
}
#endif //FF_HAVE_XFCONF
#ifdef FF_HAVE_SQLITE3
#include <sqlite3.h>
typedef struct SQLiteData
{
FF_LIBRARY_SYMBOL(sqlite3_open_v2)
FF_LIBRARY_SYMBOL(sqlite3_prepare_v2)
FF_LIBRARY_SYMBOL(sqlite3_step)
FF_LIBRARY_SYMBOL(sqlite3_data_count)
FF_LIBRARY_SYMBOL(sqlite3_column_int)
FF_LIBRARY_SYMBOL(sqlite3_finalize)
FF_LIBRARY_SYMBOL(sqlite3_close)
} SQLiteData;
static const SQLiteData* getSQLiteData(const FFinstance* instance)
{
FF_LIBRARY_DATA_LOAD_INIT(SQLiteData, instance->config.libSQLite3, "libsqlite3.so", 1);
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_open_v2)
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_prepare_v2)
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_step)
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_data_count)
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_column_int)
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_finalize)
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_close)
FF_LIBRARY_DATA_LOAD_RETURN
}
int ffSettingsGetSQLite3Int(FFinstance* instance, const char* dbPath, const char* query)
{
const SQLiteData* data = getSQLiteData(instance);
if(data == NULL)
return 0;
sqlite3* db;
if(data->ffsqlite3_open_v2(dbPath, &db, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK)
return 0;
sqlite3_stmt* stmt;
if(data->ffsqlite3_prepare_v2(db, query, (int) strlen(query), &stmt, NULL) != SQLITE_OK)
{
data->ffsqlite3_close(db);
return 0;
}
if(data->ffsqlite3_step(stmt) != SQLITE_ROW || data->ffsqlite3_data_count(stmt) < 1)
{
data->ffsqlite3_finalize(stmt);
data->ffsqlite3_close(db);
return 0;
}
int result = data->ffsqlite3_column_int(stmt, 0);
data->ffsqlite3_finalize(stmt);
data->ffsqlite3_close(db);
return result;
}
#else //FF_HAVE_SQLITE3
int ffSettingsGetSQLite3Int(FFinstance* instance, const char* dbPath, const char* query)
{
FF_UNUSED(instance, dbPath, query)
return 0;
}
#endif //FF_HAVE_SQLITE3
#ifdef __ANDROID__
#include <sys/system_properties.h>
bool ffSettingsGetAndroidProperty(const char* propName, FFstrbuf* result) {
+10 -3
View File
@@ -61,16 +61,22 @@
# Logo type option:
# Sets the logo type to use.
# Must be auto, builtin, file, raw, sixel or kitty.
# Must be auto, builtin, file, raw, sixel, kitty or chafa.
# Default is auto.
#--logo-type auto
# Logo width option:
# Sets the width of the logos (in characters) if the logo is an image.
# Sets the width of the logo (in characters) if the logo is an image.
# Must be a positive integer.
# Default is 65.
#--logo-width 65
# Logo height option:
# Sets the height of the logo (in characters) if the logo is an image.
# Must be a positive integer.
# Default is 0 (keeps aspect ration).
#--logo-height 0
# Logo color options:
# Overwrite a color in the logo. Also works for user provided logos.
# In the user logo, they replace $[1-9]. Use $$ to print a single $ sign.
@@ -227,6 +233,7 @@
#--lib-DConf /usr/lib/libdconf.so
#--lib-DBus /usr/lib/libdbus-1.so
#--lib-XFConf /usr/lib/libxfconf-0.so
#--lib-rpm /usr/lib/librpm.so
#--lib-sqlite3 /usr/lib/libsqlite3.so
#--lib-imagemagick /usr/lib/libMagickCore-7.Q16HDRI.so
#--lib-z /usr/lib/libz.so
#--lib-chafa /usr/lib/libchafa.so
+5 -2
View File
@@ -21,8 +21,9 @@ General options:
Logo options:
-l,--logo <logo>: set the logo to use. The type is specified by --logo-type. If default: the name of a builtin logo or a path to a file
--logo-type <type>: set the type of the logo given. Must be auto, builtin, file, raw, sixel or kitty.
--logo-type <type>: set the type of the logo given. Must be auto, builtin, file, raw, sixel, kitty or chafa.
--logo-width <width>: set the width of the logo (in characters), if it is an image
--logo-height <height>: set the height of the logo (in characters), if it is an image
--logo-color-[1-9] <color>: overwrite a color in the logo
--logo-padding <padding>: set the padding on the left and the right of the logo
--logo-padding-left <padding>: set the padding on the left of the logo
@@ -30,6 +31,7 @@ Logo options:
--logo-print-remaining <?value>: weather to print the remaining logo, if it has more lines than modules to display
--sixel <file>: short for --logo-type sixel --logo <file>
--kitty <file>: short for --logo-type kitty --logo <file>
--chafa <file>: short for --logo-type chafa --logo <file>
--file <file>: short for --logo-type file --logo <file>
--raw <file>: short for --logo-type raw --logo <file>
@@ -120,9 +122,10 @@ Library options: Set the path of a library to load
--lib-DConf <path>
--lib-DBus <path>
--lib-XFConf <path>
--lib-RPM <path>
--lib-sqlite3 <path>
--lib-imagemagick <path>
--lib-z <path>
--lib-chafa <path>
Module specific options:
--separator-string <str>: Set the string printed by the separator module
+4 -4
View File
@@ -213,15 +213,15 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc)
return false;
bool res = xcbRandrHandleMode(data, crtcInfoReply->mode);
free(crtcInfoReply);
return res ? true : ffdsAppendResolution(
res = res ? true : ffdsAppendResolution(
data->result,
(uint32_t) crtcInfoReply->width,
(uint32_t) crtcInfoReply->height,
data->defaultRefreshRate
);
free(crtcInfoReply);
return res;
}
static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output)
+4 -4
View File
@@ -161,15 +161,15 @@ static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc)
return false;
bool res = xrandrHandleMode(data, crtcInfo->mode);
data->ffXRRFreeCrtcInfo(crtcInfo);
return res ? true : ffdsAppendResolution(
res = res ? true : ffdsAppendResolution(
data->result,
(uint32_t) crtcInfo->width,
(uint32_t) crtcInfo->height,
data->defaultRefreshRate
);
data->ffXRRFreeCrtcInfo(crtcInfo);
return res;
}
static bool xrandrHandleOutput(XrandrData* data, RROutput output)
+17 -53
View File
@@ -69,23 +69,14 @@ static void detectGTKFromDConf(FFinstance* instance, FFGTKResult* result)
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;
}
//Fallback + Gnome impl
if(themeName == NULL)
else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Gnome") == 0)
{
themeName = ffSettingsGet(instance, "/org/gnome/desktop/interface/gtk-theme", "org.gnome.desktop.interface", NULL, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue;
if(iconsName == NULL)
iconsName = ffSettingsGet(instance, "/org/gnome/desktop/interface/icon-theme", "org.gnome.desktop.interface", NULL, "icon-theme", FF_VARIANT_TYPE_STRING).strValue;
if(fontName == NULL)
fontName = ffSettingsGet(instance, "/org/gnome/desktop/interface/font-name", "org.gnome.desktop.interface", NULL, "font-name", FF_VARIANT_TYPE_STRING).strValue;
if(cursorTheme == NULL)
cursorTheme = ffSettingsGet(instance, "/org/gnome/desktop/interface/cursor-theme", "org.gnome.desktop.interface", NULL, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue;
if(cursorSize <= 0)
cursorSize = ffSettingsGet(instance, "/org/gnome/desktop/interface/cursor-size", "org.gnome.desktop.interface", NULL, "cursor-size", FF_VARIANT_TYPE_INT).intValue;
}
pthread_mutex_unlock(&mutex);
applyGTKDConfSettings(result, themeName, iconsName, fontName, cursorTheme, cursorSize);
@@ -146,41 +137,8 @@ static void detectGTKFromConfigDir(FFstrbuf* configDir, const char* version, FFG
ffStrbufSubstrBefore(configDir, configDirLength);
}
static void detectGTK(FFinstance* instance, const char* version, const char* envVariable, FFGTKResult* result)
static void detectGTK(FFinstance* instance, const char* version, FFGTKResult* result)
{
FFstrbuf buffer;
ffStrbufInitA(&buffer, 128);
// From ENV: GTK*_RC_FILES
ffStrbufSetS(&buffer, getenv(envVariable));
uint32_t startIndex = 0;
while (startIndex < buffer.length)
{
uint32_t colonIndex = ffStrbufNextIndexC(&buffer, startIndex, ':');
buffer.chars[colonIndex] = '\0';
detectGTKFromConfigFile(buffer.chars + startIndex, result);
if(allPropertiesSet(result))
{
ffStrbufDestroy(&buffer);
return;
}
startIndex = colonIndex + 1;
}
//From DConf / GSettings
detectGTKFromDConf(instance, result);
if(allPropertiesSet(result))
{
ffStrbufDestroy(&buffer);
return;
}
//From config dirs
//We need to do this because we use multiple threads on configDirs
FFstrbuf baseDirCopy;
ffStrbufInitA(&baseDirCopy, 64);
@@ -191,14 +149,20 @@ static void detectGTK(FFinstance* instance, const char* version, const char* env
ffStrbufSet(&baseDirCopy, baseDir);
detectGTKFromConfigDir(&baseDirCopy, version, result);
if(allPropertiesSet(result))
break;
{
ffStrbufDestroy(&baseDirCopy);
return;
}
}
ffStrbufDestroy(&baseDirCopy);
ffStrbufDestroy(&buffer);
//Mate, Cinnamon and Gnome use dconf to save theme config
//On other DEs, this will do nothing
detectGTKFromDConf(instance, result);
}
#define FF_CALCULATE_GTK_IMPL(version) \
#define FF_DETECT_GTK_IMPL(version) \
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; \
static FFGTKResult result; \
static bool init = false; \
@@ -213,23 +177,23 @@ static void detectGTK(FFinstance* instance, const char* version, const char* env
ffStrbufInit(&result.font); \
ffStrbufInit(&result.cursor); \
ffStrbufInit(&result.cursorSize); \
detectGTK(instance, #version, "GTK"#version"_RC_FILES", &result); \
detectGTK(instance, #version, &result); \
pthread_mutex_unlock(&mutex); \
return &result;
const FFGTKResult* ffDetectGTK2(FFinstance* instance)
{
FF_CALCULATE_GTK_IMPL(2)
FF_DETECT_GTK_IMPL(2)
}
const FFGTKResult* ffDetectGTK3(FFinstance* instance)
{
FF_CALCULATE_GTK_IMPL(3)
FF_DETECT_GTK_IMPL(3)
}
const FFGTKResult* ffDetectGTK4(FFinstance* instance)
{
FF_CALCULATE_GTK_IMPL(4)
FF_DETECT_GTK_IMPL(4)
}
#undef FF_CALCULATE_GTK_IMPL
+6 -2
View File
@@ -4,6 +4,7 @@
#include <pthread.h>
#define FF_DBUS_MPRIS_PREFIX "org.mpris.MediaPlayer2."
#define FF_DBUS_TIMEOUT_MILLISECONDS 35
#ifdef FF_HAVE_DBUS
#include <dbus/dbus.h>
@@ -68,8 +69,11 @@ static bool getValue(DBusMessageIter* iter, FFstrbuf* result, DBusData* data)
while(true)
{
if((foundAValue = getValue(&subIter, result, data)))
if(getValue(&subIter, result, data))
{
foundAValue = true;
ffStrbufAppendS(result, ", ");
}
FF_DBUS_ITER_CONTINUE(subIter);
}
@@ -83,7 +87,7 @@ static bool getValue(DBusMessageIter* iter, FFstrbuf* result, DBusData* data)
static DBusMessage* getReply(DBusMessage* request, DBusData* data)
{
DBusPendingCall* pendingCall = NULL;
dbus_bool_t succesfull = data->ffdbus_connection_send_with_reply(data->connection, request, &pendingCall, DBUS_TIMEOUT_USE_DEFAULT);
dbus_bool_t succesfull = data->ffdbus_connection_send_with_reply(data->connection, request, &pendingCall, FF_DBUS_TIMEOUT_MILLISECONDS);
data->ffdbus_message_unref(request);
if(!succesfull || pendingCall == NULL)
return NULL;
+66
View File
@@ -1,5 +1,6 @@
#include "fastfetch.h"
#include <string.h>
#include <pthread.h>
#if !defined(__ANDROID__)
@@ -26,6 +27,67 @@ static void parseFile(const char* fileName, FFOSResult* result)
});
}
static void getUbuntuFlavour(FFOSResult* result)
{
const char* xdgConfigDirs = getenv("XDG_CONFIG_DIRS");
if(!ffStrSet(xdgConfigDirs))
return;
if(strstr(xdgConfigDirs, "kde") != NULL || strstr(xdgConfigDirs, "plasma") != NULL)
{
ffStrbufSetS(&result->name, "Kubuntu");
ffStrbufSetS(&result->prettyName, "Kubuntu");
ffStrbufSetS(&result->id, "kubuntu");
ffStrbufSetS(&result->idLike, "ubuntu");
return;
}
if(strstr(xdgConfigDirs, "xfce") != NULL || strstr(xdgConfigDirs, "xubuntu") != NULL)
{
ffStrbufSetS(&result->name, "Xubuntu");
ffStrbufSetS(&result->prettyName, "Xubuntu");
ffStrbufSetS(&result->id, "xubuntu");
ffStrbufSetS(&result->idLike, "ubuntu");
return;
}
if(strstr(xdgConfigDirs, "lxde") != NULL || strstr(xdgConfigDirs, "lubuntu") != NULL)
{
ffStrbufSetS(&result->name, "Lubuntu");
ffStrbufSetS(&result->prettyName, "Lubuntu");
ffStrbufSetS(&result->id, "lubuntu");
ffStrbufSetS(&result->idLike, "ubuntu");
return;
}
if(strstr(xdgConfigDirs, "budgie") != NULL)
{
ffStrbufSetS(&result->name, "Ubuntu Budgie");
ffStrbufSetS(&result->prettyName, "Ubuntu Budgie");
ffStrbufSetS(&result->id, "ubuntu-budgie");
ffStrbufSetS(&result->idLike, "ubuntu");
return;
}
if(strstr(xdgConfigDirs, "mate") != NULL)
{
ffStrbufSetS(&result->name, "Ubuntu MATE");
ffStrbufSetS(&result->prettyName, "Ubuntu MATE");
ffStrbufSetS(&result->id, "ubuntu-mate");
ffStrbufSetS(&result->idLike, "ubuntu");
return;
}
if(strstr(xdgConfigDirs, "studio") != NULL)
{
ffStrbufSetS(&result->name, "Ubuntu Studio");
ffStrbufSetS(&result->prettyName, "Ubuntu Studio");
ffStrbufSetS(&result->id, "ubuntu-studio");
ffStrbufSetS(&result->idLike, "ubuntu");
return;
}
}
#endif
const FFOSResult* ffDetectOS(const FFinstance* instance)
@@ -68,6 +130,10 @@ const FFOSResult* ffDetectOS(const FFinstance* instance)
parseFile(FASTFETCH_TARGET_DIR_USR"/lib/os-release", &result);
parseFile(FASTFETCH_TARGET_DIR_ROOT"/etc/lsb-release", &result);
}
if(ffStrbufIgnCaseCompS(&result.id, "ubuntu") == 0)
getUbuntuFlavour(&result);
#else
ffStrbufSetS(&result.name, "Android");
ffStrbufSetS(&result.id, "android");
+13 -2
View File
@@ -735,6 +735,8 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
instance->config.logoType = FF_LOGO_TYPE_SIXEL;
else if(strcasecmp(value, "kitty") == 0)
instance->config.logoType = FF_LOGO_TYPE_KITTY;
else if(strcasecmp(value, "chafa") == 0)
instance->config.logoType = FF_LOGO_TYPE_CHAFA;
else
{
fprintf(stderr, "Error: unknown logo type: %s\n", value);
@@ -757,6 +759,8 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
}
else if(strcasecmp(key, "--logo-width") == 0)
instance->config.logoWidth = optionParseUInt32(key, value);
else if(strcasecmp(key, "--logo-height") == 0)
instance->config.logoHeight = optionParseUInt32(key, value);
else if(strcasecmp(key, "--logo-padding") == 0)
{
uint32_t padding = optionParseUInt32(key, value);
@@ -789,6 +793,11 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
optionParseString(key, value, &instance->config.logoSource);
instance->config.logoType = FF_LOGO_TYPE_RAW;
}
else if(strcasecmp(key, "--chafa") == 0)
{
optionParseString(key, value, &instance->config.logoSource);
instance->config.logoType = FF_LOGO_TYPE_CHAFA;
}
///////////////////
//Display options//
@@ -982,12 +991,14 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
optionParseString(key, value, &instance->config.libDBus);
else if(strcasecmp(key, "--lib-XFConf") == 0)
optionParseString(key, value, &instance->config.libXFConf);
else if(strcasecmp(key, "--lib-rpm") == 0)
optionParseString(key, value, &instance->config.librpm);
else if(strcasecmp(key, "--lib-sqlite") == 0 || strcasecmp(key, "--lib-sqlite3") == 0)
optionParseString(key, value, &instance->config.libSQLite3);
else if(strcasecmp(key, "--lib-imagemagick") == 0)
optionParseString(key, value, &instance->config.libImageMagick);
else if(strcasecmp(key, "--lib-z") == 0)
optionParseString(key, value, &instance->config.libZ);
else if(strcasecmp(key, "--lib-chafa") == 0)
optionParseString(key, value, &instance->config.libChafa);
//////////////////
//Module options//
+8 -3
View File
@@ -38,7 +38,8 @@ typedef enum FFLogoType
FF_LOGO_TYPE_FILE, //Raw text file, printed as is.
FF_LOGO_TYPE_RAW, //Raw text file, printed with color codes replacement.
FF_LOGO_TYPE_SIXEL, //Image file, printed as sixel codes.
FF_LOGO_TYPE_KITTY //Image file, printed as kitty graphics protocol
FF_LOGO_TYPE_KITTY, //Image file, printed as kitty graphics protocol
FF_LOGO_TYPE_CHAFA //Image file, printed as ascii art using libchafa
} FFLogoType;
typedef struct FFconfig
@@ -47,6 +48,7 @@ typedef struct FFconfig
FFLogoType logoType;
FFstrbuf logoColors[FASTFETCH_LOGO_MAX_COLORS];
uint32_t logoWidth;
uint32_t logoHeight;
uint32_t logoPaddingLeft;
uint32_t logoPaddingRight;
bool logoPrintRemaining;
@@ -135,9 +137,10 @@ typedef struct FFconfig
FFstrbuf libDConf;
FFstrbuf libDBus;
FFstrbuf libXFConf;
FFstrbuf librpm;
FFstrbuf libSQLite3;
FFstrbuf libImageMagick;
FFstrbuf libZ;
FFstrbuf libChafa;
FFstrbuf diskFolders;
@@ -405,7 +408,7 @@ bool ffWriteFileContent(const char* fileName, const FFstrbuf* buffer);
bool ffFileExists(const char* fileName, mode_t mode);
void ffSuppressIO(bool suppress); // Not thread safe!
void ffGetTerminalResponse(const char* request, char end, const char* format, ...);
void ffGetTerminalResponse(const char* request, const char* format, ...);
//common/printing.c
void ffPrintError(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, const FFstrbuf* formatString, uint32_t numFormatArgs, const char* message, ...);
@@ -463,6 +466,8 @@ FFvariant ffSettingsGetGSettings(FFinstance* instance, const char* schemaName, c
FFvariant ffSettingsGet(FFinstance* instance, const char* dconfKey, const char* gsettingsSchemaName, const char* gsettingsPath, const char* gsettingsKey, FFvarianttype type);
FFvariant ffSettingsGetXFConf(FFinstance* instance, const char* channelName, const char* propertyName, FFvarianttype type);
int ffSettingsGetSQLite3Int(FFinstance* instance, const char* dbPath, const char* query);
#ifdef __ANDROID__
bool ffSettingsGetAndroidProperty(const char* propName, FFstrbuf* result);
#endif
+178 -2
View File
@@ -22,7 +22,7 @@ typedef struct FFlogo
static const FFlogo* getLogoUnknown()
{
FF_LOGO_INIT
FF_LOGO_NAMES("unkown", "question mark", "?")
FF_LOGO_NAMES("unknown", "question mark", "?")
FF_LOGO_LINES(
" ________\n"
" _jgN########Ngg_\n"
@@ -408,6 +408,82 @@ static const FFlogo* getLogoDebianSmall()
FF_LOGO_RETURN
}
static const FFlogo* getLogoDevuan()
{
FF_LOGO_INIT
FF_LOGO_NAMES("devuan", "devuan-linux")
FF_LOGO_LINES(
" ..,,;;;::;,..\n"
" `':ddd;:,.\n"
" `'dPPd:,.\n"
" `:b$$b`.\n"
" 'P$$$d`\n"
" .$$$$$`\n"
" ;$$$$$P\n"
" .:P$$$$$$`\n"
" .,:b$$$$$$$;'\n"
" .,:dP$$$$$$$$b:'\n"
" .,:;db$$$$$$$$$$Pd'`\n"
" ,db$$$$$$$$$$$$$$b:'`\n"
":$$$$$$$$$$$$b:'`\n"
" `$$$$$bd:''`\n"
" `'''`\n"
)
FF_LOGO_COLORS(
"35" //magenta
)
FF_LOGO_RETURN
}
static const FFlogo* getLogoDevuanSmall()
{
FF_LOGO_INIT
FF_LOGO_NAMES("devuan_small", "devuan-linux-small")
FF_LOGO_LINES(
" ..:::.\n"
" ..-==-\n"
" .+#:\n"
" =@@\n"
" :+%@#:\n"
".:=+#@@%*:\n"
"#@@@#=:\n"
)
FF_LOGO_COLORS(
"34" //blue
)
FF_LOGO_RETURN
}
static const FFlogo* getLogoDeepin()
{
FF_LOGO_INIT
FF_LOGO_NAMES("deepin", "deepin-linux")
FF_LOGO_LINES(
"$1 ............\n"
" .';;;;;. .,;,.\n"
" .,;;;;;;;. ';;;;;;;.\n"
" .;::::::::' .,::;;,''''',.\n"
" ,'.:::::::: .;;'. ';\n"
" ;' 'cccccc, ,' :: '.. .:\n"
" ,, :ccccc. ;: .c, '' :. ,;\n"
".l. cllll' ., .lc :; .l' l.\n"
".c :lllc ;cl: .l' .ll. :'\n"
".l 'looc. . ,o: 'oo' c,\n"
".o. .:ool::coc' .ooo' o.\n"
" :: ..... .;dddo ;c\n"
" l:... .';lddddo. ,o\n"
" lxxxxxdoolllodxxxxxxxxxc :l\n"
" ,dxxxxxxxxxxxxxxxxxxl. 'o,\n"
" ,dkkkkkkkkkkkkko;. .;o;\n"
" .;okkkkkdl;. .,cl:.\n"
" .,:cccccccc:,."
)
FF_LOGO_COLORS(
"32" //green
)
FF_LOGO_RETURN
}
static const FFlogo* getLogoEndeavour()
{
FF_LOGO_INIT
@@ -632,6 +708,39 @@ static const FFlogo* getLogoKDENeon()
FF_LOGO_RETURN
}
static const FFlogo* getLogoKubuntu()
{
FF_LOGO_INIT
FF_LOGO_NAMES("kubuntu", "kubuntu-linux", "kde-ubuntu", "ubuntu-kde", "ubuntu-plasma")
FF_LOGO_LINES(
"$1 `.:/ossyyyysso/:.\n"
" .:oyyyyyyyyyyyyyyyyyyo:`\n"
" -oyyyyyyyo$2dMMy$1yyyyyyysyyyyo-\n"
" -syyyyyyyyyy$2dMMy$1oyyyy$2dmMMy$1yyyys-\n"
" oyyys$2dMy$1syyyy$2dMMMMMMMMMMMMMy$1yyyyyyo\n"
" `oyyyy$2dMMMMy$1syysoooooo$2dMMMMy$1yyyyyyyyo`\n"
" oyyyyyy$2dMMMMy$1yyyyyyyyyyys$2dMMy$1sssssyyyo\n"
"-yyyyyyyy$2dMy$1syyyyyyyyyyyyyys$2dMMMMMy$1syyy-\n"
"oyyyysoo$2dMy$1yyyyyyyyyyyyyyyyyy$2dMMMMy$1syyyo\n"
"yyys$2dMMMMMy$1yyyyyyyyyyyyyyyyyysosyyyyyyyy\n"
"yyys$2dMMMMMy$1yyyyyyyyyyyyyyyyyyyyyyyyyyyyy\n"
"oyyyyysos$2dy$1yyyyyyyyyyyyyyyyyy$2dMMMMy$1syyyo\n"
"-yyyyyyyy$2dMy$1syyyyyyyyyyyyyys$2dMMMMMy$1syyy-\n"
" oyyyyyy$2dMMMy$1syyyyyyyyyyys$2dMMy$1oyyyoyyyo\n"
" `oyyyy$2dMMMy$1syyyoooooo$2dMMMMy$1oyyyyyyyyo\n"
" oyyysyyoyyyys$2dMMMMMMMMMMMy$1yyyyyyyo\n"
" -syyyyyyyyy$2dMMMy$1syyy$2dMMMy$1syyyys-\n"
" -oyyyyyyy$2dMMy$1yyyyyysosyyyyo-\n"
" ./oyyyyyyyyyyyyyyyyyyo/.\n"
" `.:/oosyyyysso/:.`"
)
FF_LOGO_COLORS(
"34", //blue
"37" //white
)
FF_LOGO_RETURN
}
static const FFlogo* getLogoLinux()
{
FF_LOGO_INIT
@@ -1112,6 +1221,67 @@ static const FFlogo* getLogoRedHatEnterpriseLinux()
FF_LOGO_RETURN
}
static const FFlogo* getLogoRedstarOS()
{
FF_LOGO_INIT
FF_LOGO_NAMES("redstar", "redstar-os", "redstaros", "redstaros-linux", "redstar-os-linux")
FF_LOGO_LINES(
"$1 ..\n"
" .oK0l\n"
" :0KKKKd.\n"
" .xKO0KKKKd\n"
" ,Od' .d0000l\n"
" .c;. .'''... ..'.\n"
".,:cloddxxxkkkkOOOOkkkkkkkkxxxxxxxxxkkkx:\n"
";kOOOOOOOkxOkc'...',;;;;,,,'',;;:cllc:,.\n"
" .okkkkd,.lko .......',;:cllc:;,,'''''.\n"
" .cdo. :xd' cd:. ..';'',,,'',,;;;,'.\n"
" . .ddl.;doooc'..;oc;'..';::;,'.\n"
" coo;.oooolllllllcccc:'. .\n"
" .ool''lllllccccccc:::::;.\n"
" ;lll. .':cccc:::::::;;;;'\n"
" :lcc:'',..';::::;;;;;;;,,.\n"
" :cccc::::;...';;;;;,,,,,,.\n"
" ,::::::;;;,'. ..',,,,'''.\n"
" ........ ......"
)
FF_LOGO_COLORS(
"31" //red
)
FF_LOGO_RETURN
}
static const FFlogo* getLogoRockyLinux()
{
FF_LOGO_INIT
FF_LOGO_NAMES("rocky", "rocky-linux", "rockylinux")
FF_LOGO_LINES(
" __wgliliiligw_,\n"
" _williiiiiiliilililw,\n"
" _%iiiiiilililiiiiiiiiiii_\n"
" .Qliiiililiiiiiiililililiilm.\n"
" _iiiiiliiiiiililiiiiiiiiiiliil,\n"
" .lililiiilililiiiilililililiiiii,\n"
"_liiiiiiliiiiiiiliiiiiF{iiiiiilili,\n"
"jliililiiilililiiili@` ~ililiiiiiL\n"
"iiiliiiiliiiiiiili>` ~liililii\n"
"liliiiliiilililii` -9liiiil\n"
"iiiiiliiliiiiii~ ''4lili\n"
"4ililiiiiilil~| -w, )4lf\n"
"-liiiiililiF' _liig, )'\n"
" )iiiliii@` _QIililig,\n"
" )iiii>` .Qliliiiililw\n"
" )<>~ .mliiiiiliiiiiil,\n"
" _gllilililiililii~\n"
" giliiiiiiiiiiiiT`\n"
" -^~$ililili@~~'"
)
FF_LOGO_COLORS(
"32" //green
)
FF_LOGO_RETURN
}
static const FFlogo* getLogoUbuntu()
{
FF_LOGO_INIT
@@ -1261,7 +1431,10 @@ static GetLogoMethod* getLogos()
getLogoCentOS,
getLogoCentOSSmall,
getLogoDebian,
getLogoDevuan,
getLogoDevuanSmall,
getLogoDebianSmall,
getLogoDeepin,
getLogoEndeavour,
getLogoFedora,
getLogoFedoraSmall,
@@ -1270,6 +1443,7 @@ static GetLogoMethod* getLogos()
getLogoGentoo,
getLogoGentooSmall,
getLogoKDENeon,
getLogoKubuntu,
getLogoLinux,
getLogoManjaro,
getLogoManjaroSmall,
@@ -1288,6 +1462,8 @@ static GetLogoMethod* getLogos()
getLogoReborn,
getLogoRebornSmall,
getLogoRedHatEnterpriseLinux,
getLogoRedstarOS,
getLogoRockyLinux,
getLogoUbuntu,
getLogoUbuntuSmall,
getLogoVoid,
@@ -1337,7 +1513,7 @@ static const FFlogo* detectBuiltinLogoWithVersion(const FFstrbuf* versionString,
if(logoHasName(newLogo, name->chars)) \
{ \
long version = strtol(versionString->chars, NULL, 10); \
return (version == 0 || version == LONG_MAX || version == LONG_MIN || version > ver) ? newLogo : oldLogo; \
return (version == 0 || version == LONG_MAX || version == LONG_MIN || version >= ver) ? newLogo : oldLogo; \
}
FF_PRINT_LOGO_VERSIONED_IF_EXISTS(getLogoFedora(), getLogoFedoraOld(), 34)
+264 -97
View File
@@ -5,13 +5,16 @@
#define FF_KITTY_MAX_CHUNK_SIZE 4096
#define FF_CACHE_FILE_HEIGHT "height"
#define FF_CACHE_FILE_WIDTH "width"
#define FF_CACHE_FILE_SIXEL "sixel"
#define FF_CACHE_FILE_KITTY_COMPRESSED "kittyc"
#define FF_CACHE_FILE_KITTY_UNCOMPRESSED "kittyu"
#define FF_CACHE_FILE_CHAFA "chafa"
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#ifdef FF_HAVE_ZLIB
#include <zlib.h>
@@ -79,42 +82,54 @@ static inline bool checkAllocationResult(void* data, size_t length)
return true;
}
static void finishPrinting(FFinstance* instance, const FFLogoRequestData* requestData)
static inline uint32_t simpleCeil(double value)
{
instance->state.logoWidth = (uint32_t) (requestData->imagePixelWidth / requestData->characterPixelWidth) + instance->config.logoPaddingLeft + instance->config.logoPaddingRight;
instance->state.logoHeight = (uint32_t) (requestData->imagePixelHeight / requestData->characterPixelHeight);
//Seems to be required on all consoles that support sixel. TBH i don't know why.
if(requestData->type == FF_LOGO_TYPE_SIXEL)
instance->state.logoHeight += 1;
fputs("\033[9999999D", stdout);
printf("\033[%uA", instance->state.logoHeight);
uint32_t result = (uint32_t) value;
return value == (double) result ? result : result + 1;
}
static void writeResult(FFinstance* instance, FFLogoRequestData* requestData, const FFstrbuf* result, const char* cacheFileName)
static void writeCacheStrbuf(FFLogoRequestData* requestData, const FFstrbuf* value, const char* cacheFileName)
{
uint32_t cacheDirLength = requestData->cacheDir.length;
ffStrbufAppendS(&requestData->cacheDir, cacheFileName);
ffWriteFileContent(requestData->cacheDir.chars, value);
ffStrbufSubstrBefore(&requestData->cacheDir, cacheDirLength);
}
static void writeCacheUint32(FFLogoRequestData* requestData, uint32_t value, const char* cacheFileName)
{
FFstrbuf content;
content.chars = (char*) &value;
content.length = sizeof(value);
writeCacheStrbuf(requestData, &content, cacheFileName);
}
static void printImagePixels(FFinstance* instance, FFLogoRequestData* requestData, const FFstrbuf* result, const char* cacheFileName)
{
//Calculate character dimensions
instance->state.logoWidth = requestData->logoCharacterWidth + instance->config.logoPaddingLeft + instance->config.logoPaddingRight;
instance->state.logoHeight = requestData->logoCharacterHeight;
if(requestData->type == FF_LOGO_TYPE_KITTY)
instance->state.logoHeight -= 1;
//Write cache files
writeCacheStrbuf(requestData, result, cacheFileName);
if(instance->config.logoWidth == 0)
writeCacheUint32(requestData, instance->state.logoWidth, FF_CACHE_FILE_WIDTH);
if(instance->config.logoHeight == 0)
writeCacheUint32(requestData, instance->state.logoHeight, FF_CACHE_FILE_HEIGHT);
//Write result to stdout
ffPrintCharTimes(' ', instance->config.logoPaddingLeft);
fflush(stdout);
ffWriteFDContent(STDOUT_FILENO, result);
//Write result to cache file
uint32_t cacheDirLength = requestData->cacheDir.length;
ffStrbufAppendS(&requestData->cacheDir, cacheFileName);
ffWriteFileContent(requestData->cacheDir.chars, result);
ffStrbufSubstrBefore(&requestData->cacheDir, cacheDirLength);
//Write height cache file
ffStrbufAppendS(&requestData->cacheDir, FF_CACHE_FILE_HEIGHT);
FFstrbuf content;
content.chars = (char*) &requestData->imagePixelHeight;
content.length = sizeof(requestData->imagePixelHeight);
ffWriteFileContent(requestData->cacheDir.chars, &content);
ffStrbufSubstrBefore(&requestData->cacheDir, cacheDirLength);
//Write escape codes to stdout
finishPrinting(instance, requestData);
//Go to upper left corner
fputs("\033[9999999D", stdout);
printf("\033[%uA", instance->state.logoHeight);
}
static bool printImageSixel(FFinstance* instance, FFLogoRequestData* requestData, const ImageData* imageData)
@@ -130,7 +145,7 @@ static bool printImageSixel(FFinstance* instance, FFLogoRequestData* requestData
result.chars = (char*) blob;
result.length = (uint32_t) length;
writeResult(instance, requestData, &result, FF_CACHE_FILE_SIXEL);
printImagePixels(instance, requestData, &result, FF_CACHE_FILE_SIXEL);
free(blob);
return true;
@@ -179,20 +194,79 @@ static bool printImageKitty(FFinstance* instance, FFLogoRequestData* requestData
const char* currentPos = chars;
size_t remainingLength = length;
ffStrbufAppendF(&result, "\033_Ga=T,f=32,s=%u,v=%u", requestData->imagePixelWidth, requestData->imagePixelHeight);
ffStrbufAppendF(&result, "\033_Ga=T,f=32,s=%u,v=%u", requestData->logoPixelWidth, requestData->logoPixelHeight);
if(isCompressed)
ffStrbufAppendS(&result, ",o=z");
appendKittyChunk(&result, &currentPos, &remainingLength, false);
while(remainingLength > 0)
appendKittyChunk(&result, &currentPos, &remainingLength, true);
writeResult(instance, requestData, &result, isCompressed ? FF_CACHE_FILE_KITTY_COMPRESSED : FF_CACHE_FILE_KITTY_UNCOMPRESSED);
printImagePixels(instance, requestData, &result, isCompressed ? FF_CACHE_FILE_KITTY_COMPRESSED : FF_CACHE_FILE_KITTY_UNCOMPRESSED);
ffStrbufDestroy(&result);
free(chars);
return true;
}
#ifdef FF_HAVE_CHAFA
#include <chafa/chafa.h>
static bool printImageChafa(FFinstance* instance, FFLogoRequestData* requestData, const ImageData* imageData)
{
FF_LIBRARY_LOAD(chafa, instance->config.libChafa, false, "libchafa.so", 1)
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_symbol_map_new, false)
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_symbol_map_add_by_tags, false)
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_canvas_config_new, false)
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_canvas_config_set_geometry, false)
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_canvas_config_set_symbol_map, false)
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_canvas_new, false)
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_canvas_draw_all_pixels, false)
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_canvas_print, false)
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_canvas_unref, false)
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_canvas_config_unref, false)
FF_LIBRARY_LOAD_SYMBOL(chafa, chafa_symbol_map_unref, false)
FF_LIBRARY_LOAD_SYMBOL(chafa, g_string_free, false)
imageData->ffCopyMagickString(imageData->imageInfo->magick, "RGBA", 5);
size_t length;
void* blob = imageData->ffImageToBlob(imageData->imageInfo, imageData->image, &length, imageData->exceptionInfo);
if(!checkAllocationResult(blob, length))
return false;
ChafaSymbolMap* symbolMap = ffchafa_symbol_map_new();
ffchafa_symbol_map_add_by_tags(symbolMap, CHAFA_SYMBOL_TAG_ALL);
ChafaCanvasConfig* canvasConfig = ffchafa_canvas_config_new();
ffchafa_canvas_config_set_geometry(canvasConfig, (gint) requestData->logoCharacterWidth, (gint) requestData->logoCharacterHeight);
ffchafa_canvas_config_set_symbol_map(canvasConfig, symbolMap);
ChafaCanvas* canvas = ffchafa_canvas_new(canvasConfig);
ffchafa_canvas_draw_all_pixels(
canvas,
CHAFA_PIXEL_RGBA8_UNASSOCIATED,
blob,
(gint) imageData->image->columns,
(gint) imageData->image->rows,
(gint) imageData->image->columns * 4
);
GString* str = ffchafa_canvas_print(canvas, NULL);
FFstrbuf result;
result.allocated = (uint32_t) str->allocated_len;
result.length = (uint32_t) str->len;
result.chars = str->str;
ffLogoPrint(instance, result.chars, false);
writeCacheStrbuf(requestData, &result, FF_CACHE_FILE_CHAFA);
ffg_string_free(str, TRUE);
ffchafa_canvas_unref(canvas);
ffchafa_canvas_config_unref(canvasConfig);
ffchafa_symbol_map_unref(symbolMap);
return true;
}
#endif
FFLogoImageResult ffLogoPrintImageImpl(FFinstance* instance, FFLogoRequestData* requestData, const FFIMData* imData)
{
FF_LIBRARY_LOAD_SYMBOL(imData->library, AcquireExceptionInfo, FF_LOGO_IMAGE_RESULT_INIT_ERROR)
@@ -222,31 +296,43 @@ FFLogoImageResult ffLogoPrintImageImpl(FFinstance* instance, FFLogoRequestData*
//+1, because we need to copy the null byte too
imageData.ffCopyMagickString(imageInfoIn->filename, instance->config.logoSource.chars, instance->config.logoSource.length + 1);
Image* originalImage = ffReadImage(imageInfoIn, imageData.exceptionInfo);
imageData.image = ffReadImage(imageInfoIn, imageData.exceptionInfo);
ffDestroyImageInfo(imageInfoIn);
if(originalImage == NULL)
{
ffDestroyExceptionInfo(imageData.exceptionInfo);
return FF_LOGO_IMAGE_RESULT_RUN_ERROR;
}
//imagePixelWidth is set in ffLogoPrintImageIfExists
requestData->imagePixelHeight = (uint32_t) ((requestData->imagePixelWidth / (double) originalImage->columns) * (double) originalImage->rows);
if(requestData->imagePixelHeight < 1)
{
ffDestroyImage(originalImage);
ffDestroyExceptionInfo(imageData.exceptionInfo);
return FF_LOGO_IMAGE_RESULT_RUN_ERROR;
}
imageData.image = (Image*) imData->resizeFunc(originalImage, requestData->imagePixelWidth, requestData->imagePixelHeight, imageData.exceptionInfo);
ffDestroyImage(originalImage);
if(imageData.image == NULL)
{
ffDestroyExceptionInfo(imageData.exceptionInfo);
return FF_LOGO_IMAGE_RESULT_RUN_ERROR;
}
if(requestData->logoPixelWidth == 0 && requestData->logoPixelHeight == 0)
{
requestData->logoPixelWidth = (uint32_t) imageData.image->columns;
requestData->logoPixelHeight = (uint32_t) imageData.image->rows;
}
else if(requestData->logoPixelWidth == 0)
requestData->logoPixelWidth = (uint32_t) ((double) imageData.image->columns / (double) imageData.image->rows * requestData->logoPixelHeight);
else if(requestData->logoPixelHeight == 0)
requestData->logoPixelHeight = (uint32_t) ((double) imageData.image->rows / (double) imageData.image->columns * requestData->logoPixelWidth);
requestData->logoCharacterWidth = simpleCeil((double) requestData->logoPixelWidth / requestData->characterPixelWidth);
requestData->logoCharacterHeight = simpleCeil((double) requestData->logoPixelHeight / requestData->characterPixelHeight);
if(requestData->logoPixelWidth == 0 || requestData->logoPixelHeight == 0 || requestData->logoCharacterWidth == 0 || requestData->logoCharacterHeight == 0)
{
ffDestroyImage(imageData.image);
ffDestroyExceptionInfo(imageData.exceptionInfo);
return FF_LOGO_IMAGE_RESULT_RUN_ERROR;
}
Image* resized = imData->resizeFunc(imageData.image, requestData->logoPixelWidth, requestData->logoPixelHeight, imageData.exceptionInfo);
ffDestroyImage(imageData.image);
if(resized == NULL)
{
ffDestroyExceptionInfo(imageData.exceptionInfo);
return FF_LOGO_IMAGE_RESULT_RUN_ERROR;
}
imageData.image = resized;
imageData.imageInfo = ffAcquireImageInfo();
if(imageData.imageInfo == NULL)
{
@@ -255,10 +341,16 @@ FFLogoImageResult ffLogoPrintImageImpl(FFinstance* instance, FFLogoRequestData*
return FF_LOGO_IMAGE_RESULT_RUN_ERROR;
}
bool printSuccessful;
if(requestData->type == FF_LOGO_TYPE_KITTY)
bool printSuccessful = false;
if(requestData->type == FF_LOGO_TYPE_CHAFA)
{
#ifdef FF_HAVE_CHAFA
printSuccessful = printImageChafa(instance, requestData, &imageData);
#endif
}
else if(requestData->type == FF_LOGO_TYPE_KITTY)
printSuccessful = printImageKitty(instance, requestData, &imageData);
else
else if(requestData->type == FF_LOGO_TYPE_SIXEL)
printSuccessful = printImageSixel(instance, requestData, &imageData);
ffDestroyImageInfo(imageData.imageInfo);
@@ -277,32 +369,80 @@ static int getCacheFD(FFLogoRequestData* requestData, const char* fileName)
return fd;
}
static bool printCached(FFinstance* instance, FFLogoRequestData* requestData)
static void readCachedStrbuf(FFLogoRequestData* requestData, FFstrbuf* result, const char* cacheFileName)
{
uint32_t cacheDirLength = requestData->cacheDir.length;
ffStrbufAppendS(&requestData->cacheDir, FF_CACHE_FILE_HEIGHT);
ffStrbufAppendS(&requestData->cacheDir, cacheFileName);
ffAppendFileContent(requestData->cacheDir.chars, result);
ffStrbufSubstrBefore(&requestData->cacheDir, cacheDirLength);
}
static uint32_t readCachedUint32(FFLogoRequestData* requestData, const char* cacheFileName)
{
FFstrbuf content;
ffStrbufInitA(&content, sizeof(requestData->imagePixelHeight) + 1); // +1 because strbuf is null terminated
memset(content.chars, 0, sizeof(requestData->imagePixelHeight));
ffStrbufInit(&content);
readCachedStrbuf(requestData, &content, cacheFileName);
ffAppendFileContent(requestData->cacheDir.chars, &content);
memcpy(&requestData->imagePixelHeight, content.chars, sizeof(requestData->imagePixelHeight));
uint32_t result = 0;
if(content.length != sizeof(result))
{
ffStrbufDestroy(&content);
return 0;
}
memcpy(&result, content.chars, sizeof(result));
ffStrbufDestroy(&content);
ffStrbufSubstrBefore(&requestData->cacheDir, cacheDirLength);
if(requestData->imagePixelHeight < 1)
return result;
}
static bool printCachedChars(FFinstance* instance, FFLogoRequestData* requestData)
{
FFstrbuf content;
ffStrbufInitA(&content, 32768);
if(requestData->type == FF_LOGO_TYPE_CHAFA)
readCachedStrbuf(requestData, &content, FF_CACHE_FILE_CHAFA);
if(content.length == 0)
{
ffStrbufDestroy(&content);
return false;
}
int fd;
ffLogoPrint(instance, content.chars, false);
ffStrbufDestroy(&content);
return true;
}
static bool printCachedPixel(FFinstance* instance, FFLogoRequestData* requestData)
{
requestData->logoCharacterWidth = instance->config.logoWidth;
if(requestData->logoCharacterWidth == 0)
{
requestData->logoCharacterWidth = readCachedUint32(requestData, FF_CACHE_FILE_WIDTH);
if(requestData->logoCharacterWidth == 0)
return false;
}
requestData->logoCharacterHeight = instance->config.logoHeight;
if(requestData->logoCharacterHeight == 0)
{
requestData->logoCharacterHeight = readCachedUint32(requestData, FF_CACHE_FILE_HEIGHT);
if(requestData->logoCharacterHeight == 0)
return false;
}
int fd = -1;
if(requestData->type == FF_LOGO_TYPE_KITTY)
{
fd = getCacheFD(requestData, FF_CACHE_FILE_KITTY_COMPRESSED);
if(fd == -1)
fd = getCacheFD(requestData, FF_CACHE_FILE_KITTY_UNCOMPRESSED);
}
else
else if(requestData->type == FF_LOGO_TYPE_SIXEL)
fd = getCacheFD(requestData, FF_CACHE_FILE_SIXEL);
if(fd == -1)
@@ -314,47 +454,72 @@ static bool printCached(FFinstance* instance, FFLogoRequestData* requestData)
char buffer[32768];
ssize_t readBytes;
while((readBytes = read(fd, buffer, sizeof(buffer))) > 0)
(void) write(STDOUT_FILENO, buffer, (size_t) readBytes);
FF_UNUSED(write(STDOUT_FILENO, buffer, (size_t) readBytes));
close(fd);
finishPrinting(instance, requestData);
instance->state.logoWidth = requestData->logoCharacterWidth + instance->config.logoPaddingLeft + instance->config.logoPaddingRight;
instance->state.logoHeight = requestData->logoCharacterHeight;
//Go to upper left corner
fputs("\033[9999999D", stdout);
printf("\033[%uA", instance->state.logoHeight);
return true;
}
static bool getTermInfo(struct winsize* winsize)
static bool printCached(FFinstance* instance, FFLogoRequestData* requestData)
{
//Initialize every member to 0, because it isn't guaranteed that every terminal sets them all
memset(winsize, 0, sizeof(struct winsize));
ioctl(STDOUT_FILENO, TIOCGWINSZ, winsize);
if(winsize->ws_row == 0 || winsize->ws_col == 0)
ffGetTerminalResponse("\033[18t", 't', "\033[8;%hu;%hut", &winsize->ws_row, &winsize->ws_col);
if(winsize->ws_ypixel == 0 || winsize->ws_xpixel == 0)
ffGetTerminalResponse("\033[14t", 't', "\033[4;%hu;%hut", &winsize->ws_ypixel, &winsize->ws_xpixel);
return
winsize->ws_row > 0 &&
winsize->ws_col > 0 &&
winsize->ws_ypixel > 0 &&
winsize->ws_xpixel > 0;
if(requestData->type == FF_LOGO_TYPE_CHAFA)
return printCachedChars(instance, requestData);
else
return printCachedPixel(instance, requestData);
}
bool ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type)
static bool getCharacterPixelDimensions(FFLogoRequestData* requestData)
{
struct winsize winsize;
//Initialize every member to 0, because it isn't guaranteed that every terminal sets them all
memset(&winsize, 0, sizeof(struct winsize));
ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize);
if(winsize.ws_row == 0 || winsize.ws_col == 0)
ffGetTerminalResponse("\033[18t", "\033[8;%hu;%hut", &winsize.ws_row, &winsize.ws_col);
if(winsize.ws_row == 0 || winsize.ws_col == 0)
return false;
if(winsize.ws_ypixel == 0 || winsize.ws_xpixel == 0)
ffGetTerminalResponse("\033[14t", "\033[4;%hu;%hut", &winsize.ws_ypixel, &winsize.ws_xpixel);
requestData->characterPixelWidth = winsize.ws_xpixel / (double) winsize.ws_col;
requestData->characterPixelHeight = winsize.ws_ypixel / (double) winsize.ws_row;
return requestData->characterPixelWidth > 1.0 && requestData->characterPixelHeight > 1.0;
}
FFLogoImageResult ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type)
{
//Performance optimisation
#ifndef FF_HAVE_CHAFA
if(type == FF_LOGO_TYPE_CHAFA)
return FF_LOGO_IMAGE_RESULT_INIT_ERROR;
#endif
FFLogoRequestData requestData;
if(!getTermInfo(&requestData.winsize))
return false;
requestData.type = type;
requestData.characterPixelWidth = requestData.winsize.ws_xpixel / (double) requestData.winsize.ws_col;
requestData.characterPixelHeight = requestData.winsize.ws_ypixel / (double) requestData.winsize.ws_row;
requestData.imagePixelWidth = (uint32_t) (instance->config.logoWidth * requestData.characterPixelWidth);
if(requestData.imagePixelWidth < 1)
return false;
requestData.characterPixelWidth = 1;
requestData.characterPixelHeight = 1;
if(
(type != FF_LOGO_TYPE_CHAFA || instance->config.logoWidth == 0 || instance->config.logoHeight == 0) &&
!getCharacterPixelDimensions(&requestData)
)
return FF_LOGO_IMAGE_RESULT_RUN_ERROR;
requestData.logoPixelWidth = simpleCeil((double) instance->config.logoWidth * requestData.characterPixelWidth);
requestData.logoPixelHeight = simpleCeil((double) instance->config.logoHeight * requestData.characterPixelHeight);
ffStrbufInitA(&requestData.cacheDir, PATH_MAX * 2);
ffStrbufAppend(&requestData.cacheDir, &instance->state.cacheDir);
@@ -365,19 +530,21 @@ bool ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type)
{
//We can safely return here, because if realpath failed, we surely won't be able to read the file
ffStrbufDestroy(&requestData.cacheDir);
return false;
return FF_LOGO_IMAGE_RESULT_RUN_ERROR;
}
ffStrbufRecalculateLength(&requestData.cacheDir);
if(!ffStrbufEndsWithC(&requestData.cacheDir, '/'))
ffStrbufAppendC(&requestData.cacheDir, '/');
ffStrbufAppendF(&requestData.cacheDir, "%u", requestData.imagePixelWidth);
ffStrbufAppendF(&requestData.cacheDir, "%u", requestData.logoPixelWidth);
ffStrbufAppendC(&requestData.cacheDir, '*');
ffStrbufAppendF(&requestData.cacheDir, "%u", requestData.logoPixelHeight);
ffStrbufAppendC(&requestData.cacheDir, '/');
if(!instance->config.recache && printCached(instance, &requestData))
{
ffStrbufDestroy(&requestData.cacheDir);
return true;
return FF_LOGO_IMAGE_RESULT_SUCCESS;
}
FFLogoImageResult result = FF_LOGO_IMAGE_RESULT_INIT_ERROR;
@@ -392,13 +559,13 @@ bool ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type)
#endif
ffStrbufDestroy(&requestData.cacheDir);
return result == FF_LOGO_IMAGE_RESULT_SUCCESS;
return result;
}
#else //FF_HAVE_IMAGEMAGICK{6, 7}
bool ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type)
FFLogoImageResult ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type)
{
FF_UNUSED(instance);
return false;
FF_UNUSED(instance, type);
return FF_LOGO_IMAGE_RESULT_RUN_ERROR;
}
#endif //FF_HAVE_IMAGEMAGICK{6, 7}
+7 -13
View File
@@ -3,32 +3,26 @@
#ifndef FF_INCLUDED_LOGO_SIXEL_sixel
#define FF_INCLUDED_LOGO_SIXEL_sixel
#include "fastfetch.h"
#include "../logo.h"
#if defined(FF_HAVE_IMAGEMAGICK7) || defined(FF_HAVE_IMAGEMAGICK6)
#include <sys/ioctl.h>
#define MAGICKCORE_HDRI_ENABLE 1
#define MAGICKCORE_QUANTUM_DEPTH 16
typedef enum FFLogoImageResult
{
FF_LOGO_IMAGE_RESULT_SUCCESS, //Logo printed
FF_LOGO_IMAGE_RESULT_INIT_ERROR, //Failed to load library, try again with next IM version
FF_LOGO_IMAGE_RESULT_RUN_ERROR //Failed to load / convert image, cancle whole sixel code
} FFLogoImageResult;
typedef struct FFLogoRequestData
{
FFLogoType type;
FFstrbuf cacheDir;
struct winsize winsize;
double characterPixelWidth;
double characterPixelHeight;
uint32_t imagePixelWidth;
uint32_t imagePixelHeight;
uint32_t logoPixelWidth;
uint32_t logoPixelHeight;
uint32_t logoCharacterHeight;
uint32_t logoCharacterWidth;
} FFLogoRequestData;
typedef struct FFIMData
+39 -14
View File
@@ -158,16 +158,43 @@ static void logoPrintFile(FFinstance* instance, bool doColorReplacement)
static void logoPrintDetected(FFinstance* instance)
{
if(instance->config.logoSource.length > 0)
//If no logo source is given, detect the logo from OS and print the right builtin one
if(instance->config.logoSource.length == 0)
{
if(
!ffLogoPrintBuiltinIfExists(instance) &&
!ffLogoPrintImageIfExists(instance, FF_LOGO_TYPE_KITTY)
) logoPrintFile(instance, true);
ffLogoPrintBuiltinDetected(instance);
return;
}
ffLogoPrintBuiltinDetected(instance);
//If a logo source is given, first look if it is the name of a builtin logo
if(ffLogoPrintBuiltinIfExists(instance))
return;
const FFTerminalShellResult* terminalShell = ffDetectTerminalShell(instance);
FFLogoImageResult imageResult = FF_LOGO_IMAGE_RESULT_INIT_ERROR;
//Terminals that are known to support kitty graphics protocol
//Try to load the logo as image.
if(
ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "kitty") == 0 ||
ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "konsole") == 0 ||
ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "wezterm") == 0 ||
ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "wayst") == 0
) {
imageResult = ffLogoPrintImageIfExists(instance, FF_LOGO_TYPE_KITTY);
if(imageResult == FF_LOGO_IMAGE_RESULT_SUCCESS)
return;
}
//If the logo can be loaded as an image, convert it to ascii art.
//This happens in all terminals, that don't support kitty graphics protocol
if(
imageResult != FF_LOGO_IMAGE_RESULT_RUN_ERROR &&
ffLogoPrintImageIfExists(instance, FF_LOGO_TYPE_CHAFA) == FF_LOGO_IMAGE_RESULT_SUCCESS
) return;
//Print the content of the file as logo
logoPrintFile(instance, true);
}
void ffPrintLogo(FFinstance* instance)
@@ -175,12 +202,10 @@ void ffPrintLogo(FFinstance* instance)
if(instance->config.mainColor.length == 0)
ffLogoSetMainColor(instance);
if(( //Logo type needs set logo name, but nothing was given. Print question mark
instance->config.logoType == FF_LOGO_TYPE_BUILTIN ||
instance->config.logoType == FF_LOGO_TYPE_FILE ||
instance->config.logoType == FF_LOGO_TYPE_RAW ||
instance->config.logoType == FF_LOGO_TYPE_SIXEL
) && instance->config.logoSource.length == 0)
if( //Logo type needs set logo name, but nothing was given. Print question mark
instance->config.logoType != FF_LOGO_TYPE_AUTO &&
instance->config.logoSource.length == 0
)
ffLogoPrintUnknown(instance);
else if(instance->config.logoType == FF_LOGO_TYPE_BUILTIN)
{
@@ -191,9 +216,9 @@ void ffPrintLogo(FFinstance* instance)
logoPrintFile(instance, true);
else if(instance->config.logoType == FF_LOGO_TYPE_RAW)
logoPrintFile(instance, false);
else if(instance->config.logoType == FF_LOGO_TYPE_SIXEL || instance->config.logoType == FF_LOGO_TYPE_KITTY)
else if(instance->config.logoType == FF_LOGO_TYPE_SIXEL || instance->config.logoType == FF_LOGO_TYPE_KITTY || instance->config.logoType == FF_LOGO_TYPE_CHAFA)
{
if(!ffLogoPrintImageIfExists(instance, instance->config.logoType))
if(ffLogoPrintImageIfExists(instance, instance->config.logoType) != FF_LOGO_IMAGE_RESULT_SUCCESS)
ffLogoPrintBuiltinDetected(instance);
}
else
+9 -2
View File
@@ -15,7 +15,14 @@ void ffLogoPrintUnknown(FFinstance* instance);
bool ffLogoPrintBuiltinIfExists(FFinstance* instance);
void ffLogoPrintBuiltinDetected(FFinstance* instance);
//sixel/image.c
bool ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type);
typedef enum FFLogoImageResult
{
FF_LOGO_IMAGE_RESULT_SUCCESS, //Logo printed
FF_LOGO_IMAGE_RESULT_INIT_ERROR, //Failed to load library, try again with next IM version
FF_LOGO_IMAGE_RESULT_RUN_ERROR //Failed to load / convert image, cancle whole sixel code
} FFLogoImageResult;
//image/image.c
FFLogoImageResult ffLogoPrintImageIfExists(FFinstance* instance, FFLogoType type);
#endif
+7 -43
View File
@@ -6,44 +6,6 @@
#define FF_PACKAGES_MODULE_NAME "Packages"
#define FF_PACKAGES_NUM_FORMAT_ARGS 9
#ifdef FF_HAVE_RPM
#include <rpm/rpmlib.h>
#include <rpm/rpmts.h>
#include <rpm/rpmdb.h>
#include <rpm/rpmlog.h>
static uint32_t getRpmPackageCount(FFinstance* instance)
{
FF_LIBRARY_LOAD(rpm, instance->config.librpm, 0, "librpm.so", 5)
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmReadConfigFiles, 0)
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmtsCreate, 0)
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmtsInitIterator, 0)
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmdbGetIteratorCount, 0)
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmdbFreeIterator, 0)
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmtsFree, 0)
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmlogSetMask, 0)
// Don't print any error messages
ffrpmlogSetMask(RPMLOG_MASK(RPMLOG_EMERG));
uint32_t count = 0;
rpmts ts = NULL;
rpmdbMatchIterator mi = NULL;
if (ffrpmReadConfigFiles(NULL, NULL)) goto exit;
if (!(ts = ffrpmtsCreate())) goto exit;
if (!(mi = ffrpmtsInitIterator(ts, RPMDBI_LABEL, NULL, 0))) goto exit;
count = (uint32_t) ffrpmdbGetIteratorCount(mi);
exit:
if (mi) ffrpmdbFreeIterator(mi);
if (ts) ffrpmtsFree(ts);
dlclose(rpm);
return count;
}
#endif
static uint32_t getNumElements(const char* dirname, unsigned char type)
{
DIR* dirp = opendir(dirname);
@@ -183,11 +145,13 @@ void ffPrintPackages(FFinstance* instance)
uint32_t pacman = getNumElements(FASTFETCH_TARGET_DIR_ROOT"/var/lib/pacman/local", DT_DIR);
uint32_t dpkg = getNumStrings(FASTFETCH_TARGET_DIR_ROOT"/var/lib/dpkg/status", "Status: ");
#ifdef FF_HAVE_RPM
uint32_t rpm = getRpmPackageCount(instance);
#else
uint32_t rpm = 0;
#endif
// We do our own sql querys instead of using (lib)rpm, because:
// - simply faster
// - we get package count on SUSE platforms
// - we don't need to regulary increase librpm version, which increases rapidly without providing a major version symlink
uint32_t rpm = (uint32_t) ffSettingsGetSQLite3Int(instance, "/var/lib/rpm/rpmdb.sqlite", "SELECT count(blob) FROM Packages");
if(rpm == 0)
rpm = (uint32_t) ffSettingsGetSQLite3Int(instance, "/var/cache/dnf/packages.db", "SELECT count(pkg) FROM installed");
uint32_t emerge = countFilesIn(FASTFETCH_TARGET_DIR_ROOT"/var/db/pkg", "SIZE");
uint32_t xbps = getNumElements(FASTFETCH_TARGET_DIR_ROOT"/var/db/xbps", DT_REG);
+34 -8
View File
@@ -17,17 +17,43 @@ void ffPrintUptime(FFinstance* instance)
if(days == 0 && hours == 0 && minutes == 0)
{
printf("%u seconds\n", seconds);
return;
}
else
if(days > 0)
{
if(days > 0)
printf("%u day%s%s, ", days, days <= 1 ? "" : "s", days < 100 ? "" : "(!)");
if(hours > 0)
printf("%u hour%s, ", hours, hours <= 1 ? "" : "s");
if(minutes > 0)
printf("%u min%s", minutes, minutes <= 1 ? "" : "s");
putchar('\n');
printf("%u day", days);
if(days > 1)
putchar('s');
if(days >= 100)
fputs("(!)", stdout);
if(hours > 0 || minutes > 0)
fputs(", ", stdout);
}
if(hours > 0)
{
printf("%u hour", hours);
if(hours > 1)
putchar('s');
if(minutes > 0)
fputs(", ", stdout);
}
if(minutes > 0)
{
printf("%u min", minutes);
if(minutes > 1)
putchar('s');
}
putchar('\n');
}
else
{