Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -413,8 +413,16 @@ if (BUILD_TESTS)
PRIVATE libfastfetch
)

add_executable(fastfetch-test-list
tests/list.c
)
target_link_libraries(fastfetch-test-list
PRIVATE libfastfetch
)

enable_testing()
add_test(NAME test-strbuf COMMAND fastfetch-test-strbuf)
add_test(NAME test-list COMMAND fastfetch-test-list)
endif()

##################
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ The following libraries are used if present at runtime:
* [`libXFConf`](https://gitlab.xfce.org/xfce/xfconf): Needed for XFWM theme and XFCE Terminal font.
* [`libsqlite3`](https://www.sqlite.org/index.html): Needed for pkg & rpm package count.
* [`librpm`](http://rpm.org/): Slower fallback for rpm package count. Needed on openSUSE.
* [`libplist`](https://github.com/libimobiledevice/libplist): Binary `plist` file parser. Needed for iTerm2 Terminal font.
* [`libplist`](https://github.com/libimobiledevice/libplist): Binary `plist` file parser ( macOS ). Needed for iTerm2 Terminal font and WM Theme.

## Support status
All categories not listed here should work without needing a specific implementation.
Expand Down
83 changes: 83 additions & 0 deletions src/modules/wmtheme.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,87 @@ static void printOpenbox(FFinstance* instance, const FFstrbuf* dePrettyName)
ffStrbufDestroy(&absolutePath);
}

#ifdef FF_HAVE_LIBPLIST
#include "common/library.h"
#include "common/io.h"
#include <plist/plist.h>

static const char* quartzCompositorParsePlist(FFinstance* instance, const FFstrbuf* content, FFstrbuf* theme) {
FF_LIBRARY_LOAD(libplist, &instance->config.libplist, "dlopen libplist failed", "libplist-2.0"FF_LIBRARY_EXTENSION, 2);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libplist, plist_is_binary);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libplist, plist_from_bin);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libplist, plist_from_xml);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libplist, plist_dict_get_item);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libplist, plist_get_string_ptr);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libplist, plist_get_uint_val);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libplist, plist_free);

plist_t root_node = NULL;
if (ffplist_is_binary(content->chars, content->length))
ffplist_from_bin(content->chars, content->length, &root_node);
else
ffplist_from_xml(content->chars, content->length, &root_node);

if(root_node == NULL)
return "parsing Quartz Compositor preference file failed";

plist_t pWmThemeColor = ffplist_dict_get_item(root_node, "AppleAccentColor");
uint64_t wmThemeColor = 100;
if (pWmThemeColor != NULL)
ffplist_get_uint_val(pWmThemeColor, &wmThemeColor);
switch (wmThemeColor)
{
case (uint64_t)-1: ffStrbufAppendS(theme, " (Graphite)");
case 0: ffStrbufAppendS(theme, "Red"); break;
case 1: ffStrbufAppendS(theme, "Orange"); break;
case 2: ffStrbufAppendS(theme, "Yellow"); break;
case 3: ffStrbufAppendS(theme, "Green"); break;
case 5: ffStrbufAppendS(theme, "Purple"); break;
case 6: ffStrbufAppendS(theme, "Pink"); break;
default: ffStrbufAppendS(theme, "Blue"); break;
}

plist_t pWmTheme = ffplist_dict_get_item(root_node, "AppleInterfaceStyle");
ffStrbufAppendF(theme, " (%s)", pWmTheme != NULL ? ffplist_get_string_ptr(pWmTheme, NULL) : "Light");

ffplist_free(root_node);
return NULL;
}

static void printQuartzCompositor(FFinstance* instance) {
FFstrbuf fileName;
ffStrbufInitS(&fileName, instance->state.passwd->pw_dir);
ffStrbufAppendS(&fileName, "/Library/Preferences/.GlobalPreferences.plist");

FFstrbuf content;
ffStrbufInit(&content);
ffAppendFileBuffer(fileName.chars, &content);
ffStrbufDestroy(&fileName);
if(content.length == 0)
{
ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmTheme, "reading Quartz Compositor preference file failed");
ffStrbufDestroy(&content);
return;
}

FFstrbuf theme;
ffStrbufInit(&theme);
const char* error = quartzCompositorParsePlist(instance, &content, &theme);
ffStrbufDestroy(&content);

if(error != NULL)
ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmTheme, "%s", error);
else
printWMTheme(instance, theme.chars);
}
#else
static void printQuartzCompositor(FFinstance* instance)
{
FF_UNUSED(instance);
ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmTheme, "Fastfetch was compiled without libplist support");
}
#endif

