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