LCOV - code coverage report
Current view: top level - src/platform - terminal.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 3 3
Test Date: 2026-04-20 19:54:22 Functions: 100.0 % 1 1

            Line data    Source code
       1              : /* SPDX-License-Identifier: GPL-3.0-or-later */
       2              : /* Copyright 2026 Peter Csaszar */
       3              : 
       4              : #ifndef PLATFORM_TERMINAL_H
       5              : #define PLATFORM_TERMINAL_H
       6              : 
       7              : #include <stddef.h>
       8              : #include <stdint.h>
       9              : 
      10              : /** Logical key codes returned by terminal_read_key(). */
      11              : typedef enum {
      12              :     TERM_KEY_QUIT      = 0,  /* Ctrl-C                          */
      13              :     TERM_KEY_NEXT_PAGE = 1,  /* PgDn                            */
      14              :     TERM_KEY_PREV_PAGE = 2,  /* PgUp                            */
      15              :     TERM_KEY_NEXT_LINE = 3,  /* Down-arrow                      */
      16              :     TERM_KEY_PREV_LINE = 4,  /* Up-arrow                        */
      17              :     TERM_KEY_IGNORE    = 5,  /* unknown / Space                 */
      18              :     TERM_KEY_ENTER     = 6,  /* Enter (\n or \r)                */
      19              :     TERM_KEY_ESC       = 7,  /* bare ESC                        */
      20              :     TERM_KEY_BACK      = 8,  /* Backspace / DEL                 */
      21              :     TERM_KEY_LEFT      = 9,  /* Left arrow                      */
      22              :     TERM_KEY_RIGHT     = 10, /* Right arrow                     */
      23              :     TERM_KEY_HOME      = 11, /* Home key                        */
      24              :     TERM_KEY_END       = 12, /* End key                         */
      25              :     TERM_KEY_DELETE    = 13, /* Delete (forward delete)         */
      26              :     TERM_KEY_CTRL_A    = 14, /* Ctrl-A (beginning of line)      */
      27              :     TERM_KEY_CTRL_E    = 15, /* Ctrl-E (end of line)            */
      28              :     TERM_KEY_CTRL_K    = 16, /* Ctrl-K (kill to end of line)    */
      29              :     TERM_KEY_CTRL_W    = 17, /* Ctrl-W (delete previous word)   */
      30              :     TERM_KEY_CTRL_D    = 18, /* Ctrl-D (EOF / delete forward)   */
      31              : } TermKey;
      32              : 
      33              : /** Opaque saved terminal state (used for raw-mode enter/exit). */
      34              : typedef struct TermRawState TermRawState;
      35              : 
      36              : /** Returns the terminal width in columns, or 80 if unknown. */
      37              : int terminal_cols(void);
      38              : 
      39              : /** Returns the terminal height in rows, or 0 if unknown. */
      40              : int terminal_rows(void);
      41              : 
      42              : /** Returns 1 if fd is connected to a terminal, 0 otherwise. */
      43              : int terminal_is_tty(int fd);
      44              : 
      45              : /**
      46              :  * Save current terminal mode and enter raw mode
      47              :  * (no echo, no canonical, no signal generation).
      48              :  * Returns an allocated TermRawState on success, NULL on failure.
      49              :  * Caller must call terminal_raw_exit() to restore and free.
      50              :  */
      51              : TermRawState *terminal_raw_enter(void);
      52              : 
      53              : /**
      54              :  * Restore the terminal to the state saved in *state and free it.
      55              :  * Sets *state = NULL.  Safe to call with NULL or *state == NULL.
      56              :  */
      57              : void terminal_raw_exit(TermRawState **state);
      58              : 
      59              : /** RAII cleanup wrapper for terminal_raw_exit. */
      60           25 : static inline void terminal_raw_exit_ptr(TermRawState **p) {
      61           25 :     terminal_raw_exit(p);
      62           25 : }
      63              : #define RAII_TERM_RAW __attribute__((cleanup(terminal_raw_exit_ptr)))
      64              : 
      65              : /**
      66              :  * Read one keypress and return a TermKey code.
      67              :  * The terminal must already be in raw mode.
      68              :  * Fully consumes multi-byte escape sequences.
      69              :  */
      70              : TermKey terminal_read_key(void);
      71              : 
      72              : /**
      73              :  * Wait up to @p timeout_ms for a keystroke to be ready on stdin.
      74              :  * Returns 1 when at least one byte is pending (read_key will not
      75              :  * block for that first byte), 0 on timeout, -1 on interrupt or
      76              :  * error. The terminal need not be in raw mode. Pass a negative
      77              :  * timeout to block indefinitely.
      78              :  */
      79              : int     terminal_wait_key(int timeout_ms);
      80              : 
      81              : /**
      82              :  * Returns the last printable ASCII character (32–126) that caused
      83              :  * terminal_read_key() to return TERM_KEY_IGNORE.
      84              :  * Returns 0 if the last ignored keystroke was not a printable character.
      85              :  */
      86              : int terminal_last_printable(void);
      87              : 
      88              : /**
      89              :  * Display column width of Unicode codepoint cp.
      90              :  * Returns 0 for non-printable/control characters,
      91              :  * 1 for normal characters, 2 for wide (CJK/emoji) characters.
      92              :  */
      93              : int terminal_wcwidth(uint32_t cp);
      94              : 
      95              : /**
      96              :  * Prompt for a password with echo suppressed.
      97              :  * Writes at most size-1 bytes to buf (NUL-terminated).
      98              :  * Returns the number of characters read, or -1 on error.
      99              :  */
     100              : int terminal_read_password(const char *prompt, char *buf, size_t size);
     101              : 
     102              : /**
     103              :  * Enable terminal-resize notifications. On POSIX this installs a
     104              :  * SIGWINCH handler that flips an internal flag; on Windows this is a
     105              :  * no-op (resize is picked up on the next read via a different path).
     106              :  * Safe to call multiple times.
     107              :  */
     108              : void terminal_enable_resize_notifications(void);
     109              : 
     110              : /**
     111              :  * If a terminal-resize event has occurred since the last call, clear
     112              :  * the pending flag and return 1; otherwise return 0. Used by TUI
     113              :  * loops to detect SIGWINCH between reads.
     114              :  */
     115              : int  terminal_consume_resize(void);
     116              : 
     117              : /**
     118              :  * Install signal handlers for SIGTERM, SIGHUP, and SIGINT that restore
     119              :  * the terminal from raw mode before allowing the default handler to run.
     120              :  *
     121              :  * The handlers:
     122              :  *   1. Call tcsetattr(STDIN_FILENO, TCSANOW, &saved) using the termios
     123              :  *      state captured by the most recent terminal_raw_enter() call.
     124              :  *   2. Write "\033[?25h" (show cursor) to STDOUT_FILENO via write(2).
     125              :  *   3. Reset the signal to SIG_DFL and re-raise it so the shell sees
     126              :  *      the correct exit status (e.g. 128+SIGTERM).
     127              :  *
     128              :  * Must be called after terminal_raw_enter() succeeds.  All three
     129              :  * operations used (tcsetattr, write, signal, raise) are
     130              :  * async-signal-safe per POSIX.
     131              :  *
     132              :  * Safe to call multiple times; subsequent calls update the saved state
     133              :  * pointer to the most recent TermRawState.
     134              :  */
     135              : void terminal_install_cleanup_handlers(TermRawState *state);
     136              : 
     137              : #endif /* PLATFORM_TERMINAL_H */
        

Generated by: LCOV version 2.0-1