tty.c revision 1.12.6.2 1 /* $NetBSD: tty.c,v 1.12.6.2 2000/03/05 23:21:38 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.12.6.2 2000/03/05 23:21:38 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
51 #include "curses.h"
52
53 /*
54 * In general, curses should leave tty hardware settings alone (speed, parity,
55 * word size). This is most easily done in BSD by using TCSASOFT on all
56 * tcsetattr calls. On other systems, it would be better to get and restore
57 * those attributes at each change, or at least when stopped and restarted.
58 * See also the comments in getterm().
59 */
60 #ifdef TCSASOFT
61 int __tcaction = 1; /* Ignore hardware settings. */
62 #else
63 int __tcaction = 0;
64 #endif
65
66 struct termios __orig_termios, __baset;
67 int __endwin;
68 static struct termios cbreakt, rawt, *curt;
69 static int useraw;
70 static int ovmin = 1;
71 static int ovtime = 0;
72
73 #ifndef OXTABS
74 #ifdef XTABS /* SMI uses XTABS. */
75 #define OXTABS XTABS
76 #else
77 #define OXTABS 0
78 #endif
79 #endif
80
81 /*
82 * gettmode --
83 * Do terminal type initialization.
84 */
85 int
86 gettmode()
87 {
88 useraw = 0;
89
90 if (tcgetattr(STDIN_FILENO, &__orig_termios))
91 return (ERR);
92
93 __baset = __orig_termios;
94 __baset.c_oflag &= ~OXTABS;
95
96 GT = 0; /* historical. was used before we wired OXTABS
97 * off */
98 NONL = (__baset.c_oflag & ONLCR) == 0;
99
100 /*
101 * XXX
102 * System V and SMI systems overload VMIN and VTIME, such that
103 * VMIN is the same as the VEOF element, and VTIME is the same
104 * as the VEOL element. This means that, if VEOF was ^D, the
105 * default VMIN is 4. Majorly stupid.
106 */
107 cbreakt = __baset;
108 cbreakt.c_lflag &= ~ICANON;
109 cbreakt.c_cc[VMIN] = 1;
110 cbreakt.c_cc[VTIME] = 0;
111
112 rawt = cbreakt;
113 rawt.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | INLCR | IGNCR | ICRNL | IXON);
114 rawt.c_oflag &= ~OPOST;
115 rawt.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
116
117 /*
118 * In general, curses should leave hardware-related settings alone.
119 * This includes parity and word size. Older versions set the tty
120 * to 8 bits, no parity in raw(), but this is considered to be an
121 * artifact of the old tty interface. If it's desired to change
122 * parity and word size, the TCSASOFT bit has to be removed from the
123 * calls that switch to/from "raw" mode.
124 */
125 if (!__tcaction) {
126 rawt.c_iflag &= ~ISTRIP;
127 rawt.c_cflag &= ~(CSIZE | PARENB);
128 rawt.c_cflag |= CS8;
129 }
130
131 curt = &__baset;
132 return (tcsetattr(STDIN_FILENO, __tcaction ?
133 TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
134 }
135
136 int
137 raw()
138 {
139 /* Check if we need to restart ... */
140 if (__endwin) {
141 __endwin = 0;
142 __restartwin();
143 }
144
145 useraw = __pfast = __rawmode = 1;
146 curt = &rawt;
147 return (tcsetattr(STDIN_FILENO, __tcaction ?
148 TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
149 }
150
151 int
152 noraw()
153 {
154 /* Check if we need to restart ... */
155 if (__endwin) {
156 __endwin = 0;
157 __restartwin();
158 }
159
160 useraw = __pfast = __rawmode = 0;
161 curt = &__baset;
162 return (tcsetattr(STDIN_FILENO, __tcaction ?
163 TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
164 }
165
166 int
167 cbreak()
168 {
169 /* Check if we need to restart ... */
170 if (__endwin) {
171 __endwin = 0;
172 __restartwin();
173 }
174
175 __rawmode = 1;
176 curt = useraw ? &rawt : &cbreakt;
177 return (tcsetattr(STDIN_FILENO, __tcaction ?
178 TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
179 }
180
181 int
182 nocbreak()
183 {
184 /* Check if we need to restart ... */
185 if (__endwin) {
186 __endwin = 0;
187 __restartwin();
188 }
189
190 __rawmode = 0;
191 curt = useraw ? &rawt : &__baset;
192 return (tcsetattr(STDIN_FILENO, __tcaction ?
193 TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
194 }
195
196 int
197 __delay()
198 {
199 /* Check if we need to restart ... */
200 if (__endwin) {
201 __endwin = 0;
202 __restartwin();
203 }
204
205 rawt.c_cc[VMIN] = 1;
206 rawt.c_cc[VTIME] = 0;
207 cbreakt.c_cc[VMIN] = 1;
208 cbreakt.c_cc[VTIME] = 0;
209 __baset.c_cc[VMIN] = 1;
210 __baset.c_cc[VTIME] = 0;
211
212 return (tcsetattr(STDIN_FILENO, __tcaction ?
213 TCSASOFT : TCSANOW, curt) ? ERR : OK);
214 }
215
216 int
217 __nodelay()
218 {
219 /* Check if we need to restart ... */
220 if (__endwin) {
221 __endwin = 0;
222 __restartwin();
223 }
224
225 rawt.c_cc[VMIN] = 0;
226 rawt.c_cc[VTIME] = 0;
227 cbreakt.c_cc[VMIN] = 0;
228 cbreakt.c_cc[VTIME] = 0;
229 __baset.c_cc[VMIN] = 0;
230 __baset.c_cc[VTIME] = 0;
231
232 return (tcsetattr(STDIN_FILENO, __tcaction ?
233 TCSASOFT : TCSANOW, curt) ? ERR : OK);
234 }
235
236 void
237 __save_termios()
238 {
239 /* Check if we need to restart ... */
240 if (__endwin) {
241 __endwin = 0;
242 __restartwin();
243 }
244
245 ovmin = cbreakt.c_cc[VMIN];
246 ovtime = cbreakt.c_cc[VTIME];
247 }
248
249 void
250 __restore_termios()
251 {
252 /* Check if we need to restart ... */
253 if (__endwin) {
254 __endwin = 0;
255 __restartwin();
256 }
257
258 rawt.c_cc[VMIN] = ovmin;
259 rawt.c_cc[VTIME] = ovtime;
260 cbreakt.c_cc[VMIN] = ovmin;
261 cbreakt.c_cc[VTIME] = ovtime;
262 __baset.c_cc[VMIN] = ovmin;
263 __baset.c_cc[VTIME] = ovtime;
264 }
265
266 int
267 __timeout(delay)
268 int delay;
269 {
270 /* Check if we need to restart ... */
271 if (__endwin) {
272 __endwin = 0;
273 __restartwin();
274 }
275
276 ovmin = cbreakt.c_cc[VMIN];
277 ovtime = cbreakt.c_cc[VTIME];
278 rawt.c_cc[VMIN] = 0;
279 rawt.c_cc[VTIME] = delay;
280 cbreakt.c_cc[VMIN] = 0;
281 cbreakt.c_cc[VTIME] = delay;
282 __baset.c_cc[VMIN] = 0;
283 __baset.c_cc[VTIME] = delay;
284
285 return (tcsetattr(STDIN_FILENO, __tcaction ?
286 TCSASOFT | TCSANOW : TCSANOW, curt) ? ERR : OK);
287 }
288
289 int
290 __notimeout()
291 {
292 /* Check if we need to restart ... */
293 if (__endwin) {
294 __endwin = 0;
295 __restartwin();
296 }
297
298 rawt.c_cc[VMIN] = 1;
299 rawt.c_cc[VTIME] = 0;
300 cbreakt.c_cc[VMIN] = 1;
301 cbreakt.c_cc[VTIME] = 0;
302 __baset.c_cc[VMIN] = 1;
303 __baset.c_cc[VTIME] = 0;
304
305 return (tcsetattr(STDIN_FILENO, __tcaction ?
306 TCSASOFT | TCSANOW : TCSANOW, curt) ? ERR : OK);
307 }
308
309 int
310 echo()
311 {
312 /* Check if we need to restart ... */
313 if (__endwin) {
314 __endwin = 0;
315 __restartwin();
316 }
317
318 rawt.c_lflag |= ECHO;
319 cbreakt.c_lflag |= ECHO;
320 __baset.c_lflag |= ECHO;
321
322 __echoit = 1;
323 return (tcsetattr(STDIN_FILENO, __tcaction ?
324 TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
325 }
326
327 int
328 noecho()
329 {
330 /* Check if we need to restart ... */
331 if (__endwin) {
332 __endwin = 0;
333 __restartwin();
334 }
335
336 rawt.c_lflag &= ~ECHO;
337 cbreakt.c_lflag &= ~ECHO;
338 __baset.c_lflag &= ~ECHO;
339
340 __echoit = 0;
341 return (tcsetattr(STDIN_FILENO, __tcaction ?
342 TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
343 }
344
345 int
346 nl()
347 {
348 /* Check if we need to restart ... */
349 if (__endwin) {
350 __endwin = 0;
351 __restartwin();
352 }
353
354 rawt.c_iflag |= ICRNL;
355 rawt.c_oflag |= ONLCR;
356 cbreakt.c_iflag |= ICRNL;
357 cbreakt.c_oflag |= ONLCR;
358 __baset.c_iflag |= ICRNL;
359 __baset.c_oflag |= ONLCR;
360
361 __pfast = __rawmode;
362 return (tcsetattr(STDIN_FILENO, __tcaction ?
363 TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
364 }
365
366 int
367 nonl()
368 {
369 /* Check if we need to restart ... */
370 if (__endwin) {
371 __endwin = 0;
372 __restartwin();
373 }
374
375 rawt.c_iflag &= ~ICRNL;
376 rawt.c_oflag &= ~ONLCR;
377 cbreakt.c_iflag &= ~ICRNL;
378 cbreakt.c_oflag &= ~ONLCR;
379 __baset.c_iflag &= ~ICRNL;
380 __baset.c_oflag &= ~ONLCR;
381
382 __pfast = 1;
383 return (tcsetattr(STDIN_FILENO, __tcaction ?
384 TCSASOFT | TCSADRAIN : TCSADRAIN, curt) ? ERR : OK);
385 }
386
387 void
388 __startwin()
389 {
390 static char *stdbuf;
391 static size_t len;
392
393 (void) fflush(stdout);
394
395 /*
396 * Some C libraries default to a 1K buffer when talking to a tty.
397 * With a larger screen, especially across a network, we'd like
398 * to get it to all flush in a single write. Make it twice as big
399 * as just the characters (so that we have room for cursor motions
400 * and attribute information) but no more than 8K.
401 */
402 if (stdbuf == NULL) {
403 if ((len = LINES * COLS * 2) > 8192)
404 len = 8192;
405 if ((stdbuf = malloc(len)) == NULL)
406 len = 0;
407 }
408 (void) setvbuf(stdout, stdbuf, _IOFBF, len);
409
410 tputs(TI, 0, __cputchar);
411 tputs(VS, 0, __cputchar);
412 tputs(KS, 0, __cputchar);
413 }
414
415 int
416 endwin()
417 {
418 __endwin = 1;
419 return __stopwin();
420 }
421
422 bool
423 isendwin()
424 {
425 return (__endwin ? TRUE : FALSE);
426 }
427
428 int
429 flushinp()
430 {
431 (void) fpurge(stdin);
432 return (OK);
433 }
434
435 /*
436 * The following routines, savetty and resetty are completely useless and
437 * are left in only as stubs. If people actually use them they will almost
438 * certainly screw up the state of the world.
439 */
440 static struct termios savedtty;
441 int
442 savetty()
443 {
444 return (tcgetattr(STDIN_FILENO, &savedtty) ? ERR : OK);
445 }
446
447 int
448 resetty()
449 {
450 return (tcsetattr(STDIN_FILENO, __tcaction ?
451 TCSASOFT | TCSADRAIN : TCSADRAIN, &savedtty) ? ERR : OK);
452 }
453