void ffPrintWMTheme(FFinstance* instance)
{
#ifdef __ANDROID__
Expand Down Expand Up @@ -261,6 +342,8 @@ void ffPrintWMTheme(FFinstance* instance)
printWMThemeFromSettings(instance, "/org/mate/Marco/general/theme", "org.mate.Marco.general", NULL, "theme");
else if(ffStrbufIgnCaseCompS(&result->wmPrettyName, "Openbox") == 0)
printOpenbox(instance, &result->dePrettyName);
else if(ffStrbufIgnCaseCompS(&result->wmPrettyName, "Quartz Compositor") == 0)
printQuartzCompositor(instance);
else
ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmTheme, "Unknown WM: %s", result->wmPrettyName.chars);
}
6 changes: 4 additions & 2 deletions src/util/FFlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ uint32_t ffListFirstIndexComp(const FFlist* list, void* compElement, bool(*compF

void ffListDestroy(FFlist* list)
{
if(list->data != NULL)
free(list->data);
//Avoid free-after-use. These 3 assignments are cheap so don't remove them
list->capacity = list->length = 0;
free(list->data);
list->data = NULL;
}
29 changes: 12 additions & 17 deletions src/util/FFstrbuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ void ffStrbufInitCopy(FFstrbuf* strbuf, const FFstrbuf* src)
ffStrbufAppend(strbuf, src);
}

void ffStrbufInitS(FFstrbuf* strbuf, const char* str)
{
ffStrbufInitA(strbuf, 0);
ffStrbufAppendS(strbuf, str);
}

uint32_t ffStrbufGetFree(const FFstrbuf* strbuf)
{
if(strbuf->allocated == 0)
Expand Down Expand Up @@ -94,14 +100,7 @@ void ffStrbufAppendS(FFstrbuf* strbuf, const char* value)
if(value == NULL)
return;

for(uint32_t i = 0; value[i] != '\0'; i++)
{
if(i % 16 == 0)
ffStrbufEnsureFree(strbuf, 16);
strbuf->chars[strbuf->length++] = value[i];
}

strbuf->chars[strbuf->length] = '\0';
ffStrbufAppendNS(strbuf, (uint32_t)strlen(value), value);
}

void ffStrbufAppendNS(FFstrbuf* strbuf, uint32_t length, const char* value)
Expand All @@ -110,15 +109,8 @@ void ffStrbufAppendNS(FFstrbuf* strbuf, uint32_t length, const char* value)
return;

ffStrbufEnsureFree(strbuf, length);

for(uint32_t i = 0; i < length; i++)
{
if(value[i] == '\0')
break;

strbuf->chars[strbuf->length++] = value[i];
}

memcpy(&strbuf->chars[strbuf->length], value, length);
strbuf->length += length;
strbuf->chars[strbuf->length] = '\0';
}

Expand Down Expand Up @@ -572,5 +564,8 @@ uint16_t ffStrbufToUInt16(const FFstrbuf* strbuf, uint16_t defaultValue)

void ffStrbufDestroy(FFstrbuf* strbuf)
{
//Avoid free-after-use. These 3 assignments are cheap so don't remove them
strbuf->allocated = strbuf->length = 0;
free(strbuf->chars);
strbuf->chars = NULL;
}
1 change: 1 addition & 0 deletions src/util/FFstrbuf.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ typedef struct FFstrbuf
void ffStrbufInit(FFstrbuf* strbuf);
void ffStrbufInitA(FFstrbuf* strbuf, uint32_t allocate);
void ffStrbufInitCopy(FFstrbuf* strbuf, const FFstrbuf* src);
void ffStrbufInitS(FFstrbuf* strbuf, const char* str);

void ffStrbufEnsureFree(FFstrbuf* strbuf, uint32_t free);

Expand Down
89 changes: 89 additions & 0 deletions tests/list.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#include "fastfetch.h"

#include <string.h>
#include <stdarg.h>
#include <stdlib.h>

static void testFailed(const FFlist* list, const char* message, ...)
{
va_list args;
va_start(args, message);
fputs(FASTFETCH_TEXT_MODIFIER_ERROR, stderr);
vfprintf(stderr, message, args);
for (uint32_t i = 0; i < list->length; ++i)
{
fprintf(stderr, "%u ", *(uint32_t*)ffListGet(list, i));
}
fputc('\n', stderr);
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stderr);
fputc('\n', stderr);
va_end(args);
exit(1);
}

