LCOV - code coverage report
Current view: top level - src/esys/repo/tui - is_tty.cpp (source / functions) Hit Total Coverage
Test: esysrepo_coverage.info Lines: 0 14 0.0 %
Date: 2026-08-01 10:43:40 Functions: 0 4 0.0 %

          Line data    Source code
       1             : /*!
       2             :  * \file esys/repo/tui/is_tty.cpp
       3             :  * \brief
       4             :  *
       5             :  * \cond
       6             :  * __legal_b__
       7             :  *
       8             :  * Copyright (c) 2026 Michel Gillet
       9             :  * Distributed under the MIT License.
      10             :  * (See accompanying file LICENSE.txt or
      11             :  * copy at https://opensource.org/licenses/MIT)
      12             :  *
      13             :  * __legal_e__
      14             :  * \endcond
      15             :  *
      16             :  */
      17             : 
      18             : #include "esys/repo/esysrepo_prec.h"
      19             : #include "esys/repo/tui/is_tty.h"
      20             : 
      21             : #ifdef _WIN32
      22             : #include <io.h>
      23             : #include <stdio.h>
      24             : #include <windows.h>
      25             : #else
      26             : #include <sys/ioctl.h>
      27             : #include <unistd.h>
      28             : #include <stdio.h>
      29             : #endif
      30             : 
      31             : namespace esys::repo::tui
      32             : {
      33             : 
      34             : namespace
      35             : {
      36             : 
      37             : #ifdef _WIN32
      38             : bool g_console_prepared = false;
      39             : UINT g_prev_output_cp = 0;
      40             : UINT g_prev_input_cp = 0;
      41             : DWORD g_prev_out_mode = 0;
      42             : DWORD g_prev_in_mode = 0;
      43             : bool g_have_out_mode = false;
      44             : bool g_have_in_mode = false;
      45             : #endif
      46             : 
      47             : } // namespace
      48             : 
      49           0 : bool is_tty()
      50             : {
      51             : #ifdef _WIN32
      52             :     // FTXUI needs a real Win32 console for both stdout and stdin (VT + ReadConsoleInput).
      53             :     // Git Bash / mintty / pipes often fail GetConsoleMode even when isatty is true.
      54             :     const HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
      55             :     const HANDLE in = GetStdHandle(STD_INPUT_HANDLE);
      56             :     if (out == nullptr || out == INVALID_HANDLE_VALUE) return false;
      57             :     if (in == nullptr || in == INVALID_HANDLE_VALUE) return false;
      58             : 
      59             :     DWORD out_mode = 0;
      60             :     DWORD in_mode = 0;
      61             :     if (GetConsoleMode(out, &out_mode) == 0) return false;
      62             :     if (GetConsoleMode(in, &in_mode) == 0) return false;
      63             : 
      64             :     if (_isatty(_fileno(stdout)) == 0) return false;
      65             :     if (_isatty(_fileno(stdin)) == 0) return false;
      66             :     return true;
      67             : #else
      68           0 :     return ::isatty(::fileno(stdout)) != 0 && ::isatty(::fileno(stdin)) != 0;
      69             : #endif
      70             : }
      71             : 
      72           0 : bool prepare_console_for_tui()
      73             : {
      74             : #ifdef _WIN32
      75             :     const HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
      76             :     const HANDLE in = GetStdHandle(STD_INPUT_HANDLE);
      77             :     if (out == nullptr || out == INVALID_HANDLE_VALUE) return false;
      78             :     if (in == nullptr || in == INVALID_HANDLE_VALUE) return false;
      79             : 
      80             :     // Save previous settings once so restore_console_after_tui can undo.
      81             :     if (!g_console_prepared)
      82             :     {
      83             :         g_prev_output_cp = GetConsoleOutputCP();
      84             :         g_prev_input_cp = GetConsoleCP();
      85             :         g_have_out_mode = GetConsoleMode(out, &g_prev_out_mode) != 0;
      86             :         g_have_in_mode = GetConsoleMode(in, &g_prev_in_mode) != 0;
      87             :         g_console_prepared = true;
      88             :     }
      89             : 
      90             :     // Re-apply every call: ScreenInteractive / other writers may reset modes.
      91             :     SetConsoleOutputCP(CP_UTF8);
      92             :     SetConsoleCP(CP_UTF8);
      93             : 
      94             :     DWORD out_mode = 0;
      95             :     if (GetConsoleMode(out, &out_mode) != 0)
      96             :     {
      97             :         out_mode |= ENABLE_PROCESSED_OUTPUT;
      98             :         out_mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
      99             :         out_mode |= DISABLE_NEWLINE_AUTO_RETURN;
     100             :         SetConsoleMode(out, out_mode);
     101             :     }
     102             : 
     103             :     DWORD in_mode = 0;
     104             :     if (GetConsoleMode(in, &in_mode) != 0)
     105             :     {
     106             :         in_mode |= ENABLE_EXTENDED_FLAGS;
     107             :         in_mode |= ENABLE_VIRTUAL_TERMINAL_INPUT;
     108             :         in_mode |= ENABLE_PROCESSED_INPUT;
     109             :         SetConsoleMode(in, in_mode);
     110             :     }
     111             : 
     112             :     return true;
     113             : #else
     114           0 :     return true;
     115             : #endif
     116             : }
     117             : 
     118           0 : void restore_console_after_tui()
     119             : {
     120             : #ifdef _WIN32
     121             :     if (!g_console_prepared) return;
     122             : 
     123             :     const HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
     124             :     const HANDLE in = GetStdHandle(STD_INPUT_HANDLE);
     125             :     if (out != nullptr && out != INVALID_HANDLE_VALUE && g_have_out_mode)
     126             :         SetConsoleMode(out, g_prev_out_mode);
     127             :     if (in != nullptr && in != INVALID_HANDLE_VALUE && g_have_in_mode)
     128             :         SetConsoleMode(in, g_prev_in_mode);
     129             : 
     130             :     if (g_prev_output_cp != 0) SetConsoleOutputCP(g_prev_output_cp);
     131             :     if (g_prev_input_cp != 0) SetConsoleCP(g_prev_input_cp);
     132             : 
     133             :     g_console_prepared = false;
     134             :     g_have_out_mode = false;
     135             :     g_have_in_mode = false;
     136             : #endif
     137           0 : }
     138             : 
     139           0 : bool query_console_size(int &cols, int &rows)
     140             : {
     141           0 :     cols = 0;
     142           0 :     rows = 0;
     143             : #ifdef _WIN32
     144             :     const HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
     145             :     if (out == nullptr || out == INVALID_HANDLE_VALUE) return false;
     146             : 
     147             :     CONSOLE_SCREEN_BUFFER_INFO info;
     148             :     if (GetConsoleScreenBufferInfo(out, &info) == 0) return false;
     149             : 
     150             :     cols = static_cast<int>(info.srWindow.Right - info.srWindow.Left + 1);
     151             :     rows = static_cast<int>(info.srWindow.Bottom - info.srWindow.Top + 1);
     152             :     return cols > 0 && rows > 0;
     153             : #else
     154           0 :     winsize ws{};
     155           0 :     if (::ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != 0) return false;
     156           0 :     cols = static_cast<int>(ws.ws_col);
     157           0 :     rows = static_cast<int>(ws.ws_row);
     158           0 :     return cols > 0 && rows > 0;
     159             : #endif
     160             : }
     161             : 
     162             : } // namespace esys::repo::tui

Generated by: LCOV version 1.14