xref: /netbsd-src/lib/libcurses/tty.c (revision 2a399c6883d870daece976daec6ffa7bb7f934ce)
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