mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 10:22:12 +02:00
Merge pull request #258 from CarterLi/master
[macOS] support Temps, Font; Host pretty print; other improvements
This commit is contained in:
+7
-2
@@ -193,7 +193,6 @@ set(LIBFASTFETCH_SRC
|
||||
src/detection/terminalShell.c
|
||||
src/detection/vulkan.c
|
||||
src/detection/datetime.c
|
||||
src/detection/temps.c
|
||||
src/detection/title.c
|
||||
src/detection/host/host.c
|
||||
src/detection/os/os.c
|
||||
@@ -243,6 +242,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/modules/colors.c
|
||||
src/modules/opengl.c
|
||||
src/modules/opencl.c
|
||||
src/modules/users.c
|
||||
)
|
||||
|
||||
if(BSD OR APPLE)
|
||||
@@ -262,6 +262,8 @@ if(LINUX OR ANDROID OR BSD)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/detection/cpuUsage/cpuUsage_linux.c
|
||||
src/detection/disk/disk_linux.c
|
||||
src/detection/poweradapter/poweradapter_linux.c
|
||||
src/detection/temps/temps_linux.c
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -271,7 +273,6 @@ if(LINUX OR BSD)
|
||||
src/detection/os/os_linux.c
|
||||
src/detection/gpu/gpu_linux.c
|
||||
src/detection/battery/battery_linux.c
|
||||
src/detection/poweradapter/poweradapter_linux.c
|
||||
src/detection/displayserver/linux/displayserver_linux.c
|
||||
src/detection/displayserver/linux/wayland.c
|
||||
src/detection/displayserver/linux/xcb.c
|
||||
@@ -280,6 +281,7 @@ if(LINUX OR BSD)
|
||||
src/detection/terminalfont/terminalfont_linux.c
|
||||
src/detection/media/media_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/font/font_linux.c
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -300,6 +302,8 @@ if(APPLE)
|
||||
src/detection/media/media_apple.m
|
||||
src/detection/disk/disk_apple.m
|
||||
src/detection/wmtheme/wmtheme_apple.c
|
||||
src/detection/temps/temps_apple.c
|
||||
src/detection/font/font_apple.m
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -320,6 +324,7 @@ if(ANDROID)
|
||||
src/detection/terminalfont/terminalfont_android.c
|
||||
src/detection/media/media_android.c
|
||||
src/detection/wmtheme/wmtheme_android.c
|
||||
src/detection/font/font_android.c
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -177,9 +177,14 @@ __fastfetch_completion()
|
||||
"--allow-slow-operations"
|
||||
"--disable-linewrap"
|
||||
"--hide-cursor"
|
||||
"--cpu-temp"
|
||||
"--gpu-temp"
|
||||
"--battery-temp"
|
||||
"--font-inline"
|
||||
"--localip-show-ipv4"
|
||||
"--localip-show-ipv6"
|
||||
"--localip-show-loop"
|
||||
"--localip-name-prefix"
|
||||
"--escape-bedrock"
|
||||
"--pipe"
|
||||
"--title-fqdn"
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
--structure Title:Separator:OS:Host:Kernel:Uptime:Processes:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Song:PublicIP:LocalIP:DateTime:Locale:Vulkan:OpenGL:OpenCL:Break:Colors
|
||||
--structure Title:Separator:OS:Host:Kernel:Uptime:Processes:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Song:PublicIP:LocalIP:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Break:Colors
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@
|
||||
--wm-theme-format Name: {}
|
||||
--theme-format Plasma: {}; Plasma colors: {}; Plasma colors pretty: {}; GTK2: {}; GTK3: {}; GTK4: {}; GTK: {}
|
||||
--icons-format Plasma: {}; GTK2: {}; GTK3: {}; GTK4: {}; GTK: {}
|
||||
--font-format Plasma raw: {}; Plasma name: {}; Plasma size: {}; Plasma styles: {}; Plasma pretty: {}; GTK2 raw: {}; GTK2 name: {}; GTK2 size: {}; GTK2 styles: {}; GTK2 pretty: {}; GTK3 raw: {}; GTK3 name: {}; GTK3 size: {}; GTK3 styles: {}; GTK3 pretty: {}; GTK4 raw: {}; GTK4 name: {}; GTK4 size: {}; GTK4 styles: {}; GTK4 pretty: {}; GTK: {}
|
||||
--font-format Type: {}; Font: {}
|
||||
--cursor-format Theme: {}; Size: {}
|
||||
--terminal-format Process: {}; Path: {}; Exe: {}
|
||||
--terminal-font-format Pretty: {}; Name: {}; Size: {}; Styles: {}
|
||||
|
||||
@@ -220,6 +220,10 @@ static void defaultConfig(FFinstance* instance)
|
||||
ffStrbufInitA(&instance->config.libplist, 0);
|
||||
ffStrbufInitA(&instance->config.libcJSON, 0);
|
||||
|
||||
instance->config.cpuTemp = false;
|
||||
instance->config.gpuTemp = false;
|
||||
instance->config.batteryTemp = false;
|
||||
|
||||
instance->config.titleFQDN = false;
|
||||
|
||||
ffStrbufInitA(&instance->config.diskFolders, 0);
|
||||
@@ -229,9 +233,12 @@ static void defaultConfig(FFinstance* instance)
|
||||
|
||||
ffStrbufInitA(&instance->config.separatorString, 0);
|
||||
|
||||
instance->config.fontInline = true;
|
||||
|
||||
instance->config.localIpShowIpV4 = true;
|
||||
instance->config.localIpShowIpV6 = false;
|
||||
instance->config.localIpShowLoop = false;
|
||||
ffStrbufInit(&instance->config.localIpNamePrefix);
|
||||
|
||||
instance->config.publicIpTimeout = 0;
|
||||
|
||||
|
||||
@@ -94,9 +94,14 @@ Module specific options:
|
||||
--disk-folders <folders>: A colon separated list of folder paths for the disk output. Default is "/:/home"
|
||||
--disk-removable <?value>: Sets if removable volume should be printed. Default is false
|
||||
--battery-dir <folder>: The directory where the battery folders are. Standard: /sys/class/power_supply/
|
||||
--cpu-temp <?value>: Detect and display CPU temperature if supported. Default is false
|
||||
--gpu-temp <?value>: Detect and display GPU temperature if supported. Default is false
|
||||
--battery-temp <?value>: Detect and display Battery temperature if supported. Default is false
|
||||
--font-inline <?value>: Display fonts of different DE in one line
|
||||
--localip-show-ipv4 <?value>: Show ipv4 addresses in local ip module. Default is true
|
||||
--localip-show-ipv6 <?value>: Show ipv6 addresses in local ip module. Default is false
|
||||
--localip-show-loop <?value>: Show loop back addresses (127.0.0.1) in local ip module. Default is false
|
||||
--localip-name-prefix <str>: Show ips with given name prefix only. Default is empty
|
||||
--public-ip-timeout: Time in milliseconds to wait for the public ip server to respond. Default is disabled (0)
|
||||
--player-name: The name of the player to use
|
||||
--gl <value>: Sets the opengl context creation library to use. Must be auto, egl, glx or osmesa. Default is auto
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
#define FF_BATTERY_TEMP_UNSET (0/0.0)
|
||||
|
||||
typedef struct BatteryResult
|
||||
{
|
||||
FFstrbuf manufacturer;
|
||||
@@ -12,6 +14,7 @@ typedef struct BatteryResult
|
||||
FFstrbuf technology;
|
||||
FFstrbuf capacity;
|
||||
FFstrbuf status;
|
||||
double temperature;
|
||||
} BatteryResult;
|
||||
|
||||
const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results);
|
||||
|
||||
@@ -1,9 +1,34 @@
|
||||
#include "fastfetch.h"
|
||||
#include "battery.h"
|
||||
#include "util/apple/cf_helpers.h"
|
||||
#include "detection/temps/temps_apple.h"
|
||||
|
||||
#include <IOKit/IOKitLib.h>
|
||||
|
||||
static double detectBatteryTemp()
|
||||
{
|
||||
FFlist temps;
|
||||
ffListInit(&temps, sizeof(FFTempValue));
|
||||
|
||||
ffDetectCoreTemps(FF_TEMP_BATTERY, &temps);
|
||||
|
||||
if(temps.length == 0)
|
||||
return FF_BATTERY_TEMP_UNSET;
|
||||
|
||||
double result = 0;
|
||||
for(uint32_t i = 0; i < temps.length; ++i)
|
||||
{
|
||||
FFTempValue* tempValue = (FFTempValue*)ffListGet(&temps, i);
|
||||
result += tempValue->value;
|
||||
//TODO: do we really need this?
|
||||
ffStrbufDestroy(&tempValue->name);
|
||||
ffStrbufDestroy(&tempValue->deviceClass);
|
||||
}
|
||||
result /= temps.length;
|
||||
ffListDestroy(&temps);
|
||||
return result;
|
||||
}
|
||||
|
||||
const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
@@ -69,6 +94,11 @@ const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results)
|
||||
else
|
||||
ffStrbufAppendS(&battery->status, "");
|
||||
|
||||
if(instance->config.batteryTemp)
|
||||
battery->temperature = detectBatteryTemp();
|
||||
else
|
||||
battery->temperature = FF_BATTERY_TEMP_UNSET;
|
||||
|
||||
CFRelease(properties);
|
||||
IOObjectRelease(registryEntry);
|
||||
}
|
||||
|
||||
@@ -70,6 +70,8 @@ static void parseBattery(FFstrbuf* dir, FFlist* results)
|
||||
ffStrbufAppendS(dir, "/status");
|
||||
ffReadFileBuffer(dir->chars, &result->status);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
|
||||
result->temperature = FF_BATTERY_TEMP_UNSET;
|
||||
}
|
||||
|
||||
const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "cpu.h"
|
||||
#include "common/sysctl.h"
|
||||
#include "detection/temps/temps_apple.h"
|
||||
|
||||
static double getFrequency(const char* propName)
|
||||
{
|
||||
@@ -12,33 +13,64 @@ static double getFrequency(const char* propName)
|
||||
return herz / 1000.0; //to GHz
|
||||
}
|
||||
|
||||
static double detectCpuTemp(const FFstrbuf* cpuName)
|
||||
{
|
||||
FFlist temps;
|
||||
ffListInit(&temps, sizeof(FFTempValue));
|
||||
|
||||
if(ffStrbufStartsWithS(cpuName, "Apple M1"))
|
||||
ffDetectCoreTemps(FF_TEMP_CPU_M1X, &temps);
|
||||
else if(ffStrbufStartsWithS(cpuName, "Apple M2"))
|
||||
ffDetectCoreTemps(FF_TEMP_CPU_M2X, &temps);
|
||||
else //TODO: PPC?
|
||||
ffDetectCoreTemps(FF_TEMP_CPU_X64, &temps);
|
||||
|
||||
if(temps.length == 0)
|
||||
return FF_CPU_TEMP_UNSET;
|
||||
|
||||
double result = 0;
|
||||
for(uint32_t i = 0; i < temps.length; ++i)
|
||||
{
|
||||
FFTempValue* tempValue = (FFTempValue*)ffListGet(&temps, i);
|
||||
result += tempValue->value;
|
||||
//TODO: do we really need this?
|
||||
ffStrbufDestroy(&tempValue->name);
|
||||
ffStrbufDestroy(&tempValue->deviceClass);
|
||||
}
|
||||
result /= temps.length;
|
||||
ffListDestroy(&temps);
|
||||
return result;
|
||||
}
|
||||
|
||||
void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu, bool cached)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
|
||||
//TODO find a way to detect this
|
||||
cpu->temperature = FF_CPU_TEMP_UNSET;
|
||||
if(!cached)
|
||||
{
|
||||
ffSysctlGetString("machdep.cpu.brand_string", &cpu->name);
|
||||
ffSysctlGetString("machdep.cpu.vendor", &cpu->vendor);
|
||||
|
||||
if(cached)
|
||||
return;
|
||||
cpu->coresPhysical = (uint16_t) ffSysctlGetInt("hw.physicalcpu_max", 1);
|
||||
if(cpu->coresPhysical == 1)
|
||||
cpu->coresPhysical = (uint16_t) ffSysctlGetInt("hw.physicalcpu", 1);
|
||||
|
||||
ffSysctlGetString("machdep.cpu.brand_string", &cpu->name);
|
||||
ffSysctlGetString("machdep.cpu.vendor", &cpu->vendor);
|
||||
cpu->coresLogical = (uint16_t) ffSysctlGetInt("hw.logicalcpu_max", 1);
|
||||
if(cpu->coresLogical == 1)
|
||||
cpu->coresLogical = (uint16_t) ffSysctlGetInt("hw.ncpu", 1);
|
||||
|
||||
cpu->coresPhysical = (uint16_t) ffSysctlGetInt("hw.physicalcpu_max", 1);
|
||||
if(cpu->coresPhysical == 1)
|
||||
cpu->coresPhysical = (uint16_t) ffSysctlGetInt("hw.physicalcpu", 1);
|
||||
cpu->coresOnline = (uint16_t) ffSysctlGetInt("hw.logicalcpu", 1);
|
||||
if(cpu->coresOnline == 1)
|
||||
cpu->coresOnline = (uint16_t) ffSysctlGetInt("hw.activecpu", 1);
|
||||
|
||||
cpu->coresLogical = (uint16_t) ffSysctlGetInt("hw.logicalcpu_max", 1);
|
||||
if(cpu->coresLogical == 1)
|
||||
cpu->coresLogical = (uint16_t) ffSysctlGetInt("hw.ncpu", 1);
|
||||
cpu->frequencyMin = getFrequency("hw.cpufrequency_min");
|
||||
cpu->frequencyMax = getFrequency("hw.cpufrequency_max");
|
||||
if(cpu->frequencyMax == 0.0)
|
||||
cpu->frequencyMax = getFrequency("hw.cpufrequency");
|
||||
}
|
||||
|
||||
cpu->coresOnline = (uint16_t) ffSysctlGetInt("hw.logicalcpu", 1);
|
||||
if(cpu->coresOnline == 1)
|
||||
cpu->coresOnline = (uint16_t) ffSysctlGetInt("hw.activecpu", 1);
|
||||
|
||||
cpu->frequencyMin = getFrequency("hw.cpufrequency_min");
|
||||
cpu->frequencyMax = getFrequency("hw.cpufrequency_max");
|
||||
if(cpu->frequencyMax == 0.0)
|
||||
cpu->frequencyMax = getFrequency("hw.cpufrequency");
|
||||
if (instance->config.cpuTemp)
|
||||
cpu->temperature = detectCpuTemp(&cpu->name);
|
||||
else
|
||||
cpu->temperature = FF_CPU_TEMP_UNSET;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "cpu.h"
|
||||
#include "common/io.h"
|
||||
#include "common/properties.h"
|
||||
#include "detection/temps.h"
|
||||
#include "detection/temps/temps_linux.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
@@ -80,7 +80,10 @@ static double detectCPUTemp(const FFinstance* instance)
|
||||
|
||||
void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu, bool cached)
|
||||
{
|
||||
cpu->temperature = detectCPUTemp(instance);
|
||||
if(instance->config.cpuTemp)
|
||||
cpu->temperature = detectCPUTemp(instance);
|
||||
else
|
||||
cpu->temperature = FF_CPU_TEMP_UNSET;
|
||||
|
||||
if(cached)
|
||||
return;
|
||||
|
||||
@@ -27,21 +27,21 @@ const FFDateTimeResult* ffDetectDateTime(const FFinstance* instance)
|
||||
result.yearShort = (uint8_t) (result.year % 100);
|
||||
result.month = (uint8_t) (tm->tm_mon + 1);
|
||||
|
||||
ffStrbufInit(&result.monthPretty);
|
||||
ffStrbufInitA(&result.monthPretty, FASTFETCH_STRBUF_DEFAULT_ALLOC);
|
||||
result.monthPretty.length = (uint32_t) strftime(result.monthPretty.chars, ffStrbufGetFree(&result.monthPretty), "%m", tm);
|
||||
|
||||
ffStrbufInit(&result.monthName);
|
||||
ffStrbufInitA(&result.monthName, FASTFETCH_STRBUF_DEFAULT_ALLOC);
|
||||
result.monthName.length = (uint32_t) strftime(result.monthName.chars, ffStrbufGetFree(&result.monthName), "%B", tm);
|
||||
|
||||
ffStrbufInit(&result.monthNameShort);
|
||||
ffStrbufInitA(&result.monthNameShort, FASTFETCH_STRBUF_DEFAULT_ALLOC);
|
||||
result.monthNameShort.length = (uint32_t) strftime(result.monthNameShort.chars, ffStrbufGetFree(&result.monthNameShort), "%b", tm);
|
||||
|
||||
result.week = (uint8_t) (tm->tm_yday / 7 + 1);
|
||||
|
||||
ffStrbufInit(&result.weekday);
|
||||
ffStrbufInitA(&result.weekday, FASTFETCH_STRBUF_DEFAULT_ALLOC);
|
||||
result.weekday.length = (uint32_t) strftime(result.weekday.chars, ffStrbufGetFree(&result.weekday), "%A", tm);
|
||||
|
||||
ffStrbufInit(&result.weekdayShort);
|
||||
ffStrbufInitA(&result.weekdayShort, FASTFETCH_STRBUF_DEFAULT_ALLOC);
|
||||
result.weekdayShort.length = (uint32_t) strftime(result.weekdayShort.chars, ffStrbufGetFree(&result.weekdayShort), "%a", tm);
|
||||
|
||||
result.dayInYear = (uint8_t) (tm->tm_yday + 1);
|
||||
@@ -50,22 +50,22 @@ const FFDateTimeResult* ffDetectDateTime(const FFinstance* instance)
|
||||
|
||||
result.hour = (uint8_t) tm->tm_hour;
|
||||
|
||||
ffStrbufInit(&result.hourPretty);
|
||||
ffStrbufInitA(&result.hourPretty, FASTFETCH_STRBUF_DEFAULT_ALLOC);
|
||||
result.hourPretty.length = (uint32_t) strftime(result.hourPretty.chars, ffStrbufGetFree(&result.hourPretty), "%H", tm);
|
||||
|
||||
result.hour12 = (uint8_t) (result.hour % 12);
|
||||
|
||||
ffStrbufInit(&result.hour12Pretty);
|
||||
ffStrbufInitA(&result.hour12Pretty, FASTFETCH_STRBUF_DEFAULT_ALLOC);
|
||||
result.hour12Pretty.length = (uint32_t) strftime(result.hour12Pretty.chars, ffStrbufGetFree(&result.hour12Pretty), "%I", tm);
|
||||
|
||||
result.minute = (uint8_t) tm->tm_min;
|
||||
|
||||
ffStrbufInit(&result.minutePretty);
|
||||
ffStrbufInitA(&result.minutePretty, FASTFETCH_STRBUF_DEFAULT_ALLOC);
|
||||
result.minutePretty.length = (uint32_t) strftime(result.minutePretty.chars, ffStrbufGetFree(&result.minutePretty), "%M", tm);
|
||||
|
||||
result.second = (uint8_t) tm->tm_sec;
|
||||
|
||||
ffStrbufInit(&result.secondPretty);
|
||||
ffStrbufInitA(&result.secondPretty, FASTFETCH_STRBUF_DEFAULT_ALLOC);
|
||||
result.secondPretty.length = (uint32_t) strftime(result.secondPretty.chars, ffStrbufGetFree(&result.secondPretty), "%S", tm);
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_detection_font_font
|
||||
#define FF_INCLUDED_detection_font_font
|
||||
|
||||
#include "fastfetch.h"
|
||||
#include "util/FFstrbuf.h"
|
||||
#include "util/FFlist.h"
|
||||
|
||||
typedef struct FFFontResult
|
||||
{
|
||||
const char* type;
|
||||
FFstrbuf fontPretty;
|
||||
} FFFontResult;
|
||||
|
||||
const char* ffDetectFontImpl(FFinstance* instance, FFlist* result);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "common/font.h"
|
||||
|
||||
const char* ffDetectFontImpl(FFinstance* instance, FFlist* result)
|
||||
{
|
||||
FF_UNUSED(instance, result);
|
||||
return "Font detection is not supported on Android";
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
#include "common/font.h"
|
||||
#include "util/apple/cf_helpers.h"
|
||||
#include "font.h"
|
||||
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
#define FF_FONT_MODULE_NAME "Font"
|
||||
|
||||
static void detectFontForType(CTFontUIFontType uiType, FFFontResult* result)
|
||||
{
|
||||
CTFontRef ctFont = CTFontCreateUIFontForLanguage(uiType, 12, NULL);
|
||||
|
||||
ffStrbufInit(&result->fontPretty);
|
||||
ffCfStrGetString(CTFontCopyFullName(ctFont), &result->fontPretty);
|
||||
|
||||
FFstrbuf familyName;
|
||||
ffStrbufInit(&familyName);
|
||||
ffCfStrGetString(CTFontCopyFamilyName(ctFont), &familyName);
|
||||
|
||||
if (ffStrbufComp(&familyName, &result->fontPretty) != 0)
|
||||
{
|
||||
ffStrbufAppendF(&result->fontPretty, " (%*s)", familyName.length, familyName.chars);
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&familyName);
|
||||
}
|
||||
|
||||
const char* ffDetectFontImpl(FFinstance* instance, FFlist* result)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
|
||||
FFFontResult* resultSystem = (FFFontResult*)ffListAdd(result);
|
||||
resultSystem->type = "SYS";
|
||||
detectFontForType(kCTFontUIFontSystem, resultSystem);
|
||||
|
||||
FFFontResult* resultUser = (FFFontResult*)ffListAdd(result);
|
||||
resultUser->type = "USER";
|
||||
detectFontForType(kCTFontUIFontUser, resultUser);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
#include "detection/qt.h"
|
||||
#include "detection/gtk.h"
|
||||
#include "common/parsing.h"
|
||||
#include "common/font.h"
|
||||
#include "font.h"
|
||||
|
||||
const char* ffDetectFontImpl(FFinstance* instance, FFlist* result)
|
||||
{
|
||||
const FFstrbuf* qtRaw = &ffDetectQt(instance)->font;
|
||||
const FFstrbuf* gtk2Raw = &ffDetectGTK2(instance)->font;
|
||||
const FFstrbuf* gtk3Raw = &ffDetectGTK3(instance)->font;
|
||||
const FFstrbuf* gtk4Raw = &ffDetectGTK4(instance)->font;
|
||||
|
||||
if(qtRaw->length > 0)
|
||||
{
|
||||
FFfont qt;
|
||||
ffFontInitQt(&qt, qtRaw->chars);
|
||||
|
||||
FFFontResult* resultQt = (FFFontResult *)ffListAdd(result);
|
||||
resultQt->type = "QT";
|
||||
ffStrbufInitCopy(&resultQt->fontPretty, &qt.pretty);
|
||||
|
||||
ffFontDestroy(&qt);
|
||||
}
|
||||
|
||||
if(gtk2Raw->length > 0 || gtk3Raw->length > 0 || gtk4Raw->length > 0)
|
||||
{
|
||||
FFfont gtk2;
|
||||
ffFontInitPango(>k2, gtk2Raw->chars);
|
||||
|
||||
FFfont gtk3;
|
||||
ffFontInitPango(>k3, gtk3Raw->chars);
|
||||
|
||||
FFfont gtk4;
|
||||
ffFontInitPango(>k4, gtk4Raw->chars);
|
||||
|
||||
FFFontResult* resultGtk = (FFFontResult *)ffListAdd(result);
|
||||
resultGtk->type = "GTK";
|
||||
ffStrbufInit(&resultGtk->fontPretty);
|
||||
ffParseGTK(&resultGtk->fontPretty, >k2.pretty, >k3.pretty, >k4.pretty);
|
||||
|
||||
ffFontDestroy(>k2);
|
||||
ffFontDestroy(>k3);
|
||||
ffFontDestroy(>k4);
|
||||
}
|
||||
|
||||
if(result->length == 0)
|
||||
return "No fonts found";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -1,10 +1,42 @@
|
||||
#include "gpu.h"
|
||||
#include "common/library.h"
|
||||
#include "detection/cpu/cpu.h"
|
||||
#include "detection/temps/temps_apple.h"
|
||||
#include "util/apple/cf_helpers.h"
|
||||
|
||||
#include <IOKit/graphics/IOGraphicsLib.h>
|
||||
|
||||
static double detectGpuTemp(const FFstrbuf* gpuName)
|
||||
{
|
||||
FFlist temps;
|
||||
ffListInit(&temps, sizeof(FFTempValue));
|
||||
|
||||
if(ffStrbufStartsWithS(gpuName, "Apple M1"))
|
||||
ffDetectCoreTemps(FF_TEMP_GPU_M1X, &temps);
|
||||
else if(ffStrbufStartsWithS(gpuName, "Apple M2"))
|
||||
ffDetectCoreTemps(FF_TEMP_GPU_M2X, &temps);
|
||||
else if(ffStrbufStartsWithS(gpuName, "Radeon") || ffStrbufStartsWithS(gpuName, "AMD"))
|
||||
ffDetectCoreTemps(FF_TEMP_GPU_AMD, &temps);
|
||||
else
|
||||
ffDetectCoreTemps(FF_TEMP_GPU_UNKNOWN, &temps);
|
||||
|
||||
if(temps.length == 0)
|
||||
return FF_GPU_TEMP_UNSET;
|
||||
|
||||
double result = 0;
|
||||
for(uint32_t i = 0; i < temps.length; ++i)
|
||||
{
|
||||
FFTempValue* tempValue = (FFTempValue*)ffListGet(&temps, i);
|
||||
result += tempValue->value;
|
||||
//TODO: do we really need this?
|
||||
ffStrbufDestroy(&tempValue->name);
|
||||
ffStrbufDestroy(&tempValue->deviceClass);
|
||||
}
|
||||
result /= temps.length;
|
||||
ffListDestroy(&temps);
|
||||
return result;
|
||||
}
|
||||
|
||||
const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
@@ -52,7 +84,10 @@ const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance)
|
||||
if(ffCfDictGetInt(properties, CFSTR("gpu-core-count"), &gpu->coreCount))
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
if(instance->config.gpuTemp)
|
||||
gpu->temperature = detectGpuTemp(&gpu->name);
|
||||
else
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
|
||||
CFRelease(properties);
|
||||
IOObjectRelease(registryEntry);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "common/library.h"
|
||||
#include "common/properties.h"
|
||||
#include "common/parsing.h"
|
||||
#include "detection/temps.h"
|
||||
#include "detection/temps/temps_linux.h"
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <pci/pci.h>
|
||||
@@ -200,7 +200,8 @@ static void pciHandleDevice(const FFinstance* instance, FFlist* results, PCIData
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
pciDetectTemperatur(instance, gpu, device);
|
||||
if(instance->config.gpuTemp)
|
||||
pciDetectTemperatur(instance, gpu, device);
|
||||
}
|
||||
|
||||
static const char* pciDetectGPUs(const FFinstance* instance, FFlist* gpus)
|
||||
|
||||
@@ -1,11 +1,120 @@
|
||||
#include "host.h"
|
||||
#include "common/sysctl.h"
|
||||
|
||||
static const char* getProductName(const FFstrbuf* hwModel)
|
||||
{
|
||||
//https://github.com/hykilpikonna/hyfetch/blob/master/neofetch#L1386
|
||||
if(ffStrbufCompS(hwModel, "Mac14,7") == 0) return "MacBook Pro (13-inch, M2, 2022)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro18,3") == 0 ||
|
||||
ffStrbufCompS(hwModel, "MacBookPro18,4") == 0) return "MacBook Pro (14-inch, 2021)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro18,1") == 0 ||
|
||||
ffStrbufCompS(hwModel, "MacBookPro18,2") == 0) return "MacBook Pro (16-inch, 2021)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro17,1") == 0) return "MacBook Pro (13-inch, M1, 2020)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro16,4") == 0) return "MacBook Pro (16-inch, 2019)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro16,3") == 0) return "MacBook Pro (13-inch, 2020, Two Thunderbolt 3 ports)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro16,2") == 0) return "MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro16,1") == 0) return "MacBook Pro (16-inch, 2019)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro15,4") == 0) return "MacBook Pro (13-inch, 2019, Two Thunderbolt 3 ports)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro15,3") == 0) return "MacBook Pro (15-inch, 2019)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro15,2") == 0) return "MacBook Pro (13-inch, 2018/2019, Four Thunderbolt 3 ports)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro15,1") == 0) return "MacBook Pro (15-inch, 2018/2019)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro14,3") == 0) return "MacBook Pro (15-inch, 2017)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro14,2") == 0) return "MacBook Pro (13-inch, 2017, Four Thunderbolt 3 ports)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro14,1") == 0) return "MacBook Pro (13-inch, 2017, Two Thunderbolt 3 ports)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro13,3") == 0) return "MacBook Pro (15-inch, 2016)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro13,2") == 0) return "MacBook Pro (13-inch, 2016, Four Thunderbolt 3 ports)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro13,1") == 0) return "MacBook Pro (13-inch, 2016, Two Thunderbolt 3 ports)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro12,1") == 0) return "MacBook Pro (Retina, 13-inch, Early 2015)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro11,4") == 0 ||
|
||||
ffStrbufCompS(hwModel, "MacBookPro11,5") == 0) return "MacBook Pro (Retina, 15-inch, Mid 2015)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro11,2") == 0 ||
|
||||
ffStrbufCompS(hwModel, "MacBookPro11,3") == 0) return "MacBook Pro (Retina, 15-inch, Late 2013/Mid 2014)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro11,1") == 0) return "MacBook Pro (Retina, 13-inch, Late 2013/Mid 2014)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro10,2") == 0) return "MacBook Pro (Retina, 13-inch, Late 2012/Early 2013)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro10,1") == 0) return "MacBook Pro (Retina, 15-inch, Mid 2012/Early 2013)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro9,2") == 0) return "MacBook Pro (13-inch, Mid 2012)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro9,1") == 0) return "MacBook Pro (15-inch, Mid 2012)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro8,3") == 0) return "MacBook Pro (17-inch, 2011)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro8,2") == 0) return "MacBook Pro (15-inch, 2011)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro8,1") == 0) return "MacBook Pro (13-inch, 2011)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro7,1") == 0) return "MacBook Pro (13-inch, Mid 2010)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro6,2") == 0) return "MacBook Pro (15-inch, Mid 2010)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro6,1") == 0) return "MacBook Pro (17-inch, Mid 2010)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro5,5") == 0) return "MacBook Pro (13-inch, Mid 2009)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro5,3") == 0) return "MacBook Pro (15-inch, Mid 2009)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro5,2") == 0) return "MacBook Pro (17-inch, Mid/Early 2009)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro5,1") == 0) return "MacBook Pro (15-inch, Late 2008)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookPro4,1") == 0) return "MacBook Pro (17/15-inch, Early 2008)";
|
||||
if(ffStrbufCompS(hwModel, "Mac14,2") == 0) return "MacBook Air (M2, 2022)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookAir10,1") == 0) return "MacBook Air (M1, 2020)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookAir9,1") == 0) return "MacBook Air (Retina, 13-inch, 2020)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookAir8,2") == 0) return "MacBook Air (Retina, 13-inch, 2019)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookAir8,1") == 0) return "MacBook Air (Retina, 13-inch, 2018)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookAir7,2") == 0) return "MacBook Air (13-inch, Early 2015/2017)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookAir7,1") == 0) return "MacBook Air (11-inch, Early 2015)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookAir6,2") == 0) return "MacBook Air (13-inch, Mid 2013/Early 2014)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookAir6,1") == 0) return "MacBook Air (11-inch, Mid 2013/Early 2014)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookAir5,2") == 0) return "MacBook Air (13-inch, Mid 2012)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookAir5,1") == 0) return "MacBook Air (11-inch, Mid 2012)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookAir4,2") == 0) return "MacBook Air (13-inch, Mid 2011)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookAir4,1") == 0) return "MacBook Air (11-inch, Mid 2011)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookAir3,2") == 0) return "MacBook Air (13-inch, Late 2010)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookAir3,1") == 0) return "MacBook Air (11-inch, Late 2010)";
|
||||
if(ffStrbufCompS(hwModel, "MacBookAir2,1") == 0) return "MacBook Air (Mid 2009)";
|
||||
if(ffStrbufCompS(hwModel, "MacBook10,1") == 0) return "MacBook (Retina, 12-inch, 2017)";
|
||||
if(ffStrbufCompS(hwModel, "MacBook9,1") == 0) return "MacBook (Retina, 12-inch, Early 2016)";
|
||||
if(ffStrbufCompS(hwModel, "MacBook8,1") == 0) return "MacBook (Retina, 12-inch, Early 2015)";
|
||||
if(ffStrbufCompS(hwModel, "MacBook7,1") == 0) return "MacBook (13-inch, Mid 2010)";
|
||||
if(ffStrbufCompS(hwModel, "MacBook6,1") == 0) return "MacBook (13-inch, Late 2009)";
|
||||
if(ffStrbufCompS(hwModel, "MacBook5,2") == 0) return "MacBook (13-inch, Early/Mid 2009)";
|
||||
if(ffStrbufCompS(hwModel, "Mac13,1") == 0) return "Mac Studio (2022, Two USB-C front ports)";
|
||||
if(ffStrbufCompS(hwModel, "Mac13,2") == 0) return "Mac Studio (2022, Two Thunderbolt 4 front ports)";
|
||||
if(ffStrbufCompS(hwModel, "Macmini9,1") == 0) return "Mac mini (M1, 2020)";
|
||||
if(ffStrbufCompS(hwModel, "Macmini8,1") == 0) return "Mac mini (2018)";
|
||||
if(ffStrbufCompS(hwModel, "Macmini7,1") == 0) return "Mac mini (Mid 2014)";
|
||||
if(ffStrbufCompS(hwModel, "Macmini6,1") == 0 ||
|
||||
ffStrbufCompS(hwModel, "Macmini6,2") == 0) return "Mac mini (Late 2012)";
|
||||
if(ffStrbufCompS(hwModel, "Macmini5,1") == 0 ||
|
||||
ffStrbufCompS(hwModel, "Macmini5,2") == 0) return "Mac mini (Mid 2011)";
|
||||
if(ffStrbufCompS(hwModel, "Macmini4,1") == 0) return "Mac mini (Mid 2010)";
|
||||
if(ffStrbufCompS(hwModel, "Macmini3,1") == 0) return "Mac mini (Early/Late 2009)";
|
||||
if(ffStrbufCompS(hwModel, "MacPro7,1") == 0) return "Mac Pro (2019)";
|
||||
if(ffStrbufCompS(hwModel, "MacPro6,1") == 0) return "Mac Pro (Late 2013)";
|
||||
if(ffStrbufCompS(hwModel, "MacPro5,1") == 0) return "Mac Pro (Mid 2010 - Mid 2012)";
|
||||
if(ffStrbufCompS(hwModel, "MacPro4,1") == 0) return "Mac Pro (Early 2009)";
|
||||
if(ffStrbufCompS(hwModel, "iMac21,1") == 0 ||
|
||||
ffStrbufCompS(hwModel, "iMac21,2") == 0) return "iMac (24-inch, M1, 2021)";
|
||||
if(ffStrbufCompS(hwModel, "iMac20,1") == 0 ||
|
||||
ffStrbufCompS(hwModel, "iMac20,2") == 0) return "iMac (Retina 5K, 27-inch, 2020)";
|
||||
if(ffStrbufCompS(hwModel, "iMac19,1") == 0 ||
|
||||
ffStrbufCompS(hwModel, "iMac19,2") == 0) return "iMac (Retina 4K, 21.5-inch, 2019)";
|
||||
if(ffStrbufCompS(hwModel, "iMacPro1,1") == 0) return "iMac Pro (2017)";
|
||||
if(ffStrbufCompS(hwModel, "iMac18,3") == 0) return "iMac (Retina 5K, 27-inch, 2017)";
|
||||
if(ffStrbufCompS(hwModel, "iMac18,2") == 0) return "iMac (Retina 4K, 21.5-inch, 2017)";
|
||||
if(ffStrbufCompS(hwModel, "iMac18,1") == 0) return "iMac (21.5-inch, 2017)";
|
||||
if(ffStrbufCompS(hwModel, "iMac17,1") == 0) return "iMac (Retina 5K, 27-inch, Late 2015)";
|
||||
if(ffStrbufCompS(hwModel, "iMac16,2") == 0) return "iMac (Retina 4K, 21.5-inch, Late 2015)";
|
||||
if(ffStrbufCompS(hwModel, "iMac16,1") == 0) return "iMac (21.5-inch, Late 2015)";
|
||||
if(ffStrbufCompS(hwModel, "iMac15,1") == 0) return "iMac (Retina 5K, 27-inch, Late 2014 - Mid 2015)";
|
||||
if(ffStrbufCompS(hwModel, "iMac14,4") == 0) return "iMac (21.5-inch, Mid 2014)";
|
||||
if(ffStrbufCompS(hwModel, "iMac14,2") == 0) return "iMac (27-inch, Late 2013)";
|
||||
if(ffStrbufCompS(hwModel, "iMac14,1") == 0) return "iMac (21.5-inch, Late 2013)";
|
||||
if(ffStrbufCompS(hwModel, "iMac13,2") == 0) return "iMac (27-inch, Late 2012)";
|
||||
if(ffStrbufCompS(hwModel, "iMac13,1") == 0) return "iMac (21.5-inch, Late 2012)";
|
||||
if(ffStrbufCompS(hwModel, "iMac12,2") == 0) return "iMac (27-inch, Mid 2011)";
|
||||
if(ffStrbufCompS(hwModel, "iMac12,1") == 0) return "iMac (21.5-inch, Mid 2011)";
|
||||
if(ffStrbufCompS(hwModel, "iMac11,3") == 0) return "iMac (27-inch, Mid 2010)";
|
||||
if(ffStrbufCompS(hwModel, "iMac11,2") == 0) return "iMac (21.5-inch, Mid 2010)";
|
||||
if(ffStrbufCompS(hwModel, "iMac10,1") == 0) return "iMac (27/21.5-inch, Late 2009)";
|
||||
if(ffStrbufCompS(hwModel, "iMac9,1") == 0) return "iMac (24/20-inch, Early 2009)";
|
||||
return hwModel->chars;
|
||||
}
|
||||
|
||||
void ffDetectHostImpl(FFHostResult* host)
|
||||
{
|
||||
ffStrbufInit(&host->productName);
|
||||
ffStrbufInit(&host->productFamily);
|
||||
|
||||
ffStrbufInitA(&host->productFamily, 0);
|
||||
ffStrbufInitA(&host->sysVendor, 0);
|
||||
ffStrbufInitA(&host->productVersion, 0);
|
||||
ffStrbufInitA(&host->productSku, 0);
|
||||
@@ -20,5 +129,6 @@ void ffDetectHostImpl(FFHostResult* host)
|
||||
ffStrbufInitA(&host->chassisVendor, 0);
|
||||
ffStrbufInitA(&host->chassisVersion, 0);
|
||||
|
||||
ffSysctlGetString("hw.model", &host->productName);
|
||||
ffSysctlGetString("hw.model", &host->productFamily);
|
||||
ffStrbufAppendS(&host->productName, getProductName(&host->productFamily));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,405 @@
|
||||
#include "fastfetch.h"
|
||||
#include "temps_apple.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
#include <IOKit/IOKitLib.h>
|
||||
|
||||
static const char kDataTypeFlt[] = "flt ";
|
||||
static const char kDataTypeFp1f[] = "fp1f";
|
||||
static const char kDataTypeFp4c[] = "fp4c";
|
||||
static const char kDataTypeFp5b[] = "fp5b";
|
||||
static const char kDataTypeFp6a[] = "fp6a";
|
||||
static const char kDataTypeFp79[] = "fp79";
|
||||
static const char kDataTypeFp88[] = "fp88";
|
||||
static const char kDataTypeFpa6[] = "fpa6";
|
||||
static const char kDataTypeFpc4[] = "fpc4";
|
||||
static const char kDataTypeFpe2[] = "fpe2";
|
||||
static const char kDataTypeSp1e[] = "sp1e";
|
||||
static const char kDataTypeSp3c[] = "sp3c";
|
||||
static const char kDataTypeSp4b[] = "sp4b";
|
||||
static const char kDataTypeSp5a[] = "sp5a";
|
||||
static const char kDataTypeSp69[] = "sp69";
|
||||
static const char kDataTypeSp78[] = "sp78";
|
||||
static const char kDataTypeSp87[] = "sp87";
|
||||
static const char kDataTypeSp96[] = "sp96";
|
||||
static const char kDataTypeSpb4[] = "spb4";
|
||||
static const char kDataTypeSpf0[] = "spf0";
|
||||
static const char kDataTypeUi8[] = "ui8 ";
|
||||
static const char kDataTypeUi16[] = "ui16";
|
||||
static const char kDataTypeUi32[] = "ui32";
|
||||
static const char kDataTypeUi64[] = "ui64";
|
||||
static const char kDataTypeSi8[] = "si8 ";
|
||||
static const char kDataTypeSi16[] = "si16";
|
||||
static const char kDataTypePwm[] = "{pwm";
|
||||
|
||||
static const char *kIOAppleSmcHiddenClassName = "AppleSMC";
|
||||
static const char kSmcCmdReadBytes = 5;
|
||||
static const char kSmcCmdReadKeyInfo = 9;
|
||||
static const uint32_t kKernelIndexSmc = 2;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char major;
|
||||
char minor;
|
||||
char build;
|
||||
char reserved[1];
|
||||
uint16_t release;
|
||||
} SmcKeyData_vers_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t version;
|
||||
uint16_t length;
|
||||
uint32_t cpuPLimit;
|
||||
uint32_t gpuPLimit;
|
||||
uint32_t memPLimit;
|
||||
} SmcKeyData_pLimitData_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t dataSize;
|
||||
uint32_t dataType;
|
||||
char dataAttributes;
|
||||
} SmcKeyData_keyInfo_t;
|
||||
|
||||
typedef unsigned char SmcBytes_t[32];
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t key;
|
||||
SmcKeyData_vers_t vers;
|
||||
SmcKeyData_pLimitData_t pLimitData;
|
||||
SmcKeyData_keyInfo_t keyInfo;
|
||||
char result;
|
||||
char status;
|
||||
char data8;
|
||||
uint32_t data32;
|
||||
SmcBytes_t bytes;
|
||||
} SmcKeyData_t;
|
||||
|
||||
typedef char UInt32Char_t[5];
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32Char_t key;
|
||||
uint32_t dataSize;
|
||||
UInt32Char_t dataType;
|
||||
SmcBytes_t bytes;
|
||||
} SmcVal_t;
|
||||
|
||||
static uint32_t smcStrtoul(const char *str, int size, int base)
|
||||
{
|
||||
uint32_t total = 0;
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
if (base == 16)
|
||||
total += (uint32_t)(str[i] << (size - 1 - i) * 8);
|
||||
else
|
||||
total += (uint32_t)((unsigned char)(str[i]) << (size - 1 - i) * 8);
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
static void smcUltostr(char *str, uint32_t val)
|
||||
{
|
||||
str[0] = '\0';
|
||||
sprintf(str, "%c%c%c%c",
|
||||
(unsigned int)val >> 24,
|
||||
(unsigned int)val >> 16,
|
||||
(unsigned int)val >> 8,
|
||||
(unsigned int)val);
|
||||
}
|
||||
|
||||
static const char *smcCall(io_connect_t conn, uint32_t selector, SmcKeyData_t *inputStructure, SmcKeyData_t *outputStructure)
|
||||
{
|
||||
size_t structureInputSize;
|
||||
size_t structureOutputSize;
|
||||
structureInputSize = sizeof(SmcKeyData_t);
|
||||
structureOutputSize = sizeof(SmcKeyData_t);
|
||||
|
||||
if (IOConnectCallStructMethod(conn, selector, inputStructure, structureInputSize, outputStructure, &structureOutputSize) != kIOReturnSuccess)
|
||||
return "IOConnectCallStructMethod(conn) failed";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Provides key info, using a cache to dramatically improve the energy impact of smcFanControl
|
||||
static const char *smcGetKeyInfo(io_connect_t conn, const uint32_t key, SmcKeyData_keyInfo_t *key_info)
|
||||
{
|
||||
SmcKeyData_t inputStructure = {0};
|
||||
SmcKeyData_t outputStructure = {0};
|
||||
|
||||
inputStructure.key = key;
|
||||
inputStructure.data8 = kSmcCmdReadKeyInfo;
|
||||
|
||||
const char *error = smcCall(conn, kKernelIndexSmc, &inputStructure, &outputStructure);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
*key_info = outputStructure.keyInfo;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *smcReadSmcVal(io_connect_t conn, const UInt32Char_t key, SmcVal_t *val)
|
||||
{
|
||||
SmcKeyData_t inputStructure = {0};
|
||||
SmcKeyData_t outputStructure = {0};
|
||||
|
||||
inputStructure.key = smcStrtoul(key, 4, 16);
|
||||
strcpy(val->key, key);
|
||||
|
||||
const char *error = smcGetKeyInfo(conn, inputStructure.key, &outputStructure.keyInfo);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
val->dataSize = outputStructure.keyInfo.dataSize;
|
||||
smcUltostr(val->dataType, outputStructure.keyInfo.dataType);
|
||||
inputStructure.keyInfo.dataSize = val->dataSize;
|
||||
inputStructure.data8 = kSmcCmdReadBytes;
|
||||
|
||||
error = smcCall(conn, kKernelIndexSmc, &inputStructure, &outputStructure);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
memcpy(val->bytes, outputStructure.bytes, sizeof(outputStructure.bytes));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *smcOpen(io_connect_t *conn)
|
||||
{
|
||||
CFMutableDictionaryRef matchDict = IOServiceMatching(kIOAppleSmcHiddenClassName);
|
||||
if (matchDict == NULL)
|
||||
return "IOServiceMatching(\"AppleSmartBattery\") failed";
|
||||
|
||||
io_iterator_t iterator;
|
||||
if (IOServiceGetMatchingServices(MACH_PORT_NULL, matchDict, &iterator) != kIOReturnSuccess)
|
||||
return "IOServiceGetMatchingServices() failed";
|
||||
|
||||
io_object_t device = IOIteratorNext(iterator);
|
||||
IOObjectRelease(iterator);
|
||||
if (device == 0)
|
||||
return "No SMC device found";
|
||||
|
||||
kern_return_t result = IOServiceOpen(device, mach_task_self(), 0, conn);
|
||||
IOObjectRelease(device);
|
||||
if (result != kIOReturnSuccess)
|
||||
return "IOServiceOpen() failed";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *smcReadValue(io_connect_t conn, const UInt32Char_t key, double *value)
|
||||
{
|
||||
SmcVal_t val = {0};
|
||||
const char* error = smcReadSmcVal(conn, key, &val);
|
||||
if (error != NULL)
|
||||
return error;
|
||||
|
||||
if (strcmp(val.dataType, kDataTypeUi8) == 0 ||
|
||||
strcmp(val.dataType, kDataTypeUi16) == 0 ||
|
||||
strcmp(val.dataType, kDataTypeUi32) == 0 ||
|
||||
strcmp(val.dataType, kDataTypeUi64) == 0)
|
||||
{
|
||||
uint64_t tmp = 0;
|
||||
for (uint32_t i = 0; i < val.dataSize; i++)
|
||||
tmp += (uint64_t)((uint8_t)(val.bytes[i]) * pow(256, val.dataSize - 1 - i));
|
||||
*value = tmp;
|
||||
}
|
||||
else if (strcmp(val.dataType, kDataTypeFlt) == 0)
|
||||
{
|
||||
*value = *(float *)(val.bytes);
|
||||
}
|
||||
else if (strcmp(val.dataType, kDataTypeFp1f) && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 32768.0;
|
||||
}
|
||||
else if (strcmp(val.dataType, kDataTypeFp4c) && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 4096.0;
|
||||
}
|
||||
else if (strcmp(val.dataType, kDataTypeFp5b) == 0 && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 2048.0;
|
||||
}
|
||||
else if (strcmp(val.dataType, kDataTypeFp6a) == 0 && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 1024.0;
|
||||
}
|
||||
else if (strcmp(val.dataType, kDataTypeFp79) == 0 && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 512.0;
|
||||
}
|
||||
else if (strcmp(val.dataType, kDataTypeFp88) == 0 && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 256.0;
|
||||
}
|
||||
else if (strcmp(val.dataType, kDataTypeFpa6) == 0 && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 64.0;
|
||||
}
|
||||
else if (strcmp(val.dataType, kDataTypeFpc4) == 0 && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 16.0;
|
||||
}
|
||||
else if (strcmp(val.dataType, kDataTypeFpe2) == 0 && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 4.0;
|
||||
}
|
||||
else if (strcmp(val.dataType, kDataTypeSp1e) == 0 && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 16384.0;
|
||||
}
|
||||
else if (strcmp(val.dataType, kDataTypeSp3c) == 0 && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 4096.0;
|
||||
}
|
||||
else if (strcmp(val.dataType, kDataTypeSp4b) == 0 && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 2048.0;
|
||||
}
|
||||
else if (strcmp(val.dataType, kDataTypeSp5a) == 0 && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 1024.0;
|
||||
}
|
||||
else if (strcmp(val.dataType, kDataTypeSp69) == 0 && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 512.0;
|
||||
}
|
||||
else if (strcmp(val.dataType, kDataTypeSp78) == 0 && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 256.0;
|
||||
}
|
||||
else if (strcmp(val.dataType, kDataTypeSp87) == 0 && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 128.0;
|
||||
}
|
||||
else if (strcmp(val.dataType, kDataTypeSp96) == 0 && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 64.0;
|
||||
}
|
||||
else if (strcmp(val.dataType, kDataTypeSpb4) == 0 && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 16.0;
|
||||
}
|
||||
else if (strcmp(val.dataType, kDataTypeSpf0) == 0 && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 1.0;
|
||||
}
|
||||
else if (strcmp(val.dataType, kDataTypeSi8) == 0 && val.dataSize == 1)
|
||||
{
|
||||
signed char *bytes = (signed char *)val.bytes;
|
||||
int16_t temp = 0;
|
||||
temp += (int8_t)(bytes[0]);
|
||||
*value = temp;
|
||||
}
|
||||
else if (strcmp(val.dataType, kDataTypeSi16) == 0 && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(int16_t *)(val.bytes));
|
||||
}
|
||||
else if (strcmp(val.dataType, kDataTypePwm) == 0 && val.dataSize == 2)
|
||||
{
|
||||
*value = (double)ntohs(*(uint16_t *)(val.bytes)) * 100 / 65536.0;
|
||||
}
|
||||
else
|
||||
return "Unknown SMC data type";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void detectTemp(io_connect_t conn, const char *sensor, const char *name, FFlist *list)
|
||||
{
|
||||
double temp = 0;
|
||||
const char* error = smcReadValue(conn, sensor, &temp);
|
||||
if (error)
|
||||
return;
|
||||
|
||||
FFTempValue* tempValue= (FFTempValue*)ffListAdd(list);
|
||||
tempValue->value = temp;
|
||||
|
||||
assert(strlen(sensor) == 4);
|
||||
ffStrbufInitNS(&tempValue->deviceClass, 4, sensor);
|
||||
|
||||
ffStrbufInitS(&tempValue->name, name);
|
||||
}
|
||||
|
||||
const char *ffDetectCoreTemps(enum FFTempType type, FFlist *result)
|
||||
{
|
||||
static io_connect_t conn;
|
||||
static dispatch_once_t once_control;
|
||||
dispatch_once_f(&once_control, &conn, (dispatch_function_t) smcOpen);
|
||||
if(!conn)
|
||||
return "smcOpen() failed";
|
||||
|
||||
// https://github.com/exelban/stats/blob/master/Modules/Sensors/values.swift
|
||||
switch (type)
|
||||
{
|
||||
case FF_TEMP_CPU_X64:
|
||||
detectTemp(conn, "TC0D", "CPU diode", result);
|
||||
detectTemp(conn, "TC0E", "CPU diode virtual", result);
|
||||
detectTemp(conn, "TC0E", "CPU diode filtered", result);
|
||||
detectTemp(conn, "TC0P", "CPU proximity", result);
|
||||
break;
|
||||
|
||||
case FF_TEMP_CPU_M1X:
|
||||
detectTemp(conn, "Tp09", "CPU efficient core 1", result);
|
||||
detectTemp(conn, "Tp0T", "CPU efficient core 2", result);
|
||||
|
||||
detectTemp(conn, "Tp01", "CPU performance core 1", result);
|
||||
detectTemp(conn, "Tp05", "CPU performance core 2", result);
|
||||
detectTemp(conn, "Tp0D", "CPU performance core 3", result);
|
||||
detectTemp(conn, "Tp0H", "CPU performance core 4", result);
|
||||
detectTemp(conn, "Tp0L", "CPU performance core 5", result);
|
||||
detectTemp(conn, "Tp0P", "CPU performance core 6", result);
|
||||
detectTemp(conn, "Tp0X", "CPU performance core 7", result);
|
||||
detectTemp(conn, "Tp0b", "CPU performance core 8", result);
|
||||
break;
|
||||
|
||||
case FF_TEMP_CPU_M2X:
|
||||
detectTemp(conn, "Tp05", "CPU efficient core 1", result);
|
||||
detectTemp(conn, "Tp0D", "CPU efficient core 2", result);
|
||||
detectTemp(conn, "Tp0j", "CPU efficient core 3", result);
|
||||
detectTemp(conn, "Tp0r", "CPU efficient core 4", result);
|
||||
|
||||
detectTemp(conn, "Tp01", "CPU performance core 1", result);
|
||||
detectTemp(conn, "Tp09", "CPU performance core 2", result);
|
||||
detectTemp(conn, "Tp0f", "CPU performance core 3", result);
|
||||
detectTemp(conn, "Tp0n", "CPU performance core 4", result);
|
||||
break;
|
||||
|
||||
case FF_TEMP_GPU_INTEL:
|
||||
detectTemp(conn, "TCGC", "GPU Intel Graphics", result);
|
||||
detectTemp(conn, "TG0D", "GPU diode", result);
|
||||
detectTemp(conn, "TG0P", "GPU proximity", result);
|
||||
break;
|
||||
|
||||
case FF_TEMP_GPU_AMD:
|
||||
detectTemp(conn, "TGDD", "GPU AMD Radeon", result);
|
||||
detectTemp(conn, "TG0D", "GPU diode", result);
|
||||
detectTemp(conn, "TG0P", "GPU proximity", result);
|
||||
break;
|
||||
|
||||
case FF_TEMP_GPU_UNKNOWN: // Nvidia?
|
||||
detectTemp(conn, "TG0D", "GPU diode", result);
|
||||
detectTemp(conn, "TG0P", "GPU proximity", result);
|
||||
break;
|
||||
|
||||
case FF_TEMP_GPU_M1X:
|
||||
detectTemp(conn, "Tg05", "GPU 1", result);
|
||||
detectTemp(conn, "Tg0D", "GPU 2", result);
|
||||
detectTemp(conn, "Tg0L", "GPU 3", result);
|
||||
detectTemp(conn, "Tg0T", "GPU 4", result);
|
||||
break;
|
||||
|
||||
case FF_TEMP_GPU_M2X:
|
||||
detectTemp(conn, "Tg0f", "GPU 1", result);
|
||||
detectTemp(conn, "Tg0n", "GPU 2", result);
|
||||
break;
|
||||
|
||||
case FF_TEMP_BATTERY:
|
||||
detectTemp(conn, "TB1T", "Battery", result);
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_detection_temps_apple
|
||||
#define FF_INCLUDED_detection_temps_apple
|
||||
|
||||
#include "fastfetch.h"
|
||||
#include "util/FFlist.h"
|
||||
|
||||
typedef struct FFTempValue
|
||||
{
|
||||
FFstrbuf name;
|
||||
FFstrbuf deviceClass;
|
||||
double value;
|
||||
} FFTempValue;
|
||||
|
||||
enum FFTempType
|
||||
{
|
||||
FF_TEMP_CPU_X64,
|
||||
FF_TEMP_CPU_M1X,
|
||||
FF_TEMP_CPU_M2X,
|
||||
|
||||
FF_TEMP_GPU_INTEL,
|
||||
FF_TEMP_GPU_AMD,
|
||||
FF_TEMP_GPU_UNKNOWN,
|
||||
FF_TEMP_GPU_M1X,
|
||||
FF_TEMP_GPU_M2X,
|
||||
|
||||
FF_TEMP_BATTERY,
|
||||
};
|
||||
|
||||
const char *ffDetectCoreTemps(enum FFTempType type, FFlist *result);
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "fastfetch.h"
|
||||
#include "detection/temps.h"
|
||||
#include "common/io.h"
|
||||
#include "temps_linux.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_detection_temps
|
||||
#define FF_INCLUDED_detection_temps
|
||||
#ifndef FF_INCLUDED_detection_temps_linux
|
||||
#define FF_INCLUDED_detection_temps_linux
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
@@ -1253,6 +1253,12 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
|
||||
//Module options//
|
||||
//////////////////
|
||||
|
||||
else if(strcasecmp(key, "--cpu-temp") == 0)
|
||||
instance->config.cpuTemp = optionParseBoolean(value);
|
||||
else if(strcasecmp(key, "--gpu-temp") == 0)
|
||||
instance->config.gpuTemp = optionParseBoolean(value);
|
||||
else if(strcasecmp(key, "--battery-temp") == 0)
|
||||
instance->config.batteryTemp = optionParseBoolean(value);
|
||||
else if(strcasecmp(key, "--title-fqdn") == 0)
|
||||
instance->config.titleFQDN = optionParseBoolean(value);
|
||||
else if(strcasecmp(key, "--disk-folders") == 0)
|
||||
@@ -1263,12 +1269,16 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
|
||||
optionParseString(key, value, &instance->config.batteryDir);
|
||||
else if(strcasecmp(key, "--separator-string") == 0)
|
||||
optionParseString(key, value, &instance->config.separatorString);
|
||||
else if(strcasecmp(key, "--font-inline") == 0)
|
||||
instance->config.fontInline = optionParseBoolean(value);
|
||||
else if(strcasecmp(key, "--localip-show-ipv4") == 0)
|
||||
instance->config.localIpShowIpV4 = optionParseBoolean(value);
|
||||
else if(strcasecmp(key, "--localip-show-ipv6") == 0)
|
||||
instance->config.localIpShowIpV6 = optionParseBoolean(value);
|
||||
else if(strcasecmp(key, "--localip-show-loop") == 0)
|
||||
instance->config.localIpShowLoop = optionParseBoolean(value);
|
||||
else if(strcasecmp(key, "--localip-name-prefix") == 0)
|
||||
optionParseString(key, value, &instance->config.localIpNamePrefix);
|
||||
else if(strcasecmp(key, "--os-file") == 0)
|
||||
optionParseString(key, value, &instance->config.osFile);
|
||||
else if(strcasecmp(key, "--player-name") == 0)
|
||||
@@ -1428,6 +1438,8 @@ static void parseStructureCommand(FFinstance* instance, FFdata* data, const char
|
||||
ffPrintOpenGL(instance);
|
||||
else if(strcasecmp(line, "opencl") == 0)
|
||||
ffPrintOpenCL(instance);
|
||||
else if(strcasecmp(line, "users") == 0)
|
||||
ffPrintUsers(instance);
|
||||
else
|
||||
ffPrintErrorString(instance, line, 0, NULL, NULL, "<no implementation provided>");
|
||||
}
|
||||
|
||||
@@ -152,6 +152,10 @@ typedef struct FFconfig
|
||||
FFstrbuf libplist;
|
||||
FFstrbuf libcJSON;
|
||||
|
||||
bool cpuTemp;
|
||||
bool gpuTemp;
|
||||
bool batteryTemp;
|
||||
|
||||
bool titleFQDN;
|
||||
|
||||
FFstrbuf diskFolders;
|
||||
@@ -161,9 +165,12 @@ typedef struct FFconfig
|
||||
|
||||
FFstrbuf separatorString;
|
||||
|
||||
bool fontInline;
|
||||
|
||||
bool localIpShowLoop;
|
||||
bool localIpShowIpV4;
|
||||
bool localIpShowIpV6;
|
||||
FFstrbuf localIpNamePrefix;
|
||||
|
||||
uint32_t publicIpTimeout;
|
||||
|
||||
@@ -270,5 +277,6 @@ void ffPrintColors(FFinstance* instance);
|
||||
void ffPrintVulkan(FFinstance* instance);
|
||||
void ffPrintOpenGL(FFinstance* instance);
|
||||
void ffPrintOpenCL(FFinstance* instance);
|
||||
void ffPrintUsers(FFinstance* instance);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -52,6 +52,7 @@ int main(int argc, char** argv)
|
||||
//ffPrintVulkan(&instance);
|
||||
//ffPrintOpenGL(&instance);
|
||||
//ffPrintOpenCL(&instance);
|
||||
//ffPrintUsers(&instance);
|
||||
ffPrintBreak(&instance);
|
||||
ffPrintColors(&instance);
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#define FF_BATTERY_MODULE_NAME "Battery"
|
||||
#define FF_BATTERY_NUM_FORMAT_ARGS 5
|
||||
|
||||
static void printBattery(FFinstance* instance, const BatteryResult* result, uint8_t index)
|
||||
static void printBattery(FFinstance* instance, BatteryResult* result, uint8_t index)
|
||||
{
|
||||
if(instance->config.battery.outputFormat.length == 0)
|
||||
{
|
||||
@@ -32,6 +32,9 @@ static void printBattery(FFinstance* instance, const BatteryResult* result, uint
|
||||
putchar(']');
|
||||
}
|
||||
|
||||
if(result->temperature == result->temperature) //FF_BATTERY_TEMP_UNSET
|
||||
printf(" - %.1f°C", result->temperature);
|
||||
|
||||
putchar('\n');
|
||||
}
|
||||
else
|
||||
@@ -41,7 +44,8 @@ static void printBattery(FFinstance* instance, const BatteryResult* result, uint
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->modelName},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->technology},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->capacity},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->status}
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->status},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &result->temperature},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,9 @@ void ffPrintCPU(FFinstance* instance)
|
||||
if(cpu->frequencyMax > 0.0)
|
||||
printf(" @ %.9g GHz", cpu->frequencyMax);
|
||||
|
||||
if(cpu->temperature == cpu->temperature) //FF_CPU_TEMP_UNSET
|
||||
printf(" - %.1f°C", cpu->temperature);
|
||||
|
||||
putchar('\n');
|
||||
}
|
||||
else
|
||||
|
||||
+13
-4
@@ -11,6 +11,8 @@
|
||||
#define FF_CURSOR_MODULE_NAME "Cursor"
|
||||
#define FF_CURSOR_NUM_FORMAT_ARGS 2
|
||||
|
||||
#if !(defined(__ANDROID__) || defined(__APPLE__))
|
||||
|
||||
static void printCursor(FFinstance* instance, FFstrbuf* cursorTheme, const FFstrbuf* cursorSize)
|
||||
{
|
||||
ffStrbufRemoveIgnCaseEndS(cursorTheme, "cursors");
|
||||
@@ -190,12 +192,17 @@ static bool printCursorFromEnv(FFinstance* instance)
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void ffPrintCursor(FFinstance* instance)
|
||||
{
|
||||
#ifdef __ANDROID__
|
||||
ffPrintError(instance, FF_CURSOR_MODULE_NAME, 0, &instance->config.cursor, "Cursor detection is not supported on Android");
|
||||
return;
|
||||
#endif
|
||||
#if defined(__ANDROID__) || defined(__APPLE__)
|
||||
|
||||
FF_UNUSED(instance);
|
||||
ffPrintError(instance, FF_CURSOR_MODULE_NAME, 0, &instance->config.cursor, "Cursor detection is not supported");
|
||||
return;
|
||||
|
||||
#else
|
||||
|
||||
const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance);
|
||||
|
||||
@@ -243,4 +250,6 @@ void ffPrintCursor(FFinstance* instance)
|
||||
) return;
|
||||
|
||||
printCursorGTK(instance);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
+33
-70
@@ -1,21 +1,13 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/font.h"
|
||||
#include "common/printing.h"
|
||||
#include "common/parsing.h"
|
||||
#include "detection/qt.h"
|
||||
#include "detection/gtk.h"
|
||||
#include "detection/font/font.h"
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
|
||||
#define FF_FONT_MODULE_NAME "Font"
|
||||
#define FF_FONT_NUM_FORMAT_ARGS 21
|
||||
#define FF_FONT_NUM_FORMAT_ARGS 2
|
||||
|
||||
void ffPrintFont(FFinstance* instance)
|
||||
{
|
||||
#ifdef __ANDROID__
|
||||
ffPrintError(instance, FF_FONT_MODULE_NAME, 0, &instance->config.font, "Font detection is not supported on Android");
|
||||
return;
|
||||
#endif
|
||||
|
||||
const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance);
|
||||
|
||||
if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, "TTY") == 0)
|
||||
@@ -24,76 +16,47 @@ void ffPrintFont(FFinstance* instance)
|
||||
return;
|
||||
}
|
||||
|
||||
const FFstrbuf* plasmaRaw = &ffDetectQt(instance)->font;
|
||||
const FFstrbuf* gtk2Raw = &ffDetectGTK2(instance)->font;
|
||||
const FFstrbuf* gtk3Raw = &ffDetectGTK3(instance)->font;
|
||||
const FFstrbuf* gtk4Raw = &ffDetectGTK4(instance)->font;
|
||||
|
||||
if(plasmaRaw->length == 0 && gtk2Raw->length == 0 && gtk3Raw->length == 0 && gtk4Raw->length == 0)
|
||||
FFlist list;
|
||||
ffListInit(&list, sizeof(FFFontResult));
|
||||
const char* error = ffDetectFontImpl(instance, &list);
|
||||
if(error)
|
||||
{
|
||||
ffPrintError(instance, FF_FONT_MODULE_NAME, 0, &instance->config.font, "No fonts found");
|
||||
ffPrintError(instance, FF_FONT_MODULE_NAME, 0, &instance->config.font, "%s", error);
|
||||
return;
|
||||
}
|
||||
|
||||
FFfont plasma;
|
||||
ffFontInitQt(&plasma, plasmaRaw->chars);
|
||||
|
||||
FFfont gtk2;
|
||||
ffFontInitPango(>k2, gtk2Raw->chars);
|
||||
|
||||
FFfont gtk3;
|
||||
ffFontInitPango(>k3, gtk3Raw->chars);
|
||||
|
||||
FFfont gtk4;
|
||||
ffFontInitPango(>k4, gtk4Raw->chars);
|
||||
|
||||
FFstrbuf gtk;
|
||||
ffStrbufInitA(>k, 64);
|
||||
ffParseGTK(>k, >k2.pretty, >k3.pretty, >k4.pretty);
|
||||
|
||||
if(instance->config.font.outputFormat.length == 0)
|
||||
if (instance->config.font.outputFormat.length == 0 && instance->config.fontInline)
|
||||
{
|
||||
ffPrintLogoAndKey(instance, FF_FONT_MODULE_NAME, 0, &instance->config.font.key);
|
||||
if(plasma.pretty.length > 0)
|
||||
for(uint32_t i = 0; i < list.length; ++i)
|
||||
{
|
||||
ffStrbufWriteTo(&plasma.pretty, stdout);
|
||||
fputs(" [QT]", stdout);
|
||||
|
||||
if(gtk.length > 0)
|
||||
fputs(", ", stdout);
|
||||
FFFontResult* font = (FFFontResult*)ffListGet(&list, i);
|
||||
printf("[%s] %*s%s", font->type, font->fontPretty.length, font->fontPretty.chars, i < list.length - 1 ? ", " : "");
|
||||
ffStrbufDestroy(&font->fontPretty);
|
||||
}
|
||||
ffStrbufPutTo(>k, stdout);
|
||||
putchar('\n');
|
||||
}
|
||||
else
|
||||
{
|
||||
ffPrintFormat(instance, FF_FONT_MODULE_NAME, 0, &instance->config.font, FF_FONT_NUM_FORMAT_ARGS, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, plasmaRaw},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &plasma.name},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &plasma.size},
|
||||
{FF_FORMAT_ARG_TYPE_LIST, &plasma.styles},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &plasma.pretty},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, gtk2Raw},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, >k2.name},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, >k2.size},
|
||||
{FF_FORMAT_ARG_TYPE_LIST, >k2.styles},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, >k2.pretty},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, gtk3Raw},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, >k3.name},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, >k3.size},
|
||||
{FF_FORMAT_ARG_TYPE_LIST, >k3.styles},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, >k3.pretty},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, gtk4Raw},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, >k4.name},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, >k4.size},
|
||||
{FF_FORMAT_ARG_TYPE_LIST, >k4.styles},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, >k4.pretty},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, >k}
|
||||
});
|
||||
for(uint32_t i = 0; i < list.length; ++i)
|
||||
{
|
||||
FFFontResult* font = (FFFontResult*)ffListGet(&list, i);
|
||||
if(instance->config.font.outputFormat.length == 0)
|
||||
{
|
||||
char keyChars[32];
|
||||
snprintf(keyChars, sizeof(keyChars), "%s (%s)", FF_FONT_MODULE_NAME, font->type);
|
||||
ffPrintLogoAndKey(instance, keyChars, 0, &instance->config.font.key);
|
||||
puts(font->fontPretty.chars);
|
||||
}
|
||||
else
|
||||
{
|
||||
ffPrintFormat(instance, FF_FONT_MODULE_NAME, 0, &instance->config.font, FF_FONT_NUM_FORMAT_ARGS, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRING, font->type},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &font->fontPretty}
|
||||
});
|
||||
}
|
||||
ffStrbufDestroy(&font->fontPretty);
|
||||
}
|
||||
}
|
||||
|
||||
ffFontDestroy(&plasma);
|
||||
ffFontDestroy(>k2);
|
||||
ffFontDestroy(>k3);
|
||||
ffFontDestroy(>k4);
|
||||
ffStrbufDestroy(>k);
|
||||
ffListDestroy(&list);
|
||||
}
|
||||
|
||||
+4
-1
@@ -25,11 +25,14 @@ static void printGPUResult(FFinstance* instance, uint8_t index, FFcache* cache,
|
||||
if(gpu->coreCount != FF_GPU_CORE_COUNT_UNSET)
|
||||
ffStrbufAppendF(&output, " (%d)", gpu->coreCount);
|
||||
|
||||
if(gpu->temperature == gpu->temperature) //FF_GPU_TEMP_UNSET
|
||||
ffStrbufAppendF(&output, " - %.1f°C", gpu->temperature);
|
||||
|
||||
ffPrintAndAppendToCache(instance, FF_GPU_MODULE_NAME, index, &instance->config.gpu, cache, &output, FF_GPU_NUM_FORMAT_ARGS, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &gpu->vendor},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &gpu->name},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &gpu->driver},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &gpu->temperature},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &gpu->temperature}, //FIXME: temperature shouldn't be cached
|
||||
{FF_FORMAT_ARG_TYPE_INT, &gpu->coreCount},
|
||||
});
|
||||
|
||||
|
||||
+9
-4
@@ -10,10 +10,13 @@
|
||||
|
||||
void ffPrintIcons(FFinstance* instance)
|
||||
{
|
||||
#ifdef __ANDROID__
|
||||
ffPrintError(instance, FF_ICONS_MODULE_NAME, 0, &instance->config.icons, "Icons detection is not supported on Android");
|
||||
return;
|
||||
#endif
|
||||
#if defined(__ANDROID__) || defined(__APPLE__)
|
||||
|
||||
FF_UNUSED(instance);
|
||||
ffPrintError(instance, FF_ICONS_MODULE_NAME, 0, &instance->config.icons, "Icons detection is not supported");
|
||||
return;
|
||||
|
||||
#else
|
||||
|
||||
const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance);
|
||||
|
||||
@@ -64,4 +67,6 @@ void ffPrintIcons(FFinstance* instance)
|
||||
}
|
||||
|
||||
ffStrbufDestroy(>kPretty);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -62,6 +62,9 @@ void ffPrintLocalIp(FFinstance* instance)
|
||||
if (strncmp(ifa->ifa_name, "lo", 2) == 0 && (ifa->ifa_name[2] == '\0' || isdigit(ifa->ifa_name[2])) && !instance->config.localIpShowLoop)
|
||||
continue;
|
||||
|
||||
if (instance->config.localIpNamePrefix.length && strncmp(ifa->ifa_name, instance->config.localIpNamePrefix.chars, instance->config.localIpNamePrefix.length) != 0)
|
||||
continue;
|
||||
|
||||
if (ifa->ifa_addr->sa_family == AF_INET) { // check it is IP4
|
||||
// is a valid IP4 Address
|
||||
if (!instance->config.localIpShowIpV4)
|
||||
|
||||
+9
-4
@@ -10,10 +10,13 @@
|
||||
|
||||
void ffPrintTheme(FFinstance* instance)
|
||||
{
|
||||
#ifdef __ANDROID__
|
||||
ffPrintError(instance, FF_THEME_MODULE_NAME, 0, &instance->config.theme, "Theme detection is not supported on Android");
|
||||
return;
|
||||
#endif
|
||||
#if defined(__ANDROID__) || defined(__APPLE__)
|
||||
|
||||
FF_UNUSED(instance);
|
||||
ffPrintError(instance, FF_THEME_MODULE_NAME, 0, &instance->config.theme, "Theme detection is not supported");
|
||||
return;
|
||||
|
||||
#else
|
||||
|
||||
const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance);
|
||||
|
||||
@@ -98,4 +101,6 @@ void ffPrintTheme(FFinstance* instance)
|
||||
|
||||
ffStrbufDestroy(&plasmaColorPretty);
|
||||
ffStrbufDestroy(>kPretty);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/printing.h"
|
||||
|
||||
#include <utmpx.h>
|
||||
|
||||
#define FF_USERS_MODULE_NAME "Users"
|
||||
#define FF_USERS_NUM_FORMAT_ARGS 1
|
||||
|
||||
void ffPrintUsers(FFinstance* instance)
|
||||
{
|
||||
struct utmpx* n = NULL;
|
||||
setutxent();
|
||||
|
||||
FFlist users;
|
||||
ffListInit(&users, sizeof(n->ut_user));
|
||||
|
||||
next:
|
||||
while((n = getutxent()))
|
||||
{
|
||||
if(n->ut_type == USER_PROCESS)
|
||||
{
|
||||
for(uint32_t i = 0; i < users.length; ++i)
|
||||
{
|
||||
if(strcmp((const char*)ffListGet(&users, i), n->ut_user) == 0)
|
||||
goto next;
|
||||
}
|
||||
strcpy((char*)ffListAdd(&users), n->ut_user);
|
||||
}
|
||||
}
|
||||
|
||||
FFstrbuf result;
|
||||
ffStrbufInit(&result);
|
||||
for(uint32_t i = 0; i < users.length; ++i)
|
||||
{
|
||||
if(i > 0)
|
||||
ffStrbufAppendS(&result, ", ");
|
||||
ffStrbufAppendS(&result, (const char*)ffListGet(&users, i));
|
||||
}
|
||||
ffListDestroy(&users);
|
||||
|
||||
if(instance->config.uptime.outputFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(instance, FF_USERS_MODULE_NAME, 0, &instance->config.uptime.key);
|
||||
puts(result.chars);
|
||||
}
|
||||
else
|
||||
{
|
||||
ffPrintFormat(instance, FF_USERS_MODULE_NAME, 0, &instance->config.uptime, FF_USERS_NUM_FORMAT_ARGS, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result},
|
||||
});
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&result);
|
||||
}
|
||||
+2
-1
@@ -29,12 +29,13 @@ void ffListDestroy(FFlist* list);
|
||||
|
||||
static inline void ffListInit(FFlist* list, uint32_t elementSize)
|
||||
{
|
||||
assert(elementSize > 0);
|
||||
ffListInitA(list, elementSize, 0);
|
||||
}
|
||||
|
||||
static inline void* ffListGet(const FFlist* list, uint32_t index)
|
||||
{
|
||||
assert(list->capacity > 0);
|
||||
assert(list->capacity > index);
|
||||
return list->data + (index * list->elementSize);
|
||||
}
|
||||
|
||||
|
||||
+2
-53
@@ -363,42 +363,6 @@ void ffStrbufSubstrAfterLastC(FFstrbuf* strbuf, char c)
|
||||
ffStrbufSubstrAfter(strbuf, index);
|
||||
}
|
||||
|
||||
bool ffStrbufStartsWithIgnCaseS(const FFstrbuf* strbuf, const char* start)
|
||||
{
|
||||
for(uint32_t i = 0; start[i] != '\0'; i++)
|
||||
{
|
||||
if(i >= strbuf->length)
|
||||
return false;
|
||||
|
||||
if(tolower(strbuf->chars[i]) != tolower(start[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ffStrbufStartsWithIgnCase(const FFstrbuf* strbuf, const FFstrbuf* start)
|
||||
{
|
||||
if (start->length > strbuf->length)
|
||||
return false;
|
||||
return ffStrbufStartsWithIgnCaseS(strbuf, start->chars);
|
||||
}
|
||||
|
||||
bool ffStrbufEndsWithC(const FFstrbuf* strbuf, char c)
|
||||
{
|
||||
return strbuf->length == 0 ? false :
|
||||
strbuf->chars[strbuf->length - 1] == c;
|
||||
}
|
||||
|
||||
bool ffStrbufEndsWithS(const FFstrbuf* strbuf, const char* end)
|
||||
{
|
||||
uint32_t endLength = (uint32_t) strlen(end);
|
||||
|
||||
if(endLength > strbuf->length)
|
||||
return false;
|
||||
|
||||
return memcmp(strbuf->chars + strbuf->length - endLength, end, endLength) == 0;
|
||||
}
|
||||
|
||||
uint32_t ffStrbufCountC(const FFstrbuf* strbuf, char c)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
@@ -411,26 +375,11 @@ uint32_t ffStrbufCountC(const FFstrbuf* strbuf, char c)
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool testEndsWithIgnCaseS(const FFstrbuf* strbuf, const char* end, uint32_t* endLength)
|
||||
{
|
||||
*endLength = (uint32_t) strlen(end);
|
||||
|
||||
if(*endLength > strbuf->length)
|
||||
return false;
|
||||
|
||||
for(uint32_t i = 0; i < *endLength; ++i)
|
||||
{
|
||||
if(tolower(strbuf->chars[strbuf->length - *endLength + i]) != tolower(end[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ffStrbufRemoveIgnCaseEndS(FFstrbuf* strbuf, const char* end)
|
||||
{
|
||||
uint32_t endLength;
|
||||
if(testEndsWithIgnCaseS(strbuf, end, &endLength))
|
||||
uint32_t endLength = (uint32_t) strlen(end);
|
||||
if(ffStrbufEndsWithIgnCaseNS(strbuf, endLength, end))
|
||||
{
|
||||
ffStrbufSubstrBefore(strbuf, strbuf->length - endLength);
|
||||
return true;
|
||||
|
||||
+70
-12
@@ -70,12 +70,6 @@ void ffStrbufSubstrAfterFirstC(FFstrbuf* strbuf, char c);
|
||||
void ffStrbufSubstrAfterFirstS(FFstrbuf* strbuf, const char* str);
|
||||
void ffStrbufSubstrAfterLastC(FFstrbuf* strbuf, char c);
|
||||
|
||||
bool ffStrbufStartsWithIgnCase(const FFstrbuf* strbuf, const FFstrbuf* start);
|
||||
bool ffStrbufStartsWithIgnCaseS(const FFstrbuf* strbuf, const char* start);
|
||||
|
||||
bool ffStrbufEndsWithC(const FFstrbuf* strbuf, char c);
|
||||
bool ffStrbufEndsWithS(const FFstrbuf* strbuf, const char* end);
|
||||
|
||||
FF_C_NODISCARD uint32_t ffStrbufCountC(const FFstrbuf* strbuf, char c);
|
||||
|
||||
bool ffStrbufRemoveIgnCaseEndS(FFstrbuf* strbuf, const char* end);
|
||||
@@ -110,9 +104,20 @@ static inline void ffStrbufSetS(FFstrbuf* strbuf, const char* value)
|
||||
ffStrbufAppendNS(strbuf, (uint32_t) strlen(value), value);
|
||||
}
|
||||
|
||||
static inline void ffStrbufInitS(FFstrbuf* strbuf, const char* str)
|
||||
static inline void ffStrbufInit(FFstrbuf* strbuf)
|
||||
{
|
||||
ffStrbufInitA(strbuf, 0);
|
||||
}
|
||||
|
||||
static inline void ffStrbufInitNS(FFstrbuf* strbuf, uint32_t length, const char* str)
|
||||
{
|
||||
ffStrbufInit(strbuf);
|
||||
ffStrbufAppendNS(strbuf, length, str);
|
||||
}
|
||||
|
||||
static inline void ffStrbufInitS(FFstrbuf* strbuf, const char* str)
|
||||
{
|
||||
ffStrbufInit(strbuf);
|
||||
ffStrbufAppendS(strbuf, str);
|
||||
}
|
||||
|
||||
@@ -124,11 +129,6 @@ static inline void ffStrbufAppend(FFstrbuf* strbuf, const FFstrbuf* value)
|
||||
ffStrbufAppendNS(strbuf, value->length, value->chars);
|
||||
}
|
||||
|
||||
static inline void ffStrbufInit(FFstrbuf* strbuf)
|
||||
{
|
||||
ffStrbufInitA(strbuf, 0);
|
||||
}
|
||||
|
||||
static inline void ffStrbufPrependS(FFstrbuf* strbuf, const char* value)
|
||||
{
|
||||
if(value == NULL)
|
||||
@@ -199,4 +199,62 @@ static inline FF_C_NODISCARD bool ffStrbufStartsWith(const FFstrbuf* strbuf, con
|
||||
{
|
||||
return ffStrbufStartsWithSN(strbuf, start->chars, start->length);
|
||||
}
|
||||
|
||||
static inline FF_C_NODISCARD bool ffStrbufStartsWithIgnCaseNS(const FFstrbuf* strbuf, uint32_t length, const char* start)
|
||||
{
|
||||
if(length > strbuf->length)
|
||||
return false;
|
||||
return strncasecmp(strbuf->chars, start, length) == 0;
|
||||
}
|
||||
|
||||
static inline FF_C_NODISCARD bool ffStrbufStartsWithIgnCaseS(const FFstrbuf* strbuf, const char* start)
|
||||
{
|
||||
return ffStrbufStartsWithIgnCaseNS(strbuf, (uint32_t) strlen(start), start);
|
||||
}
|
||||
|
||||
static inline FF_C_NODISCARD bool ffStrbufStartsWithIgnCase(const FFstrbuf* strbuf, const FFstrbuf* start)
|
||||
{
|
||||
return ffStrbufStartsWithIgnCaseNS(strbuf, start->length, start->chars);
|
||||
}
|
||||
|
||||
static inline FF_C_NODISCARD bool ffStrbufEndsWithC(const FFstrbuf* strbuf, char c)
|
||||
{
|
||||
return strbuf->length == 0 ? false :
|
||||
strbuf->chars[strbuf->length - 1] == c;
|
||||
}
|
||||
|
||||
static inline FF_C_NODISCARD bool ffStrbufEndsWithNS(const FFstrbuf* strbuf, uint32_t endLength, const char* end)
|
||||
{
|
||||
if(endLength > strbuf->length)
|
||||
return false;
|
||||
|
||||
return memcmp(strbuf->chars + strbuf->length - endLength, end, endLength) == 0;
|
||||
}
|
||||
|
||||
static inline FF_C_NODISCARD bool ffStrbufEndsWithS(const FFstrbuf* strbuf, const char* end)
|
||||
{
|
||||
return ffStrbufEndsWithNS(strbuf, (uint32_t) strlen(end), end);
|
||||
}
|
||||
|
||||
static inline FF_C_NODISCARD bool ffStrbufEndsWith(const FFstrbuf* strbuf, const FFstrbuf* end)
|
||||
{
|
||||
return ffStrbufEndsWithNS(strbuf, end->length, end->chars);
|
||||
}
|
||||
|
||||
static inline FF_C_NODISCARD bool ffStrbufEndsWithIgnCaseNS(const FFstrbuf* strbuf, uint32_t endLength, const char* end)
|
||||
{
|
||||
if(endLength > strbuf->length)
|
||||
return false;
|
||||
return strcasecmp(strbuf->chars + strbuf->length - endLength, end) == 0;
|
||||
}
|
||||
|
||||
static inline FF_C_NODISCARD bool ffStrbufEndsWithIgnCaseS(const FFstrbuf* strbuf, const char* end)
|
||||
{
|
||||
return ffStrbufEndsWithIgnCaseNS(strbuf, (uint32_t) strlen(end), end);
|
||||
}
|
||||
|
||||
static inline FF_C_NODISCARD bool ffStrbufEndsWithIgnCase(const FFstrbuf* strbuf, const FFstrbuf* end)
|
||||
{
|
||||
return ffStrbufEndsWithIgnCaseNS(strbuf, end->length, end->chars);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -156,6 +156,21 @@ int main(int argc, char** argv)
|
||||
VERIFY(ffStrbufNextIndexS(&strbuf, 1, "1") == 3);
|
||||
VERIFY(ffStrbufNextIndexS(&strbuf, 4, "1") == 5);
|
||||
|
||||
//ignCase
|
||||
ffStrbufSetS(&strbuf, "AbCdEfG");
|
||||
|
||||
VERIFY(ffStrbufIgnCaseCompS(&strbuf, "aBcDeFg") == 0);
|
||||
VERIFY(ffStrbufStartsWithIgnCaseS(&strbuf, "ABCD"));
|
||||
VERIFY(ffStrbufEndsWithIgnCaseS(&strbuf, "defg"));
|
||||
VERIFY(!ffStrbufStartsWithIgnCaseS(&strbuf, "aBcDeFgH"));
|
||||
VERIFY(!ffStrbufEndsWithIgnCaseS(&strbuf, "0aBcDeFg"));
|
||||
|
||||
//ensure
|
||||
ffStrbufEnsureEndsWithC(&strbuf, '^');
|
||||
VERIFY(ffStrbufCompS(&strbuf, "^aBcDeFg"));
|
||||
ffStrbufEnsureEndsWithC(&strbuf, '$');
|
||||
VERIFY(ffStrbufCompS(&strbuf, "^aBcDeFg$"));
|
||||
|
||||
//Destroy
|
||||
|
||||
ffStrbufDestroy(&strbuf);
|
||||
|
||||
Reference in New Issue
Block a user