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 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) 133 raw(void) 134 { 135 return NCURSES_SP_NAME(raw) (CURRENT_SCREEN); 136 } 137 #endif 138 139 NCURSES_EXPORT(int) 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) 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) 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) 217 qiflush(void) 218 { 219 NCURSES_SP_NAME(qiflush) (CURRENT_SCREEN); 220 } 221 #endif 222 223 NCURSES_EXPORT(int) 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) 272 noraw(void) 273 { 274 return NCURSES_SP_NAME(noraw) (CURRENT_SCREEN); 275 } 276 #endif 277 278 NCURSES_EXPORT(int) 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) 314 nocbreak(void) 315 { 316 return NCURSES_SP_NAME(nocbreak) (CURRENT_SCREEN); 317 } 318 #endif 319 320 NCURSES_EXPORT(void) 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) 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) 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) 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