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