1 /* $NetBSD: tty.c,v 1.40 2007/05/28 15:01:58 blymn Exp $ */
4 * Copyright (c) 1992, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
35 static char sccsid
[] = "@(#)tty.c 8.6 (Berkeley) 1/10/95";
37 __RCSID("$NetBSD: tty.c,v 1.40 2007/05/28 15:01:58 blymn Exp $");
41 #include <sys/types.h>
46 #include <sys/fcntl.h>
47 #include <sys/ioctl.h>
50 #include "curses_private.h"
53 * In general, curses should leave tty hardware settings alone (speed, parity,
54 * word size). This is most easily done in BSD by using TCSASOFT on all
55 * tcsetattr calls. On other systems, it would be better to get and restore
56 * those attributes at each change, or at least when stopped and restarted.
57 * See also the comments in getterm().
60 int __tcaction
= 1; /* Ignore hardware settings. */
66 #ifdef XTABS /* SMI uses XTABS. */
75 * Return the current baudrate
80 if (_cursesi_screen
->notty
== TRUE
)
83 return cfgetospeed(&_cursesi_screen
->baset
);
88 * Do terminal type initialization.
93 if (_cursesi_gettmode(_cursesi_screen
) == ERR
)
96 __GT
= _cursesi_screen
->GT
;
97 __NONL
= _cursesi_screen
->NONL
;
102 * _cursesi_gettmode --
103 * Do the terminal type initialisation for the tty attached to the
107 _cursesi_gettmode(SCREEN
*screen
)
111 if (tcgetattr(fileno(screen
->infd
), &screen
->orig_termios
)) {
112 /* if the input fd is not a tty try the output */
113 if (tcgetattr(fileno(screen
->infd
), &screen
->orig_termios
)) {
114 /* not a tty ... we will disable tty related stuff */
115 screen
->notty
= TRUE
;
122 screen
->baset
= screen
->orig_termios
;
123 screen
->baset
.c_oflag
&= ~OXTABS
;
125 screen
->GT
= 0; /* historical. was used before we wired OXTABS off */
126 screen
->NONL
= (screen
->baset
.c_oflag
& ONLCR
) == 0;
130 * System V and SMI systems overload VMIN and VTIME, such that
131 * VMIN is the same as the VEOF element, and VTIME is the same
132 * as the VEOL element. This means that, if VEOF was ^D, the
133 * default VMIN is 4. Majorly stupid.
135 screen
->cbreakt
= screen
->baset
;
136 screen
->cbreakt
.c_lflag
&= ~(ECHO
| ECHONL
| ICANON
);
137 screen
->cbreakt
.c_cc
[VMIN
] = 1;
138 screen
->cbreakt
.c_cc
[VTIME
] = 0;
140 screen
->rawt
= screen
->cbreakt
;
141 screen
->rawt
.c_iflag
&= ~(IGNBRK
| BRKINT
| PARMRK
| INLCR
| IGNCR
|
143 screen
->rawt
.c_oflag
&= ~OPOST
;
144 screen
->rawt
.c_lflag
&= ~(ISIG
| IEXTEN
);
147 * In general, curses should leave hardware-related settings alone.
148 * This includes parity and word size. Older versions set the tty
149 * to 8 bits, no parity in raw(), but this is considered to be an
150 * artifact of the old tty interface. If it's desired to change
151 * parity and word size, the TCSASOFT bit has to be removed from the
152 * calls that switch to/from "raw" mode.
155 screen
->rawt
.c_iflag
&= ~ISTRIP
;
156 screen
->rawt
.c_cflag
&= ~(CSIZE
| PARENB
);
157 screen
->rawt
.c_cflag
|= CS8
;
160 screen
->curt
= &screen
->baset
;
161 return (tcsetattr(fileno(screen
->infd
), __tcaction
?
162 TCSASOFT
| TCSADRAIN
: TCSADRAIN
, screen
->curt
) ? ERR
: OK
);
167 * Put the terminal into raw mode
173 __CTRACE(__CTRACE_MISC
, "raw()\n");
175 /* Check if we need to restart ... */
176 if (_cursesi_screen
->endwin
)
179 _cursesi_screen
->useraw
= __pfast
= __rawmode
= 1;
180 _cursesi_screen
->curt
= &_cursesi_screen
->rawt
;
181 if (_cursesi_screen
->notty
== TRUE
)
183 return (tcsetattr(fileno(_cursesi_screen
->infd
), __tcaction
?
184 TCSASOFT
| TCSADRAIN
: TCSADRAIN
,
185 _cursesi_screen
->curt
) ? ERR
: OK
);
190 * Put the terminal into cooked mode
196 __CTRACE(__CTRACE_MISC
, "noraw()\n");
198 /* Check if we need to restart ... */
199 if (_cursesi_screen
->endwin
)
202 _cursesi_screen
->useraw
= __pfast
= __rawmode
= 0;
203 if (_cursesi_screen
->notty
== TRUE
)
205 _cursesi_screen
->curt
= &_cursesi_screen
->baset
;
206 return (tcsetattr(fileno(_cursesi_screen
->infd
), __tcaction
?
207 TCSASOFT
| TCSADRAIN
: TCSADRAIN
,
208 _cursesi_screen
->curt
) ? ERR
: OK
);
219 __CTRACE(__CTRACE_MISC
, "cbreak()\n");
221 /* Check if we need to restart ... */
222 if (_cursesi_screen
->endwin
)
226 if (_cursesi_screen
->notty
== TRUE
)
228 _cursesi_screen
->curt
= _cursesi_screen
->useraw
?
229 &_cursesi_screen
->rawt
: &_cursesi_screen
->cbreakt
;
230 return (tcsetattr(fileno(_cursesi_screen
->infd
), __tcaction
?
231 TCSASOFT
| TCSADRAIN
: TCSADRAIN
,
232 _cursesi_screen
->curt
) ? ERR
: OK
);
237 * Disable cbreak mode
243 __CTRACE(__CTRACE_MISC
, "nocbreak()\n");
245 /* Check if we need to restart ... */
246 if (_cursesi_screen
->endwin
)
250 if (_cursesi_screen
->notty
== TRUE
)
252 /* if we were in halfdelay mode then nuke the timeout */
253 if ((_cursesi_screen
->half_delay
== TRUE
) &&
254 (__notimeout() == ERR
))
257 _cursesi_screen
->half_delay
= FALSE
;
258 _cursesi_screen
->curt
= _cursesi_screen
->useraw
?
259 &_cursesi_screen
->rawt
: &_cursesi_screen
->baset
;
260 return (tcsetattr(fileno(_cursesi_screen
->infd
), __tcaction
?
261 TCSASOFT
| TCSADRAIN
: TCSADRAIN
,
262 _cursesi_screen
->curt
) ? ERR
: OK
);
267 * Put the terminal into cbreak mode with the specified timeout.
271 halfdelay(int duration
)
273 if ((duration
< 1) || (duration
> 255))
279 if (__timeout(duration
) == ERR
)
282 _cursesi_screen
->half_delay
= TRUE
;
290 __CTRACE(__CTRACE_MISC
, "__delay()\n");
292 /* Check if we need to restart ... */
293 if (_cursesi_screen
->endwin
)
296 if (_cursesi_screen
->notty
== TRUE
)
298 _cursesi_screen
->rawt
.c_cc
[VMIN
] = 1;
299 _cursesi_screen
->rawt
.c_cc
[VTIME
] = 0;
300 _cursesi_screen
->cbreakt
.c_cc
[VMIN
] = 1;
301 _cursesi_screen
->cbreakt
.c_cc
[VTIME
] = 0;
302 _cursesi_screen
->baset
.c_cc
[VMIN
] = 1;
303 _cursesi_screen
->baset
.c_cc
[VTIME
] = 0;
305 if (tcsetattr(fileno(_cursesi_screen
->infd
), __tcaction
?
306 TCSASOFT
: TCSANOW
, _cursesi_screen
->curt
)) {
318 __CTRACE(__CTRACE_MISC
, "__nodelay()\n");
320 /* Check if we need to restart ... */
321 if (_cursesi_screen
->endwin
)
324 if (_cursesi_screen
->notty
== TRUE
)
326 _cursesi_screen
->rawt
.c_cc
[VMIN
] = 0;
327 _cursesi_screen
->rawt
.c_cc
[VTIME
] = 0;
328 _cursesi_screen
->cbreakt
.c_cc
[VMIN
] = 0;
329 _cursesi_screen
->cbreakt
.c_cc
[VTIME
] = 0;
330 _cursesi_screen
->baset
.c_cc
[VMIN
] = 0;
331 _cursesi_screen
->baset
.c_cc
[VTIME
] = 0;
333 if (tcsetattr(fileno(_cursesi_screen
->infd
), __tcaction
?
334 TCSASOFT
: TCSANOW
, _cursesi_screen
->curt
)) {
345 /* Check if we need to restart ... */
346 if (_cursesi_screen
->endwin
)
349 if (_cursesi_screen
->notty
== TRUE
)
351 _cursesi_screen
->ovmin
= _cursesi_screen
->cbreakt
.c_cc
[VMIN
];
352 _cursesi_screen
->ovtime
= _cursesi_screen
->cbreakt
.c_cc
[VTIME
];
356 __restore_termios(void)
358 /* Check if we need to restart ... */
359 if (_cursesi_screen
->endwin
)
362 if (_cursesi_screen
->notty
== TRUE
)
364 _cursesi_screen
->rawt
.c_cc
[VMIN
] = _cursesi_screen
->ovmin
;
365 _cursesi_screen
->rawt
.c_cc
[VTIME
] = _cursesi_screen
->ovtime
;
366 _cursesi_screen
->cbreakt
.c_cc
[VMIN
] = _cursesi_screen
->ovmin
;
367 _cursesi_screen
->cbreakt
.c_cc
[VTIME
] = _cursesi_screen
->ovtime
;
368 _cursesi_screen
->baset
.c_cc
[VMIN
] = _cursesi_screen
->ovmin
;
369 _cursesi_screen
->baset
.c_cc
[VTIME
] = _cursesi_screen
->ovtime
;
376 __CTRACE(__CTRACE_MISC
, "__timeout()\n");
378 /* Check if we need to restart ... */
379 if (_cursesi_screen
->endwin
)
382 if (_cursesi_screen
->notty
== TRUE
)
384 _cursesi_screen
->ovmin
= _cursesi_screen
->cbreakt
.c_cc
[VMIN
];
385 _cursesi_screen
->ovtime
= _cursesi_screen
->cbreakt
.c_cc
[VTIME
];
386 _cursesi_screen
->rawt
.c_cc
[VMIN
] = 0;
387 _cursesi_screen
->rawt
.c_cc
[VTIME
] = delay
;
388 _cursesi_screen
->cbreakt
.c_cc
[VMIN
] = 0;
389 _cursesi_screen
->cbreakt
.c_cc
[VTIME
] = delay
;
390 _cursesi_screen
->baset
.c_cc
[VMIN
] = 0;
391 _cursesi_screen
->baset
.c_cc
[VTIME
] = delay
;
393 if (tcsetattr(fileno(_cursesi_screen
->infd
),
394 __tcaction
? TCSASOFT
| TCSANOW
: TCSANOW
,
395 _cursesi_screen
->curt
)) {
407 __CTRACE(__CTRACE_MISC
, "__notimeout()\n");
409 /* Check if we need to restart ... */
410 if (_cursesi_screen
->endwin
)
413 if (_cursesi_screen
->notty
== TRUE
)
415 _cursesi_screen
->rawt
.c_cc
[VMIN
] = 1;
416 _cursesi_screen
->rawt
.c_cc
[VTIME
] = 0;
417 _cursesi_screen
->cbreakt
.c_cc
[VMIN
] = 1;
418 _cursesi_screen
->cbreakt
.c_cc
[VTIME
] = 0;
419 _cursesi_screen
->baset
.c_cc
[VMIN
] = 1;
420 _cursesi_screen
->baset
.c_cc
[VTIME
] = 0;
422 return (tcsetattr(fileno(_cursesi_screen
->infd
),
423 __tcaction
? TCSASOFT
| TCSANOW
: TCSANOW
,
424 _cursesi_screen
->curt
) ? ERR
: OK
);
431 __CTRACE(__CTRACE_MISC
, "echo()\n");
433 /* Check if we need to restart ... */
434 if (_cursesi_screen
->endwin
)
445 __CTRACE(__CTRACE_MISC
, "noecho()\n");
447 /* Check if we need to restart ... */
448 if (_cursesi_screen
->endwin
)
459 __CTRACE(__CTRACE_MISC
, "nl()\n");
461 /* Check if we need to restart ... */
462 if (_cursesi_screen
->endwin
)
465 if (_cursesi_screen
->notty
== TRUE
)
467 _cursesi_screen
->rawt
.c_iflag
|= ICRNL
;
468 _cursesi_screen
->rawt
.c_oflag
|= ONLCR
;
469 _cursesi_screen
->cbreakt
.c_iflag
|= ICRNL
;
470 _cursesi_screen
->cbreakt
.c_oflag
|= ONLCR
;
471 _cursesi_screen
->baset
.c_iflag
|= ICRNL
;
472 _cursesi_screen
->baset
.c_oflag
|= ONLCR
;
474 _cursesi_screen
->nl
= 1;
475 _cursesi_screen
->pfast
= _cursesi_screen
->rawmode
;
476 return (tcsetattr(fileno(_cursesi_screen
->infd
), __tcaction
?
477 TCSASOFT
| TCSADRAIN
: TCSADRAIN
,
478 _cursesi_screen
->curt
) ? ERR
: OK
);
485 __CTRACE(__CTRACE_MISC
, "nonl()\n");
487 /* Check if we need to restart ... */
488 if (_cursesi_screen
->endwin
)
491 if (_cursesi_screen
->notty
== TRUE
)
493 _cursesi_screen
->rawt
.c_iflag
&= ~ICRNL
;
494 _cursesi_screen
->rawt
.c_oflag
&= ~ONLCR
;
495 _cursesi_screen
->cbreakt
.c_iflag
&= ~ICRNL
;
496 _cursesi_screen
->cbreakt
.c_oflag
&= ~ONLCR
;
497 _cursesi_screen
->baset
.c_iflag
&= ~ICRNL
;
498 _cursesi_screen
->baset
.c_oflag
&= ~ONLCR
;
500 _cursesi_screen
->nl
= 0;
502 return (tcsetattr(fileno(_cursesi_screen
->infd
), __tcaction
?
503 TCSASOFT
| TCSADRAIN
: TCSADRAIN
,
504 _cursesi_screen
->curt
) ? ERR
: OK
);
507 #ifndef _CURSES_USE_MACROS
511 (void) intrflush(stdscr
, FALSE
);
517 (void) intrflush(stdscr
, TRUE
);
519 #endif /* _CURSES_USE_MACROS */
522 intrflush(WINDOW
*win
, bool bf
) /*ARGSUSED*/
524 /* Check if we need to restart ... */
525 if (_cursesi_screen
->endwin
)
528 if (_cursesi_screen
->notty
== TRUE
)
531 _cursesi_screen
->rawt
.c_lflag
&= ~NOFLSH
;
532 _cursesi_screen
->cbreakt
.c_lflag
&= ~NOFLSH
;
533 _cursesi_screen
->baset
.c_lflag
&= ~NOFLSH
;
535 _cursesi_screen
->rawt
.c_lflag
|= NOFLSH
;
536 _cursesi_screen
->cbreakt
.c_lflag
|= NOFLSH
;
537 _cursesi_screen
->baset
.c_lflag
|= NOFLSH
;
541 return (tcsetattr(fileno(_cursesi_screen
->infd
), __tcaction
?
542 TCSASOFT
| TCSADRAIN
: TCSADRAIN
,
543 _cursesi_screen
->curt
) ? ERR
: OK
);
547 __startwin(SCREEN
*screen
)
550 (void) fflush(screen
->infd
);
553 * Some C libraries default to a 1K buffer when talking to a tty.
554 * With a larger screen, especially across a network, we'd like
555 * to get it to all flush in a single write. Make it twice as big
556 * as just the characters (so that we have room for cursor motions
557 * and attribute information) but no more than 8K.
559 if (screen
->stdbuf
== NULL
) {
560 screen
->len
= LINES
* COLS
* 2;
561 if (screen
->len
> 8192)
563 if ((screen
->stdbuf
= malloc(screen
->len
)) == NULL
)
566 (void) setvbuf(screen
->outfd
, screen
->stdbuf
, _IOFBF
, screen
->len
);
568 t_puts(screen
->cursesi_genbuf
, __tc_ti
, 0, __cputchar_args
,
569 (void *) screen
->outfd
);
570 t_puts(screen
->cursesi_genbuf
, __tc_vs
, 0, __cputchar_args
,
571 (void *) screen
->outfd
);
572 if (screen
->curscr
->flags
& __KEYPAD
)
573 t_puts(screen
->cursesi_genbuf
, __tc_ks
, 0, __cputchar_args
,
574 (void *) screen
->outfd
);
582 __CTRACE(__CTRACE_MISC
, "endwin\n");
590 return (_cursesi_screen
->endwin
? TRUE
: FALSE
);
596 (void) fpurge(_cursesi_screen
->infd
);
601 * The following routines, savetty and resetty are completely useless and
602 * are left in only as stubs. If people actually use them they will almost
603 * certainly screw up the state of the world.
605 /*static struct termios savedtty;*/
609 if (_cursesi_screen
->notty
== TRUE
)
611 return (tcgetattr(fileno(_cursesi_screen
->infd
),
612 &_cursesi_screen
->savedtty
) ? ERR
: OK
);
618 if (_cursesi_screen
->notty
== TRUE
)
620 return (tcsetattr(fileno(_cursesi_screen
->infd
), __tcaction
?
621 TCSASOFT
| TCSADRAIN
: TCSADRAIN
,
622 &_cursesi_screen
->savedtty
) ? ERR
: OK
);
627 * Return the character of the erase key.
632 if (_cursesi_screen
->notty
== TRUE
)
634 return _cursesi_screen
->baset
.c_cc
[VERASE
];
639 * Return the character of the kill key.
644 if (_cursesi_screen
->notty
== TRUE
)
646 return _cursesi_screen
->baset
.c_cc
[VKILL
];
651 * Return the wide character of the erase key.
654 erasewchar( wchar_t *ch
)
659 if (_cursesi_screen
->notty
== TRUE
)
661 *ch
= _cursesi_screen
->baset
.c_cc
[VERASE
];
663 #endif /* HAVE_WCHAR */
668 * Return the wide character of the kill key.
671 killwchar( wchar_t *ch
)
676 if (_cursesi_screen
->notty
== TRUE
)
678 *ch
= _cursesi_screen
->baset
.c_cc
[VKILL
];
680 #endif /* HAVE_WCHAR */