1 /* $NetBSD: tty.c,v 1.42 2010/02/03 15:34:40 roy 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.42 2010/02/03 15:34:40 roy 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. */
67 #ifdef XTABS /* SMI uses XTABS. */
76 * Return the current baudrate
81 if (_cursesi_screen
->notty
== TRUE
)
84 return cfgetospeed(&_cursesi_screen
->baset
);
89 * Do terminal type initialization.
94 if (_cursesi_gettmode(_cursesi_screen
) == ERR
)
97 __GT
= _cursesi_screen
->GT
;
98 __NONL
= _cursesi_screen
->NONL
;
103 * _cursesi_gettmode --
104 * Do the terminal type initialisation for the tty attached to the
108 _cursesi_gettmode(SCREEN
*screen
)
112 if (tcgetattr(fileno(screen
->infd
), &screen
->orig_termios
)) {
113 /* if the input fd is not a tty try the output */
114 if (tcgetattr(fileno(screen
->infd
), &screen
->orig_termios
)) {
115 /* not a tty ... we will disable tty related stuff */
116 screen
->notty
= TRUE
;
123 screen
->baset
= screen
->orig_termios
;
124 screen
->baset
.c_oflag
&= ~OXTABS
;
126 screen
->GT
= 0; /* historical. was used before we wired OXTABS off */
127 screen
->NONL
= (screen
->baset
.c_oflag
& ONLCR
) == 0;
131 * System V and SMI systems overload VMIN and VTIME, such that
132 * VMIN is the same as the VEOF element, and VTIME is the same
133 * as the VEOL element. This means that, if VEOF was ^D, the
134 * default VMIN is 4. Majorly stupid.
136 screen
->cbreakt
= screen
->baset
;
137 screen
->cbreakt
.c_lflag
&= ~(ECHO
| ECHONL
| ICANON
);
138 screen
->cbreakt
.c_cc
[VMIN
] = 1;
139 screen
->cbreakt
.c_cc
[VTIME
] = 0;
141 screen
->rawt
= screen
->cbreakt
;
142 screen
->rawt
.c_iflag
&= ~(IGNBRK
| BRKINT
| PARMRK
| INLCR
| IGNCR
|
144 screen
->rawt
.c_oflag
&= ~OPOST
;
145 screen
->rawt
.c_lflag
&= ~(ISIG
| IEXTEN
);
148 * In general, curses should leave hardware-related settings alone.
149 * This includes parity and word size. Older versions set the tty
150 * to 8 bits, no parity in raw(), but this is considered to be an
151 * artifact of the old tty interface. If it's desired to change
152 * parity and word size, the TCSASOFT bit has to be removed from the
153 * calls that switch to/from "raw" mode.
156 screen
->rawt
.c_iflag
&= ~ISTRIP
;
157 screen
->rawt
.c_cflag
&= ~(CSIZE
| PARENB
);
158 screen
->rawt
.c_cflag
|= CS8
;
161 screen
->curt
= &screen
->baset
;
162 return (tcsetattr(fileno(screen
->infd
), __tcaction
?
163 TCSASOFT
| TCSADRAIN
: TCSADRAIN
, screen
->curt
) ? ERR
: OK
);
168 * Put the terminal into raw mode
174 __CTRACE(__CTRACE_MISC
, "raw()\n");
176 /* Check if we need to restart ... */
177 if (_cursesi_screen
->endwin
)
180 _cursesi_screen
->useraw
= __pfast
= __rawmode
= 1;
181 _cursesi_screen
->curt
= &_cursesi_screen
->rawt
;
182 if (_cursesi_screen
->notty
== TRUE
)
184 return (tcsetattr(fileno(_cursesi_screen
->infd
), __tcaction
?
185 TCSASOFT
| TCSADRAIN
: TCSADRAIN
,
186 _cursesi_screen
->curt
) ? ERR
: OK
);
191 * Put the terminal into cooked mode
197 __CTRACE(__CTRACE_MISC
, "noraw()\n");
199 /* Check if we need to restart ... */
200 if (_cursesi_screen
->endwin
)
203 _cursesi_screen
->useraw
= __pfast
= __rawmode
= 0;
204 if (_cursesi_screen
->notty
== TRUE
)
206 _cursesi_screen
->curt
= &_cursesi_screen
->baset
;
207 return (tcsetattr(fileno(_cursesi_screen
->infd
), __tcaction
?
208 TCSASOFT
| TCSADRAIN
: TCSADRAIN
,
209 _cursesi_screen
->curt
) ? ERR
: OK
);
220 __CTRACE(__CTRACE_MISC
, "cbreak()\n");
222 /* Check if we need to restart ... */
223 if (_cursesi_screen
->endwin
)
227 if (_cursesi_screen
->notty
== TRUE
)
229 _cursesi_screen
->curt
= _cursesi_screen
->useraw
?
230 &_cursesi_screen
->rawt
: &_cursesi_screen
->cbreakt
;
231 return (tcsetattr(fileno(_cursesi_screen
->infd
), __tcaction
?
232 TCSASOFT
| TCSADRAIN
: TCSADRAIN
,
233 _cursesi_screen
->curt
) ? ERR
: OK
);
238 * Disable cbreak mode
244 __CTRACE(__CTRACE_MISC
, "nocbreak()\n");
246 /* Check if we need to restart ... */
247 if (_cursesi_screen
->endwin
)
251 if (_cursesi_screen
->notty
== TRUE
)
253 /* if we were in halfdelay mode then nuke the timeout */
254 if ((_cursesi_screen
->half_delay
== TRUE
) &&
255 (__notimeout() == ERR
))
258 _cursesi_screen
->half_delay
= FALSE
;
259 _cursesi_screen
->curt
= _cursesi_screen
->useraw
?
260 &_cursesi_screen
->rawt
: &_cursesi_screen
->baset
;
261 return (tcsetattr(fileno(_cursesi_screen
->infd
), __tcaction
?
262 TCSASOFT
| TCSADRAIN
: TCSADRAIN
,
263 _cursesi_screen
->curt
) ? ERR
: OK
);
268 * Put the terminal into cbreak mode with the specified timeout.
272 halfdelay(int duration
)
274 if ((duration
< 1) || (duration
> 255))
280 if (__timeout(duration
) == ERR
)
283 _cursesi_screen
->half_delay
= TRUE
;
291 __CTRACE(__CTRACE_MISC
, "__delay()\n");
293 /* Check if we need to restart ... */
294 if (_cursesi_screen
->endwin
)
297 if (_cursesi_screen
->notty
== TRUE
)
299 _cursesi_screen
->rawt
.c_cc
[VMIN
] = 1;
300 _cursesi_screen
->rawt
.c_cc
[VTIME
] = 0;
301 _cursesi_screen
->cbreakt
.c_cc
[VMIN
] = 1;
302 _cursesi_screen
->cbreakt
.c_cc
[VTIME
] = 0;
303 _cursesi_screen
->baset
.c_cc
[VMIN
] = 1;
304 _cursesi_screen
->baset
.c_cc
[VTIME
] = 0;
306 if (tcsetattr(fileno(_cursesi_screen
->infd
), __tcaction
?
307 TCSASOFT
: TCSANOW
, _cursesi_screen
->curt
)) {
319 __CTRACE(__CTRACE_MISC
, "__nodelay()\n");
321 /* Check if we need to restart ... */
322 if (_cursesi_screen
->endwin
)
325 if (_cursesi_screen
->notty
== TRUE
)
327 _cursesi_screen
->rawt
.c_cc
[VMIN
] = 0;
328 _cursesi_screen
->rawt
.c_cc
[VTIME
] = 0;
329 _cursesi_screen
->cbreakt
.c_cc
[VMIN
] = 0;
330 _cursesi_screen
->cbreakt
.c_cc
[VTIME
] = 0;
331 _cursesi_screen
->baset
.c_cc
[VMIN
] = 0;
332 _cursesi_screen
->baset
.c_cc
[VTIME
] = 0;
334 if (tcsetattr(fileno(_cursesi_screen
->infd
), __tcaction
?
335 TCSASOFT
: TCSANOW
, _cursesi_screen
->curt
)) {
346 /* Check if we need to restart ... */
347 if (_cursesi_screen
->endwin
)
350 if (_cursesi_screen
->notty
== TRUE
)
352 _cursesi_screen
->ovmin
= _cursesi_screen
->cbreakt
.c_cc
[VMIN
];
353 _cursesi_screen
->ovtime
= _cursesi_screen
->cbreakt
.c_cc
[VTIME
];
357 __restore_termios(void)
359 /* Check if we need to restart ... */
360 if (_cursesi_screen
->endwin
)
363 if (_cursesi_screen
->notty
== TRUE
)
365 _cursesi_screen
->rawt
.c_cc
[VMIN
] = _cursesi_screen
->ovmin
;
366 _cursesi_screen
->rawt
.c_cc
[VTIME
] = _cursesi_screen
->ovtime
;
367 _cursesi_screen
->cbreakt
.c_cc
[VMIN
] = _cursesi_screen
->ovmin
;
368 _cursesi_screen
->cbreakt
.c_cc
[VTIME
] = _cursesi_screen
->ovtime
;
369 _cursesi_screen
->baset
.c_cc
[VMIN
] = _cursesi_screen
->ovmin
;
370 _cursesi_screen
->baset
.c_cc
[VTIME
] = _cursesi_screen
->ovtime
;
377 __CTRACE(__CTRACE_MISC
, "__timeout()\n");
379 /* Check if we need to restart ... */
380 if (_cursesi_screen
->endwin
)
383 if (_cursesi_screen
->notty
== TRUE
)
385 _cursesi_screen
->ovmin
= _cursesi_screen
->cbreakt
.c_cc
[VMIN
];
386 _cursesi_screen
->ovtime
= _cursesi_screen
->cbreakt
.c_cc
[VTIME
];
387 _cursesi_screen
->rawt
.c_cc
[VMIN
] = 0;
388 _cursesi_screen
->rawt
.c_cc
[VTIME
] = delay
;
389 _cursesi_screen
->cbreakt
.c_cc
[VMIN
] = 0;
390 _cursesi_screen
->cbreakt
.c_cc
[VTIME
] = delay
;
391 _cursesi_screen
->baset
.c_cc
[VMIN
] = 0;
392 _cursesi_screen
->baset
.c_cc
[VTIME
] = delay
;
394 if (tcsetattr(fileno(_cursesi_screen
->infd
),
395 __tcaction
? TCSASOFT
| TCSANOW
: TCSANOW
,
396 _cursesi_screen
->curt
)) {
408 __CTRACE(__CTRACE_MISC
, "__notimeout()\n");
410 /* Check if we need to restart ... */
411 if (_cursesi_screen
->endwin
)
414 if (_cursesi_screen
->notty
== TRUE
)
416 _cursesi_screen
->rawt
.c_cc
[VMIN
] = 1;
417 _cursesi_screen
->rawt
.c_cc
[VTIME
] = 0;
418 _cursesi_screen
->cbreakt
.c_cc
[VMIN
] = 1;
419 _cursesi_screen
->cbreakt
.c_cc
[VTIME
] = 0;
420 _cursesi_screen
->baset
.c_cc
[VMIN
] = 1;
421 _cursesi_screen
->baset
.c_cc
[VTIME
] = 0;
423 return (tcsetattr(fileno(_cursesi_screen
->infd
),
424 __tcaction
? TCSASOFT
| TCSANOW
: TCSANOW
,
425 _cursesi_screen
->curt
) ? ERR
: OK
);
432 __CTRACE(__CTRACE_MISC
, "echo()\n");
434 /* Check if we need to restart ... */
435 if (_cursesi_screen
->endwin
)
446 __CTRACE(__CTRACE_MISC
, "noecho()\n");
448 /* Check if we need to restart ... */
449 if (_cursesi_screen
->endwin
)
460 __CTRACE(__CTRACE_MISC
, "nl()\n");
462 /* Check if we need to restart ... */
463 if (_cursesi_screen
->endwin
)
466 if (_cursesi_screen
->notty
== TRUE
)
468 _cursesi_screen
->rawt
.c_iflag
|= ICRNL
;
469 _cursesi_screen
->rawt
.c_oflag
|= ONLCR
;
470 _cursesi_screen
->cbreakt
.c_iflag
|= ICRNL
;
471 _cursesi_screen
->cbreakt
.c_oflag
|= ONLCR
;
472 _cursesi_screen
->baset
.c_iflag
|= ICRNL
;
473 _cursesi_screen
->baset
.c_oflag
|= ONLCR
;
475 _cursesi_screen
->nl
= 1;
476 _cursesi_screen
->pfast
= _cursesi_screen
->rawmode
;
477 return (tcsetattr(fileno(_cursesi_screen
->infd
), __tcaction
?
478 TCSASOFT
| TCSADRAIN
: TCSADRAIN
,
479 _cursesi_screen
->curt
) ? ERR
: OK
);
486 __CTRACE(__CTRACE_MISC
, "nonl()\n");
488 /* Check if we need to restart ... */
489 if (_cursesi_screen
->endwin
)
492 if (_cursesi_screen
->notty
== TRUE
)
494 _cursesi_screen
->rawt
.c_iflag
&= ~ICRNL
;
495 _cursesi_screen
->rawt
.c_oflag
&= ~ONLCR
;
496 _cursesi_screen
->cbreakt
.c_iflag
&= ~ICRNL
;
497 _cursesi_screen
->cbreakt
.c_oflag
&= ~ONLCR
;
498 _cursesi_screen
->baset
.c_iflag
&= ~ICRNL
;
499 _cursesi_screen
->baset
.c_oflag
&= ~ONLCR
;
501 _cursesi_screen
->nl
= 0;
503 return (tcsetattr(fileno(_cursesi_screen
->infd
), __tcaction
?
504 TCSASOFT
| TCSADRAIN
: TCSADRAIN
,
505 _cursesi_screen
->curt
) ? ERR
: OK
);
508 #ifndef _CURSES_USE_MACROS
512 (void) intrflush(stdscr
, FALSE
);
518 (void) intrflush(stdscr
, TRUE
);
520 #endif /* _CURSES_USE_MACROS */
523 intrflush(WINDOW
*win
, bool bf
) /*ARGSUSED*/
525 /* Check if we need to restart ... */
526 if (_cursesi_screen
->endwin
)
529 if (_cursesi_screen
->notty
== TRUE
)
532 _cursesi_screen
->rawt
.c_lflag
&= ~NOFLSH
;
533 _cursesi_screen
->cbreakt
.c_lflag
&= ~NOFLSH
;
534 _cursesi_screen
->baset
.c_lflag
&= ~NOFLSH
;
536 _cursesi_screen
->rawt
.c_lflag
|= NOFLSH
;
537 _cursesi_screen
->cbreakt
.c_lflag
|= NOFLSH
;
538 _cursesi_screen
->baset
.c_lflag
|= NOFLSH
;
542 return (tcsetattr(fileno(_cursesi_screen
->infd
), __tcaction
?
543 TCSASOFT
| TCSADRAIN
: TCSADRAIN
,
544 _cursesi_screen
->curt
) ? ERR
: OK
);
548 __startwin(SCREEN
*screen
)
551 (void) fflush(screen
->infd
);
554 * Some C libraries default to a 1K buffer when talking to a tty.
555 * With a larger screen, especially across a network, we'd like
556 * to get it to all flush in a single write. Make it twice as big
557 * as just the characters (so that we have room for cursor motions
558 * and attribute information) but no more than 8K.
560 if (screen
->stdbuf
== NULL
) {
561 screen
->len
= LINES
* COLS
* 2;
562 if (screen
->len
> 8192)
564 if ((screen
->stdbuf
= malloc(screen
->len
)) == NULL
)
567 (void) setvbuf(screen
->outfd
, screen
->stdbuf
, _IOFBF
, screen
->len
);
569 ti_puts(screen
->term
, t_enter_ca_mode(screen
->term
), 0,
570 __cputchar_args
, (void *) screen
->outfd
);
571 ti_puts(screen
->term
, t_cursor_normal(screen
->term
), 0,
572 __cputchar_args
, (void *) screen
->outfd
);
573 if (screen
->curscr
->flags
& __KEYPAD
)
574 ti_puts(screen
->term
, t_keypad_xmit(screen
->term
), 0,
575 __cputchar_args
, (void *) screen
->outfd
);
583 __CTRACE(__CTRACE_MISC
, "endwin\n");
591 return (_cursesi_screen
->endwin
? TRUE
: FALSE
);
597 (void) fpurge(_cursesi_screen
->infd
);
602 * The following routines, savetty and resetty are completely useless and
603 * are left in only as stubs. If people actually use them they will almost
604 * certainly screw up the state of the world.
606 /*static struct termios savedtty;*/
610 if (_cursesi_screen
->notty
== TRUE
)
612 return (tcgetattr(fileno(_cursesi_screen
->infd
),
613 &_cursesi_screen
->savedtty
) ? ERR
: OK
);
619 if (_cursesi_screen
->notty
== TRUE
)
621 return (tcsetattr(fileno(_cursesi_screen
->infd
), __tcaction
?
622 TCSASOFT
| TCSADRAIN
: TCSADRAIN
,
623 &_cursesi_screen
->savedtty
) ? ERR
: OK
);
628 * Return the character of the erase key.
633 if (_cursesi_screen
->notty
== TRUE
)
635 return _cursesi_screen
->baset
.c_cc
[VERASE
];
640 * Return the character of the kill key.
645 if (_cursesi_screen
->notty
== TRUE
)
647 return _cursesi_screen
->baset
.c_cc
[VKILL
];
652 * Return the wide character of the erase key.
655 erasewchar( wchar_t *ch
)
660 if (_cursesi_screen
->notty
== TRUE
)
662 *ch
= _cursesi_screen
->baset
.c_cc
[VERASE
];
664 #endif /* HAVE_WCHAR */
669 * Return the wide character of the kill key.
672 killwchar( wchar_t *ch
)
677 if (_cursesi_screen
->notty
== TRUE
)
679 *ch
= _cursesi_screen
->baset
.c_cc
[VKILL
];
681 #endif /* HAVE_WCHAR */