#include // for getenv #include // for string, allocator #include "ftxui/screen/terminal.hpp" #if defined(_WIN32) #define WIN32_LEAN_AND_MEAN #ifndef NOMINMAX #define NOMINMAX #endif #include #else #include // for winsize, ioctl, TIOCGWINSZ #include // for STDOUT_FILENO #endif namespace ftxui { namespace { bool g_cached = false; Terminal::Color g_cached_supported_color; Dimensions& FallbackSize() { #if defined(__EMSCRIPTEN__) // This dimension was chosen arbitrarily to be able to display: // https://arthursonzogni.com/FTXUI/examples // This will have to be improved when someone has time to implement and need // it. constexpr int fallback_width = 140; constexpr int fallback_height = 43; #else // The terminal size in VT100 was 80x24. It is still used nowadays by // default in many terminal emulator. That's a good choice for a fallback // value. constexpr int fallback_width = 80; constexpr int fallback_height = 24; #endif static Dimensions g_fallback_size{fallback_width, fallback_height}; return g_fallback_size; } const char* Safe(const char* c) { return (c != nullptr) ? c : ""; } bool Contains(const std::string& s, const char* key) { return s.find(key) != std::string::npos; } Terminal::Color ComputeColorSupport() { #if defined(__EMSCRIPTEN__) return Terminal::Color::TrueColor; #endif std::string COLORTERM = Safe(std::getenv("COLORTERM")); // NOLINT if (Contains(COLORTERM, "24bit") || Contains(COLORTERM, "truecolor")) { return Terminal::Color::TrueColor; } std::string TERM = Safe(std::getenv("TERM")); // NOLINT if (Contains(COLORTERM, "256") || Contains(TERM, "256")) { return Terminal::Color::Palette256; } #if defined(FTXUI_MICROSOFT_TERMINAL_FALLBACK) // Microsoft terminals do not properly declare themselve supporting true // colors: https://github.com/microsoft/terminal/issues/1040 // As a fallback, assume microsoft terminal are the ones not setting those // variables, and enable true colors. if (TERM == "" && COLORTERM == "") { return Terminal::Color::TrueColor; } #endif return Terminal::Color::Palette16; } } // namespace namespace Terminal { Dimensions Size() { #if defined(__EMSCRIPTEN__) // This dimension was chosen arbitrarily to be able to display: // https://arthursonzogni.com/FTXUI/examples // This will have to be improved when someone has time to implement and need // it. return FallbackSize(); #elif defined(_WIN32) CONSOLE_SCREEN_BUFFER_INFO csbi; if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) { return Dimensions{csbi.srWindow.Right - csbi.srWindow.Left + 1, csbi.srWindow.Bottom - csbi.srWindow.Top + 1}; } return FallbackSize(); #else winsize w{}; const int status = ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); // NOLINT // The ioctl return value result should be checked. Some operating systems // don't support TIOCGWINSZ. if (w.ws_col == 0 || w.ws_row == 0 || status < 0) { return FallbackSize(); } return Dimensions{w.ws_col, w.ws_row}; #endif } /// @brief Override terminal size in case auto-detection fails /// @param fallbackSize Terminal dimensions to fallback to void SetFallbackSize(const Dimensions& fallbackSize) { FallbackSize() = fallbackSize; } Color ColorSupport() { if (!g_cached) { g_cached = true; g_cached_supported_color = ComputeColorSupport(); } return g_cached_supported_color; } void SetColorSupport(Color color) { g_cached = true; g_cached_supported_color = color; } } // namespace Terminal } // namespace ftxui // Copyright 2020 Arthur Sonzogni. All rights reserved. // Use of this source code is governed by the MIT license that can be found in // the LICENSE file.