1 /*- 2 * Copyright (c) 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)set.c 8.1 (Berkeley) 06/09/93"; 10 #endif /* not lint */ 11 12 #include <termios.h> 13 #include <unistd.h> 14 #include <stdio.h> 15 #include "extern.h" 16 17 #define CHK(val, dft) (val <= 0 ? dft : val) 18 19 int set_tabs __P((void)); 20 21 /* 22 * Reset the terminal mode bits to a sensible state. Very useful after 23 * a child program dies in raw mode. 24 */ 25 void 26 reset_mode() 27 { 28 tcgetattr(STDERR_FILENO, &mode); 29 30 #if defined(VDISCARD) && defined(CDISCARD) 31 mode.c_cc[VDISCARD] = CHK(mode.c_cc[VDISCARD], CDISCARD); 32 #endif 33 mode.c_cc[VEOF] = CHK(mode.c_cc[VEOF], CEOF); 34 mode.c_cc[VERASE] = CHK(mode.c_cc[VERASE], CERASE); 35 #if defined(VFLUSH) && defined(CFLUSH) 36 mode.c_cc[VFLUSH] = CHK(mode.c_cc[VFLUSH], CFLUSH); 37 #endif 38 mode.c_cc[VINTR] = CHK(mode.c_cc[VINTR], CINTR); 39 mode.c_cc[VKILL] = CHK(mode.c_cc[VKILL], CKILL); 40 #if defined(VLNEXT) && defined(CLNEXT) 41 mode.c_cc[VLNEXT] = CHK(mode.c_cc[VLNEXT], CLNEXT); 42 #endif 43 mode.c_cc[VQUIT] = CHK(mode.c_cc[VQUIT], CQUIT); 44 #if defined(VREPRINT) && defined(CRPRNT) 45 mode.c_cc[VREPRINT] = CHK(mode.c_cc[VREPRINT], CRPRNT); 46 #endif 47 mode.c_cc[VSTART] = CHK(mode.c_cc[VSTART], CSTART); 48 mode.c_cc[VSTOP] = CHK(mode.c_cc[VSTOP], CSTOP); 49 mode.c_cc[VSUSP] = CHK(mode.c_cc[VSUSP], CSUSP); 50 #if defined(VWERASE) && defined(CWERASE) 51 mode.c_cc[VWERASE] = CHK(mode.c_cc[VWERASE], CWERASE); 52 #endif 53 54 mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR 55 #ifdef IUCLC 56 | IUCLC 57 #endif 58 #ifdef IXANY 59 | IXANY 60 #endif 61 | IXOFF); 62 63 mode.c_iflag |= (BRKINT | IGNPAR | ICRNL | IXON 64 #ifdef IMAXBEL 65 | IMAXBEL 66 #endif 67 ); 68 69 mode.c_oflag &= ~(0 70 #ifdef OLCUC 71 | OLCUC 72 #endif 73 #ifdef OCRNL 74 | OCRNL 75 #endif 76 #ifdef ONOCR 77 | ONOCR 78 #endif 79 #ifdef ONLRET 80 | ONLRET 81 #endif 82 #ifdef OFILL 83 | OFILL 84 #endif 85 #ifdef OFDEL 86 | OFDEL 87 #endif 88 #ifdef NLDLY 89 | NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY 90 #endif 91 ); 92 93 mode.c_oflag |= (OPOST 94 #ifdef ONLCR 95 | ONLCR 96 #endif 97 ); 98 99 mode.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | CLOCAL); 100 mode.c_cflag |= (CS8 | CREAD); 101 mode.c_lflag &= ~(ECHONL | NOFLSH | TOSTOP 102 #ifdef ECHOPTR 103 | ECHOPRT 104 #endif 105 #ifdef XCASE 106 | XCASE 107 #endif 108 ); 109 110 mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK 111 #ifdef ECHOCTL 112 | ECHOCTL 113 #endif 114 #ifdef ECHOKE 115 | ECHOKE 116 #endif 117 ); 118 119 tcsetattr(STDERR_FILENO, TCSADRAIN, &mode); 120 } 121 122 /* 123 * Determine the erase, interrupt, and kill characters from the termcap 124 * entry and command line and update their values in 'mode'. 125 */ 126 void 127 set_control_chars() 128 { 129 char *bp, *p, bs_char, buf[1024]; 130 131 bp = buf; 132 p = tgetstr("kb", &bp); 133 if (p == NULL || p[1] != '\0') 134 p = tgetstr("bc", &bp); 135 if (p != NULL && p[1] == '\0') 136 bs_char = p[0]; 137 else if (tgetflag("bs")) 138 bs_char = CTRL('h'); 139 else 140 bs_char = 0; 141 142 if (erasechar == 0 && !tgetflag("os") && mode.c_cc[VERASE] != CERASE) { 143 if (tgetflag("bs") || bs_char != 0) 144 erasechar = -1; 145 } 146 if (erasechar < 0) 147 erasechar = (bs_char != 0) ? bs_char : CTRL('h'); 148 149 if (mode.c_cc[VERASE] == 0 || erasechar != 0) 150 mode.c_cc[VERASE] = erasechar ? erasechar : CERASE; 151 152 if (mode.c_cc[VINTR] == 0 || intrchar != 0) 153 mode.c_cc[VINTR] = intrchar ? intrchar : CINTR; 154 155 if (mode.c_cc[VKILL] == 0 || killchar != 0) 156 mode.c_cc[VKILL] = killchar ? killchar : CKILL; 157 } 158 159 /* 160 * Set up various conversions in 'mode', including parity, tabs, returns, 161 * echo, and case, according to the termcap entry. If the program we're 162 * running was named with a leading upper-case character, map external 163 * uppercase to internal lowercase. 164 */ 165 void 166 set_conversions(usingupper) 167 int usingupper; 168 { 169 if (tgetflag("UC") || usingupper) { 170 #ifdef IUCLC 171 mode.c_iflag |= IUCLC; 172 mode.c_oflag |= OLCUC; 173 #endif 174 } else if (tgetflag("LC")) { 175 #ifdef IUCLC 176 mode.c_iflag &= ~IUCLC; 177 mode.c_oflag &= ~OLCUC; 178 #endif 179 } 180 mode.c_iflag &= ~(PARMRK | INPCK); 181 mode.c_lflag |= ICANON; 182 if (tgetflag("EP")) { 183 mode.c_cflag |= PARENB; 184 mode.c_cflag &= ~PARODD; 185 } 186 if (tgetflag("OP")) { 187 mode.c_cflag |= PARENB; 188 mode.c_cflag |= PARODD; 189 } 190 191 #ifdef ONLCR 192 mode.c_oflag |= ONLCR; 193 #endif 194 mode.c_iflag |= ICRNL; 195 mode.c_lflag |= ECHO; 196 mode.c_oflag |= OXTABS; 197 if (tgetflag("NL")) { /* Newline, not linefeed. */ 198 #ifdef ONLCR 199 mode.c_oflag &= ~ONLCR; 200 #endif 201 mode.c_iflag &= ~ICRNL; 202 } 203 if (tgetflag("HD")) /* Half duplex. */ 204 mode.c_lflag &= ~ECHO; 205 if (tgetflag("pt")) /* Print tabs. */ 206 mode.c_oflag &= ~OXTABS; 207 mode.c_lflag |= (ECHOE | ECHOK); 208 } 209 210 /* Output startup string. */ 211 void 212 set_init() 213 { 214 char *bp, buf[1024]; 215 int settle; 216 217 bp = buf; 218 if (tgetstr("pc", &bp) != 0) /* Get/set pad character. */ 219 PC = buf[0]; 220 221 #ifdef TAB3 222 if (oldmode.c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) { 223 oldmode.c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET); 224 tcsetattr(STDERR_FILENO, TCSADRAIN, &oldmode); 225 } 226 #endif 227 settle = set_tabs(); 228 229 if (isreset) { 230 if (tgetstr("rs", &bp) != 0 || tgetstr("is", &bp) != 0) { 231 tputs(buf, 0, outc); 232 settle = 1; 233 } 234 if (tgetstr("rf", &bp) != 0 || tgetstr("if", &bp) != 0) { 235 cat(buf); 236 settle = 1; 237 } 238 } 239 240 if (settle) { 241 (void)putc('\r', stderr); 242 (void)fflush(stderr); 243 (void)sleep(1); /* Settle the terminal. */ 244 } 245 } 246 247 /* 248 * Set the hardware tabs on the terminal, using the ct (clear all tabs), 249 * st (set one tab) and ch (horizontal cursor addressing) capabilities. 250 * This is done before if and is, so they can patch in case we blow this. 251 * Return nonzero if we set any tab stops, zero if not. 252 */ 253 int 254 set_tabs() 255 { 256 int c; 257 char *capsp, *clear_tabs; 258 char *set_column, *set_pos, *set_tab, *tg_out; 259 char caps[1024]; 260 261 capsp = caps; 262 set_tab = tgetstr("st", &capsp); 263 264 if (set_tab && (clear_tabs = tgetstr("ct", &capsp))) { 265 (void)putc('\r', stderr); /* Force to left margin. */ 266 tputs(clear_tabs, 0, outc); 267 } 268 269 set_column = tgetstr("ch", &capsp); 270 set_pos = set_column ? NULL : tgetstr("cm", &capsp); 271 272 if (set_tab) { 273 for (c = 8; c < columns; c += 8) { 274 /* 275 * Get to the right column. "OOPS" is returned by 276 * tgoto() if it can't do the job. (*snarl*) 277 */ 278 tg_out = "OOPS"; 279 if (set_column) 280 tg_out = tgoto(set_column, 0, c); 281 if (*tg_out == 'O' && set_pos) 282 tg_out = tgoto(set_pos, c, lines - 1); 283 if (*tg_out != 'O') 284 tputs(tg_out, 1, outc); 285 else 286 (void)fprintf(stderr, "%s", " "); 287 /* Set the tab. */ 288 tputs(set_tab, 0, outc); 289 } 290 putc('\r', stderr); 291 return (1); 292 } 293 return (0); 294 } 295