Home | History | Annotate | Line # | Download | only in libcurses
tty.c revision 1.9
      1 /*	$NetBSD: tty.c,v 1.9 1997/11/13 00:40:28 phil 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.5 (Berkeley) 8/13/94";
     40 #else
     41 __RCSID("$NetBSD: tty.c,v 1.9 1997/11/13 00:40:28 phil Exp $");
     42 #endif
     43 #endif /* not lint */
     44 
     45 #include <stdlib.h>
     46 #include <termios.h>
     47 #include <unistd.h>
     48 
     49 #include "curses.h"
     50 
     51 /*
     52  * In general, curses should leave tty hardware settings alone (speed, parity,
     53  * word size).  This is most easily done in BSD by using TCSASOFT on all
     54  * tcsetattr calls.  On other systems, it would be better to get and restore
     55  * those attributes at each change, or at least when stopped and restarted.
     56  * See also the comments in getterm().
     57  */
     58 #ifdef TCSASOFT
     59 int __tcaction = 1;			/* Ignore hardware settings. */
     60 #else
     61 int __tcaction = 0;
     62 #endif
     63 
     64 struct termios __orig_termios, __baset;
     65 int __endwin;
     66 static struct termios cbreakt, rawt, *curt;
     67 static int useraw;
     68 
     69 #ifndef	OXTABS
     70 #ifdef	XTABS			/* SMI uses XTABS. */
     71 #define	OXTABS	XTABS
     72 #else
     73 #define	OXTABS	0
     74 #endif
     75 #endif
     76 
     77 /*
     78  * gettmode --
     79  *	Do terminal type initialization.
     80  */
     81 int
     82 gettmode()
     83 {
     84 	useraw = 0;
     85 
     86 	if (tcgetattr(STDIN_FILENO, &__orig_termios))
     87 		return (ERR);
     88 
     89 	__baset = __orig_termios;
     90 	__baset.c_oflag &= ~OXTABS;
     91 
     92 	GT = 0;		/* historical. was used before we wired OXTABS off */
     93 	NONL = (__baset.c_oflag & ONLCR) == 0;
     94 
     95 	/*
     96 	 * XXX
     97 	 * System V and SMI systems overload VMIN and VTIME, such that
     98 	 * VMIN is the same as the VEOF element, and VTIME is the same
     99 	 * as the VEOL element.  This means that, if VEOF was ^D, the
    100 	 * default VMIN is 4.  Majorly stupid.
    101 	 */
    102 	cbreakt = __baset;
    103 	cbreakt.c_lflag &= ~ICANON;
    104 	cbreakt.c_cc[VMIN] = 1;
    105 	cbreakt.c_cc[VTIME] = 0;
    106 
    107 	rawt = cbreakt;
    108 	rawt.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|INLCR|IGNCR|ICRNL|IXON);
    109 	rawt.c_oflag &= ~OPOST;
    110 	rawt.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
    111 
    112 	/*
    113 	 * In general, curses should leave hardware-related settings alone.
    114 	 * This includes parity and word size.  Older versions set the tty
    115 	 * to 8 bits, no parity in raw(), but this is considered to be an
    116 	 * artifact of the old tty interface.  If it's desired to change
    117 	 * parity and word size, the TCSASOFT bit has to be removed from the
    118 	 * calls that switch to/from "raw" mode.
    119 	 */
    120 	if (!__tcaction) {
    121 		rawt.c_iflag &= ~ISTRIP;
    122 		rawt.c_cflag &= ~(CSIZE|PARENB);
    123 		rawt.c_cflag |= CS8;
    124 	}
    125 
    126 	curt = &__baset;
    127 	return (tcsetattr(STDIN_FILENO, __tcaction ?
    128 	    TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
    129 }
    130 
    131 int
    132 raw()
    133 {
    134 	/* Check if we need to restart ... */
    135 	if (__endwin) {
    136 		__endwin = 0;
    137 		__restartwin();
    138 	}
    139 
    140 	useraw = __pfast = __rawmode = 1;
    141 	curt = &rawt;
    142 	return (tcsetattr(STDIN_FILENO, __tcaction ?
    143 	    TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
    144 }
    145 
    146 int
    147 noraw()
    148 {
    149 	/* Check if we need to restart ... */
    150 	if (__endwin) {
    151 		__endwin = 0;
    152 		__restartwin();
    153 	}
    154 
    155 	useraw = __pfast = __rawmode = 0;
    156 	curt = &__baset;
    157 	return (tcsetattr(STDIN_FILENO, __tcaction ?
    158 	    TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
    159 }
    160 
    161 int
    162 cbreak()
    163 {
    164 	/* Check if we need to restart ... */
    165 	if (__endwin) {
    166 		__endwin = 0;
    167 		__restartwin();
    168 	}
    169 
    170 	__rawmode = 1;
    171 	curt = useraw ? &rawt : &cbreakt;
    172 	return (tcsetattr(STDIN_FILENO, __tcaction ?
    173 	    TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
    174 }
    175 
    176 int
    177 nocbreak()
    178 {
    179 	/* Check if we need to restart ... */
    180 	if (__endwin) {
    181 		__endwin = 0;
    182 		__restartwin();
    183 	}
    184 
    185 	__rawmode = 0;
    186 	curt = useraw ? &rawt : &__baset;
    187 	return (tcsetattr(STDIN_FILENO, __tcaction ?
    188 	    TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
    189 }
    190 
    191 int
    192 echo()
    193 {
    194 	/* Check if we need to restart ... */
    195 	if (__endwin) {
    196 		__endwin = 0;
    197 		__restartwin();
    198 	}
    199 
    200 	rawt.c_lflag |= ECHO;
    201 	cbreakt.c_lflag |= ECHO;
    202 	__baset.c_lflag |= ECHO;
    203 
    204 	__echoit = 1;
    205 	return (tcsetattr(STDIN_FILENO, __tcaction ?
    206 	    TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
    207 }
    208 
    209 int
    210 noecho()
    211 {
    212 	/* Check if we need to restart ... */
    213 	if (__endwin) {
    214 		__endwin = 0;
    215 		__restartwin();
    216 	}
    217 
    218 	rawt.c_lflag &= ~ECHO;
    219 	cbreakt.c_lflag &= ~ECHO;
    220 	__baset.c_lflag &= ~ECHO;
    221 
    222 	__echoit = 0;
    223 	return (tcsetattr(STDIN_FILENO, __tcaction ?
    224 	    TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
    225 }
    226 
    227 int
    228 nl()
    229 {
    230 	/* Check if we need to restart ... */
    231 	if (__endwin) {
    232 		__endwin = 0;
    233 		__restartwin();
    234 	}
    235 
    236 	rawt.c_iflag |= ICRNL;
    237 	rawt.c_oflag |= ONLCR;
    238 	cbreakt.c_iflag |= ICRNL;
    239 	cbreakt.c_oflag |= ONLCR;
    240 	__baset.c_iflag |= ICRNL;
    241 	__baset.c_oflag |= ONLCR;
    242 
    243 	__pfast = __rawmode;
    244 	return (tcsetattr(STDIN_FILENO, __tcaction ?
    245 	    TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
    246 }
    247 
    248 int
    249 nonl()
    250 {
    251 	/* Check if we need to restart ... */
    252 	if (__endwin) {
    253 		__endwin = 0;
    254 		__restartwin();
    255 	}
    256 
    257 	rawt.c_iflag &= ~ICRNL;
    258 	rawt.c_oflag &= ~ONLCR;
    259 	cbreakt.c_iflag &= ~ICRNL;
    260 	cbreakt.c_oflag &= ~ONLCR;
    261 	__baset.c_iflag &= ~ICRNL;
    262 	__baset.c_oflag &= ~ONLCR;
    263 
    264 	__pfast = 1;
    265 	return (tcsetattr(STDIN_FILENO, __tcaction ?
    266 	    TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
    267 }
    268 
    269 void
    270 __startwin()
    271 {
    272 	static char *stdbuf;
    273 	static size_t len;
    274 
    275 	(void)fflush(stdout);
    276 
    277 	/*
    278 	 * Some C libraries default to a 1K buffer when talking to a tty.
    279 	 * With a larger screen, especially across a network, we'd like
    280 	 * to get it to all flush in a single write.  Make it twice as big
    281 	 * as just the characters (so that we have room for cursor motions
    282 	 * and standout information) but no more than 8K.
    283 	 */
    284 	if (stdbuf == NULL) {
    285 		if ((len = LINES * COLS * 2) > 8192)
    286 			len = 8192;
    287 		if ((stdbuf = malloc(len)) == NULL)
    288 			len = 0;
    289 	}
    290 	(void)setvbuf(stdout, stdbuf, _IOFBF, len);
    291 
    292 	tputs(TI, 0, __cputchar);
    293 	tputs(VS, 0, __cputchar);
    294 }
    295 
    296 int
    297 endwin()
    298 {
    299 	__endwin = 1;
    300 	return __stopwin();
    301 }
    302 
    303 /*
    304  * The following routines, savetty and resetty are completely useless and
    305  * are left in only as stubs.  If people actually use them they will almost
    306  * certainly screw up the state of the world.
    307  */
    308 static struct termios savedtty;
    309 int
    310 savetty()
    311 {
    312 	return (tcgetattr(STDIN_FILENO, &savedtty) ? ERR : OK);
    313 }
    314 
    315 int
    316 resetty()
    317 {
    318 	return (tcsetattr(STDIN_FILENO, __tcaction ?
    319 	    TCSASOFT | TCSADRAIN : TCSADRAIN, &savedtty) ? ERR : OK);
    320 }
    321