xref: /original-bsd/lib/libcurses/tty.c (revision cf2e4d33)
1 /*-
2  * Copyright (c) 1992, 1993, 1994
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)tty.c	8.5 (Berkeley) 08/13/94";
10 #endif /* not lint */
11 
12 #include <stdlib.h>
13 #include <termios.h>
14 #include <unistd.h>
15 
16 #include "curses.h"
17 
18 /*
19  * In general, curses should leave tty hardware settings alone (speed, parity,
20  * word size).  This is most easily done in BSD by using TCSASOFT on all
21  * tcsetattr calls.  On other systems, it would be better to get and restore
22  * those attributes at each change, or at least when stopped and restarted.
23  * See also the comments in getterm().
24  */
25 #ifdef TCSASOFT
26 int __tcaction = 1;			/* Ignore hardware settings. */
27 #else
28 int __tcaction = 0;
29 #endif
30 
31 struct termios __orig_termios, __baset;
32 static struct termios cbreakt, rawt, *curt;
33 static int useraw;
34 
35 #ifndef	OXTABS
36 #ifdef	XTABS			/* SMI uses XTABS. */
37 #define	OXTABS	XTABS
38 #else
39 #define	OXTABS	0
40 #endif
41 #endif
42 
43 /*
44  * gettmode --
45  *	Do terminal type initialization.
46  */
47 int
48 gettmode()
49 {
50 	useraw = 0;
51 
52 	if (tcgetattr(STDIN_FILENO, &__orig_termios))
53 		return (ERR);
54 
55 	__baset = __orig_termios;
56 	__baset.c_oflag &= ~OXTABS;
57 
58 	GT = 0;		/* historical. was used before we wired OXTABS off */
59 	NONL = (__baset.c_oflag & ONLCR) == 0;
60 
61 	/*
62 	 * XXX
63 	 * System V and SMI systems overload VMIN and VTIME, such that
64 	 * VMIN is the same as the VEOF element, and VTIME is the same
65 	 * as the VEOL element.  This means that, if VEOF was ^D, the
66 	 * default VMIN is 4.  Majorly stupid.
67 	 */
68 	cbreakt = __baset;
69 	cbreakt.c_lflag &= ~ICANON;
70 	cbreakt.c_cc[VMIN] = 1;
71 	cbreakt.c_cc[VTIME] = 0;
72 
73 	rawt = cbreakt;
74 	rawt.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|INLCR|IGNCR|ICRNL|IXON);
75 	rawt.c_oflag &= ~OPOST;
76 	rawt.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
77 
78 	/*
79 	 * In general, curses should leave hardware-related settings alone.
80 	 * This includes parity and word size.  Older versions set the tty
81 	 * to 8 bits, no parity in raw(), but this is considered to be an
82 	 * artifact of the old tty interface.  If it's desired to change
83 	 * parity and word size, the TCSASOFT bit has to be removed from the
84 	 * calls that switch to/from "raw" mode.
85 	 */
86 	if (!__tcaction) {
87 		rawt.c_iflag &= ~ISTRIP;
88 		rawt.c_cflag &= ~(CSIZE|PARENB);
89 		rawt.c_cflag |= CS8;
90 	}
91 
92 	curt = &__baset;
93 	return (tcsetattr(STDIN_FILENO, __tcaction ?
94 	    TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
95 }
96 
97 int
98 raw()
99 {
100 	useraw = __pfast = __rawmode = 1;
101 	curt = &rawt;
102 	return (tcsetattr(STDIN_FILENO, __tcaction ?
103 	    TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
104 }
105 
106 int
107 noraw()
108 {
109 	useraw = __pfast = __rawmode = 0;
110 	curt = &__baset;
111 	return (tcsetattr(STDIN_FILENO, __tcaction ?
112 	    TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
113 }
114 
115 int
116 cbreak()
117 {
118 
119 	__rawmode = 1;
120 	curt = useraw ? &rawt : &cbreakt;
121 	return (tcsetattr(STDIN_FILENO, __tcaction ?
122 	    TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
123 }
124 
125 int
126 nocbreak()
127 {
128 
129 	__rawmode = 0;
130 	curt = useraw ? &rawt : &__baset;
131 	return (tcsetattr(STDIN_FILENO, __tcaction ?
132 	    TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
133 }
134 
135 int
136 echo()
137 {
138 	rawt.c_lflag |= ECHO;
139 	cbreakt.c_lflag |= ECHO;
140 	__baset.c_lflag |= ECHO;
141 
142 	__echoit = 1;
143 	return (tcsetattr(STDIN_FILENO, __tcaction ?
144 	    TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
145 }
146 
147 int
148 noecho()
149 {
150 	rawt.c_lflag &= ~ECHO;
151 	cbreakt.c_lflag &= ~ECHO;
152 	__baset.c_lflag &= ~ECHO;
153 
154 	__echoit = 0;
155 	return (tcsetattr(STDIN_FILENO, __tcaction ?
156 	    TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
157 }
158 
159 int
160 nl()
161 {
162 	rawt.c_iflag |= ICRNL;
163 	rawt.c_oflag |= ONLCR;
164 	cbreakt.c_iflag |= ICRNL;
165 	cbreakt.c_oflag |= ONLCR;
166 	__baset.c_iflag |= ICRNL;
167 	__baset.c_oflag |= ONLCR;
168 
169 	__pfast = __rawmode;
170 	return (tcsetattr(STDIN_FILENO, __tcaction ?
171 	    TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
172 }
173 
174 int
175 nonl()
176 {
177 	rawt.c_iflag &= ~ICRNL;
178 	rawt.c_oflag &= ~ONLCR;
179 	cbreakt.c_iflag &= ~ICRNL;
180 	cbreakt.c_oflag &= ~ONLCR;
181 	__baset.c_iflag &= ~ICRNL;
182 	__baset.c_oflag &= ~ONLCR;
183 
184 	__pfast = 1;
185 	return (tcsetattr(STDIN_FILENO, __tcaction ?
186 	    TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
187 }
188 
189 void
190 __startwin()
191 {
192 	static char *stdbuf;
193 	static size_t len;
194 
195 	(void)fflush(stdout);
196 
197 	/*
198 	 * Some C libraries default to a 1K buffer when talking to a tty.
199 	 * With a larger screen, especially across a network, we'd like
200 	 * to get it to all flush in a single write.  Make it twice as big
201 	 * as just the characters (so that we have room for cursor motions
202 	 * and standout information) but no more than 8K.
203 	 */
204 	if (stdbuf == NULL) {
205 		if ((len = LINES * COLS * 2) > 8192)
206 			len = 8192;
207 		if ((stdbuf = malloc(len)) == NULL)
208 			len = 0;
209 	}
210 	(void)setvbuf(stdout, stdbuf, _IOFBF, len);
211 
212 	tputs(TI, 0, __cputchar);
213 	tputs(VS, 0, __cputchar);
214 }
215 
216 int
217 endwin()
218 {
219 	__restore_stophandler();
220 
221 	if (curscr != NULL) {
222 		if (curscr->flags & __WSTANDOUT) {
223 			tputs(SE, 0, __cputchar);
224 			curscr->flags &= ~__WSTANDOUT;
225 		}
226 		__mvcur(curscr->cury, curscr->cury, curscr->maxy - 1, 0, 0);
227 	}
228 
229 	(void)tputs(VE, 0, __cputchar);
230 	(void)tputs(TE, 0, __cputchar);
231 	(void)fflush(stdout);
232 	(void)setvbuf(stdout, NULL, _IOLBF, 0);
233 
234 	return (tcsetattr(STDIN_FILENO, __tcaction ?
235 	    TCSASOFT | TCSADRAIN : TCSADRAIN, &__orig_termios) ? ERR : OK);
236 }
237 
238 /*
239  * The following routines, savetty and resetty are completely useless and
240  * are left in only as stubs.  If people actually use them they will almost
241  * certainly screw up the state of the world.
242  */
243 static struct termios savedtty;
244 int
245 savetty()
246 {
247 	return (tcgetattr(STDIN_FILENO, &savedtty) ? ERR : OK);
248 }
249 
250 int
251 resetty()
252 {
253 	return (tcsetattr(STDIN_FILENO, __tcaction ?
254 	    TCSASOFT | TCSADRAIN : TCSADRAIN, &savedtty) ? ERR : OK);
255 }
256