1 /****************************************************************************
2  * Copyright 2020 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.24 2020/02/02 23:34:34 tom Exp $")
54 
55 #if HAVE_SYS_TERMIO_H
56 #include <sys/termio.h>		/* needed for ISC */
57 #endif
58 
59 #ifdef __EMX__
60 #include <io.h>
61 #define _nc_setmode(mode) setmode(SP_PARM->_ifd, mode)
62 #else
63 #define _nc_setmode(mode)	/* nothing */
64 #endif
65 
66 #if USE_KLIBC_KBD
67 #define INCL_KBD
68 #include <os2.h>
69 #endif
70 
71 #define COOKED_INPUT	(IXON|BRKINT|PARMRK)
72 
73 #ifdef TRACE
74 #define BEFORE(N)	if (USE_TRACEF(TRACE_BITS)) _nc_locked_tracef("%s before bits: %s", N, _nc_tracebits())
75 #define AFTER(N)	if (USE_TRACEF(TRACE_BITS)) _nc_locked_tracef("%s after bits: %s", N, _nc_tracebits())
76 #else
77 #define BEFORE(s)
78 #define AFTER(s)
79 #endif /* TRACE */
80 
81 NCURSES_EXPORT(int)
82 NCURSES_SP_NAME(raw) (NCURSES_SP_DCL0)
83 {
84     int result = ERR;
85     TERMINAL *termp;
86 
87     T((T_CALLED("raw(%p)"), (void *) SP_PARM));
88     if ((termp = TerminalOf(SP_PARM)) != 0) {
89 	TTY buf;
90 
91 	BEFORE("raw");
92 	_nc_setmode(O_BINARY);
93 
94 	buf = termp->Nttyb;
95 #ifdef TERMIOS
96 	buf.c_lflag &= (unsigned) ~(ICANON | ISIG | IEXTEN);
97 	buf.c_iflag &= (unsigned) ~(COOKED_INPUT);
98 	buf.c_cc[VMIN] = 1;
99 	buf.c_cc[VTIME] = 0;
100 #else
101 	buf.sg_flags |= RAW;
102 #endif
103 	result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf);
104 	if (result == OK) {
105 #if USE_KLIBC_KBD
106 	    KBDINFO kbdinfo;
107 
108 	    kbdinfo.cb = sizeof(kbdinfo);
109 	    KbdGetStatus(&kbdinfo, 0);
110 
111 	    kbdinfo.cb = sizeof(kbdinfo);
112 	    kbdinfo.fsMask &= ~KEYBOARD_ASCII_MODE;
113 	    kbdinfo.fsMask |= KEYBOARD_BINARY_MODE;
114 	    KbdSetStatus(&kbdinfo, 0);
115 #endif
116 	    if (SP_PARM) {
117 		SP_PARM->_raw = TRUE;
118 		SP_PARM->_cbreak = 1;
119 	    }
120 	    termp->Nttyb = buf;
121 	}
122 	AFTER("raw");
123     }
124     returnCode(result);
125 }
126 
127 #if NCURSES_SP_FUNCS
128 NCURSES_EXPORT(int)
129 raw(void)
130 {
131     return NCURSES_SP_NAME(raw) (CURRENT_SCREEN);
132 }
133 #endif
134 
135 NCURSES_EXPORT(int)
136 NCURSES_SP_NAME(cbreak) (NCURSES_SP_DCL0)
137 {
138     int result = ERR;
139     TERMINAL *termp;
140 
141     T((T_CALLED("cbreak(%p)"), (void *) SP_PARM));
142     if ((termp = TerminalOf(SP_PARM)) != 0) {
143 	TTY buf;
144 
145 	BEFORE("cbreak");
146 	_nc_setmode(O_BINARY);
147 
148 	buf = termp->Nttyb;
149 #ifdef TERMIOS
150 	buf.c_lflag &= (unsigned) ~ICANON;
151 	buf.c_iflag &= (unsigned) ~ICRNL;
152 	buf.c_lflag |= ISIG;
153 	buf.c_cc[VMIN] = 1;
154 	buf.c_cc[VTIME] = 0;
155 #else
156 	buf.sg_flags |= CBREAK;
157 #endif
158 	result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf);
159 	if (result == OK) {
160 	    if (SP_PARM) {
161 		SP_PARM->_cbreak = 1;
162 	    }
163 	    termp->Nttyb = buf;
164 	}
165 	AFTER("cbreak");
166     }
167     returnCode(result);
168 }
169 
170 #if NCURSES_SP_FUNCS
171 NCURSES_EXPORT(int)
172 cbreak(void)
173 {
174     return NCURSES_SP_NAME(cbreak) (CURRENT_SCREEN);
175 }
176 #endif
177 
178 /*
179  * Note:
180  * this implementation may be wrong.  See the comment under intrflush().
181  */
182 NCURSES_EXPORT(void)
183 NCURSES_SP_NAME(qiflush) (NCURSES_SP_DCL0)
184 {
185     TERMINAL *termp;
186 
187     T((T_CALLED("qiflush(%p)"), (void *) SP_PARM));
188     if ((termp = TerminalOf(SP_PARM)) != 0) {
189 	TTY buf;
190 	int result;
191 
192 	BEFORE("qiflush");
193 	buf = termp->Nttyb;
194 #ifdef TERMIOS
195 	buf.c_lflag &= (unsigned) ~(NOFLSH);
196 	result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf);
197 #else
198 	result = ERR;
199 	/* FIXME */
200 #endif
201 	if (result == OK)
202 	    termp->Nttyb = buf;
203 	AFTER("qiflush");
204     }
205     returnVoid;
206 }
207 
208 #if NCURSES_SP_FUNCS
209 NCURSES_EXPORT(void)
210 qiflush(void)
211 {
212     NCURSES_SP_NAME(qiflush) (CURRENT_SCREEN);
213 }
214 #endif
215 
216 NCURSES_EXPORT(int)
217 NCURSES_SP_NAME(noraw) (NCURSES_SP_DCL0)
218 {
219     int result = ERR;
220     TERMINAL *termp;
221 
222     T((T_CALLED("noraw(%p)"), (void *) SP_PARM));
223     if ((termp = TerminalOf(SP_PARM)) != 0) {
224 	TTY buf;
225 
226 	BEFORE("noraw");
227 	_nc_setmode(O_TEXT);
228 
229 	buf = termp->Nttyb;
230 #ifdef TERMIOS
231 	buf.c_lflag |= ISIG | ICANON |
232 	    (termp->Ottyb.c_lflag & IEXTEN);
233 	buf.c_iflag |= COOKED_INPUT;
234 #else
235 	buf.sg_flags &= ~(RAW | CBREAK);
236 #endif
237 	result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf);
238 	if (result == OK) {
239 #if USE_KLIBC_KBD
240 	    KBDINFO kbdinfo;
241 
242 	    kbdinfo.cb = sizeof(kbdinfo);
243 	    KbdGetStatus(&kbdinfo, 0);
244 
245 	    kbdinfo.cb = sizeof(kbdinfo);
246 	    kbdinfo.fsMask &= ~KEYBOARD_BINARY_MODE;
247 	    kbdinfo.fsMask |= KEYBOARD_ASCII_MODE;
248 	    KbdSetStatus(&kbdinfo, 0);
249 #endif
250 	    if (SP_PARM) {
251 		SP_PARM->_raw = FALSE;
252 		SP_PARM->_cbreak = 0;
253 	    }
254 	    termp->Nttyb = buf;
255 	}
256 	AFTER("noraw");
257     }
258     returnCode(result);
259 }
260 
261 #if NCURSES_SP_FUNCS
262 NCURSES_EXPORT(int)
263 noraw(void)
264 {
265     return NCURSES_SP_NAME(noraw) (CURRENT_SCREEN);
266 }
267 #endif
268 
269 NCURSES_EXPORT(int)
270 NCURSES_SP_NAME(nocbreak) (NCURSES_SP_DCL0)
271 {
272     int result = ERR;
273     TERMINAL *termp;
274 
275     T((T_CALLED("nocbreak(%p)"), (void *) SP_PARM));
276     if ((termp = TerminalOf(SP_PARM)) != 0) {
277 	TTY buf;
278 
279 	BEFORE("nocbreak");
280 	_nc_setmode(O_TEXT);
281 
282 	buf = termp->Nttyb;
283 #ifdef TERMIOS
284 	buf.c_lflag |= ICANON;
285 	buf.c_iflag |= ICRNL;
286 #else
287 	buf.sg_flags &= ~CBREAK;
288 #endif
289 	result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf);
290 	if (result == OK) {
291 	    if (SP_PARM) {
292 		SP_PARM->_cbreak = 0;
293 	    }
294 	    termp->Nttyb = buf;
295 	}
296 	AFTER("nocbreak");
297     }
298     returnCode(result);
299 }
300 
301 #if NCURSES_SP_FUNCS
302 NCURSES_EXPORT(int)
303 nocbreak(void)
304 {
305     return NCURSES_SP_NAME(nocbreak) (CURRENT_SCREEN);
306 }
307 #endif
308 
309 NCURSES_EXPORT(void)
310 NCURSES_SP_NAME(noqiflush) (NCURSES_SP_DCL0)
311 {
312     TERMINAL *termp;
313 
314     T((T_CALLED("noqiflush(%p)"), (void *) SP_PARM));
315     if ((termp = TerminalOf(SP_PARM)) != 0) {
316 	TTY buf;
317 	int result;
318 
319 	BEFORE("noqiflush");
320 	buf = termp->Nttyb;
321 #ifdef TERMIOS
322 	buf.c_lflag |= NOFLSH;
323 	result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf);
324 #else
325 	/* FIXME */
326 	result = ERR;
327 #endif
328 	if (result == OK)
329 	    termp->Nttyb = buf;
330 	AFTER("noqiflush");
331     }
332     returnVoid;
333 }
334 
335 #if NCURSES_SP_FUNCS
336 NCURSES_EXPORT(void)
337 noqiflush(void)
338 {
339     NCURSES_SP_NAME(noqiflush) (CURRENT_SCREEN);
340 }
341 #endif
342 
343 /*
344  * This call does the same thing as the qiflush()/noqiflush() pair.  We know
345  * for certain that SVr3 intrflush() tweaks the NOFLSH bit; on the other hand,
346  * the match (in the SVr4 man pages) between the language describing NOFLSH in
347  * termio(7) and the language describing qiflush()/noqiflush() in
348  * curs_inopts(3x) is too exact to be coincidence.
349  */
350 NCURSES_EXPORT(int)
351 NCURSES_SP_NAME(intrflush) (NCURSES_SP_DCLx WINDOW *win GCC_UNUSED, bool flag)
352 {
353     int result = ERR;
354     TERMINAL *termp;
355 
356     T((T_CALLED("intrflush(%p,%d)"), (void *) SP_PARM, flag));
357     if (SP_PARM == 0)
358 	returnCode(ERR);
359 
360     if ((termp = TerminalOf(SP_PARM)) != 0) {
361 	TTY buf;
362 
363 	BEFORE("intrflush");
364 	buf = termp->Nttyb;
365 #ifdef TERMIOS
366 	if (flag)
367 	    buf.c_lflag &= (unsigned) ~(NOFLSH);
368 	else
369 	    buf.c_lflag |= (NOFLSH);
370 	result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf);
371 #else
372 	/* FIXME */
373 #endif
374 	if (result == OK) {
375 	    termp->Nttyb = buf;
376 	}
377 	AFTER("intrflush");
378     }
379     returnCode(result);
380 }
381 
382 #if NCURSES_SP_FUNCS
383 NCURSES_EXPORT(int)
384 intrflush(WINDOW *win GCC_UNUSED, bool flag)
385 {
386     return NCURSES_SP_NAME(intrflush) (CURRENT_SCREEN, win, flag);
387 }
388 #endif
389