mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 18:32:10 +02:00
Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b87983c86b | |||
| 779dbab647 | |||
| 47373998d5 | |||
| 11809e30b5 | |||
| 35253e085c | |||
| 112e83b7c3 | |||
| c74b34aa39 | |||
| b2e0034c34 | |||
| e3cdf9d9fd | |||
| 6cdb694e33 | |||
| 83016289e9 | |||
| f9562d7132 | |||
| 2f66bc2c95 | |||
| d7c848225c | |||
| 8404ae8e70 | |||
| d75f72c8fe | |||
| 9fa00081e3 | |||
| fca37b59c8 | |||
| 2fe7476c67 | |||
| 03cbd64d8a | |||
| f65aeed96f | |||
| b63f419cde | |||
| 99aa2f7b45 | |||
| b251c32c12 | |||
| 034e23d7e3 | |||
| bba912d42e | |||
| 597652c35a | |||
| 7f67846ad9 | |||
| bc2e292e22 | |||
| 75dc228120 | |||
| bc783f6efd | |||
| 85e1d2b40c | |||
| 3338189354 | |||
| d4c836fd25 | |||
| 6787f1eba8 | |||
| eedc277bcf | |||
| d4b32eaaec | |||
| 910f63f0ad | |||
| 9a0aa2ac72 | |||
| dce81055fe | |||
| 66a4fc1600 |
@@ -41,4 +41,3 @@ Output of `fastfetch --list-features`:
|
||||
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 too much work) for you, post the output of `fastfetch --show-errors --recache --multithreading false --disable-linewrap false`.
|
||||
-->
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
name: Logo request
|
||||
about: Request a new logo
|
||||
title: ''
|
||||
labels: logo request
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
# OS
|
||||
```
|
||||
paste content of /etc/os-release here. If this file doesn't exist, describe a way to identify the distro.
|
||||
```
|
||||
|
||||
# Ascii
|
||||
```
|
||||
paste ascii art here. If you leave this empty, i will try to find the logo myself.
|
||||
```
|
||||
@@ -1,3 +1,45 @@
|
||||
# 1.6.5
|
||||
|
||||
Fixes parsing quoted values in config files
|
||||
|
||||
# 1.6.4
|
||||
|
||||
Releasing this, so fedora can package fastfetch. Thanks to @jonathanspw for doing that!
|
||||
|
||||
Features:
|
||||
* --set-keyless option (#215)
|
||||
* Replace `\n`, `\t`, `\e` and `\\` in user provided strings, just like c would do it (#215)
|
||||
* APK (Alpine Package Keeper) support (@mxkrsv, #216)
|
||||
|
||||
Logos:
|
||||
* Alma Linux (@jonathanspw, #214)
|
||||
|
||||
Bugfixes:
|
||||
* replace deprecated gethostbyname call with getaddrinfo (#217)
|
||||
|
||||
# 1.6.3
|
||||
|
||||
Fixes installing presets in their own directory (@ceamac, #212)
|
||||
|
||||
# 1.6.2
|
||||
|
||||
Releasing this, so void linux can package fastfetch.
|
||||
|
||||
Logos:
|
||||
* Rosa linux (#206)
|
||||
* KISS linux (@draumaz, #207)
|
||||
* LangitKetujuh (@hervyqa, #208)
|
||||
|
||||
Bugfixes:
|
||||
* Using musl as libc does work now (#210)
|
||||
* XBPS packages are once again printed (#209)
|
||||
* configured target dirs are applied to install directories too
|
||||
* empty XDG_* env vars don't cause a crash anymore
|
||||
|
||||
# 1.6.1
|
||||
|
||||
Fixes build on android (#205)
|
||||
|
||||
# 1.6.0
|
||||
|
||||
Features:
|
||||
|
||||
+17
-13
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs
|
||||
|
||||
project(fastfetch
|
||||
VERSION 1.6.0
|
||||
VERSION 1.6.5
|
||||
LANGUAGES C
|
||||
)
|
||||
|
||||
@@ -493,37 +493,42 @@ endif()
|
||||
# install target #
|
||||
##################
|
||||
|
||||
#https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT.html
|
||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
set(CMAKE_INSTALL_PREFIX "${TARGET_DIR_USR}" CACHE PATH "..." FORCE)
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_INSTALL_SYSCONFDIR)
|
||||
set(CMAKE_INSTALL_SYSCONFDIR "/etc")
|
||||
set(CMAKE_INSTALL_SYSCONFDIR "${TARGET_DIR_ROOT}/etc")
|
||||
endif()
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
install(
|
||||
TARGETS fastfetch flashfetch
|
||||
DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
DESTINATION "${CMAKE_INSTALL_BINDIR}"
|
||||
)
|
||||
|
||||
install(
|
||||
FILES src/data/config_system.txt
|
||||
DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/${CMAKE_PROJECT_NAME}
|
||||
FILES "${CMAKE_SOURCE_DIR}/src/data/config_system.txt"
|
||||
DESTINATION "${CMAKE_INSTALL_SYSCONFDIR}/${CMAKE_PROJECT_NAME}"
|
||||
RENAME "config.conf"
|
||||
)
|
||||
|
||||
install(
|
||||
FILES completions/bash
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/bash-completion/completions
|
||||
RENAME ${CMAKE_PROJECT_NAME}
|
||||
FILES "${CMAKE_SOURCE_DIR}/completions/bash"
|
||||
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/bash-completion/completions"
|
||||
RENAME "${CMAKE_PROJECT_NAME}"
|
||||
)
|
||||
|
||||
install(
|
||||
DIRECTORY presets
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${CMAKE_PROJECT_NAME}
|
||||
DIRECTORY "${CMAKE_SOURCE_DIR}/presets"
|
||||
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/${CMAKE_PROJECT_NAME}"
|
||||
)
|
||||
|
||||
install(
|
||||
FILES ./LICENSE
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/licenses/${CMAKE_PROJECT_NAME}
|
||||
FILES "${CMAKE_SOURCE_DIR}/LICENSE"
|
||||
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/licenses/${CMAKE_PROJECT_NAME}"
|
||||
)
|
||||
|
||||
##################
|
||||
@@ -531,7 +536,6 @@ install(
|
||||
##################
|
||||
|
||||
set(CPACK_GENERATOR "DEB;RPM;TGZ;ZIP")
|
||||
set(CPACK_PACKAGING_INSTALL_PREFIX "/usr")
|
||||
set(CPACK_SET_DESTDIR ON)
|
||||
|
||||
set(CPACK_PACKAGE_CONTACT "Linus Dierheimer <Linus@Dierheimer.de>")
|
||||
|
||||
@@ -50,7 +50,7 @@ Title, Separator, OS, Host, Kernel, Uptime, Processes, Packages, Shell, Resoluti
|
||||
|
||||
##### Logos
|
||||
```
|
||||
Alpine, Android, Arch, Arco, Artix, Bedrock, 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
|
||||
AlmaLinux, Alpine, Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, Debian, Devuan, Deepin, Endeavour, Fedora, Garuda, Gentoo, KDE Neon, KISS, Kubuntu, LangitKetujuh, Linux, Manjaro, Mint, NixOS, OpenSUSE, OpenSUSE Tumbleweed, OpenSUSE LEAP, Pop!_OS, RebornOS, RedstarOS, Rocky, Rosa, 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.
|
||||
@@ -60,7 +60,7 @@ Alpine, Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, Debian, Devuan, De
|
||||
|
||||
##### Package managers
|
||||
```
|
||||
Pacman, dpkg, rpm, emerge, xbps, nix, Flatpak, Snap
|
||||
Pacman, dpkg, rpm, emerge, xbps, nix, Flatpak, Snap, apk
|
||||
```
|
||||
|
||||
##### WM themes
|
||||
|
||||
@@ -156,6 +156,7 @@ __fastfetch_completion()
|
||||
"-s"
|
||||
"--structure"
|
||||
"--set"
|
||||
"--set-keyless"
|
||||
"--gl"
|
||||
"--os-format"
|
||||
"--os-key"
|
||||
|
||||
+8
-1
@@ -1,5 +1,6 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/caching.h"
|
||||
#include "common/parsing.h"
|
||||
#include "detection/qt.h"
|
||||
#include "detection/gtk.h"
|
||||
#include "detection/displayserver.h"
|
||||
@@ -20,7 +21,7 @@ static void initConfigDirs(FFstate* state)
|
||||
ffListInit(&state->configDirs, sizeof(FFstrbuf));
|
||||
|
||||
const char* xdgConfigHome = getenv("XDG_CONFIG_HOME");
|
||||
if(xdgConfigHome != NULL)
|
||||
if(ffStrSet(xdgConfigHome))
|
||||
{
|
||||
FFstrbuf* buffer = (FFstrbuf*) ffListAdd(&state->configDirs);
|
||||
ffStrbufInitA(buffer, 64);
|
||||
@@ -54,6 +55,12 @@ static void initConfigDirs(FFstate* state)
|
||||
uint32_t colonIndex = ffStrbufNextIndexC(&xdgConfigDirs, startIndex, ':');
|
||||
xdgConfigDirs.chars[colonIndex] = '\0';
|
||||
|
||||
if(!ffStrSet(xdgConfigDirs.chars + startIndex))
|
||||
{
|
||||
startIndex = colonIndex + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
FFstrbuf* buffer = (FFstrbuf*) ffListAdd(&state->configDirs);
|
||||
ffStrbufInitA(buffer, 64);
|
||||
ffStrbufAppendS(buffer, xdgConfigDirs.chars + startIndex);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "common/networking.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
|
||||
@@ -10,7 +11,6 @@ void ffNetworkingGetHttp(const char* host, const char* path, uint32_t timeout, F
|
||||
struct addrinfo hints = {0};
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = 0;
|
||||
|
||||
struct addrinfo* addr;
|
||||
|
||||
|
||||
+38
-2
@@ -5,6 +5,10 @@ void ffPrintLogoAndKey(FFinstance* instance, const char* moduleName, uint8_t mod
|
||||
{
|
||||
ffLogoPrintLine(instance);
|
||||
|
||||
//This is used by --set-keyless, in this case we wan't neither the module name nor the separator
|
||||
if(moduleName == NULL)
|
||||
return;
|
||||
|
||||
if(!instance->config.pipe)
|
||||
{
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET FASTFETCH_TEXT_MODIFIER_BOLT, stdout);
|
||||
@@ -26,7 +30,7 @@ void ffPrintLogoAndKey(FFinstance* instance, const char* moduleName, uint8_t mod
|
||||
ffParseFormatString(&key, customKeyFormat, 1, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_UINT8, &moduleIndex}
|
||||
});
|
||||
ffStrbufWriteTo(&key, stdout);
|
||||
ffPrintUserString(key.chars);
|
||||
ffStrbufDestroy(&key);
|
||||
}
|
||||
|
||||
@@ -49,7 +53,8 @@ void ffPrintFormatString(FFinstance* instance, const char* moduleName, uint8_t m
|
||||
if(buffer.length > 0)
|
||||
{
|
||||
ffPrintLogoAndKey(instance, moduleName, moduleIndex, customKeyFormat);
|
||||
ffStrbufPutTo(&buffer, stdout);
|
||||
ffPrintUserString(buffer.chars);
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&buffer);
|
||||
@@ -125,3 +130,34 @@ void ffPrintCharTimes(char c, uint32_t times)
|
||||
for(uint32_t i = 0; i < times; i++)
|
||||
putchar(c);
|
||||
}
|
||||
|
||||
void ffPrintUserString(const char* value)
|
||||
{
|
||||
while(*value != '\0')
|
||||
{
|
||||
if(*value != '\\')
|
||||
{
|
||||
putchar(*value);
|
||||
++value;
|
||||
continue;
|
||||
}
|
||||
|
||||
++value;
|
||||
|
||||
if(*value == 'n')
|
||||
putchar('\n');
|
||||
else if(*value == 't')
|
||||
putchar('\t');
|
||||
else if(*value == 'e')
|
||||
putchar('\e');
|
||||
else if(*value == '\\')
|
||||
putchar('\\');
|
||||
else
|
||||
{
|
||||
putchar('\\');
|
||||
putchar(*value);
|
||||
}
|
||||
|
||||
++value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,5 +13,6 @@ void ffPrintErrorString(FFinstance* instance, const char* moduleName, uint8_t mo
|
||||
void ffPrintError(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, const char* message, ...);
|
||||
void ffPrintColor(const FFstrbuf* colorValue);
|
||||
void ffPrintCharTimes(char c, uint32_t times);
|
||||
void ffPrintUserString(const char* str);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -303,4 +303,4 @@
|
||||
#--lib-egl /usr/lib/libEGL.so
|
||||
#--lib-glx /usr/lib/libGLX.so
|
||||
#--lib-osmesa /usr/lib/libOSMesa.so
|
||||
#--lib-opencl /usr/lib/libOpenCL.so
|
||||
#--lib-opencl /usr/lib/libOpenCL.so
|
||||
|
||||
@@ -43,6 +43,7 @@ Display options:
|
||||
-c,--color <color>: sets the color of the keys. Must be a linux console color code or the name of a color (+)
|
||||
--separator <str>: sets the separator between key and value. Default is a colon with a space
|
||||
--set <key=value>: hard set the value of a key
|
||||
--set-keyless <key=value>: hard set the value of a key, but don't print the key or the separator
|
||||
--show-errors <?value>: print occuring errors
|
||||
--disable-linewrap <?value>: weather to disable linewrap during the run
|
||||
--hide-cursor <?value>: weather to hide the cursor during the run
|
||||
|
||||
@@ -160,6 +160,8 @@ void ffdsConnectWayland(const FFinstance* instance, FFDisplayServerResult* resul
|
||||
#ifdef FF_HAVE_WAYLAND
|
||||
if(detectWayland(instance, result))
|
||||
return;
|
||||
#else
|
||||
FF_UNUSED(instance);
|
||||
#endif
|
||||
|
||||
const char* xdgSessionType = getenv("XDG_SESSION_TYPE");
|
||||
|
||||
@@ -107,11 +107,6 @@ static void detectGTKFromConfigFile(const char* filename, FFGTKResult* result)
|
||||
|
||||
static void detectGTKFromConfigDir(FFstrbuf* configDir, const char* version, FFGTKResult* result)
|
||||
{
|
||||
//In case of an empty env variable
|
||||
ffStrbufTrim(configDir, ' ');
|
||||
if(configDir->length == 0)
|
||||
return;
|
||||
|
||||
uint32_t configDirLength = configDir->length;
|
||||
|
||||
// <configdir>/gtk-<version>.0/settings.ini
|
||||
|
||||
+3
-1
@@ -7,7 +7,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#if !defined(__ANDROID__)
|
||||
#if __ANDROID__
|
||||
#include "common/settings.h"
|
||||
#else
|
||||
|
||||
static bool parseFile(const char* fileName, FFOSResult* result)
|
||||
{
|
||||
|
||||
+19
-3
@@ -27,9 +27,25 @@ const FFTitleResult* ffDetectTitle(const FFinstance* instance)
|
||||
ffStrbufAppendS(&result.hostname, instance->state.utsname.nodename);
|
||||
|
||||
ffStrbufInitA(&result.fqdn, HOST_NAME_MAX);
|
||||
struct hostent* host = gethostbyname(result.hostname.chars);
|
||||
if(host != NULL)
|
||||
ffStrbufAppendS(&result.fqdn, host->h_name);
|
||||
|
||||
struct addrinfo hints = {0};
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
|
||||
struct addrinfo* info = NULL;
|
||||
|
||||
if(getaddrinfo(result.hostname.chars, "80", &hints, &info) == 0)
|
||||
{
|
||||
struct addrinfo* current = info;
|
||||
while(result.fqdn.length == 0 && current != NULL)
|
||||
{
|
||||
ffStrbufAppendS(&result.fqdn, current->ai_canonname);
|
||||
current = current->ai_next;
|
||||
}
|
||||
|
||||
freeaddrinfo(info);
|
||||
}
|
||||
|
||||
if(result.fqdn.length == 0)
|
||||
ffStrbufAppend(&result.fqdn, &result.hostname);
|
||||
|
||||
|
||||
+72
-55
@@ -4,14 +4,21 @@
|
||||
#include "common/parsing.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
typedef struct CustomValue
|
||||
{
|
||||
bool printKey;
|
||||
FFstrbuf value;
|
||||
} CustomValue;
|
||||
|
||||
// Things only needed by fastfetch
|
||||
typedef struct FFdata
|
||||
{
|
||||
FFvaluestore valuestore;
|
||||
FFvaluestore customValues;
|
||||
FFstrbuf structure;
|
||||
bool loadUserConfig;
|
||||
} FFdata;
|
||||
@@ -106,7 +113,7 @@ static inline void printCommandHelp(const char* command)
|
||||
}
|
||||
else if(strcasecmp(command, "packages-format") == 0)
|
||||
{
|
||||
constructAndPrintCommandHelpFormat("packages", "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (emerge), {7} (xbps), {8} (nix-user), {9} (nix-default), {10} (flatpak), {11} (snap)", 11,
|
||||
constructAndPrintCommandHelpFormat("packages", "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (emerge), {7} (xbps), {8} (nix-system), {9} (nix-user), {10} (nix-default), {11} (apk), {12} (flatpak), {13} (snap)", 13,
|
||||
"Number of all packages",
|
||||
"Number of pacman packages",
|
||||
"Pacman branch on manjaro",
|
||||
@@ -117,6 +124,7 @@ static inline void printCommandHelp(const char* command)
|
||||
"Number of nix-system packages",
|
||||
"Number of nix-user packages",
|
||||
"Number of nix-default packages",
|
||||
"Number of apk packages",
|
||||
"Number of flatpak packages",
|
||||
"Number of snap packages"
|
||||
);
|
||||
@@ -446,58 +454,58 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
|
||||
|
||||
static void parseConfigFile(FFinstance* instance, FFdata* data, FILE* file)
|
||||
{
|
||||
char* lineStart = NULL;
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
ssize_t read;
|
||||
|
||||
FFstrbuf line;
|
||||
ffStrbufInitA(&line, 256); //The default structure line needs this size
|
||||
|
||||
while ((read = getline(&lineStart, &len, file)) != -1)
|
||||
while ((read = getline(&line, &len, file)) != -1)
|
||||
{
|
||||
ffStrbufSetS(&line, lineStart);
|
||||
ffStrbufTrimRight(&line, '\n');
|
||||
ffStrbufTrim(&line, ' ');
|
||||
char* lineStart = line;
|
||||
char* lineEnd = line + read - 1;
|
||||
|
||||
if(line.length == 0 || line.chars[0] == '#')
|
||||
//Trim line left
|
||||
while(isspace(*lineStart))
|
||||
++lineStart;
|
||||
|
||||
//Continue if line is empty or a comment
|
||||
if(*lineStart == '\0' || *lineStart == '#')
|
||||
continue;
|
||||
|
||||
uint32_t firstSpace = ffStrbufFirstIndexC(&line, ' ');
|
||||
//Trim line right
|
||||
while(lineEnd > lineStart && isspace(*lineEnd))
|
||||
--lineEnd;
|
||||
*(lineEnd + 1) = '\0';
|
||||
|
||||
if(firstSpace >= line.length)
|
||||
char* valueStart = strchr(lineStart, ' ');
|
||||
|
||||
//If the line has no white space, it is only a key
|
||||
if(valueStart == NULL)
|
||||
{
|
||||
parseOption(instance, data, line.chars, NULL);
|
||||
parseOption(instance, data, lineStart, NULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
//Separate key and value by simply replacing the first space with a \0
|
||||
char* valueStart = &line.chars[firstSpace];
|
||||
//separate the key from the value
|
||||
*valueStart = '\0';
|
||||
++valueStart;
|
||||
|
||||
//Trim whitespace at beginning of value
|
||||
while(*valueStart == ' ')
|
||||
//Trim space of value left
|
||||
while(isspace(*valueStart))
|
||||
++valueStart;
|
||||
|
||||
//If we want whitespace in values, we need to quote it. This is done to keep consistency with shell.
|
||||
if(*valueStart == '"')
|
||||
if((*valueStart == '"' || *valueStart == '\'') && *valueStart == *lineEnd && lineEnd > valueStart)
|
||||
{
|
||||
char* last = line.chars + line.length - 1;
|
||||
if(*last == '"')
|
||||
{
|
||||
++valueStart;
|
||||
*last = '\0';
|
||||
--line.length;
|
||||
}
|
||||
++valueStart;
|
||||
*lineEnd = '\0';
|
||||
--lineEnd;
|
||||
}
|
||||
|
||||
parseOption(instance, data, line.chars, valueStart);
|
||||
parseOption(instance, data, lineStart, valueStart);
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&line);
|
||||
|
||||
if(lineStart != NULL)
|
||||
free(lineStart);
|
||||
if(line != NULL)
|
||||
free(line);
|
||||
}
|
||||
|
||||
static void optionParseConfigFile(FFinstance* instance, FFdata* data, const char* key, const char* value)
|
||||
@@ -668,6 +676,32 @@ static uint32_t optionParseUInt32(const char* key, const char* value)
|
||||
return num;
|
||||
}
|
||||
|
||||
static void optionParseCustomValue(FFdata* data, const char* key, const char* value, bool printKey)
|
||||
{
|
||||
if(value == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error: usage: %s <key=value>\n", key);
|
||||
exit(411);
|
||||
}
|
||||
|
||||
char* separator = strchr(value, '=');
|
||||
|
||||
if(separator == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error: usage: %s <key=value>, '=' missing\n", key);
|
||||
exit(412);
|
||||
}
|
||||
|
||||
*separator = '\0';
|
||||
|
||||
bool created;
|
||||
CustomValue* customValue = ffValuestoreSet(&data->customValues, value, &created);
|
||||
if(created)
|
||||
ffStrbufInit(&customValue->value);
|
||||
ffStrbufSetS(&customValue->value, separator + 1);
|
||||
customValue->printKey = printKey;
|
||||
}
|
||||
|
||||
static void parseOption(FFinstance* instance, FFdata* data, const char* key, const char* value)
|
||||
{
|
||||
///////////////////////
|
||||
@@ -879,25 +913,9 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
|
||||
else if(strcasecmp(key, "-c") == 0 || strcasecmp(key, "--color") == 0)
|
||||
optionParseColor(key, value, &instance->config.mainColor);
|
||||
else if(strcasecmp(key, "--set") == 0)
|
||||
{
|
||||
if(value == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error: usage: %s <key=value>\n", key);
|
||||
exit(411);
|
||||
}
|
||||
|
||||
char* separator = strchr(value, '=');
|
||||
|
||||
if(separator == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error: usage: %s <key=value>, '=' missing\n", key);
|
||||
exit(412);
|
||||
}
|
||||
|
||||
*separator = '\0';
|
||||
|
||||
ffValuestoreSet(&data->valuestore, value, separator + 1);
|
||||
}
|
||||
optionParseCustomValue(data, key, value, true);
|
||||
else if(strcasecmp(key, "--set-keyless") == 0)
|
||||
optionParseCustomValue(data, key, value, false);
|
||||
|
||||
////////////////////////////////
|
||||
//Format + Key + Error options//
|
||||
@@ -1264,7 +1282,6 @@ static void parseArguments(FFinstance* instance, FFdata* data, int argc, const c
|
||||
{
|
||||
if(i == argc - 1 || (
|
||||
*argv[i + 1] == '-' &&
|
||||
strcasecmp(argv[i], "--offsetx") != 0 && // --offsetx allows negative values
|
||||
strcasecmp(argv[i], "--separator-string") != 0 // Separator string can start with a -
|
||||
)) {
|
||||
parseOption(instance, data, argv[i], NULL);
|
||||
@@ -1279,10 +1296,10 @@ static void parseArguments(FFinstance* instance, FFdata* data, int argc, const c
|
||||
|
||||
static void parseStructureCommand(FFinstance* instance, FFdata* data, const char* line)
|
||||
{
|
||||
const char* setValue = ffValuestoreGet(&data->valuestore, line);
|
||||
if(setValue != NULL)
|
||||
CustomValue* customValue = ffValuestoreGet(&data->customValues, line);
|
||||
if(customValue != NULL)
|
||||
{
|
||||
ffPrintCustom(instance, line, setValue);
|
||||
ffPrintCustom(instance, customValue->printKey ? line : NULL, customValue->value.chars);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1373,7 +1390,7 @@ int main(int argc, const char** argv)
|
||||
|
||||
//Data stores things only needed for the configuration of fastfetch
|
||||
FFdata data;
|
||||
ffValuestoreInit(&data.valuestore);
|
||||
ffValuestoreInit(&data.customValues, sizeof(CustomValue));
|
||||
ffStrbufInitA(&data.structure, 256);
|
||||
data.loadUserConfig = true;
|
||||
|
||||
|
||||
@@ -43,6 +43,42 @@ static const FFlogo* getLogoNone()
|
||||
FF_LOGO_RETURN
|
||||
}
|
||||
|
||||
static const FFlogo* getLogoAlmaLinux()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
FF_LOGO_NAMES("almalinux")
|
||||
FF_LOGO_LINES(
|
||||
"$1 'c:.\n"
|
||||
"$1 lkkkx, .. $2.. ,cc,\n"
|
||||
"$1 okkkk:ckkx' $2.lxkkx.okkkkd\n"
|
||||
"$1 .:llcokkx' $2:kkkxkko:xkkd,\n"
|
||||
"$1 .xkkkkdood: $2;kx, .lkxlll;\n"
|
||||
"$1 xkkx. $2xk' xkkkkk:\n"
|
||||
"$1 'xkx. $2xd .....,.\n"
|
||||
"$3 .. $1:xkl' $2:c ..''..\n"
|
||||
"$3 .dkx' $1.:ldl:'. $2' $4':lollldkkxo;\n"
|
||||
"$3 .''lkkko' $4ckkkx.\n"
|
||||
"$3'xkkkd:kkd. .. $5;' $4:kkxo.\n"
|
||||
"$3,xkkkd;kk' ,d; $5ld. $4':dkd::cc,\n"
|
||||
"$3 .,,.;xkko'.';lxo. $5dx, $4:kkk'xkkkkc\n"
|
||||
"$3 'dkkkkkxo:. $5;kx $4.kkk:;xkkd.\n"
|
||||
"$3 ..... $5.;dk:. $5lkk. $4:;,\n"
|
||||
" $5:kkkkkkkdoxkkx\n"
|
||||
" ,c,,;;;:xkkd.\n"
|
||||
" ;kkkkl...\n"
|
||||
" ;kkkkl\n"
|
||||
" ,od;";
|
||||
)
|
||||
FF_LOGO_COLORS(
|
||||
"31", // red
|
||||
"1;33", // yellow
|
||||
"34", // blue
|
||||
"1;32", // light green
|
||||
"36" // cyan
|
||||
)
|
||||
FF_LOGO_RETURN
|
||||
}
|
||||
|
||||
static const FFlogo* getLogoAlpine()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
@@ -775,6 +811,27 @@ static const FFlogo* getLogoKDENeon()
|
||||
FF_LOGO_RETURN
|
||||
}
|
||||
|
||||
static const FFlogo* getLogoKISSLinux()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
FF_LOGO_NAMES("kiss", "kiss-linux", "kisslinux")
|
||||
FF_LOGO_LINES(
|
||||
" $3 ___ \n"
|
||||
" ($2.· $3| \n"
|
||||
" ($1<> $3| \n"
|
||||
" / $2__$3 \\ \n"
|
||||
" ( $1/ \\ $3/| \n"
|
||||
"$1_$3/\\ $2__)$3/$1_$3) \n"
|
||||
"$1\\/$3-____$1\\/$2 \n"
|
||||
)
|
||||
FF_LOGO_COLORS(
|
||||
"35", //magenta
|
||||
"37", //white
|
||||
"34" //blue
|
||||
)
|
||||
FF_LOGO_RETURN
|
||||
}
|
||||
|
||||
static const FFlogo* getLogoKubuntu()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
@@ -808,6 +865,32 @@ static const FFlogo* getLogoKubuntu()
|
||||
FF_LOGO_RETURN
|
||||
}
|
||||
|
||||
static const FFlogo* getLogoLangitKetujuh()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
FF_LOGO_NAMES("l7", "langitketujuh", "LangitKetujuh")
|
||||
FF_LOGO_LINES(
|
||||
"\n"
|
||||
"\n"
|
||||
" $2. '7L7L7L7L7L7L7L7L7L7L7L7L7L7L7L7L7L7\n"
|
||||
" $2L7. '7L7L7L7L7L7L7L7L7L7L7L7L7L7L7L7\n"
|
||||
" $2L7L7L 7L7L7L7L7L7L7L7L7L7L7L7L7L7\n"
|
||||
" $2L7L7L7 L7L7L7\n"
|
||||
" $2L7L7L7 'L7L7L7L7L7L7L7L7L7L7\n"
|
||||
" $2L7L7L7 'L7L7L7L7L7L7L7L7\n"
|
||||
" $2L7L7L7 'L7L7L7L7L7L7\n"
|
||||
" $2L7L7L7 L7L7L7\n"
|
||||
" $2L7L7L7L7L7L7L7L7L7L7LL7L7L7. '7L7L7\n"
|
||||
" $2L7L7L7L7L7L7L7L7L7L7L7L7L7L7L7L. 'L7\n"
|
||||
" $2L7L7L7L7L7L7L7L7L7L7L7L7L7L7L7L7L7. '\n"
|
||||
)
|
||||
FF_LOGO_COLORS(
|
||||
"34", //blue
|
||||
"37" //white
|
||||
)
|
||||
FF_LOGO_RETURN
|
||||
}
|
||||
|
||||
static const FFlogo* getLogoLinux()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
@@ -1358,6 +1441,38 @@ static const FFlogo* getLogoRockyLinux()
|
||||
FF_LOGO_RETURN
|
||||
}
|
||||
|
||||
static const FFlogo* getLogoRosaLinux()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
FF_LOGO_NAMES("rosa", "rosa-linux", "rosalinux")
|
||||
FF_LOGO_LINES(
|
||||
" ROSAROSAROSAROSAR\n"
|
||||
" ROSA AROS\n"
|
||||
" ROS SAROSAROSAROSAR AROS\n"
|
||||
" RO ROSAROSAROSAROSAROSAR RO\n"
|
||||
" ARO AROSAROSAROSARO AROS ROS\n"
|
||||
" ARO ROSAROS OSAR ROSA ROS\n"
|
||||
" RO AROSA ROSAROSAROSA ROSAR RO\n"
|
||||
"RO ROSAR ROSAROSAROSAR R ROSARO RO\n"
|
||||
"RO ROSA AROSAROSAROSA AR ROSARO AR\n"
|
||||
"RO AROS ROSAROSAROSA ROS AROSARO AR\n"
|
||||
"RO AROS ROSAROSARO ROSARO ROSARO AR\n"
|
||||
"RO ROS AROSAROS ROSAROSA AROSAR AR\n"
|
||||
"RO ROSA ROS ROSAROSAR ROSARO RO\n"
|
||||
" RO ROS AROSAROSAROSA ROSARO AR\n"
|
||||
" ARO ROSA ROSAROSAROS AROSAR ARO\n"
|
||||
" ARO OROSA R ROSAROS ROS\n"
|
||||
" RO AROSAROS AROSAROSAR RO\n"
|
||||
" AROS AROSAROSAROSARO AROS\n"
|
||||
" ROSA SARO\n"
|
||||
" ROSAROSAROSAROSAR"
|
||||
)
|
||||
FF_LOGO_COLORS(
|
||||
"34" //blue
|
||||
)
|
||||
FF_LOGO_RETURN
|
||||
}
|
||||
|
||||
static const FFlogo* getLogoUbuntu()
|
||||
{
|
||||
FF_LOGO_INIT
|
||||
@@ -1493,6 +1608,7 @@ GetLogoMethod* ffLogoBuiltinGetAll()
|
||||
static GetLogoMethod logoMethods[] = {
|
||||
ffLogoBuiltinGetUnknown,
|
||||
getLogoNone,
|
||||
getLogoAlmaLinux,
|
||||
getLogoAlpine,
|
||||
getLogoAlpineSmall,
|
||||
getLogoAndroid,
|
||||
@@ -1520,7 +1636,9 @@ GetLogoMethod* ffLogoBuiltinGetAll()
|
||||
getLogoGentoo,
|
||||
getLogoGentooSmall,
|
||||
getLogoKDENeon,
|
||||
getLogoKISSLinux,
|
||||
getLogoKubuntu,
|
||||
getLogoLangitKetujuh,
|
||||
getLogoLinux,
|
||||
getLogoManjaro,
|
||||
getLogoManjaroSmall,
|
||||
@@ -1541,6 +1659,7 @@ GetLogoMethod* ffLogoBuiltinGetAll()
|
||||
getLogoRedHatEnterpriseLinux,
|
||||
getLogoRedstarOS,
|
||||
getLogoRockyLinux,
|
||||
getLogoRosaLinux,
|
||||
getLogoUbuntu,
|
||||
getLogoUbuntuSmall,
|
||||
getLogoVoid,
|
||||
|
||||
@@ -4,5 +4,6 @@
|
||||
void ffPrintCustom(FFinstance* instance, const char* key, const char* value)
|
||||
{
|
||||
ffPrintLogoAndKey(instance, key, 0, NULL);
|
||||
puts(value);
|
||||
ffPrintUserString(value);
|
||||
puts(FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
}
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
|
||||
#ifndef __ANDROID__
|
||||
#include "common/io.h"
|
||||
#elif
|
||||
#else
|
||||
#include <ctype.h>
|
||||
#endif
|
||||
|
||||
|
||||
+41
-8
@@ -12,7 +12,7 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
#define FF_PACKAGES_MODULE_NAME "Packages"
|
||||
#define FF_PACKAGES_NUM_FORMAT_ARGS 12
|
||||
#define FF_PACKAGES_NUM_FORMAT_ARGS 13
|
||||
|
||||
typedef struct PackageCounts
|
||||
{
|
||||
@@ -23,6 +23,7 @@ typedef struct PackageCounts
|
||||
uint32_t xbps;
|
||||
uint32_t nixSystem;
|
||||
uint32_t nixDefault;
|
||||
uint32_t apk;
|
||||
uint32_t flatpak;
|
||||
uint32_t snap;
|
||||
|
||||
@@ -195,6 +196,30 @@ static uint32_t getRpmFromLibrpm(const FFinstance* instance)
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint32_t getXBPS(FFstrbuf* baseDir)
|
||||
{
|
||||
DIR* dir = opendir(baseDir->chars);
|
||||
if(dir == NULL)
|
||||
return 0;
|
||||
|
||||
uint32_t result = 0;
|
||||
|
||||
struct dirent *entry;
|
||||
while((entry = readdir(dir)) != NULL)
|
||||
{
|
||||
if(entry->d_type != DT_REG || strncasecmp(entry->d_name, "pkgdb-", 6) != 0)
|
||||
continue;
|
||||
|
||||
ffStrbufAppendC(baseDir, '/');
|
||||
ffStrbufAppendS(baseDir, entry->d_name);
|
||||
result = getNumStrings(baseDir->chars, "<string>installed</string>");
|
||||
break;
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void getPackageCounts(const FFinstance* instance, FFstrbuf* baseDir, PackageCounts* packageCounts)
|
||||
{
|
||||
uint32_t baseDirLength = baseDir->length;
|
||||
@@ -221,12 +246,7 @@ static void getPackageCounts(const FFinstance* instance, FFstrbuf* baseDir, Pack
|
||||
|
||||
//xps
|
||||
ffStrbufAppendS(baseDir, "/var/db/xbps");
|
||||
packageCounts->xbps += getNumElements(baseDir->chars, DT_REG);
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
//flatpak
|
||||
ffStrbufAppendS(baseDir, "/var/lib/flatpak/app");
|
||||
packageCounts->flatpak += getNumElements(baseDir->chars, DT_DIR);
|
||||
packageCounts->xbps += getXBPS(baseDir);
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
//nix system
|
||||
@@ -239,6 +259,16 @@ static void getPackageCounts(const FFinstance* instance, FFstrbuf* baseDir, Pack
|
||||
packageCounts->nixDefault += getNixPackages(baseDir->chars);
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
//apk
|
||||
ffStrbufAppendS(baseDir, "/lib/apk/db/installed");
|
||||
packageCounts->apk += getNumStrings(baseDir->chars, "C:Q");
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
//flatpak
|
||||
ffStrbufAppendS(baseDir, "/var/lib/flatpak/app");
|
||||
packageCounts->flatpak += getNumElements(baseDir->chars, DT_DIR);
|
||||
ffStrbufSubstrBefore(baseDir, baseDirLength);
|
||||
|
||||
//snap
|
||||
ffStrbufAppendS(baseDir, "/snap");
|
||||
uint32_t snap = getNumElements(baseDir->chars, DT_DIR);
|
||||
@@ -313,7 +343,7 @@ void ffPrintPackages(FFinstance* instance)
|
||||
|
||||
ffStrbufDestroy(&baseDir);
|
||||
|
||||
uint32_t all = counts.dpkg + counts.emerge + counts.flatpak + counts.nixSystem + counts.nixDefault + nixUser + counts.pacman + counts.rpm + counts.snap + counts.xbps;
|
||||
uint32_t all = counts.pacman + counts.dpkg + counts.rpm + counts.emerge + counts.xbps + counts.nixSystem + nixUser + counts.nixDefault + counts.apk + counts.flatpak + counts.snap;
|
||||
if(all == 0)
|
||||
{
|
||||
ffPrintError(instance, FF_PACKAGES_MODULE_NAME, 0, &instance->config.packages, "No packages from known package managers found");
|
||||
@@ -344,6 +374,7 @@ void ffPrintPackages(FFinstance* instance)
|
||||
FF_PRINT_PACKAGE(dpkg)
|
||||
FF_PRINT_PACKAGE(rpm)
|
||||
FF_PRINT_PACKAGE(emerge)
|
||||
FF_PRINT_PACKAGE(xbps)
|
||||
|
||||
if(counts.nixSystem > 0)
|
||||
{
|
||||
@@ -366,6 +397,7 @@ void ffPrintPackages(FFinstance* instance)
|
||||
printf(", ");
|
||||
}
|
||||
|
||||
FF_PRINT_PACKAGE(apk)
|
||||
FF_PRINT_PACKAGE(flatpak)
|
||||
FF_PRINT_PACKAGE(snap)
|
||||
|
||||
@@ -389,6 +421,7 @@ void ffPrintPackages(FFinstance* instance)
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &counts.nixSystem},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &nixUser},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &counts.nixDefault},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &counts.apk},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &counts.flatpak},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &counts.snap}
|
||||
});
|
||||
|
||||
+27
-36
@@ -1,55 +1,46 @@
|
||||
#include "FFvaluestore.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void ffValuestoreInit(FFvaluestore* vs)
|
||||
typedef char KeyType[33]; //32 byte key + \0
|
||||
|
||||
void ffValuestoreInit(FFvaluestore* vs, uint32_t valueSize)
|
||||
{
|
||||
vs->capacity = 32;
|
||||
vs->pairs = calloc(vs->capacity, sizeof(FFvaluestorePair));
|
||||
vs->size = 0;
|
||||
ffListInit(vs, sizeof(KeyType) + valueSize);
|
||||
}
|
||||
|
||||
void ffValuestoreSet(FFvaluestore* vs, const char* name, const char* value)
|
||||
void* ffValuestoreGet(FFvaluestore* vs, const char* key)
|
||||
{
|
||||
for(uint32_t i = 0; i < vs->size; i++)
|
||||
for(uint32_t i = 0; i < vs->length; i++)
|
||||
{
|
||||
if(strcasecmp(vs->pairs[i].name, name) == 0)
|
||||
{
|
||||
strcpy(vs->pairs[i].value, value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(vs->size == vs->capacity)
|
||||
{
|
||||
vs->pairs = realloc(vs->pairs, vs->capacity * sizeof(FFvaluestorePair) * 2);
|
||||
vs->capacity *= 2;
|
||||
}
|
||||
|
||||
strcpy(vs->pairs[vs->size].name, name);
|
||||
strcpy(vs->pairs[vs->size].value, value);
|
||||
|
||||
++vs->size;
|
||||
}
|
||||
|
||||
const char* ffValuestoreGet(FFvaluestore* vs, const char* name)
|
||||
{
|
||||
for(uint32_t i = 0; i < vs->size; i++)
|
||||
{
|
||||
if(strcasecmp(vs->pairs[i].name, name) == 0)
|
||||
return vs->pairs[i].value;
|
||||
char* element = ffListGet(vs, i);
|
||||
if(strcmp(element, key) == 0)
|
||||
return element + sizeof(KeyType);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool ffValuestoreContains(FFvaluestore* vs, const char* name)
|
||||
void* ffValuestoreSet(FFvaluestore* vs, const char* key, bool* created)
|
||||
{
|
||||
return ffValuestoreGet(vs, name) != NULL;
|
||||
char* element = ffValuestoreGet(vs, key);
|
||||
if(element != NULL)
|
||||
{
|
||||
if(created != NULL)
|
||||
*created = false;
|
||||
return element;
|
||||
}
|
||||
|
||||
element = ffListAdd(vs);
|
||||
strncpy(element, key, sizeof(KeyType) - 1);
|
||||
element[sizeof(KeyType) - 1] = '\0';
|
||||
|
||||
if(created != NULL)
|
||||
*created = true;
|
||||
return element + sizeof(KeyType);
|
||||
}
|
||||
|
||||
void ffValuestoreDelete(FFvaluestore* vs)
|
||||
void ffValuestoreDestroy(FFvaluestore* vs)
|
||||
{
|
||||
free(vs->pairs);
|
||||
ffListDestroy(vs);
|
||||
}
|
||||
|
||||
+6
-19
@@ -3,26 +3,13 @@
|
||||
#ifndef FASTFETCH_INCLUDED_FFVALUESTORE
|
||||
#define FASTFETCH_INCLUDED_FFVALUESTORE
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "util/FFlist.h"
|
||||
|
||||
typedef struct FFvaluestorePair
|
||||
{
|
||||
char name[32];
|
||||
char value[1024];
|
||||
} FFvaluestorePair;
|
||||
typedef FFlist FFvaluestore;
|
||||
|
||||
typedef struct FFvaluestore
|
||||
{
|
||||
FFvaluestorePair* pairs;
|
||||
uint32_t size;
|
||||
uint32_t capacity;
|
||||
} FFvaluestore;
|
||||
|
||||
void ffValuestoreInit(FFvaluestore* vs);
|
||||
void ffValuestoreSet(FFvaluestore* vs, const char* name, const char* value);
|
||||
const char* ffValuestoreGet(FFvaluestore* vs, const char* name);
|
||||
bool ffValuestoreContains(FFvaluestore* vs, const char* name);
|
||||
void ffValuestoreDelete(FFvaluestore* vs);
|
||||
void ffValuestoreInit(FFvaluestore* vs, uint32_t valueSize);
|
||||
void* ffValuestoreGet(FFvaluestore* vs, const char* key);
|
||||
void* ffValuestoreSet(FFvaluestore* vs, const char* key, bool* created); //created may be NULL
|
||||
void ffValuestoreDestroy(FFvaluestore* vs);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user