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