/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file LICENSE.rst or https://cmake.org/licensing for details. */ #include "cmStdIoStream.h" #include #include #include #include // IWYU pragma: keep #include // IWYU pragma: keep #ifdef _WIN32 # include # include // for _get_osfhandle #else # include # include # include # include # include #endif #include "cm_fileno.hxx" #ifndef _WIN32 # include "cmSystemTools.h" #endif namespace cm { namespace StdIo { namespace { #ifdef _WIN32 # ifndef ENABLE_VIRTUAL_TERMINAL_INPUT # define ENABLE_VIRTUAL_TERMINAL_INPUT 0x0200 # endif # ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING # define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 # endif #else // List of known `TERM` names that support VT100 escape sequences. // Order by `LC_COLLATE=C sort` to search using `std::lower_bound`. std::array const kVT100Names{ { "Eterm"_s, "alacritty"_s, "alacritty-direct"_s, "ansi"_s, "color-xterm"_s, "con132x25"_s, "con132x30"_s, "con132x43"_s, "con132x60"_s, "con80x25"_s, "con80x28"_s, "con80x30"_s, "con80x43"_s, "con80x50"_s, "con80x60"_s, "cons25"_s, "console"_s, "cygwin"_s, "dtterm"_s, "eterm-color"_s, "gnome"_s, "gnome-256color"_s, "konsole"_s, "konsole-256color"_s, "kterm"_s, "linux"_s, "linux-c"_s, "mach-color"_s, "mlterm"_s, "msys"_s, "putty"_s, "putty-256color"_s, "rxvt"_s, "rxvt-256color"_s, "rxvt-cygwin"_s, "rxvt-cygwin-native"_s, "rxvt-unicode"_s, "rxvt-unicode-256color"_s, "screen"_s, "screen-256color"_s, "screen-256color-bce"_s, "screen-bce"_s, "screen-w"_s, "screen.linux"_s, "st-256color"_s, "tmux"_s, "tmux-256color"_s, "vt100"_s, "xterm"_s, "xterm-16color"_s, "xterm-256color"_s, "xterm-88color"_s, "xterm-color"_s, "xterm-debian"_s, "xterm-kitty"_s, "xterm-termite"_s, } }; bool TermIsVT100() { if (cm::optional term = cmSystemTools::GetEnvVar("TERM")) { // NOLINTNEXTLINE(readability-qualified-auto) auto i = std::lower_bound(kVT100Names.begin(), kVT100Names.end(), *term); if (i != kVT100Names.end() && *i == *term) { return true; } } return false; } #endif } // anonymous namespace Stream::Stream(std::ios& s, FILE* file, Direction direction) : IOS_(s) , FD_(cm_fileno(file)) { #ifdef _WIN32 auto h = reinterpret_cast(_get_osfhandle(this->FD_)); if (GetConsoleMode(h, &this->ConsoleOrigMode_)) { this->Console_ = h; DWORD vtMode = this->ConsoleOrigMode_ | (direction == Direction::In ? ENABLE_VIRTUAL_TERMINAL_INPUT : ENABLE_VIRTUAL_TERMINAL_PROCESSING); if (SetConsoleMode(this->Console_, vtMode)) { this->Kind_ = TermKind::VT100; } else { SetConsoleMode(this->Console_, this->ConsoleOrigMode_); this->Kind_ = TermKind::Console; } } #else static_cast(direction); if (isatty(this->FD_) && TermIsVT100()) { this->Kind_ = TermKind::VT100; } #endif } #ifdef _WIN32 Stream::~Stream() { if (this->Console_) { this->IOS_.rdbuf()->pubsync(); SetConsoleMode(this->Console_, this->ConsoleOrigMode_); } } #else Stream::~Stream() = default; #endif IStream::IStream(std::istream& is, FILE* file) : Stream(is, file, Direction::In) { } std::istream& IStream::IOS() const { return dynamic_cast(this->Stream::IOS()); } OStream::OStream(std::ostream& os, FILE* file) : Stream(os, file, Direction::Out) { } std::ostream& OStream::IOS() const { return dynamic_cast(this->Stream::IOS()); } } }