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