1 /****************************************************************************
2  * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
3  *                                                                          *
4  * Permission is hereby granted, free of charge, to any person obtaining a  *
5  * copy of this software and associated documentation files (the            *
6  * "Software"), to deal in the Software without restriction, including      *
7  * without limitation the rights to use, copy, modify, merge, publish,      *
8  * distribute, distribute with modifications, sublicense, and/or sell       *
9  * copies of the Software, and to permit persons to whom the Software is    *
10  * furnished to do so, subject to the following conditions:                 *
11  *                                                                          *
12  * The above copyright notice and this permission notice shall be included  *
13  * in all copies or substantial portions of the Software.                   *
14  *                                                                          *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
16  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
18  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
19  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
20  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
21  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
22  *                                                                          *
23  * Except as contained in this notice, the name(s) of the above copyright   *
24  * holders shall not be used in advertising or otherwise to promote the     *
25  * sale, use or other dealings in this Software without prior written       *
26  * authorization.                                                           *
27  ****************************************************************************/
28 
29 /****************************************************************************
30  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
31  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
32  *     and: Thomas E. Dickey                        1998-on                 *
33  *     and: Juergen Pfeifer                         2009                    *
34  ****************************************************************************/
35 
36 /*
37  *	raw.c
38  *
39  *	Routines:
40  *		raw()
41  *		cbreak()
42  *		noraw()
43  *		nocbreak()
44  *		qiflush()
45  *		noqiflush()
46  *		intrflush()
47  *
48  */
49 
50 #include <curses.priv.h>
51 
52 MODULE_ID("$Id: lib_raw.c,v 1.19 2010/04/24 23:49:12 tom Exp $")
53 
54 #if SVR4_TERMIO && !defined(_POSIX_SOURCE)
55 #define _POSIX_SOURCE
56 #endif
57 
58 #if HAVE_SYS_TERMIO_H
59 #include <sys/termio.h>		/* needed for ISC */
60 #endif
61 
62 #ifdef __EMX__
63 #include <io.h>
64 #define _nc_setmode(mode) setmode(SP_PARM->_ifd, mode)
65 #else
66 #define _nc_setmode(mode)	/* nothing */
67 #endif
68 
69 #define COOKED_INPUT	(IXON|BRKINT|PARMRK)
70 
71 #ifdef TRACE
72 #define BEFORE(N)	if (USE_TRACEF(TRACE_BITS)) _nc_locked_tracef("%s before bits: %s", N, _nc_tracebits())
73 #define AFTER(N)	if (USE_TRACEF(TRACE_BITS)) _nc_locked_tracef("%s after bits: %s", N, _nc_tracebits())
74 #else
75 #define BEFORE(s)
76 #define AFTER(s)
77 #endif /* TRACE */
78 
79 NCURSES_EXPORT(int)
80 NCURSES_SP_NAME(raw) (NCURSES_SP_DCL0)
81 {
82     int result = ERR;
83     TERMINAL *termp;
84 
85     T((T_CALLED("raw(%p)"), (void *) SP_PARM));
86     if ((termp = TerminalOf(SP_PARM)) != 0) {
87 	TTY buf;
88 
89 	BEFORE("raw");
90 	_nc_setmode(O_BINARY);
91 
92 	buf = termp->Nttyb;
93 #ifdef TERMIOS
94 	buf.c_lflag &= (unsigned) ~(ICANON | ISIG | IEXTEN);
95 	buf.c_iflag &= (unsigned) ~(COOKED_INPUT);
96 	buf.c_cc[VMIN] = 1;
97 	buf.c_cc[VTIME] = 0;
98 #else
99 	buf.sg_flags |= RAW;
100 #endif
101 	result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf);
102 	if (result == OK) {
103 	    SP_PARM->_raw = TRUE;
104 	    SP_PARM->_cbreak = 1;
105 	    termp->Nttyb = buf;
106 	}
107 	AFTER("raw");
108     }
109     returnCode(result);
110 }
111 
112 #if NCURSES_SP_FUNCS
113 NCURSES_EXPORT(int)
114 raw(void)
115 {
116     return NCURSES_SP_NAME(raw) (CURRENT_SCREEN);
117 }
118 #endif
119 
120 NCURSES_EXPORT(int)
121 NCURSES_SP_NAME(cbreak) (NCURSES_SP_DCL0)
122 {
123     int result = ERR;
124     TERMINAL *termp;
125 
126     T((T_CALLED("cbreak(%p)"), (void *) SP_PARM));
127     if ((termp = TerminalOf(SP_PARM)) != 0) {
128 	TTY buf;
129 
130 	BEFORE("cbreak");
131 	_nc_setmode(O_BINARY);
132 
133 	buf = termp->Nttyb;
134 #ifdef TERMIOS
135 	buf.c_lflag &= (unsigned) ~ICANON;
136 	buf.c_iflag &= (unsigned) ~ICRNL;
137 	buf.c_lflag |= ISIG;
138 	buf.c_cc[VMIN] = 1;
139 	buf.c_cc[VTIME] = 0;
140 #else
141 	buf.sg_flags |= CBREAK;
142 #endif
143 	result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf);
144 	if (result == OK) {
145 	    SP_PARM->_cbreak = 1;
146 	    termp->Nttyb = buf;
147 	}
148 	AFTER("cbreak");
149     }
150     returnCode(result);
151 }
152 
153 #if NCURSES_SP_FUNCS
154 NCURSES_EXPORT(int)
155 cbreak(void)
156 {
157     return NCURSES_SP_NAME(cbreak) (CURRENT_SCREEN);
158 }
159 #endif
160 
161 /*
162  * Note:
163  * this implementation may be wrong.  See the comment under intrflush().
164  */
165 NCURSES_EXPORT(void)
166 NCURSES_SP_NAME(qiflush) (NCURSES_SP_DCL0)
167 {
168     int result = ERR;
169     TERMINAL *termp;
170 
171     T((T_CALLED("qiflush(%p)"), (void *) SP_PARM));
172     if ((termp = TerminalOf(SP_PARM)) != 0) {
173 	TTY buf;
174 
175 	BEFORE("qiflush");
176 	buf = termp->Nttyb;
177 #ifdef TERMIOS
178 	buf.c_lflag &= (unsigned) ~(NOFLSH);
179 	result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf);
180 #else
181 	/* FIXME */
182 #endif
183 	if (result == OK)
184 	    termp->Nttyb = buf;
185 	AFTER("qiflush");
186     }
187     returnVoid;
188 }
189 
190 #if NCURSES_SP_FUNCS
191 NCURSES_EXPORT(void)
192 qiflush(void)
193 {
194     NCURSES_SP_NAME(qiflush) (CURRENT_SCREEN);
195 }
196 #endif
197 
198 NCURSES_EXPORT(int)
199 NCURSES_SP_NAME(noraw) (NCURSES_SP_DCL0)
200 {
201     int result = ERR;
202     TERMINAL *termp;
203 
204     T((T_CALLED("noraw(%p)"), (void *) SP_PARM));
205     if ((termp = TerminalOf(SP_PARM)) != 0) {
206 	TTY buf;
207 
208 	BEFORE("noraw");
209 	_nc_setmode(O_TEXT);
210 
211 	buf = termp->Nttyb;
212 #ifdef TERMIOS
213 	buf.c_lflag |= ISIG | ICANON |
214 	    (termp->Ottyb.c_lflag & IEXTEN);
215 	buf.c_iflag |= COOKED_INPUT;
216 #else
217 	buf.sg_flags &= ~(RAW | CBREAK);
218 #endif
219 	result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf);
220 	if (result == OK) {
221 	    SP_PARM->_raw = FALSE;
222 	    SP_PARM->_cbreak = 0;
223 	    termp->Nttyb = buf;
224 	}
225 	AFTER("noraw");
226     }
227     returnCode(result);
228 }
229 
230 #if NCURSES_SP_FUNCS
231 NCURSES_EXPORT(int)
232 noraw(void)
233 {
234     return NCURSES_SP_NAME(noraw) (CURRENT_SCREEN);
235 }
236 #endif
237 
238 NCURSES_EXPORT(int)
239 NCURSES_SP_NAME(nocbreak) (NCURSES_SP_DCL0)
240 {
241     int result = ERR;
242     TERMINAL *termp;
243 
244     T((T_CALLED("nocbreak(%p)"), (void *) SP_PARM));
245     if ((termp = TerminalOf(SP_PARM)) != 0) {
246 	TTY buf;
247 
248 	BEFORE("nocbreak");
249 	_nc_setmode(O_TEXT);
250 
251 	buf = termp->Nttyb;
252 #ifdef TERMIOS
253 	buf.c_lflag |= ICANON;
254 	buf.c_iflag |= ICRNL;
255 #else
256 	buf.sg_flags &= ~CBREAK;
257 #endif
258 	result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf);
259 	if (result == OK) {
260 	    SP_PARM->_cbreak = 0;
261 	    termp->Nttyb = buf;
262 	}
263 	AFTER("nocbreak");
264     }
265     returnCode(result);
266 }
267 
268 #if NCURSES_SP_FUNCS
269 NCURSES_EXPORT(int)
270 nocbreak(void)
271 {
272     return NCURSES_SP_NAME(nocbreak) (CURRENT_SCREEN);
273 }
274 #endif
275 
276 NCURSES_EXPORT(void)
277 NCURSES_SP_NAME(noqiflush) (NCURSES_SP_DCL0)
278 {
279     int result = ERR;
280     TERMINAL *termp;
281 
282     T((T_CALLED("noqiflush(%p)"), (void *) SP_PARM));
283     if ((termp = TerminalOf(SP_PARM)) != 0) {
284 	TTY buf;
285 
286 	BEFORE("noqiflush");
287 	buf = termp->Nttyb;
288 #ifdef TERMIOS
289 	buf.c_lflag |= NOFLSH;
290 	result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf);
291 #else
292 	/* FIXME */
293 #endif
294 	if (result == OK)
295 	    termp->Nttyb = buf;
296 	AFTER("noqiflush");
297     }
298     returnVoid;
299 }
300 
301 #if NCURSES_SP_FUNCS
302 NCURSES_EXPORT(void)
303 noqiflush(void)
304 {
305     NCURSES_SP_NAME(noqiflush) (CURRENT_SCREEN);
306 }
307 #endif
308 
309 /*
310  * This call does the same thing as the qiflush()/noqiflush() pair.  We know
311  * for certain that SVr3 intrflush() tweaks the NOFLSH bit; on the other hand,
312  * the match (in the SVr4 man pages) between the language describing NOFLSH in
313  * termio(7) and the language describing qiflush()/noqiflush() in
314  * curs_inopts(3x) is too exact to be coincidence.
315  */
316 NCURSES_EXPORT(int)
317 NCURSES_SP_NAME(intrflush) (NCURSES_SP_DCLx WINDOW *win GCC_UNUSED, bool flag)
318 {
319     int result = ERR;
320     TERMINAL *termp;
321 
322     T((T_CALLED("intrflush(%p,%d)"), (void *) SP_PARM, flag));
323     if (SP_PARM == 0)
324 	returnCode(ERR);
325 
326     if ((termp = TerminalOf(SP_PARM)) != 0) {
327 	TTY buf;
328 
329 	BEFORE("intrflush");
330 	buf = termp->Nttyb;
331 #ifdef TERMIOS
332 	if (flag)
333 	    buf.c_lflag &= (unsigned) ~(NOFLSH);
334 	else
335 	    buf.c_lflag |= (NOFLSH);
336 	result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf);
337 #else
338 	/* FIXME */
339 #endif
340 	if (result == OK) {
341 	    termp->Nttyb = buf;
342 	}
343 	AFTER("intrflush");
344     }
345     returnCode(result);
346 }
347 
348 #if NCURSES_SP_FUNCS
349 NCURSES_EXPORT(int)
350 intrflush(WINDOW *win GCC_UNUSED, bool flag)
351 {
352     return NCURSES_SP_NAME(intrflush) (CURRENT_SCREEN, win, flag);
353 }
354 #endif
355