int main(int argc, char** argv)
{
FF_UNUSED(argc, argv)

FFlist list;

//initA

ffListInitA(&list, sizeof(uint32_t), 0);

if(ffListGet(&list, 0) != NULL)
testFailed(&list, "ffListGet(&list, 0) != NULL");

if(list.elementSize != sizeof(int))
testFailed(&list, "list.elementSize != sizeof(int)");

if(list.capacity != 0)
testFailed(&list, "list.capacity != 0");

if(list.length != 0)
testFailed(&list, "list.length != 0");

//add
for (uint32_t i = 1; i <= FF_LIST_DEFAULT_ALLOC + 1; ++i)
{
*(uint32_t*)ffListAdd(&list) = i;

if(list.elementSize != sizeof(uint32_t))
testFailed(&list, "list.elementSize != sizeof(uint32_t)");

if(list.length != i)
testFailed(&list, "list.length != i");

if(i <= FF_LIST_DEFAULT_ALLOC)
{
if(list.capacity != FF_LIST_DEFAULT_ALLOC)
testFailed(&list, "list.length != FF_LIST_DEFAULT_ALLOC");
}
else
{
if(list.capacity != FF_LIST_DEFAULT_ALLOC * 2)
testFailed(&list, "list.length != FF_LIST_DEFAULT_ALLOC * 2");
}

if(*(uint32_t*)ffListGet(&list, 0) != 1)
testFailed(&list, "*(int*)ffListGet(&list, 0) != 1");

if(*(uint32_t*)ffListGet(&list, i - 1) != i)
testFailed(&list, "*(int*)ffListGet(&list, i - 1) != i");
}

//Destroy
ffListDestroy(&list);

if(list.elementSize != sizeof(uint32_t))
testFailed(&list, "list.elementSize != sizeof(uint32_t)");

if(list.capacity != 0)
testFailed(&list, "list.capacity != 0");

if(list.length != 0)
testFailed(&list, "list.length != 0");

//Success
puts("\033[32mAll tests passed!"FASTFETCH_TEXT_MODIFIER_RESET);
}
58 changes: 52 additions & 6 deletions tests/strbuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,58 @@ int main(int argc, char** argv)

//initA

ffStrbufInitA(&strbuf, 64);
ffStrbufInitA(&strbuf, 0);

if(strbuf.allocated != 64)
testFailed(&strbuf, "strbuf.allocated != 64");
if(strbuf.chars[0] != 0) //make sure chars[0] is accessable
testFailed(&strbuf, "strbuf.chars[0] != 0");

if(strbuf.allocated != 0)
testFailed(&strbuf, "strbuf.allocated != 0");

if(strbuf.length != 0)
testFailed(&strbuf, "testSrbuf.length != 0");
testFailed(&strbuf, "strbuf.length != 0");

//appendS

ffStrbufAppendS(&strbuf, "123456789");
ffStrbufAppendS(&strbuf, "12345");

if(strbuf.length != 5)
testFailed(&strbuf, "strbuf.length != 5");

if(strbuf.allocated < 6)
testFailed(&strbuf, "strbuf.allocated < 6");

if(ffStrbufCompS(&strbuf, "12345") != 0)
testFailed(&strbuf, "strbuf.data != \"12345\"");

//appendNS

ffStrbufAppendNS(&strbuf, 4, "67890");

if(strbuf.length != 9)
testFailed(&strbuf, "strbuf.length != 9");

if(strcmp(strbuf.chars, "123456789") != 0)
if(strbuf.allocated < 10)
testFailed(&strbuf, "strbuf.allocated < 10");

if(ffStrbufCompS(&strbuf, "123456789") != 0)
testFailed(&strbuf, "strbuf.data != \"123456789\"");

//appendS long

ffStrbufAppendS(&strbuf, "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890");

if(strbuf.length != 109)
testFailed(&strbuf, "strbuf.length != 109");

if(strbuf.allocated < 110)
testFailed(&strbuf, "strbuf.allocated < 110");

if(strbuf.chars[strbuf.length] != 0)
testFailed(&strbuf, "strbuf.chars[strbuf.length] != 0");

strbuf.length = 9;

//startsWithS

if(!ffStrbufStartsWithS(&strbuf, "123"))
Expand Down Expand Up @@ -79,6 +113,18 @@ int main(int argc, char** argv)
if(strcmp(strbuf.chars, "12316") != 0)
testFailed(&strbuf, "strbuf.chars != \"12316\"");

//Destroy

ffStrbufDestroy(&strbuf);
if(strbuf.allocated != 0)
testFailed(&strbuf, "strbuf.allocated != 0");

if(strbuf.length != 0)
testFailed(&strbuf, "strbuf.length != 0");

if(strbuf.chars != NULL)
testFailed(&strbuf, "strbuf.chars != NULL");

//Success
puts("\033[32mAll tests passed!"FASTFETCH_TEXT_MODIFIER_RESET);
}