From 8cbeb709f918bed57ddb6c99484a7cbb55ec4336 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 26 Jul 2023 10:27:40 +0800 Subject: [PATCH] TerminalSize: add new module --- CHANGELOG.md | 1 + CMakeLists.txt | 6 ++ README.md | 2 +- doc/json_schema.json | 2 + presets/all | 2 +- presets/all.jsonc | 1 + src/common/io/io.h | 6 +- src/common/io/io_unix.c | 19 ++-- src/common/io/io_windows.c | 57 ++++++++++++ src/common/jsonconfig.c | 1 + src/detection/terminalsize/terminalsize.h | 18 ++++ .../terminalsize/terminalsize_linux.c | 26 ++++++ .../terminalsize/terminalsize_windows.c | 41 +++++++++ src/fastfetch.c | 3 + src/fastfetch.h | 1 + src/modules/modules.h | 1 + src/modules/options.h | 1 + src/modules/terminalsize/option.h | 11 +++ src/modules/terminalsize/terminalsize.c | 86 +++++++++++++++++++ src/modules/terminalsize/terminalsize.h | 11 +++ 20 files changed, 279 insertions(+), 17 deletions(-) create mode 100644 src/detection/terminalsize/terminalsize.h create mode 100644 src/detection/terminalsize/terminalsize_linux.c create mode 100644 src/detection/terminalsize/terminalsize_windows.c create mode 100644 src/modules/terminalsize/option.h create mode 100644 src/modules/terminalsize/terminalsize.c create mode 100644 src/modules/terminalsize/terminalsize.h diff --git a/CHANGELOG.md b/CHANGELOG.md index 8eca06e84..707a35f87 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ Features: * Support iTerm non-ascii font detection (Terminal, macOS) * Add option `--title-color-user`, `--title-color-at` and `--title-color-host` (Title) * Add Exherbo logo and package manager count (Packages, Linux, #503) +* Add module `Terminal Size` which prints the number of terminal width and height in charactors and pixels Bugfixes: * Fix possible hanging (TerminalFont, #493) diff --git a/CMakeLists.txt b/CMakeLists.txt index 48dc065cb..702019783 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -319,6 +319,7 @@ set(LIBFASTFETCH_SRC src/modules/media/media.c src/modules/terminal/terminal.c src/modules/terminalfont/terminalfont.c + src/modules/terminalsize/terminalsize.c src/modules/theme/theme.c src/modules/title/title.c src/modules/uptime/uptime.c @@ -378,6 +379,7 @@ if(LINUX) src/detection/temps/temps_linux.c src/detection/terminalfont/terminalfont_linux.c src/detection/terminalshell/terminalshell_linux.c + src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_linux.c src/detection/uptime/uptime_linux.c src/detection/users/users_linux.c @@ -421,6 +423,7 @@ elseif(ANDROID) src/detection/temps/temps_linux.c src/detection/terminalfont/terminalfont_android.c src/detection/terminalshell/terminalshell_linux.c + src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_nosupport.c src/detection/uptime/uptime_linux.c src/detection/users/users_linux.c @@ -472,6 +475,7 @@ elseif(BSD) src/detection/temps/temps_bsd.c src/detection/terminalfont/terminalfont_linux.c src/detection/terminalshell/terminalshell_linux.c + src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_linux.c src/detection/uptime/uptime_bsd.c src/detection/users/users_linux.c @@ -517,6 +521,7 @@ elseif(APPLE) src/detection/temps/temps_apple.c src/detection/terminalfont/terminalfont_apple.m src/detection/terminalshell/terminalshell_linux.c + src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_nosupport.c src/detection/uptime/uptime_bsd.c src/detection/users/users_linux.c @@ -561,6 +566,7 @@ elseif(WIN32) src/detection/swap/swap_windows.c src/detection/terminalfont/terminalfont_windows.c src/detection/terminalshell/terminalshell_windows.c + src/detection/terminalsize/terminalsize_windows.c src/detection/temps/temps_windows.cpp src/detection/theme/theme_nosupport.c src/detection/uptime/uptime_windows.c diff --git a/README.md b/README.md index 36a8c7462..4cd69b8ca 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ All categories not listed here should work without needing a specific implementa ##### Available Modules ``` -Battery, Bios, Bluetooth, Board, Break, Brightness, Colors, Command, CPU, CPUUsage, Cursor, Custom, Date, DateTime, DE, Disk, Display, Font, Gamepad, GPU, Host, Icons, Kernel, LM, Locale, LocalIP, Media, Memory, OpenCL, OpenGL, Packages, Player, Power Adapter, Processes, PublicIP, Separator, OS, Shell, Sound, Swap, Terminal, Terminal Font, Theme, Time, Title, Uptime, Vulkan, Wallpaper, Wifi, WM, WMTheme +Battery, Bios, Bluetooth, Board, Break, Brightness, Colors, Command, CPU, CPUUsage, Cursor, Custom, Date, DateTime, DE, Disk, Display, Font, Gamepad, GPU, Host, Icons, Kernel, LM, Locale, LocalIP, Media, Memory, OpenCL, OpenGL, Packages, Player, Power Adapter, Processes, PublicIP, Separator, OS, Shell, Sound, Swap, Terminal, Terminal Font, Terminal Size, Theme, Time, Title, Uptime, Vulkan, Wallpaper, Wifi, WM, WMTheme ``` ##### Builtin logos diff --git a/doc/json_schema.json b/doc/json_schema.json index f9521c4cb..1d5aa740f 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -482,6 +482,7 @@ "swap", "terminal", "terminalfont", + "terminalsize", "title", "theme", "uptime", @@ -549,6 +550,7 @@ "swap", "terminal", "terminalfont", + "terminalsize", "theme", "uptime", "users", diff --git a/presets/all b/presets/all index b669e6643..506ee7a65 100644 --- a/presets/all +++ b/presets/all @@ -1 +1 @@ ---structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Display:Brightness:LM:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Wallpaper:Terminal:TerminalFont:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Bluetooth:Sound:Gamepad:Weather:Break:Colors +--structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Display:Brightness:LM:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Wallpaper:Terminal:TerminalFont:TerminalSize:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Bluetooth:Sound:Gamepad:Weather:Break:Colors diff --git a/presets/all.jsonc b/presets/all.jsonc index b25c8baa8..3659006d0 100644 --- a/presets/all.jsonc +++ b/presets/all.jsonc @@ -26,6 +26,7 @@ "wallpaper", "terminal", "terminalfont", + "terminalsize", "cpu", "cpuusage", "gpu", diff --git a/src/common/io/io.h b/src/common/io/io.h index e28a9b3c0..cfe730550 100644 --- a/src/common/io/io.h +++ b/src/common/io/io.h @@ -83,10 +83,8 @@ typedef enum FFPathType bool ffPathExists(const char* path, FFPathType pathType); -#ifndef _WIN32 - FF_C_SCANF(2, 3) - void ffGetTerminalResponse(const char* request, const char* format, ...); -#endif +FF_C_SCANF(2, 3) +const char* ffGetTerminalResponse(const char* request, const char* format, ...); // Not thread safe! bool ffSuppressIO(bool suppress); diff --git a/src/common/io/io_unix.c b/src/common/io/io_unix.c index 54e561190..7680cab81 100644 --- a/src/common/io/io_unix.c +++ b/src/common/io/io_unix.c @@ -107,30 +107,25 @@ bool ffPathExists(const char* path, FFPathType type) return false; } -void ffGetTerminalResponse(const char* request, const char* format, ...) +const char* ffGetTerminalResponse(const char* request, const char* format, ...) { struct termios oldTerm, newTerm; if(tcgetattr(STDIN_FILENO, &oldTerm) == -1) - return; + return "tcgetattr(STDIN_FILENO, &oldTerm) failed"; newTerm = oldTerm; newTerm.c_lflag &= (tcflag_t) ~(ICANON | ECHO); if(tcsetattr(STDIN_FILENO, TCSANOW, &newTerm) == -1) - return; + return "tcsetattr(STDIN_FILENO, TCSANOW, &newTerm)"; fputs(request, stdout); fflush(stdout); - struct pollfd pfd; - pfd.fd = STDIN_FILENO; - pfd.events = POLLIN; - pfd.revents = 0; - //Give the terminal 35ms to respond - if(poll(&pfd, 1, 35) <= 0) + if(poll(&(struct pollfd) { .fd = STDIN_FILENO, .events = POLLIN }, 1, 35) <= 0) { tcsetattr(STDIN_FILENO, TCSANOW, &oldTerm); - return; + return "poll() timeout or failed"; } char buffer[512]; @@ -139,7 +134,7 @@ void ffGetTerminalResponse(const char* request, const char* format, ...) tcsetattr(STDIN_FILENO, TCSANOW, &oldTerm); if(readed <= 0) - return; + return "read(STDIN_FILENO, buffer, sizeof(buffer) - 1) failed"; buffer[readed] = '\0'; @@ -147,6 +142,8 @@ void ffGetTerminalResponse(const char* request, const char* format, ...) va_start(args, format); vsscanf(buffer, format, args); va_end(args); + + return NULL; } bool ffSuppressIO(bool suppress) diff --git a/src/common/io/io_windows.c b/src/common/io/io_windows.c index f1f40a2b0..bf19540a2 100644 --- a/src/common/io/io_windows.c +++ b/src/common/io/io_windows.c @@ -1,6 +1,8 @@ #include "io.h" #include "util/stringUtils.h" +#include + static void createSubfolders(const char* fileName) { FF_STRBUF_AUTO_DESTROY path = ffStrbufCreate(); @@ -144,3 +146,58 @@ void ffListFilesRecursively(const char* path) ffStrbufEnsureEndsWithC(&folder, '/'); listFilesRecursively(&folder, 0, NULL); } + +const char* ffGetTerminalResponse(const char* request, const char* format, ...) +{ + HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE); + DWORD prev_mode; + GetConsoleMode(hInput, &prev_mode); + SetConsoleMode(hInput, 0); + + FlushConsoleInputBuffer(hInput); + + DWORD bytes = 0; + WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), request, (DWORD) strlen(request), &bytes, NULL); + + while (true) + { + if (WaitForSingleObjectEx(hInput, 35, TRUE) != WAIT_OBJECT_0) + { + SetConsoleMode(hInput, prev_mode); + return "WaitForSingleObject() failed or timeout"; + } + + // Ignore all unexpected input events + INPUT_RECORD record; + DWORD len = 0; + if (!PeekConsoleInputW(hInput, &record, 1, &len)) + break; + + if ( + record.EventType == KEY_EVENT && + record.Event.KeyEvent.uChar.UnicodeChar != L'\r' && + record.Event.KeyEvent.uChar.UnicodeChar != L'\n' + ) + break; + else + ReadConsoleInputW(hInput, &record, 1, &len); + } + + char buffer[512]; + bytes = 0; + ReadFile(hInput, buffer, sizeof(buffer) - 1, &bytes, NULL); + + SetConsoleMode(hInput, prev_mode); + + if(bytes <= 0) + return "ReadFile() failed"; + + buffer[bytes] = '\0'; + + va_list args; + va_start(args, format); + vsscanf(buffer, format, args); + va_end(args); + + return NULL; +} diff --git a/src/common/jsonconfig.c b/src/common/jsonconfig.c index 08fbb999b..5fd490657 100644 --- a/src/common/jsonconfig.c +++ b/src/common/jsonconfig.c @@ -188,6 +188,7 @@ static bool parseModuleJsonObject(const char* type, yyjson_val* module) return tryModule(type, module, FF_TERMINAL_MODULE_NAME, ffParseTerminalJsonObject) || tryModule(type, module, FF_TERMINALFONT_MODULE_NAME, ffParseTerminalFontJsonObject) || + tryModule(type, module, FF_TERMINALSIZE_MODULE_NAME, ffParseTerminalSizeJsonObject) || tryModule(type, module, FF_TITLE_MODULE_NAME, ffParseTitleJsonObject) || tryModule(type, module, FF_THEME_MODULE_NAME, ffParseThemeJsonObject) || false; diff --git a/src/detection/terminalsize/terminalsize.h b/src/detection/terminalsize/terminalsize.h new file mode 100644 index 000000000..b1b51ebe5 --- /dev/null +++ b/src/detection/terminalsize/terminalsize.h @@ -0,0 +1,18 @@ +#pragma once + +#ifndef FF_INCLUDED_detection_terminalsize_terminalsize +#define FF_INCLUDED_detection_terminalsize_terminalsize + +#include "fastfetch.h" + +typedef struct FFTerminalSizeResult +{ + uint16_t rows; + uint16_t columns; + uint16_t width; + uint16_t height; +} FFTerminalSizeResult; + +bool ffDetectTerminalSize(FFTerminalSizeResult* result); + +#endif diff --git a/src/detection/terminalsize/terminalsize_linux.c b/src/detection/terminalsize/terminalsize_linux.c new file mode 100644 index 000000000..68a75cbb2 --- /dev/null +++ b/src/detection/terminalsize/terminalsize_linux.c @@ -0,0 +1,26 @@ +#include "terminalsize.h" +#include "common/io/io.h" + +#include +#include + +bool ffDetectTerminalSize(FFTerminalSizeResult* result) +{ + struct winsize winsize = {}; + ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize); + + if (winsize.ws_row == 0 || winsize.ws_col == 0) + ffGetTerminalResponse("\033[18t", "\033[8;%hu;%hut", &winsize.ws_row, &winsize.ws_col); + + if (winsize.ws_ypixel == 0 || winsize.ws_xpixel == 0) + ffGetTerminalResponse("\033[14t", "\033[4;%hu;%hut", &winsize.ws_ypixel, &winsize.ws_xpixel); + + if (winsize.ws_row == 0 && winsize.ws_col == 0) + return false; + + result->rows = winsize.ws_row; + result->columns = winsize.ws_col; + result->width = winsize.ws_xpixel; + result->height = winsize.ws_ypixel; + return true; +} diff --git a/src/detection/terminalsize/terminalsize_windows.c b/src/detection/terminalsize/terminalsize_windows.c new file mode 100644 index 000000000..a0b554517 --- /dev/null +++ b/src/detection/terminalsize/terminalsize_windows.c @@ -0,0 +1,41 @@ +#include "terminalsize.h" +#include "common/io/io.h" + +#include + +bool ffDetectTerminalSize(FFTerminalSizeResult* result) +{ + { + CONSOLE_SCREEN_BUFFER_INFO csbi; + if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) + { + result->columns = (uint16_t) (csbi.srWindow.Right - csbi.srWindow.Left + 1); + result->rows = (uint16_t) (csbi.srWindow.Bottom - csbi.srWindow.Top + 1); + } + else + { + ffGetTerminalResponse("\033[18t", "\033[8;%hu;%hut", &result->rows, &result->columns); + } + } + + if (result->columns == 0 && result->rows == 0) + return false; + + { + CONSOLE_FONT_INFO cfi; + if(GetCurrentConsoleFont(GetStdHandle(STD_OUTPUT_HANDLE), FALSE, &cfi)) // Only works for ConHost + { + result->width = result->columns * (uint16_t) cfi.dwFontSize.X; + result->height = result->rows * (uint16_t) cfi.dwFontSize.Y; + } + else + { + // Pending https://github.com/microsoft/terminal/issues/8581 + // if (result->width == 0 && result->height == 0) + // ffGetTerminalResponse("\033[14t", "\033[4;%hu;%hut", &result->height, &result->width); + return false; + } + } + + return result->columns > 0 && result->rows > 0; +} diff --git a/src/fastfetch.c b/src/fastfetch.c index 9c41dc3c7..f201c7849 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -971,6 +971,7 @@ static void parseOption(FFdata* data, const char* key, const char* value) else if(ffParseCursorCommandOptions(&instance.config.cursor, key, value)) {} else if(ffParseTerminalCommandOptions(&instance.config.terminal, key, value)) {} else if(ffParseTerminalFontCommandOptions(&instance.config.terminalFont, key, value)) {} + else if(ffParseTerminalSizeCommandOptions(&instance.config.terminalSize, key, value)) {} else if(ffParseCPUCommandOptions(&instance.config.cpu, key, value)) {} else if(ffParseCPUUsageCommandOptions(&instance.config.cpuUsage, key, value)) {} else if(ffParseGPUCommandOptions(&instance.config.gpu, key, value)) {} @@ -1182,6 +1183,8 @@ static void parseStructureCommand(const char* line, FFlist* customValues) ffPrintTerminal(&instance.config.terminal); else if(ffStrEqualsIgnCase(line, FF_TERMINALFONT_MODULE_NAME)) ffPrintTerminalFont(&instance.config.terminalFont); + else if(ffStrEqualsIgnCase(line, FF_TERMINALSIZE_MODULE_NAME)) + ffPrintTerminalSize(&instance.config.terminalSize); else if(ffStrEqualsIgnCase(line, FF_CPU_MODULE_NAME)) ffPrintCPU(&instance.config.cpu); else if(ffStrEqualsIgnCase(line, FF_CPUUSAGE_MODULE_NAME)) diff --git a/src/fastfetch.h b/src/fastfetch.h index 645bc20d0..85256e0ed 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -82,6 +82,7 @@ typedef struct FFconfig FFCursorOptions cursor; FFTerminalOptions terminal; FFTerminalFontOptions terminalFont; + FFTerminalSizeOptions terminalSize; FFCPUOptions cpu; FFCPUUsageOptions cpuUsage; FFCustomOptions custom; diff --git a/src/modules/modules.h b/src/modules/modules.h index 6959ab815..f2a6f6799 100644 --- a/src/modules/modules.h +++ b/src/modules/modules.h @@ -44,6 +44,7 @@ #include "modules/swap/swap.h" #include "modules/terminal/terminal.h" #include "modules/terminalfont/terminalfont.h" +#include "modules/terminalsize/terminalsize.h" #include "modules/theme/theme.h" #include "modules/title/title.h" #include "modules/uptime/uptime.h" diff --git a/src/modules/options.h b/src/modules/options.h index 2fdc65c3e..7d9c0668d 100644 --- a/src/modules/options.h +++ b/src/modules/options.h @@ -43,6 +43,7 @@ #include "modules/swap/option.h" #include "modules/terminal/option.h" #include "modules/terminalfont/option.h" +#include "modules/terminalsize/option.h" #include "modules/theme/option.h" #include "modules/title/option.h" #include "modules/uptime/option.h" diff --git a/src/modules/terminalsize/option.h b/src/modules/terminalsize/option.h new file mode 100644 index 000000000..16f482466 --- /dev/null +++ b/src/modules/terminalsize/option.h @@ -0,0 +1,11 @@ +#pragma once + +// This file will be included in "fastfetch.h", do NOT put unnecessary things here + +#include "common/option.h" + +typedef struct FFTerminalSizeOptions +{ + const char* moduleName; + FFModuleArgs moduleArgs; +} FFTerminalSizeOptions; diff --git a/src/modules/terminalsize/terminalsize.c b/src/modules/terminalsize/terminalsize.c new file mode 100644 index 000000000..e33966eb5 --- /dev/null +++ b/src/modules/terminalsize/terminalsize.c @@ -0,0 +1,86 @@ +#include "common/printing.h" +#include "common/jsonconfig.h" +#include "detection/terminalsize/terminalsize.h" +#include "modules/terminalsize/terminalsize.h" +#include "util/stringUtils.h" + +#define FF_TERMINALSIZE_DISPLAY_NAME "Terminal Size" +#define FF_TERMINALSIZE_NUM_FORMAT_ARGS 4 + +void ffPrintTerminalSize(FFTerminalSizeOptions* options) +{ + FFTerminalSizeResult result = {}; + + if(!ffDetectTerminalSize(&result)) + { + ffPrintError(FF_TERMINALSIZE_DISPLAY_NAME, 0, &options->moduleArgs, "Failed to detect terminal size"); + } + else + { + if(options->moduleArgs.outputFormat.length == 0) + { + ffPrintLogoAndKey(FF_TERMINALSIZE_DISPLAY_NAME, 0, &options->moduleArgs.key, &options->moduleArgs.keyColor); + printf("%u columns x %u rows", result.columns, result.rows); + + if (result.width != 0 && result.height != 0) + printf(" (%upx x %upx)", result.width, result.height); + + putchar('\n'); + } + else + { + ffPrintFormat(FF_TERMINALSIZE_DISPLAY_NAME, 0, &options->moduleArgs, FF_TERMINALSIZE_NUM_FORMAT_ARGS, (FFformatarg[]){ + {FF_FORMAT_ARG_TYPE_UINT16, &result.rows}, + {FF_FORMAT_ARG_TYPE_UINT16, &result.columns}, + {FF_FORMAT_ARG_TYPE_UINT16, &result.width}, + {FF_FORMAT_ARG_TYPE_UINT16, &result.height} + }); + } + } +} + +void ffInitTerminalSizeOptions(FFTerminalSizeOptions* options) +{ + options->moduleName = FF_TERMINALSIZE_MODULE_NAME; + ffOptionInitModuleArg(&options->moduleArgs); +} + +bool ffParseTerminalSizeCommandOptions(FFTerminalSizeOptions* options, const char* key, const char* value) +{ + const char* subKey = ffOptionTestPrefix(key, FF_TERMINALSIZE_MODULE_NAME); + if (!subKey) return false; + if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) + return true; + + return false; +} + +void ffDestroyTerminalSizeOptions(FFTerminalSizeOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +void ffParseTerminalSizeJsonObject(yyjson_val* module) +{ + FFTerminalSizeOptions __attribute__((__cleanup__(ffDestroyTerminalSizeOptions))) options; + ffInitTerminalSizeOptions(&options); + + if (module) + { + yyjson_val *key_, *val; + size_t idx, max; + yyjson_obj_foreach(module, idx, max, key_, val) + { + const char* key = yyjson_get_str(key_); + if(ffStrEqualsIgnCase(key, "type")) + continue; + + if (ffJsonConfigParseModuleArgs(key, val, &options.moduleArgs)) + continue; + + ffPrintError(FF_TERMINALSIZE_MODULE_NAME, 0, &options.moduleArgs, "Unknown JSON key %s", key); + } + } + + ffPrintTerminalSize(&options); +} diff --git a/src/modules/terminalsize/terminalsize.h b/src/modules/terminalsize/terminalsize.h new file mode 100644 index 000000000..0b1b37d32 --- /dev/null +++ b/src/modules/terminalsize/terminalsize.h @@ -0,0 +1,11 @@ +#pragma once + +#include "fastfetch.h" + +#define FF_TERMINALSIZE_MODULE_NAME "TerminalSize" + +void ffPrintTerminalSize(FFTerminalSizeOptions* options); +void ffInitTerminalSizeOptions(FFTerminalSizeOptions* options); +bool ffParseTerminalSizeCommandOptions(FFTerminalSizeOptions* options, const char* key, const char* value); +void ffDestroyTerminalSizeOptions(FFTerminalSizeOptions* options); +void ffParseTerminalSizeJsonObject(yyjson_val* module);