From 328853740f728c5b2d9ae2630455211f2a9288f1 Mon Sep 17 00:00:00 2001 From: keqingmoe Date: Fri, 13 Dec 2024 10:47:50 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=8A=9F=E8=83=BD=EF=BC=9A?= =?UTF-8?q?=E5=A4=84=E7=90=86=E5=B9=B3=E5=8F=B0=E4=B8=8E=E7=BB=88=E7=AB=AF?= =?UTF-8?q?=E7=89=B9=E5=AE=9A=E7=9A=84=E7=89=B9=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/tui/plat/color_depth.cppm | 63 +++++++++++++++++++++ src/tui/{screen => plat}/colors.cppm | 6 +- src/tui/plat/plat.cppm | 15 +++++ src/tui/plat/size.cppm | 84 ++++++++++++++++++++++++++++ 4 files changed, 165 insertions(+), 3 deletions(-) create mode 100644 src/tui/plat/color_depth.cppm rename src/tui/{screen => plat}/colors.cppm (99%) create mode 100644 src/tui/plat/plat.cppm create mode 100644 src/tui/plat/size.cppm diff --git a/src/tui/plat/color_depth.cppm b/src/tui/plat/color_depth.cppm new file mode 100644 index 0000000..83accdc --- /dev/null +++ b/src/tui/plat/color_depth.cppm @@ -0,0 +1,63 @@ +/** + * @file tui/plat/color_depth.cppm + * @brief 获取终端支持的色彩深度 + * @author KeqingMoe + * @date 2024-12-13 + * @copyright Copyright (c) 2024 KeqingMoe + * @license MIT License + */ + +export module kqm.tui.plat:color_depth; + +import std; + +auto get_env(const char* env_var) noexcept -> std::string_view +{ + auto env = std::getenv(env_var); + if (!env) return std::string_view{}; + return std::string_view{env}; +} + +export namespace kqm::tui +{ + +inline namespace plat +{ + +/** + * @brief 获取当前终端支持的色彩深度 + * + * @return `std::size_t` 色彩深度 + * @retval `4uz` 16 色 + * @retval `8uz` 256 色 + * @retval `24uz` 24 bits 真彩色 + */ +auto get_color_depth() noexcept -> std::size_t +{ +#ifdef __EMSCRIPTEN__ + return 24uz; +#else + // Windows Terminal 支持 24bits 真彩色 + if (std::getenv("WT_SESSION")) { + return 24uz; + } + auto env_colorterm = get_env("COLORTERM"); + if (env_colorterm.contains("24bit") || env_colorterm.contains("truecolor")) { + return 24uz; + } + auto env_term = get_env("TERM"); + if (env_colorterm.contains("256") || env_term.contains("256")) { + return 8uz; + } +#endif + return 4uz; +} + +/** + * @brief 已缓存的色彩深度 + */ +auto color_depth = get_color_depth(); + +} + +} diff --git a/src/tui/screen/colors.cppm b/src/tui/plat/colors.cppm similarity index 99% rename from src/tui/screen/colors.cppm rename to src/tui/plat/colors.cppm index a34f338..ead77b4 100644 --- a/src/tui/screen/colors.cppm +++ b/src/tui/plat/colors.cppm @@ -1,5 +1,5 @@ /** - * @file tui/screen/colors.cppm + * @file tui/plat/colors.cppm * @brief 预定义的颜色常量 * @author KeqingMoe * @date 2024-12-9 @@ -7,14 +7,14 @@ * @license MIT License */ -export module kqm.tui.screen:colors; +export module kqm.tui.plat:colors; import std; export namespace kqm::tui { -inline namespace screen +inline namespace plat { inline namespace colors diff --git a/src/tui/plat/plat.cppm b/src/tui/plat/plat.cppm new file mode 100644 index 0000000..c95ed2c --- /dev/null +++ b/src/tui/plat/plat.cppm @@ -0,0 +1,15 @@ +/** + * @file tui/plat/plat.cppm + * @brief 获取依赖于终端的信息和依赖于平台的代码 + * @details 相关实现分散在各个模块分区内,并隔离了相关的宏和无关名,这个文件只负责汇总导出接口 + * @author KeqingMoe + * @date 2024-12-11 + * @copyright Copyright (c) 2024 KeqingMoe + * @license MIT License + */ + +export module kqm.tui.plat; + +export import :colors; +export import :color_depth; +export import :size; diff --git a/src/tui/plat/size.cppm b/src/tui/plat/size.cppm new file mode 100644 index 0000000..6bbe33d --- /dev/null +++ b/src/tui/plat/size.cppm @@ -0,0 +1,84 @@ +/** + * @file tui/plat/size.cppm + * @brief 获取终端的宽度与高度 + * @author KeqingMoe + * @date 2024-12-13 + * @copyright Copyright (c) 2024 KeqingMoe + * @license MIT License + */ + +module; + +#ifdef _WIN32 + +#define WIN32_LEAN_AND_MEAN + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#include + +#else + +#include // for winsize, ioctl, TIOCGWINSZ +#include // for STDOUT_FILENO + +#endif + +export module kqm.tui.plat:size; + +import std; + +export namespace kqm::tui +{ + +inline namespace plat +{ + +/** + * @brief 用作回退值的终端大小,first 是宽,second 是高 + */ +auto fallback_terminal_size = std::pair{ +#ifdef __EMSCRIPTEN__ + 140uz, 43uz +#else + 80uz, 24uz +#endif +}; + +/** + * @brief 获取当前终端的大小 + * + * @return `std::pair` first 是宽,second 是高 + */ +auto get_terminal_size() -> std::pair +{ +#if defined(__EMSCRIPTEN___) + return fallback_size; +#elif defined(_WIN32) + auto csbi = CONSOLE_SCREEN_BUFFER_INFO{}; + auto handle = GetStdHandle(STD_OUTPUT_HANDLE); + auto flag = GetConsoleScreenBufferInfo(handle, &csbi); + if (flag) { + auto width = csbi.srWindow.Right - csbi.srWindow.Left + 1uz; + auto height = csbi.srWindow.Bottom - csbi.srWindow.Top + 1uz; + return std::pair{width, height}; + } + return fallback_terminal_size; +#else + auto w = winsize{}; + auto status = ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); + auto width = std::size_t{w.ws_col}; + auto height = std::size_t{w.ws_row}; + + if (width == 0 || height == 0 || status < 0) { + return fallback_size; + } + return std::pair{width, height}; +#endif +} + +} + +}