1 /****************************************************************************
2 * Copyright 2020-2024,2025 Thomas E. Dickey *
3 * Copyright 1998-2016,2017 Free Software Foundation, Inc. *
4 * *
5 * Permission is hereby granted, free of charge, to any person obtaining a *
6 * copy of this software and associated documentation files (the *
7 * "Software"), to deal in the Software without restriction, including *
8 * without limitation the rights to use, copy, modify, merge, publish, *
9 * distribute, distribute with modifications, sublicense, and/or sell *
10 * copies of the Software, and to permit persons to whom the Software is *
11 * furnished to do so, subject to the following conditions: *
12 * *
13 * The above copyright notice and this permission notice shall be included *
14 * in all copies or substantial portions of the Software. *
15 * *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
19 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
22 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
23 * *
24 * Except as contained in this notice, the name(s) of the above copyright *
25 * holders shall not be used in advertising or otherwise to promote the *
26 * sale, use or other dealings in this Software without prior written *
27 * authorization. *
28 ****************************************************************************/
29
30 /****************************************************************************
31 * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
32 * and: Eric S. Raymond <esr@snark.thyrsus.com> *
33 * and: Thomas E. Dickey 1998-on *
34 * and: Juergen Pfeifer 2009 *
35 ****************************************************************************/
36
37 /*
38 * raw.c
39 *
40 * Routines:
41 * raw()
42 * cbreak()
43 * noraw()
44 * nocbreak()
45 * qiflush()
46 * noqiflush()
47 * intrflush()
48 *
49 */
50
51 #include <curses.priv.h>
52
53 MODULE_ID("$Id: lib_raw.c,v 1.35 2025/12/23 09:22:35 tom Exp $")
54
55 #if HAVE_SYS_TERMIO_H
56 #include <sys/termio.h> /* needed for ISC */
57 #endif
58
59 #ifdef __EMX__
60 #define _nc_setmode(mode) setmode(SP_PARM->_ifd, mode)
61 #else
62 #define _nc_setmode(mode) /* nothing */
63 #endif
64
65 #if USE_KLIBC_KBD
66 #define INCL_KBD
67 #include <os2.h>
68 #endif
69
70 #define COOKED_INPUT (IXON|BRKINT|PARMRK)
71
72 #ifdef TRACE
73 #define BEFORE(N) if (USE_TRACEF(TRACE_BITS)) _nc_locked_tracef("%s before bits: %s", N, _nc_tracebits())
74 #define AFTER(N) if (USE_TRACEF(TRACE_BITS)) _nc_locked_tracef("%s after bits: %s", N, _nc_tracebits())
75 #else
76 #define BEFORE(s)
77 #define AFTER(s)
78 #endif /* TRACE */
79
NCURSES_EXPORT(int)80 NCURSES_EXPORT(int)
81 NCURSES_SP_NAME(raw) (NCURSES_SP_DCL0)
82 {
83 int result = ERR;
84 TERMINAL *termp;
85
86 T((T_CALLED("raw(%p)"), (void *) SP_PARM));
87 if ((termp = TerminalOf(SP_PARM)) != NULL) {
88 TTY buf;
89
90 BEFORE("raw");
91 _nc_setmode(O_BINARY);
92
93 buf = termp->Nttyb;
94 #ifdef TERMIOS
95 buf.c_lflag &= (unsigned) ~(ICANON | ISIG | IEXTEN);
96 buf.c_iflag &= (unsigned) ~(COOKED_INPUT);
97 buf.c_cc[VMIN] = 1;
98 buf.c_cc[VTIME] = 0;
99 #elif defined(USE_WIN32CON_DRIVER)
100 buf.dwFlagIn &= (unsigned long) ~CONMODE_NORAW;
101 #else
102 buf.sg_flags |= RAW;
103 #endif
104 result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf);
105 if (result == OK) {
106 #if USE_KLIBC_KBD
107 KBDINFO kbdinfo;
108
109 kbdinfo.cb = sizeof(kbdinfo);
110 KbdGetStatus(&kbdinfo, 0);
111
112 kbdinfo.cb = sizeof(kbdinfo);
113 kbdinfo.fsMask &= ~KEYBOARD_ASCII_MODE;
114 kbdinfo.fsMask |= KEYBOARD_BINARY_MODE;
115 KbdSetStatus(&kbdinfo, 0);
116 #endif
117 if (SP_PARM) {
118 IsRaw(SP_PARM) = TRUE;
119 IsCbreak(SP_PARM) = 1;
120 }
121 termp->Nttyb = buf;
122 }
123 AFTER("raw");
124 }
125 returnCode(result);
126 }
127
128 #if NCURSES_SP_FUNCS
129 NCURSES_EXPORT(int)
raw(void)130 raw(void)
131 {
132 return NCURSES_SP_NAME(raw) (CURRENT_SCREEN);
133 }
134 #endif
135
136 NCURSES_EXPORT(int)
NCURSES_SP_NAME(cbreak)137 NCURSES_SP_NAME(cbreak) (NCURSES_SP_DCL0)
138 {
139 int result = ERR;
140 TERMINAL *termp;
141
142 T((T_CALLED("cbreak(%p)"), (void *) SP_PARM));
143 if ((termp = TerminalOf(SP_PARM)) != NULL) {
144 TTY buf;
145
146 BEFORE("cbreak");
147 _nc_setmode(O_BINARY);
148
149 buf = termp->Nttyb;
150 #ifdef TERMIOS
151 buf.c_lflag &= (unsigned) ~ICANON;
152 buf.c_iflag &= (unsigned) ~ICRNL;
153 buf.c_cc[VMIN] = 1;
154 buf.c_cc[VTIME] = 0;
155 #elif defined(USE_WIN32CON_DRIVER)
156 buf.dwFlagIn |= CONMODE_NORAW;
157 buf.dwFlagIn &= (unsigned long) ~CONMODE_NOCBREAK;
158 #else
159 buf.sg_flags |= CBREAK;
160 #endif
161 result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf);
162 if (result == OK) {
163 if (SP_PARM) {
164 IsCbreak(SP_PARM) = 1;
165 }
166 termp->Nttyb = buf;
167 }
168 AFTER("cbreak");
169 }
170 returnCode(result);
171 }
172
173 #if NCURSES_SP_FUNCS
174 NCURSES_EXPORT(int)
cbreak(void)175 cbreak(void)
176 {
177 return NCURSES_SP_NAME(cbreak) (CURRENT_SCREEN);
178 }
179 #endif
180
181 NCURSES_EXPORT(void)
NCURSES_SP_NAME(qiflush)182 NCURSES_SP_NAME(qiflush) (NCURSES_SP_DCL0)
183 {
184 TERMINAL *termp;
185
186 T((T_CALLED("qiflush(%p)"), (void *) SP_PARM));
187 if ((termp = TerminalOf(SP_PARM)) != NULL) {
188 TTY buf;
189 int result;
190
191 BEFORE("qiflush");
192 buf = termp->Nttyb;
193 #ifdef TERMIOS
194 buf.c_lflag &= (unsigned) ~(NOFLSH);
195 result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf);
196 #else
197 result = ERR;
198 /* FIXME */
199 #endif
200 if (result == OK)
201 termp->Nttyb = buf;
202 AFTER("qiflush");
203 }
204 returnVoid;
205 }
206
207 #if NCURSES_SP_FUNCS
208 NCURSES_EXPORT(void)
qiflush(void)209 qiflush(void)
210 {
211 NCURSES_SP_NAME(qiflush) (CURRENT_SCREEN);
212 }
213 #endif
214
215 NCURSES_EXPORT(int)
NCURSES_SP_NAME(noraw)216 NCURSES_SP_NAME(noraw) (NCURSES_SP_DCL0)
217 {
218 int result = ERR;
219 TERMINAL *termp;
220
221 T((T_CALLED("noraw(%p)"), (void *) SP_PARM));
222 if ((termp = TerminalOf(SP_PARM)) != NULL) {
223 TTY buf;
224
225 BEFORE("noraw");
226 _nc_setmode(O_TEXT);
227
228 buf = termp->Nttyb;
229 #ifdef TERMIOS
230 buf.c_lflag |= ISIG | ICANON |
231 (termp->Ottyb.c_lflag & IEXTEN);
232 buf.c_iflag |= COOKED_INPUT;
233 #elif defined(USE_WIN32CON_DRIVER)
234 buf.dwFlagIn |= CONMODE_NORAW;
235 #else
236 buf.sg_flags &= ~(RAW | CBREAK);
237 #endif
238 result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf);
239 if (result == OK) {
240 #if USE_KLIBC_KBD
241 KBDINFO kbdinfo;
242
243 kbdinfo.cb = sizeof(kbdinfo);
244 KbdGetStatus(&kbdinfo, 0);
245
246 kbdinfo.cb = sizeof(kbdinfo);
247 kbdinfo.fsMask &= ~KEYBOARD_BINARY_MODE;
248 kbdinfo.fsMask |= KEYBOARD_ASCII_MODE;
249 KbdSetStatus(&kbdinfo, 0);
250 #endif
251 if (SP_PARM) {
252 IsRaw(SP_PARM) = FALSE;
253 IsCbreak(SP_PARM) = 0;
254 }
255 termp->Nttyb = buf;
256 }
257 AFTER("noraw");
258 }
259 returnCode(result);
260 }
261
262 #if NCURSES_SP_FUNCS
263 NCURSES_EXPORT(int)
noraw(void)264 noraw(void)
265 {
266 return NCURSES_SP_NAME(noraw) (CURRENT_SCREEN);
267 }
268 #endif
269
270 NCURSES_EXPORT(int)
NCURSES_SP_NAME(nocbreak)271 NCURSES_SP_NAME(nocbreak) (NCURSES_SP_DCL0)
272 {
273 int result = ERR;
274 TERMINAL *termp;
275
276 T((T_CALLED("nocbreak(%p)"), (void *) SP_PARM));
277 if ((termp = TerminalOf(SP_PARM)) != NULL) {
278 TTY buf;
279
280 BEFORE("nocbreak");
281 _nc_setmode(O_TEXT);
282
283 buf = termp->Nttyb;
284 #ifdef TERMIOS
285 buf.c_lflag |= ICANON;
286 buf.c_iflag |= ICRNL;
287 #elif defined(USE_WIN32CON_DRIVER)
288 buf.dwFlagIn |= (CONMODE_NOCBREAK | CONMODE_NORAW);
289 #else
290 buf.sg_flags &= ~CBREAK;
291 #endif
292 result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf);
293 if (result == OK) {
294 if (SP_PARM) {
295 IsCbreak(SP_PARM) = 0;
296 }
297 termp->Nttyb = buf;
298 }
299 AFTER("nocbreak");
300 }
301 returnCode(result);
302 }
303
304 #if NCURSES_SP_FUNCS
305 NCURSES_EXPORT(int)
nocbreak(void)306 nocbreak(void)
307 {
308 return NCURSES_SP_NAME(nocbreak) (CURRENT_SCREEN);
309 }
310 #endif
311
312 NCURSES_EXPORT(void)
NCURSES_SP_NAME(noqiflush)313 NCURSES_SP_NAME(noqiflush) (NCURSES_SP_DCL0)
314 {
315 TERMINAL *termp;
316
317 T((T_CALLED("noqiflush(%p)"), (void *) SP_PARM));
318 if ((termp = TerminalOf(SP_PARM)) != NULL) {
319 TTY buf;
320 int result;
321
322 BEFORE("noqiflush");
323 buf = termp->Nttyb;
324 #ifdef TERMIOS
325 buf.c_lflag |= NOFLSH;
326 result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf);
327 #else
328 /* FIXME */
329 result = ERR;
330 #endif
331 if (result == OK)
332 termp->Nttyb = buf;
333 AFTER("noqiflush");
334 }
335 returnVoid;
336 }
337
338 #if NCURSES_SP_FUNCS
339 NCURSES_EXPORT(void)
noqiflush(void)340 noqiflush(void)
341 {
342 NCURSES_SP_NAME(noqiflush) (CURRENT_SCREEN);
343 }
344 #endif
345
346 /*
347 * This call does the same thing as the qiflush()/noqiflush() pair.
348 */
349 NCURSES_EXPORT(int)
NCURSES_SP_NAME(intrflush)350 NCURSES_SP_NAME(intrflush) (NCURSES_SP_DCLx WINDOW *win GCC_UNUSED, bool flag)
351 {
352 int result = ERR;
353 TERMINAL *termp;
354
355 T((T_CALLED("intrflush(%p,%d)"), (void *) SP_PARM, flag));
356 if (SP_PARM == NULL)
357 returnCode(ERR);
358
359 if ((termp = TerminalOf(SP_PARM)) != NULL) {
360 TTY buf;
361
362 BEFORE("intrflush");
363 buf = termp->Nttyb;
364 #ifdef TERMIOS
365 if (flag)
366 buf.c_lflag &= (unsigned) ~(NOFLSH);
367 else
368 buf.c_lflag |= (NOFLSH);
369 result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf);
370 #else
371 /* FIXME */
372 #endif
373 if (result == OK) {
374 termp->Nttyb = buf;
375 }
376 AFTER("intrflush");
377 }
378 returnCode(result);
379 }
380
381 #if NCURSES_SP_FUNCS
382 NCURSES_EXPORT(int)
intrflush(WINDOW * win GCC_UNUSED,bool flag)383 intrflush(WINDOW *win GCC_UNUSED, bool flag)
384 {
385 return NCURSES_SP_NAME(intrflush) (CURRENT_SCREEN, win, flag);
386 }
387 #endif
388
389 #if NCURSES_EXT_FUNCS
390 /* *INDENT-OFF* */
391
392 /*
393 * SCREEN is always opaque, but nl/raw/cbreak/echo set properties in it.
394 * As an extension, provide a way to query the properties.
395 *
396 * There are other properties which could be queried, e.g., filter, keypad,
397 * use_env, use_meta, but these particular properties are saved/restored within
398 * the wgetnstr() and wgetn_wstr() functions, which requires that the higher
399 * level curses library knows about the internal state of the lower level
400 * terminfo library.
401 */
402
403 #define is_TEST(show,what) \
404 NCURSES_EXPORT(int) \
405 NCURSES_SP_NAME(show) (NCURSES_SP_DCL0) \
406 { \
407 return ((SP_PARM != NULL) ? (what(SP_PARM) ? 1 : 0) : -1); \
408 }
409
410 is_TEST(is_nl, IsNl)
411 is_TEST(is_raw, IsRaw)
412 is_TEST(is_cbreak, IsCbreak)
413 is_TEST(is_echo, IsEcho)
414
415 #if NCURSES_SP_FUNCS
416 #undef is_TEST
417 #define is_TEST(show) \
418 NCURSES_EXPORT(int) \
419 show(void) \
420 { \
421 return NCURSES_SP_NAME(show) (CURRENT_SCREEN); \
422 }
423 is_TEST(is_nl)
424 is_TEST(is_raw)
425 is_TEST(is_cbreak)
426 is_TEST(is_echo)
427 #endif
428
429 /* *INDENT-ON* */
430 #endif /* extensions */
431