C-Menu 0.2.9
A User Interface Toolkit
Loading...
Searching...
No Matches
scriou.c
Go to the documentation of this file.
1/** @file scriou.c
2 @brief Screen IO Support for MENU
3 @author Bill Waller
4 Copyright (c) 2025
5 MIT License
6 billxwaller@gmail.com
7 @date 2026-02-09
8 */
9
10/** Terminal Handling
11 @defgroup screen_io Screen IO Support
12 @brief Provides Terminal Settings for C-MENU Applications and Restores
13 Terminal State on Exit
14 */
15
16#include <cm.h>
17#include <stdbool.h>
18#include <stdio.h>
19#include <termios.h>
20#include <unistd.h>
21
22struct termios shell_tioctl;
23struct termios curses_tioctl;
30bool set_sane_tioctl(struct termios *);
31bool mk_raw_tioctl(struct termios *);
32char di_getch();
33
35struct termios shell_in_tioctl, curses_in_tioctl;
36struct termios shell_out_tioctl, curses_out_tioctl;
37struct termios shell_err_tioctl, curses_err_tioctl;
38
39/** @brief capture_shell_tioctl() - capture shell terminal settings
40 @ingroup screen_io
41 @return - true on success
42 @details - captures terminal settings for stdin, stdout, and stderr */
45 return true;
46 tcgetattr(0, &shell_in_tioctl);
47 tcgetattr(1, &shell_out_tioctl);
48 tcgetattr(2, &shell_err_tioctl);
50 return true;
51}
52/** @brief restore_shell_tioctl() - restore shell terminal settings
53 @ingroup screen_io
54 @return - true on success
55 @details - restores terminal settings for stdin, stdout, and stderr */
58 return false;
59 tcsetattr(0, TCSANOW, &shell_in_tioctl);
60 tcsetattr(1, TCSANOW, &shell_out_tioctl);
61 tcsetattr(2, TCSANOW, &shell_err_tioctl);
62 return true;
63}
64/** @brief capture_curses_tioctl() - capture curses terminal settings
65 @ingroup screen_io
66 @return - true on success
67 @details - captures terminal settings for stdin, stdout, and stderr */
70 return true;
71 tcgetattr(0, &curses_in_tioctl);
72 tcgetattr(1, &curses_out_tioctl);
73 tcgetattr(2, &curses_err_tioctl);
75 return true;
76}
77/** @brief restore_curses_tioctl() - restore curses terminal settings
78 @ingroup screen_io
79 @return - true on success
80 @details - restores terminal settings for stdin, stdout, and stderr */
83 return false;
84 tcsetattr(0, TCSANOW, &curses_in_tioctl);
85 tcsetattr(1, TCSANOW, &curses_out_tioctl);
86 tcsetattr(2, TCSANOW, &curses_err_tioctl);
87
88 return true;
89}
90/** @brief set_sane_tioctl() - set terminal to sane settings for C-MENU
91 @ingroup screen_io
92 @param t_p - pointer to termios structure to modify
93 @return - true on success
94 @details - sets terminal to sane settings for C-MENU applications */
95bool set_sane_tioctl(struct termios *t_p) {
96 tcgetattr(0, t_p);
97 t_p->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | INPCK | ISTRIP | INLCR |
98 IGNCR | ICRNL | IXON | IXOFF);
99 t_p->c_iflag |= IUTF8;
100 t_p->c_oflag |= OPOST | ONLCR;
101 t_p->c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN);
102 t_p->c_lflag |= (ISIG | ICANON | IEXTEN | ECHO | ECHOE | ECHOK);
103 t_p->c_cflag &= ~(CSIZE | PARENB);
104 t_p->c_cflag |= CS8 | CLOCAL | CREAD;
105 tcsetattr(0, TCSANOW, t_p);
106 return true;
107}
108/** @brief mk_raw_tioctl() - set terminal to raw mode
109 @ingroup screen_io
110 @param t_p - pointer to termios structure to modify
111 @return - true on success
112 @details - unlike cfmakeraw(), this leaves ISIG enabled.
113 cfmakeraw() disables ISIG, which prevents C-MENU from handling
114 signals like Ctrl-C. Instead of using cfmakeraw(), we manually set the
115 terminal to raw mode while leaving ISIG enabled.
116 The following code is equivalent to cfmakeraw() but with ISIG left
117 enabled:
118 @code
119 t_p->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | INPCK | ISTRIP | INLCR |
120 IGNCR | ICRNL | IXON | IXOFF);
121 t_p->c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN);
122 t_p->c_cflag &= ~(CSIZE | PARENB);
123 t_p->c_cflag |= CS8 | CLOCAL;
124 @endcode
125 */
126bool mk_raw_tioctl(struct termios *t_p) {
127 tcgetattr(0, t_p);
128 t_p->c_lflag |= ISIG;
129 t_p->c_lflag &= ~(ECHO | ICANON);
130 t_p->c_cc[VMIN] = 1;
131 t_p->c_cc[VTIME] = 0;
132 tcsetattr(0, TCSAFLUSH, t_p);
133 tcgetattr(2, t_p);
134 t_p->c_lflag |= ISIG;
135 t_p->c_lflag &= ~(ECHO | ICANON);
136 t_p->c_cc[VMIN] = 1;
137 t_p->c_cc[VTIME] = 0;
138 tcsetattr(2, TCSAFLUSH, t_p);
139 return true;
140}
141/** @brief get single character from terminal in raw mode
142 @ingroup screen_io
143 @return - the character read from terminal
144 @details intended to be used when curses is not active
145 @note restores terminal settings before returning
146
147 */
148char di_getch() {
149 struct termios org_tioctl, new_tioctl;
150 char buf;
151
152 if (tcgetattr(2, &org_tioctl) == -1) {
153 fprintf(stderr, "\ndi_getch: tcgetattr failed\n");
154 return (0);
155 }
156 new_tioctl = org_tioctl;
157 new_tioctl.c_lflag &= ~(ECHO | ICANON);
158 new_tioctl.c_cc[VMIN] = 1;
159 new_tioctl.c_cc[VTIME] = 0;
160 tcsetattr(2, TCSAFLUSH, &new_tioctl);
161 read(2, &buf, 1);
162 tcsetattr(2, TCSAFLUSH, &org_tioctl);
163 return (buf);
164}
bool f_have_shell_tioctl
Definition scriou.c:24
struct termios shell_tioctl curses_tioctl
Definition scriou.c:34
bool f_have_curses_tioctl
Definition scriou.c:25
struct termios shell_out_tioctl curses_out_tioctl
Definition scriou.c:36
struct termios shell_in_tioctl curses_in_tioctl
Definition scriou.c:35
struct termios shell_err_tioctl curses_err_tioctl
Definition scriou.c:37
struct termios shell_tioctl
Definition scriou.c:22
bool capture_shell_tioctl()
capture_shell_tioctl() - capture shell terminal settings
Definition scriou.c:43
char di_getch()
get single character from terminal in raw mode
Definition scriou.c:148
bool restore_curses_tioctl()
restore_curses_tioctl() - restore curses terminal settings
Definition scriou.c:81
bool capture_curses_tioctl()
capture_curses_tioctl() - capture curses terminal settings
Definition scriou.c:68
bool mk_raw_tioctl(struct termios *)
mk_raw_tioctl() - set terminal to raw mode
Definition scriou.c:126
bool set_sane_tioctl(struct termios *)
set_sane_tioctl() - set terminal to sane settings for C-MENU
Definition scriou.c:95
bool restore_shell_tioctl()
restore_shell_tioctl() - restore shell terminal settings
Definition scriou.c:56