Home | History | Annotate | Line # | Download | only in libcurses
tty.c revision 1.20
      1 /*	$NetBSD: tty.c,v 1.20 2000/05/17 16:23:49 jdc Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1992, 1993, 1994
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *	This product includes software developed by the University of
     18  *	California, Berkeley and its contributors.
     19  * 4. Neither the name of the University nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software
     21  *    without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  */
     35 
     36 #include <sys/cdefs.h>
     37 #ifndef lint
     38 #if 0
     39 static char sccsid[] = "@(#)tty.c	8.6 (Berkeley) 1/10/95";
     40 #else
     41 __RCSID("$NetBSD: tty.c,v 1.20 2000/05/17 16:23:49 jdc Exp $");
     42 #endif
     43 #endif				/* not lint */
     44 
     45 #include <sys/types.h>
     46 
     47 #include <stdlib.h>
     48 #include <termios.h>
     49 #include <unistd.h>
     50 #include <sys/fcntl.h>
     51 #include <sys/ioctl.h>
     52 
     53 #include "curses.h"
     54 #include "curses_private.h"
     55 
     56 /*
     57  * In general, curses should leave tty hardware settings alone (speed, parity,
     58  * word size).  This is most easily done in BSD by using TCSASOFT on all
     59  * tcsetattr calls.  On other systems, it would be better to get and restore
     60  * those attributes at each change, or at least when stopped and restarted.
     61  * See also the comments in getterm().
     62  */
     63 #ifdef TCSASOFT
     64 int	__tcaction = 1;			/* Ignore hardware settings. */
     65 #else
     66 int	__tcaction = 0;
     67 #endif
     68 
     69 struct termios __orig_termios, __baset;
     70 int	__endwin;
     71 static struct termios cbreakt, rawt, *curt;
     72 static int useraw;
     73 static int ovmin = 1;
     74 static int ovtime = 0;
     75 
     76 #ifndef	OXTABS
     77 #ifdef	XTABS			/* SMI uses XTABS. */
     78 #define	OXTABS	XTABS
     79 #else
     80 #define	OXTABS	0
     81 #endif
     82 #endif
     83 
     84 /*
     85  * gettmode --
     86  *	Do terminal type initialization.
     87  */
     88 int
     89 gettmode(void)
     90 {
     91 	useraw = 0;
     92 
     93 	if (tcgetattr(STDIN_FILENO, &__orig_termios))
     94 		return (ERR);
     95 
     96 	__baset = __orig_termios;
     97 	__baset.c_oflag &= ~OXTABS;
     98 
     99 	GT = 0;			/* historical. was used before we wired OXTABS
    100 				 * off */
    101 	NONL = (__baset.c_oflag & ONLCR) == 0;
    102 
    103 	/*
    104 	 * XXX
    105 	 * System V and SMI systems overload VMIN and VTIME, such that
    106 	 * VMIN is the same as the VEOF element, and VTIME is the same
    107 	 * as the VEOL element.  This means that, if VEOF was ^D, the
    108 	 * default VMIN is 4.  Majorly stupid.
    109 	 */
    110 	cbreakt = __baset;
    111 	cbreakt.c_lflag &= ~(ECHO | ECHONL | ICANON);
    112 	cbreakt.c_cc[VMIN] = 1;
    113 	cbreakt.c_cc[VTIME] = 0;
    114 
    115 	rawt = cbreakt;
    116 	rawt.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | INLCR | IGNCR | ICRNL | IXON);
    117 	rawt.c_oflag &= ~OPOST;
    118 	rawt.c_lflag &= ~(ISIG | IEXTEN);
    119 
    120 	/*
    121 	 * In general, curses should leave hardware-related settings alone.
    122 	 * This includes parity and word size.  Older versions set the tty
    123 	 * to 8 bits, no parity in raw(), but this is considered to be an
    124 	 * artifact of the old tty interface.  If it's desired to change
    125 	 * parity and word size, the TCSASOFT bit has to be removed from the
    126 	 * calls that switch to/from "raw" mode.
    127 	 */
    128 	if (!__tcaction) {
    129 		rawt.c_iflag &= ~ISTRIP;
    130 		rawt.c_cflag &= ~(CSIZE | PARENB);
    131 		rawt.c_cflag |= CS8;
    132 	}
    133 
    134 	curt = &__baset;
    135 	return (tcsetattr(STDIN_FILENO, __tcaction ?
    136 	    TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
    137 }
    138 
    139 int
    140 raw(void)
    141 {
    142 	/* Check if we need to restart ... */
    143 	if (__endwin) {
    144 		__endwin = 0;
    145 		__restartwin();
    146 	}
    147 
    148 	useraw = __pfast = __rawmode = 1;
    149 	curt = &rawt;
    150 	return (tcsetattr(STDIN_FILENO, __tcaction ?
    151 	    TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
    152 }
    153 
    154 int
    155 noraw(void)
    156 {
    157 	/* Check if we need to restart ... */
    158 	if (__endwin) {
    159 		__endwin = 0;
    160 		__restartwin();
    161 	}
    162 
    163 	useraw = __pfast = __rawmode = 0;
    164 	curt = &__baset;
    165 	return (tcsetattr(STDIN_FILENO, __tcaction ?
    166 	    TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
    167 }
    168 
    169 int
    170 cbreak(void)
    171 {
    172 	/* Check if we need to restart ... */
    173 	if (__endwin) {
    174 		__endwin = 0;
    175 		__restartwin();
    176 	}
    177 
    178 	__rawmode = 1;
    179 	curt = useraw ? &rawt : &cbreakt;
    180 	return (tcsetattr(STDIN_FILENO, __tcaction ?
    181 	    TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
    182 }
    183 
    184 int
    185 nocbreak(void)
    186 {
    187 	/* Check if we need to restart ... */
    188 	if (__endwin) {
    189 		__endwin = 0;
    190 		__restartwin();
    191 	}
    192 
    193 	__rawmode = 0;
    194 	curt = useraw ? &rawt : &__baset;
    195 	return (tcsetattr(STDIN_FILENO, __tcaction ?
    196 	    TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
    197 }
    198 
    199 int
    200 __delay(void)
    201  {
    202 	/* Check if we need to restart ... */
    203 	if (__endwin) {
    204 		__endwin = 0;
    205 		__restartwin();
    206 	}
    207 
    208 	rawt.c_cc[VMIN] = 1;
    209 	rawt.c_cc[VTIME] = 0;
    210 	cbreakt.c_cc[VMIN] = 1;
    211 	cbreakt.c_cc[VTIME] = 0;
    212 	__baset.c_cc[VMIN] = 1;
    213 	__baset.c_cc[VTIME] = 0;
    214 
    215 	return (tcsetattr(STDIN_FILENO, __tcaction ?
    216 		TCSASOFT : TCSANOW, curt) ? ERR : OK);
    217 }
    218 
    219 int
    220 __nodelay(void)
    221 {
    222 	/* Check if we need to restart ... */
    223 	if (__endwin) {
    224 		__endwin = 0;
    225 		__restartwin();
    226 	}
    227 
    228 	rawt.c_cc[VMIN] = 0;
    229 	rawt.c_cc[VTIME] = 0;
    230 	cbreakt.c_cc[VMIN] = 0;
    231 	cbreakt.c_cc[VTIME] = 0;
    232 	__baset.c_cc[VMIN] = 0;
    233 	__baset.c_cc[VTIME] = 0;
    234 
    235 	return (tcsetattr(STDIN_FILENO, __tcaction ?
    236 		TCSASOFT : TCSANOW, curt) ? ERR : OK);
    237 }
    238 
    239 void
    240 __save_termios(void)
    241 {
    242 	/* Check if we need to restart ... */
    243 	if (__endwin) {
    244 		__endwin = 0;
    245 		__restartwin();
    246 	}
    247 
    248 	ovmin = cbreakt.c_cc[VMIN];
    249 	ovtime = cbreakt.c_cc[VTIME];
    250 }
    251 
    252 void
    253 __restore_termios(void)
    254 {
    255 	/* Check if we need to restart ... */
    256 	if (__endwin) {
    257 		__endwin = 0;
    258 		__restartwin();
    259 	}
    260 
    261 	rawt.c_cc[VMIN] = ovmin;
    262 	rawt.c_cc[VTIME] = ovtime;
    263 	cbreakt.c_cc[VMIN] = ovmin;
    264 	cbreakt.c_cc[VTIME] = ovtime;
    265 	__baset.c_cc[VMIN] = ovmin;
    266 	__baset.c_cc[VTIME] = ovtime;
    267 }
    268 
    269 int
    270 __timeout(int delay)
    271 {
    272 	/* Check if we need to restart ... */
    273 	if (__endwin) {
    274 		__endwin = 0;
    275 		__restartwin();
    276 	}
    277 
    278 	ovmin = cbreakt.c_cc[VMIN];
    279 	ovtime = cbreakt.c_cc[VTIME];
    280 	rawt.c_cc[VMIN] = 0;
    281 	rawt.c_cc[VTIME] = delay;
    282 	cbreakt.c_cc[VMIN] = 0;
    283 	cbreakt.c_cc[VTIME] = delay;
    284 	__baset.c_cc[VMIN] = 0;
    285 	__baset.c_cc[VTIME] = delay;
    286 
    287 	return (tcsetattr(STDIN_FILENO, __tcaction ?
    288 		TCSASOFT | TCSANOW : TCSANOW, curt) ? ERR : OK);
    289 }
    290 
    291 int
    292 __notimeout(void)
    293 {
    294 	/* Check if we need to restart ... */
    295 	if (__endwin) {
    296 		__endwin = 0;
    297 		__restartwin();
    298 	}
    299 
    300 	rawt.c_cc[VMIN] = 1;
    301 	rawt.c_cc[VTIME] = 0;
    302 	cbreakt.c_cc[VMIN] = 1;
    303 	cbreakt.c_cc[VTIME] = 0;
    304 	__baset.c_cc[VMIN] = 1;
    305 	__baset.c_cc[VTIME] = 0;
    306 
    307 	return (tcsetattr(STDIN_FILENO, __tcaction ?
    308 		TCSASOFT | TCSANOW : TCSANOW, curt) ? ERR : OK);
    309 }
    310 
    311 int
    312 echo(void)
    313 {
    314 	/* Check if we need to restart ... */
    315 	if (__endwin) {
    316 		__endwin = 0;
    317 		__restartwin();
    318 	}
    319 
    320 	__echoit = 1;
    321 	return (OK);
    322 }
    323 
    324 int
    325 noecho(void)
    326 {
    327 	/* Check if we need to restart ... */
    328 	if (__endwin) {
    329 		__endwin = 0;
    330 		__restartwin();
    331 	}
    332 
    333 	__echoit = 0;
    334 	return (OK);
    335 }
    336 
    337 int
    338 nl(void)
    339 {
    340 	/* Check if we need to restart ... */
    341 	if (__endwin) {
    342 		__endwin = 0;
    343 		__restartwin();
    344 	}
    345 
    346 	rawt.c_iflag |= ICRNL;
    347 	rawt.c_oflag |= ONLCR;
    348 	cbreakt.c_iflag |= ICRNL;
    349 	cbreakt.c_oflag |= ONLCR;
    350 	__baset.c_iflag |= ICRNL;
    351 	__baset.c_oflag |= ONLCR;
    352 
    353 	__pfast = __rawmode;
    354 	return (tcsetattr(STDIN_FILENO, __tcaction ?
    355 	    TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
    356 }
    357 
    358 int
    359 nonl(void)
    360 {
    361 	/* Check if we need to restart ... */
    362 	if (__endwin) {
    363 		__endwin = 0;
    364 		__restartwin();
    365 	}
    366 
    367 	rawt.c_iflag &= ~ICRNL;
    368 	rawt.c_oflag &= ~ONLCR;
    369 	cbreakt.c_iflag &= ~ICRNL;
    370 	cbreakt.c_oflag &= ~ONLCR;
    371 	__baset.c_iflag &= ~ICRNL;
    372 	__baset.c_oflag &= ~ONLCR;
    373 
    374 	__pfast = 1;
    375 	return (tcsetattr(STDIN_FILENO, __tcaction ?
    376 	    TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
    377 }
    378 
    379 int
    380 intrflush(WINDOW *win, bool bf)	/*ARGSUSED*/
    381 {
    382 	/* Check if we need to restart ... */
    383 	if (__endwin) {
    384 		__endwin = 0;
    385 		__restartwin();
    386 	}
    387 
    388 	if (bf) {
    389 		rawt.c_lflag &= ~NOFLSH;
    390 		cbreakt.c_lflag &= ~NOFLSH;
    391 		__baset.c_lflag &= ~NOFLSH;
    392 	} else {
    393 		rawt.c_lflag |= NOFLSH;
    394 		cbreakt.c_lflag |= NOFLSH;
    395 		__baset.c_lflag |= NOFLSH;
    396 	}
    397 
    398 	__pfast = 1;
    399 	return (tcsetattr(STDIN_FILENO, __tcaction ?
    400 	    TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
    401 }
    402 
    403 void
    404 __startwin(void)
    405 {
    406 	static char *stdbuf;
    407 	static size_t len;
    408 
    409 	(void) fflush(stdout);
    410 
    411 	/*
    412 	 * Some C libraries default to a 1K buffer when talking to a tty.
    413 	 * With a larger screen, especially across a network, we'd like
    414 	 * to get it to all flush in a single write.  Make it twice as big
    415 	 * as just the characters (so that we have room for cursor motions
    416 	 * and attribute information) but no more than 8K.
    417 	 */
    418 	if (stdbuf == NULL) {
    419 		if ((len = LINES * COLS * 2) > 8192)
    420 			len = 8192;
    421 		if ((stdbuf = malloc(len)) == NULL)
    422 			len = 0;
    423 	}
    424 	(void) setvbuf(stdout, stdbuf, _IOFBF, len);
    425 
    426 	tputs(TI, 0, __cputchar);
    427 	tputs(VS, 0, __cputchar);
    428 	if (curscr->flags & __KEYPAD)
    429 		tputs(KS, 0, __cputchar);
    430 }
    431 
    432 int
    433 endwin(void)
    434 {
    435 	__endwin = 1;
    436 	return __stopwin();
    437 }
    438 
    439 bool
    440 isendwin(void)
    441 {
    442 	return (__endwin ? TRUE : FALSE);
    443 }
    444 
    445 int
    446 flushinp(void)
    447 {
    448 	(void) fpurge(stdin);
    449 	return (OK);
    450 }
    451 
    452 int
    453 def_shell_mode(void)
    454 {
    455 	return (tcgetattr(STDIN_FILENO, &__orig_termios) ? ERR : OK);
    456 }
    457 
    458 int
    459 reset_shell_mode(void)
    460 {
    461 	return (tcsetattr(STDIN_FILENO, __tcaction ?
    462 	    TCSASOFT | TCSADRAIN : TCSADRAIN, &__orig_termios) ? ERR : OK);
    463 }
    464 
    465 /*
    466  * The following routines, savetty and resetty are completely useless and
    467  * are left in only as stubs.  If people actually use them they will almost
    468  * certainly screw up the state of the world.
    469  */
    470 static struct termios savedtty;
    471 int
    472 savetty(void)
    473 {
    474 	return (tcgetattr(STDIN_FILENO, &savedtty) ? ERR : OK);
    475 }
    476 
    477 int
    478 resetty(void)
    479 {
    480 	return (tcsetattr(STDIN_FILENO, __tcaction ?
    481 	    TCSASOFT | TCSADRAIN : TCSADRAIN, &savedtty) ? ERR : OK);
    482 }
    483 
    484 /*
    485  * erasechar --
    486  *     Return the character of the erase key.
    487  *
    488  */
    489 char
    490 erasechar(void)
    491 {
    492 	return __baset.c_cc[VERASE];
    493 }
    494 
    495 /*
    496  * killchar --
    497  *     Return the character of the kill key.
    498  */
    499 char
    500 killchar(void)
    501 {
    502 	return __baset.c_cc[VKILL];
    503 }
    504