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