1 /* $NetBSD: tty.c,v 1.15 2001/05/17 01:02:17 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Christos Zoulas of Cornell University. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 */ 38 39 #include <sys/cdefs.h> 40 #if !defined(lint) && !defined(SCCSID) 41 #if 0 42 static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) 6/4/93"; 43 #else 44 __RCSID("$NetBSD: tty.c,v 1.15 2001/05/17 01:02:17 christos Exp $"); 45 #endif 46 #endif /* not lint && not SCCSID */ 47 48 /* 49 * tty.c: tty interface stuff 50 */ 51 #include "sys.h" 52 #include "tty.h" 53 #include "el.h" 54 55 typedef struct ttymodes_t { 56 const char *m_name; 57 u_int m_value; 58 int m_type; 59 } ttymodes_t; 60 61 typedef struct ttymap_t { 62 int nch, och; /* Internal and termio rep of chars */ 63 el_action_t bind[3]; /* emacs, vi, and vi-cmd */ 64 } ttymap_t; 65 66 67 private const ttyperm_t ttyperm = { 68 { 69 {"iflag:", ICRNL, (INLCR | IGNCR)}, 70 {"oflag:", (OPOST | ONLCR), ONLRET}, 71 {"cflag:", 0, 0}, 72 {"lflag:", (ISIG | ICANON | ECHO | ECHOE | ECHOCTL | IEXTEN), 73 (NOFLSH | ECHONL | EXTPROC | FLUSHO)}, 74 {"chars:", 0, 0}, 75 }, 76 { 77 {"iflag:", (INLCR | ICRNL), IGNCR}, 78 {"oflag:", (OPOST | ONLCR), ONLRET}, 79 {"cflag:", 0, 0}, 80 {"lflag:", ISIG, 81 (NOFLSH | ICANON | ECHO | ECHOK | ECHONL | EXTPROC | IEXTEN | FLUSHO)}, 82 {"chars:", (C_SH(C_MIN) | C_SH(C_TIME) | C_SH(C_SWTCH) | C_SH(C_DSWTCH) | 83 C_SH(C_SUSP) | C_SH(C_DSUSP) | C_SH(C_EOL) | C_SH(C_DISCARD) | 84 C_SH(C_PGOFF) | C_SH(C_PAGE) | C_SH(C_STATUS)), 0} 85 }, 86 { 87 {"iflag:", 0, IXON | IXOFF | INLCR | ICRNL}, 88 {"oflag:", 0, 0}, 89 {"cflag:", 0, 0}, 90 {"lflag:", 0, ISIG | IEXTEN}, 91 {"chars:", 0, 0}, 92 } 93 }; 94 95 private const ttychar_t ttychar = { 96 { 97 CINTR, CQUIT, CERASE, CKILL, 98 CEOF, CEOL, CEOL2, CSWTCH, 99 CDSWTCH, CERASE2, CSTART, CSTOP, 100 CWERASE, CSUSP, CDSUSP, CREPRINT, 101 CDISCARD, CLNEXT, CSTATUS, CPAGE, 102 CPGOFF, CKILL2, CBRK, CMIN, 103 CTIME 104 }, 105 { 106 CINTR, CQUIT, CERASE, CKILL, 107 _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 108 _POSIX_VDISABLE, CERASE2, CSTART, CSTOP, 109 _POSIX_VDISABLE, CSUSP, _POSIX_VDISABLE, _POSIX_VDISABLE, 110 CDISCARD, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 111 _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 1, 112 0 113 }, 114 { 115 0, 0, 0, 0, 116 0, 0, 0, 0, 117 0, 0, 0, 0, 118 0, 0, 0, 0, 119 0, 0, 0, 0, 120 0, 0, 0, 0, 121 0 122 } 123 }; 124 125 private const ttymap_t tty_map[] = { 126 #ifdef VERASE 127 {C_ERASE, VERASE, 128 {ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}}, 129 #endif /* VERASE */ 130 #ifdef VERASE2 131 {C_ERASE2, VERASE2, 132 {ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}}, 133 #endif /* VERASE2 */ 134 #ifdef VKILL 135 {C_KILL, VKILL, 136 {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}}, 137 #endif /* VKILL */ 138 #ifdef VKILL2 139 {C_KILL2, VKILL2, 140 {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}}, 141 #endif /* VKILL2 */ 142 #ifdef VEOF 143 {C_EOF, VEOF, 144 {EM_DELETE_OR_LIST, VI_LIST_OR_EOF, ED_UNASSIGNED}}, 145 #endif /* VEOF */ 146 #ifdef VWERASE 147 {C_WERASE, VWERASE, 148 {ED_DELETE_PREV_WORD, ED_DELETE_PREV_WORD, ED_PREV_WORD}}, 149 #endif /* VWERASE */ 150 #ifdef VREPRINT 151 {C_REPRINT, VREPRINT, 152 {ED_REDISPLAY, ED_INSERT, ED_REDISPLAY}}, 153 #endif /* VREPRINT */ 154 #ifdef VLNEXT 155 {C_LNEXT, VLNEXT, 156 {ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED}}, 157 #endif /* VLNEXT */ 158 {-1, -1, 159 {ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED}} 160 }; 161 162 private const ttymodes_t ttymodes[] = { 163 #ifdef IGNBRK 164 {"ignbrk", IGNBRK, MD_INP}, 165 #endif /* IGNBRK */ 166 #ifdef BRKINT 167 {"brkint", BRKINT, MD_INP}, 168 #endif /* BRKINT */ 169 #ifdef IGNPAR 170 {"ignpar", IGNPAR, MD_INP}, 171 #endif /* IGNPAR */ 172 #ifdef PARMRK 173 {"parmrk", PARMRK, MD_INP}, 174 #endif /* PARMRK */ 175 #ifdef INPCK 176 {"inpck", INPCK, MD_INP}, 177 #endif /* INPCK */ 178 #ifdef ISTRIP 179 {"istrip", ISTRIP, MD_INP}, 180 #endif /* ISTRIP */ 181 #ifdef INLCR 182 {"inlcr", INLCR, MD_INP}, 183 #endif /* INLCR */ 184 #ifdef IGNCR 185 {"igncr", IGNCR, MD_INP}, 186 #endif /* IGNCR */ 187 #ifdef ICRNL 188 {"icrnl", ICRNL, MD_INP}, 189 #endif /* ICRNL */ 190 #ifdef IUCLC 191 {"iuclc", IUCLC, MD_INP}, 192 #endif /* IUCLC */ 193 #ifdef IXON 194 {"ixon", IXON, MD_INP}, 195 #endif /* IXON */ 196 #ifdef IXANY 197 {"ixany", IXANY, MD_INP}, 198 #endif /* IXANY */ 199 #ifdef IXOFF 200 {"ixoff", IXOFF, MD_INP}, 201 #endif /* IXOFF */ 202 #ifdef IMAXBEL 203 {"imaxbel", IMAXBEL, MD_INP}, 204 #endif /* IMAXBEL */ 205 206 #ifdef OPOST 207 {"opost", OPOST, MD_OUT}, 208 #endif /* OPOST */ 209 #ifdef OLCUC 210 {"olcuc", OLCUC, MD_OUT}, 211 #endif /* OLCUC */ 212 #ifdef ONLCR 213 {"onlcr", ONLCR, MD_OUT}, 214 #endif /* ONLCR */ 215 #ifdef OCRNL 216 {"ocrnl", OCRNL, MD_OUT}, 217 #endif /* OCRNL */ 218 #ifdef ONOCR 219 {"onocr", ONOCR, MD_OUT}, 220 #endif /* ONOCR */ 221 #ifdef ONOEOT 222 {"onoeot", ONOEOT, MD_OUT}, 223 #endif /* ONOEOT */ 224 #ifdef ONLRET 225 {"onlret", ONLRET, MD_OUT}, 226 #endif /* ONLRET */ 227 #ifdef OFILL 228 {"ofill", OFILL, MD_OUT}, 229 #endif /* OFILL */ 230 #ifdef OFDEL 231 {"ofdel", OFDEL, MD_OUT}, 232 #endif /* OFDEL */ 233 #ifdef NLDLY 234 {"nldly", NLDLY, MD_OUT}, 235 #endif /* NLDLY */ 236 #ifdef CRDLY 237 {"crdly", CRDLY, MD_OUT}, 238 #endif /* CRDLY */ 239 #ifdef TABDLY 240 {"tabdly", TABDLY, MD_OUT}, 241 #endif /* TABDLY */ 242 #ifdef XTABS 243 {"xtabs", XTABS, MD_OUT}, 244 #endif /* XTABS */ 245 #ifdef BSDLY 246 {"bsdly", BSDLY, MD_OUT}, 247 #endif /* BSDLY */ 248 #ifdef VTDLY 249 {"vtdly", VTDLY, MD_OUT}, 250 #endif /* VTDLY */ 251 #ifdef FFDLY 252 {"ffdly", FFDLY, MD_OUT}, 253 #endif /* FFDLY */ 254 #ifdef PAGEOUT 255 {"pageout", PAGEOUT, MD_OUT}, 256 #endif /* PAGEOUT */ 257 #ifdef WRAP 258 {"wrap", WRAP, MD_OUT}, 259 #endif /* WRAP */ 260 261 #ifdef CIGNORE 262 {"cignore", CIGNORE, MD_CTL}, 263 #endif /* CBAUD */ 264 #ifdef CBAUD 265 {"cbaud", CBAUD, MD_CTL}, 266 #endif /* CBAUD */ 267 #ifdef CSTOPB 268 {"cstopb", CSTOPB, MD_CTL}, 269 #endif /* CSTOPB */ 270 #ifdef CREAD 271 {"cread", CREAD, MD_CTL}, 272 #endif /* CREAD */ 273 #ifdef PARENB 274 {"parenb", PARENB, MD_CTL}, 275 #endif /* PARENB */ 276 #ifdef PARODD 277 {"parodd", PARODD, MD_CTL}, 278 #endif /* PARODD */ 279 #ifdef HUPCL 280 {"hupcl", HUPCL, MD_CTL}, 281 #endif /* HUPCL */ 282 #ifdef CLOCAL 283 {"clocal", CLOCAL, MD_CTL}, 284 #endif /* CLOCAL */ 285 #ifdef LOBLK 286 {"loblk", LOBLK, MD_CTL}, 287 #endif /* LOBLK */ 288 #ifdef CIBAUD 289 {"cibaud", CIBAUD, MD_CTL}, 290 #endif /* CIBAUD */ 291 #ifdef CRTSCTS 292 #ifdef CCTS_OFLOW 293 {"ccts_oflow", CCTS_OFLOW, MD_CTL}, 294 #else 295 {"crtscts", CRTSCTS, MD_CTL}, 296 #endif /* CCTS_OFLOW */ 297 #endif /* CRTSCTS */ 298 #ifdef CRTS_IFLOW 299 {"crts_iflow", CRTS_IFLOW, MD_CTL}, 300 #endif /* CRTS_IFLOW */ 301 #ifdef CDTRCTS 302 {"cdtrcts", CDTRCTS, MD_CTL}, 303 #endif /* CDTRCTS */ 304 #ifdef MDMBUF 305 {"mdmbuf", MDMBUF, MD_CTL}, 306 #endif /* MDMBUF */ 307 #ifdef RCV1EN 308 {"rcv1en", RCV1EN, MD_CTL}, 309 #endif /* RCV1EN */ 310 #ifdef XMT1EN 311 {"xmt1en", XMT1EN, MD_CTL}, 312 #endif /* XMT1EN */ 313 314 #ifdef ISIG 315 {"isig", ISIG, MD_LIN}, 316 #endif /* ISIG */ 317 #ifdef ICANON 318 {"icanon", ICANON, MD_LIN}, 319 #endif /* ICANON */ 320 #ifdef XCASE 321 {"xcase", XCASE, MD_LIN}, 322 #endif /* XCASE */ 323 #ifdef ECHO 324 {"echo", ECHO, MD_LIN}, 325 #endif /* ECHO */ 326 #ifdef ECHOE 327 {"echoe", ECHOE, MD_LIN}, 328 #endif /* ECHOE */ 329 #ifdef ECHOK 330 {"echok", ECHOK, MD_LIN}, 331 #endif /* ECHOK */ 332 #ifdef ECHONL 333 {"echonl", ECHONL, MD_LIN}, 334 #endif /* ECHONL */ 335 #ifdef NOFLSH 336 {"noflsh", NOFLSH, MD_LIN}, 337 #endif /* NOFLSH */ 338 #ifdef TOSTOP 339 {"tostop", TOSTOP, MD_LIN}, 340 #endif /* TOSTOP */ 341 #ifdef ECHOCTL 342 {"echoctl", ECHOCTL, MD_LIN}, 343 #endif /* ECHOCTL */ 344 #ifdef ECHOPRT 345 {"echoprt", ECHOPRT, MD_LIN}, 346 #endif /* ECHOPRT */ 347 #ifdef ECHOKE 348 {"echoke", ECHOKE, MD_LIN}, 349 #endif /* ECHOKE */ 350 #ifdef DEFECHO 351 {"defecho", DEFECHO, MD_LIN}, 352 #endif /* DEFECHO */ 353 #ifdef FLUSHO 354 {"flusho", FLUSHO, MD_LIN}, 355 #endif /* FLUSHO */ 356 #ifdef PENDIN 357 {"pendin", PENDIN, MD_LIN}, 358 #endif /* PENDIN */ 359 #ifdef IEXTEN 360 {"iexten", IEXTEN, MD_LIN}, 361 #endif /* IEXTEN */ 362 #ifdef NOKERNINFO 363 {"nokerninfo", NOKERNINFO, MD_LIN}, 364 #endif /* NOKERNINFO */ 365 #ifdef ALTWERASE 366 {"altwerase", ALTWERASE, MD_LIN}, 367 #endif /* ALTWERASE */ 368 #ifdef EXTPROC 369 {"extproc", EXTPROC, MD_LIN}, 370 #endif /* EXTPROC */ 371 372 #if defined(VINTR) 373 {"intr", C_SH(C_INTR), MD_CHAR}, 374 #endif /* VINTR */ 375 #if defined(VQUIT) 376 {"quit", C_SH(C_QUIT), MD_CHAR}, 377 #endif /* VQUIT */ 378 #if defined(VERASE) 379 {"erase", C_SH(C_ERASE), MD_CHAR}, 380 #endif /* VERASE */ 381 #if defined(VKILL) 382 {"kill", C_SH(C_KILL), MD_CHAR}, 383 #endif /* VKILL */ 384 #if defined(VEOF) 385 {"eof", C_SH(C_EOF), MD_CHAR}, 386 #endif /* VEOF */ 387 #if defined(VEOL) 388 {"eol", C_SH(C_EOL), MD_CHAR}, 389 #endif /* VEOL */ 390 #if defined(VEOL2) 391 {"eol2", C_SH(C_EOL2), MD_CHAR}, 392 #endif /* VEOL2 */ 393 #if defined(VSWTCH) 394 {"swtch", C_SH(C_SWTCH), MD_CHAR}, 395 #endif /* VSWTCH */ 396 #if defined(VDSWTCH) 397 {"dswtch", C_SH(C_DSWTCH), MD_CHAR}, 398 #endif /* VDSWTCH */ 399 #if defined(VERASE2) 400 {"erase2", C_SH(C_ERASE2), MD_CHAR}, 401 #endif /* VERASE2 */ 402 #if defined(VSTART) 403 {"start", C_SH(C_START), MD_CHAR}, 404 #endif /* VSTART */ 405 #if defined(VSTOP) 406 {"stop", C_SH(C_STOP), MD_CHAR}, 407 #endif /* VSTOP */ 408 #if defined(VWERASE) 409 {"werase", C_SH(C_WERASE), MD_CHAR}, 410 #endif /* VWERASE */ 411 #if defined(VSUSP) 412 {"susp", C_SH(C_SUSP), MD_CHAR}, 413 #endif /* VSUSP */ 414 #if defined(VDSUSP) 415 {"dsusp", C_SH(C_DSUSP), MD_CHAR}, 416 #endif /* VDSUSP */ 417 #if defined(VREPRINT) 418 {"reprint", C_SH(C_REPRINT), MD_CHAR}, 419 #endif /* VREPRINT */ 420 #if defined(VDISCARD) 421 {"discard", C_SH(C_DISCARD), MD_CHAR}, 422 #endif /* VDISCARD */ 423 #if defined(VLNEXT) 424 {"lnext", C_SH(C_LNEXT), MD_CHAR}, 425 #endif /* VLNEXT */ 426 #if defined(VSTATUS) 427 {"status", C_SH(C_STATUS), MD_CHAR}, 428 #endif /* VSTATUS */ 429 #if defined(VPAGE) 430 {"page", C_SH(C_PAGE), MD_CHAR}, 431 #endif /* VPAGE */ 432 #if defined(VPGOFF) 433 {"pgoff", C_SH(C_PGOFF), MD_CHAR}, 434 #endif /* VPGOFF */ 435 #if defined(VKILL2) 436 {"kill2", C_SH(C_KILL2), MD_CHAR}, 437 #endif /* VKILL2 */ 438 #if defined(VBRK) 439 {"brk", C_SH(C_BRK), MD_CHAR}, 440 #endif /* VBRK */ 441 #if defined(VMIN) 442 {"min", C_SH(C_MIN), MD_CHAR}, 443 #endif /* VMIN */ 444 #if defined(VTIME) 445 {"time", C_SH(C_TIME), MD_CHAR}, 446 #endif /* VTIME */ 447 {NULL, 0, -1}, 448 }; 449 450 451 452 #define tty_getty(el, td) tcgetattr((el)->el_infd, (td)) 453 #define tty_setty(el, td) tcsetattr((el)->el_infd, TCSADRAIN, (td)) 454 455 #define tty__gettabs(td) ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1) 456 #define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8) 457 #define tty__cooked_mode(td) ((td)->c_lflag & ICANON) 458 459 private void tty__getchar(struct termios *, unsigned char *); 460 private void tty__setchar(struct termios *, unsigned char *); 461 private speed_t tty__getspeed(struct termios *); 462 private int tty_setup(EditLine *); 463 464 #define t_qu t_ts 465 466 467 /* tty_setup(): 468 * Get the tty parameters and initialize the editing state 469 */ 470 private int 471 tty_setup(EditLine *el) 472 { 473 int rst = 1; 474 475 if (el->el_flags & EDIT_DISABLED) 476 return (0); 477 478 if (tty_getty(el, &el->el_tty.t_ed) == -1) { 479 #ifdef DEBUG_TTY 480 (void) fprintf(el->el_errfile, 481 "tty_setup: tty_getty: %s\n", strerror(errno)); 482 #endif /* DEBUG_TTY */ 483 return (-1); 484 } 485 el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed; 486 487 el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex); 488 el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex); 489 el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex); 490 491 el->el_tty.t_ex.c_iflag &= ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask; 492 el->el_tty.t_ex.c_iflag |= el->el_tty.t_t[EX_IO][MD_INP].t_setmask; 493 494 el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask; 495 el->el_tty.t_ex.c_oflag |= el->el_tty.t_t[EX_IO][MD_OUT].t_setmask; 496 497 el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask; 498 el->el_tty.t_ex.c_cflag |= el->el_tty.t_t[EX_IO][MD_CTL].t_setmask; 499 500 el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask; 501 el->el_tty.t_ex.c_lflag |= el->el_tty.t_t[EX_IO][MD_LIN].t_setmask; 502 503 /* 504 * Reset the tty chars to reasonable defaults 505 * If they are disabled, then enable them. 506 */ 507 if (rst) { 508 if (tty__cooked_mode(&el->el_tty.t_ts)) { 509 tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]); 510 /* 511 * Don't affect CMIN and CTIME for the editor mode 512 */ 513 for (rst = 0; rst < C_NCC - 2; rst++) 514 if (el->el_tty.t_c[TS_IO][rst] != 515 el->el_tty.t_vdisable 516 && el->el_tty.t_c[ED_IO][rst] != 517 el->el_tty.t_vdisable) 518 el->el_tty.t_c[ED_IO][rst] = 519 el->el_tty.t_c[TS_IO][rst]; 520 for (rst = 0; rst < C_NCC; rst++) 521 if (el->el_tty.t_c[TS_IO][rst] != 522 el->el_tty.t_vdisable) 523 el->el_tty.t_c[EX_IO][rst] = 524 el->el_tty.t_c[TS_IO][rst]; 525 } 526 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]); 527 if (tty_setty(el, &el->el_tty.t_ex) == -1) { 528 #ifdef DEBUG_TTY 529 (void) fprintf(el->el_errfile, 530 "tty_setup: tty_setty: %s\n", 531 strerror(errno)); 532 #endif /* DEBUG_TTY */ 533 return (-1); 534 } 535 } else 536 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]); 537 538 el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask; 539 el->el_tty.t_ed.c_iflag |= el->el_tty.t_t[ED_IO][MD_INP].t_setmask; 540 541 el->el_tty.t_ed.c_oflag &= ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask; 542 el->el_tty.t_ed.c_oflag |= el->el_tty.t_t[ED_IO][MD_OUT].t_setmask; 543 544 el->el_tty.t_ed.c_cflag &= ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask; 545 el->el_tty.t_ed.c_cflag |= el->el_tty.t_t[ED_IO][MD_CTL].t_setmask; 546 547 el->el_tty.t_ed.c_lflag &= ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask; 548 el->el_tty.t_ed.c_lflag |= el->el_tty.t_t[ED_IO][MD_LIN].t_setmask; 549 550 tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]); 551 tty_bind_char(el, 1); 552 return (0); 553 } 554 555 protected int 556 tty_init(EditLine *el) 557 { 558 559 el->el_tty.t_mode = EX_IO; 560 el->el_tty.t_vdisable = _POSIX_VDISABLE; 561 (void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t)); 562 (void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t)); 563 return (tty_setup(el)); 564 } 565 566 567 /* tty_end(): 568 * Restore the tty to its original settings 569 */ 570 protected void 571 /*ARGSUSED*/ 572 tty_end(EditLine *el) 573 { 574 575 /* XXX: Maybe reset to an initial state? */ 576 } 577 578 579 /* tty__getspeed(): 580 * Get the tty speed 581 */ 582 private speed_t 583 tty__getspeed(struct termios *td) 584 { 585 speed_t spd; 586 587 if ((spd = cfgetispeed(td)) == 0) 588 spd = cfgetospeed(td); 589 return (spd); 590 } 591 592 593 /* tty__getchar(): 594 * Get the tty characters 595 */ 596 private void 597 tty__getchar(struct termios *td, unsigned char *s) 598 { 599 600 #ifdef VINTR 601 s[C_INTR] = td->c_cc[VINTR]; 602 #endif /* VINTR */ 603 #ifdef VQUIT 604 s[C_QUIT] = td->c_cc[VQUIT]; 605 #endif /* VQUIT */ 606 #ifdef VERASE 607 s[C_ERASE] = td->c_cc[VERASE]; 608 #endif /* VERASE */ 609 #ifdef VKILL 610 s[C_KILL] = td->c_cc[VKILL]; 611 #endif /* VKILL */ 612 #ifdef VEOF 613 s[C_EOF] = td->c_cc[VEOF]; 614 #endif /* VEOF */ 615 #ifdef VEOL 616 s[C_EOL] = td->c_cc[VEOL]; 617 #endif /* VEOL */ 618 #ifdef VEOL2 619 s[C_EOL2] = td->c_cc[VEOL2]; 620 #endif /* VEOL2 */ 621 #ifdef VSWTCH 622 s[C_SWTCH] = td->c_cc[VSWTCH]; 623 #endif /* VSWTCH */ 624 #ifdef VDSWTCH 625 s[C_DSWTCH] = td->c_cc[VDSWTCH]; 626 #endif /* VDSWTCH */ 627 #ifdef VERASE2 628 s[C_ERASE2] = td->c_cc[VERASE2]; 629 #endif /* VERASE2 */ 630 #ifdef VSTART 631 s[C_START] = td->c_cc[VSTART]; 632 #endif /* VSTART */ 633 #ifdef VSTOP 634 s[C_STOP] = td->c_cc[VSTOP]; 635 #endif /* VSTOP */ 636 #ifdef VWERASE 637 s[C_WERASE] = td->c_cc[VWERASE]; 638 #endif /* VWERASE */ 639 #ifdef VSUSP 640 s[C_SUSP] = td->c_cc[VSUSP]; 641 #endif /* VSUSP */ 642 #ifdef VDSUSP 643 s[C_DSUSP] = td->c_cc[VDSUSP]; 644 #endif /* VDSUSP */ 645 #ifdef VREPRINT 646 s[C_REPRINT] = td->c_cc[VREPRINT]; 647 #endif /* VREPRINT */ 648 #ifdef VDISCARD 649 s[C_DISCARD] = td->c_cc[VDISCARD]; 650 #endif /* VDISCARD */ 651 #ifdef VLNEXT 652 s[C_LNEXT] = td->c_cc[VLNEXT]; 653 #endif /* VLNEXT */ 654 #ifdef VSTATUS 655 s[C_STATUS] = td->c_cc[VSTATUS]; 656 #endif /* VSTATUS */ 657 #ifdef VPAGE 658 s[C_PAGE] = td->c_cc[VPAGE]; 659 #endif /* VPAGE */ 660 #ifdef VPGOFF 661 s[C_PGOFF] = td->c_cc[VPGOFF]; 662 #endif /* VPGOFF */ 663 #ifdef VKILL2 664 s[C_KILL2] = td->c_cc[VKILL2]; 665 #endif /* KILL2 */ 666 #ifdef VMIN 667 s[C_MIN] = td->c_cc[VMIN]; 668 #endif /* VMIN */ 669 #ifdef VTIME 670 s[C_TIME] = td->c_cc[VTIME]; 671 #endif /* VTIME */ 672 } /* tty__getchar */ 673 674 675 /* tty__setchar(): 676 * Set the tty characters 677 */ 678 private void 679 tty__setchar(struct termios *td, unsigned char *s) 680 { 681 682 #ifdef VINTR 683 td->c_cc[VINTR] = s[C_INTR]; 684 #endif /* VINTR */ 685 #ifdef VQUIT 686 td->c_cc[VQUIT] = s[C_QUIT]; 687 #endif /* VQUIT */ 688 #ifdef VERASE 689 td->c_cc[VERASE] = s[C_ERASE]; 690 #endif /* VERASE */ 691 #ifdef VKILL 692 td->c_cc[VKILL] = s[C_KILL]; 693 #endif /* VKILL */ 694 #ifdef VEOF 695 td->c_cc[VEOF] = s[C_EOF]; 696 #endif /* VEOF */ 697 #ifdef VEOL 698 td->c_cc[VEOL] = s[C_EOL]; 699 #endif /* VEOL */ 700 #ifdef VEOL2 701 td->c_cc[VEOL2] = s[C_EOL2]; 702 #endif /* VEOL2 */ 703 #ifdef VSWTCH 704 td->c_cc[VSWTCH] = s[C_SWTCH]; 705 #endif /* VSWTCH */ 706 #ifdef VDSWTCH 707 td->c_cc[VDSWTCH] = s[C_DSWTCH]; 708 #endif /* VDSWTCH */ 709 #ifdef VERASE2 710 td->c_cc[VERASE2] = s[C_ERASE2]; 711 #endif /* VERASE2 */ 712 #ifdef VSTART 713 td->c_cc[VSTART] = s[C_START]; 714 #endif /* VSTART */ 715 #ifdef VSTOP 716 td->c_cc[VSTOP] = s[C_STOP]; 717 #endif /* VSTOP */ 718 #ifdef VWERASE 719 td->c_cc[VWERASE] = s[C_WERASE]; 720 #endif /* VWERASE */ 721 #ifdef VSUSP 722 td->c_cc[VSUSP] = s[C_SUSP]; 723 #endif /* VSUSP */ 724 #ifdef VDSUSP 725 td->c_cc[VDSUSP] = s[C_DSUSP]; 726 #endif /* VDSUSP */ 727 #ifdef VREPRINT 728 td->c_cc[VREPRINT] = s[C_REPRINT]; 729 #endif /* VREPRINT */ 730 #ifdef VDISCARD 731 td->c_cc[VDISCARD] = s[C_DISCARD]; 732 #endif /* VDISCARD */ 733 #ifdef VLNEXT 734 td->c_cc[VLNEXT] = s[C_LNEXT]; 735 #endif /* VLNEXT */ 736 #ifdef VSTATUS 737 td->c_cc[VSTATUS] = s[C_STATUS]; 738 #endif /* VSTATUS */ 739 #ifdef VPAGE 740 td->c_cc[VPAGE] = s[C_PAGE]; 741 #endif /* VPAGE */ 742 #ifdef VPGOFF 743 td->c_cc[VPGOFF] = s[C_PGOFF]; 744 #endif /* VPGOFF */ 745 #ifdef VKILL2 746 td->c_cc[VKILL2] = s[C_KILL2]; 747 #endif /* VKILL2 */ 748 #ifdef VMIN 749 td->c_cc[VMIN] = s[C_MIN]; 750 #endif /* VMIN */ 751 #ifdef VTIME 752 td->c_cc[VTIME] = s[C_TIME]; 753 #endif /* VTIME */ 754 } /* tty__setchar */ 755 756 757 /* tty_bind_char(): 758 * Rebind the editline functions 759 */ 760 protected void 761 tty_bind_char(EditLine *el, int force) 762 { 763 764 unsigned char *t_n = el->el_tty.t_c[ED_IO]; 765 unsigned char *t_o = el->el_tty.t_ed.c_cc; 766 unsigned char new[2], old[2]; 767 const ttymap_t *tp; 768 el_action_t *map, *alt; 769 const el_action_t *dmap, *dalt; 770 new[1] = old[1] = '\0'; 771 772 map = el->el_map.key; 773 alt = el->el_map.alt; 774 if (el->el_map.type == MAP_VI) { 775 dmap = el->el_map.vii; 776 dalt = el->el_map.vic; 777 } else { 778 dmap = el->el_map.emacs; 779 dalt = NULL; 780 } 781 782 for (tp = tty_map; tp->nch != -1; tp++) { 783 new[0] = t_n[tp->nch]; 784 old[0] = t_o[tp->och]; 785 if (new[0] == old[0] && !force) 786 continue; 787 /* Put the old default binding back, and set the new binding */ 788 key_clear(el, map, (char *)old); 789 map[old[0]] = dmap[old[0]]; 790 key_clear(el, map, (char *)new); 791 /* MAP_VI == 1, MAP_EMACS == 0... */ 792 map[new[0]] = tp->bind[el->el_map.type]; 793 if (dalt) { 794 key_clear(el, alt, (char *)old); 795 alt[old[0]] = dalt[old[0]]; 796 key_clear(el, alt, (char *)new); 797 alt[new[0]] = tp->bind[el->el_map.type + 1]; 798 } 799 } 800 } 801 802 803 /* tty_rawmode(): 804 * Set terminal into 1 character at a time mode. 805 */ 806 protected int 807 tty_rawmode(EditLine *el) 808 { 809 810 if (el->el_tty.t_mode == ED_IO || el->el_tty.t_mode == QU_IO) 811 return (0); 812 813 if (el->el_flags & EDIT_DISABLED) 814 return (0); 815 816 if (tty_getty(el, &el->el_tty.t_ts) == -1) { 817 #ifdef DEBUG_TTY 818 (void) fprintf(el->el_errfile, "tty_rawmode: tty_getty: %s\n", 819 strerror(errno)); 820 #endif /* DEBUG_TTY */ 821 return (-1); 822 } 823 /* 824 * We always keep up with the eight bit setting and the speed of the 825 * tty. But only we only believe changes that are made to cooked mode! 826 */ 827 el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts); 828 el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts); 829 830 if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed || 831 tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) { 832 (void) cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed); 833 (void) cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed); 834 (void) cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed); 835 (void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed); 836 } 837 if (tty__cooked_mode(&el->el_tty.t_ts)) { 838 if (el->el_tty.t_ts.c_cflag != el->el_tty.t_ex.c_cflag) { 839 el->el_tty.t_ex.c_cflag = 840 el->el_tty.t_ts.c_cflag; 841 el->el_tty.t_ex.c_cflag &= 842 ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask; 843 el->el_tty.t_ex.c_cflag |= 844 el->el_tty.t_t[EX_IO][MD_CTL].t_setmask; 845 846 el->el_tty.t_ed.c_cflag = 847 el->el_tty.t_ts.c_cflag; 848 el->el_tty.t_ed.c_cflag &= 849 ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask; 850 el->el_tty.t_ed.c_cflag |= 851 el->el_tty.t_t[ED_IO][MD_CTL].t_setmask; 852 } 853 if ((el->el_tty.t_ts.c_lflag != el->el_tty.t_ex.c_lflag) && 854 (el->el_tty.t_ts.c_lflag != el->el_tty.t_ed.c_lflag)) { 855 el->el_tty.t_ex.c_lflag = 856 el->el_tty.t_ts.c_lflag; 857 el->el_tty.t_ex.c_lflag &= 858 ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask; 859 el->el_tty.t_ex.c_lflag |= 860 el->el_tty.t_t[EX_IO][MD_LIN].t_setmask; 861 862 el->el_tty.t_ed.c_lflag = 863 el->el_tty.t_ts.c_lflag; 864 el->el_tty.t_ed.c_lflag &= 865 ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask; 866 el->el_tty.t_ed.c_lflag |= 867 el->el_tty.t_t[ED_IO][MD_LIN].t_setmask; 868 } 869 if ((el->el_tty.t_ts.c_iflag != el->el_tty.t_ex.c_iflag) && 870 (el->el_tty.t_ts.c_iflag != el->el_tty.t_ed.c_iflag)) { 871 el->el_tty.t_ex.c_iflag = 872 el->el_tty.t_ts.c_iflag; 873 el->el_tty.t_ex.c_iflag &= 874 ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask; 875 el->el_tty.t_ex.c_iflag |= 876 el->el_tty.t_t[EX_IO][MD_INP].t_setmask; 877 878 el->el_tty.t_ed.c_iflag = 879 el->el_tty.t_ts.c_iflag; 880 el->el_tty.t_ed.c_iflag &= 881 ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask; 882 el->el_tty.t_ed.c_iflag |= 883 el->el_tty.t_t[ED_IO][MD_INP].t_setmask; 884 } 885 if ((el->el_tty.t_ts.c_oflag != el->el_tty.t_ex.c_oflag) && 886 (el->el_tty.t_ts.c_oflag != el->el_tty.t_ed.c_oflag)) { 887 el->el_tty.t_ex.c_oflag = 888 el->el_tty.t_ts.c_oflag; 889 el->el_tty.t_ex.c_oflag &= 890 ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask; 891 el->el_tty.t_ex.c_oflag |= 892 el->el_tty.t_t[EX_IO][MD_OUT].t_setmask; 893 894 el->el_tty.t_ed.c_oflag = 895 el->el_tty.t_ts.c_oflag; 896 el->el_tty.t_ed.c_oflag &= 897 ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask; 898 el->el_tty.t_ed.c_oflag |= 899 el->el_tty.t_t[ED_IO][MD_OUT].t_setmask; 900 } 901 if (tty__gettabs(&el->el_tty.t_ex) == 0) 902 el->el_tty.t_tabs = 0; 903 else 904 el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0; 905 906 { 907 int i; 908 909 tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]); 910 /* 911 * Check if the user made any changes. 912 * If he did, then propagate the changes to the 913 * edit and execute data structures. 914 */ 915 for (i = 0; i < C_NCC; i++) 916 if (el->el_tty.t_c[TS_IO][i] != 917 el->el_tty.t_c[EX_IO][i]) 918 break; 919 920 if (i != C_NCC) { 921 /* 922 * Propagate changes only to the unprotected 923 * chars that have been modified just now. 924 */ 925 for (i = 0; i < C_NCC; i++) { 926 if (!((el->el_tty.t_t[ED_IO][MD_CHAR].t_setmask & C_SH(i))) 927 && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i])) 928 el->el_tty.t_c[ED_IO][i] = el->el_tty.t_c[TS_IO][i]; 929 if (el->el_tty.t_t[ED_IO][MD_CHAR].t_clrmask & C_SH(i)) 930 el->el_tty.t_c[ED_IO][i] = el->el_tty.t_vdisable; 931 } 932 tty_bind_char(el, 0); 933 tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]); 934 935 for (i = 0; i < C_NCC; i++) { 936 if (!((el->el_tty.t_t[EX_IO][MD_CHAR].t_setmask & C_SH(i))) 937 && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i])) 938 el->el_tty.t_c[EX_IO][i] = el->el_tty.t_c[TS_IO][i]; 939 if (el->el_tty.t_t[EX_IO][MD_CHAR].t_clrmask & C_SH(i)) 940 el->el_tty.t_c[EX_IO][i] = el->el_tty.t_vdisable; 941 } 942 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]); 943 } 944 } 945 } 946 if (tty_setty(el, &el->el_tty.t_ed) == -1) { 947 #ifdef DEBUG_TTY 948 (void) fprintf(el->el_errfile, "tty_rawmode: tty_setty: %s\n", 949 strerror(errno)); 950 #endif /* DEBUG_TTY */ 951 return (-1); 952 } 953 el->el_tty.t_mode = ED_IO; 954 return (0); 955 } 956 957 958 /* tty_cookedmode(): 959 * Set the tty back to normal mode 960 */ 961 protected int 962 tty_cookedmode(EditLine *el) 963 { /* set tty in normal setup */ 964 965 if (el->el_tty.t_mode == EX_IO) 966 return (0); 967 968 if (el->el_flags & EDIT_DISABLED) 969 return (0); 970 971 if (tty_setty(el, &el->el_tty.t_ex) == -1) { 972 #ifdef DEBUG_TTY 973 (void) fprintf(el->el_errfile, 974 "tty_cookedmode: tty_setty: %s\n", 975 strerror(errno)); 976 #endif /* DEBUG_TTY */ 977 return (-1); 978 } 979 el->el_tty.t_mode = EX_IO; 980 return (0); 981 } 982 983 984 /* tty_quotemode(): 985 * Turn on quote mode 986 */ 987 protected int 988 tty_quotemode(EditLine *el) 989 { 990 if (el->el_tty.t_mode == QU_IO) 991 return (0); 992 993 el->el_tty.t_qu = el->el_tty.t_ed; 994 995 el->el_tty.t_qu.c_iflag &= ~el->el_tty.t_t[QU_IO][MD_INP].t_clrmask; 996 el->el_tty.t_qu.c_iflag |= el->el_tty.t_t[QU_IO][MD_INP].t_setmask; 997 998 el->el_tty.t_qu.c_oflag &= ~el->el_tty.t_t[QU_IO][MD_OUT].t_clrmask; 999 el->el_tty.t_qu.c_oflag |= el->el_tty.t_t[QU_IO][MD_OUT].t_setmask; 1000 1001 el->el_tty.t_qu.c_cflag &= ~el->el_tty.t_t[QU_IO][MD_CTL].t_clrmask; 1002 el->el_tty.t_qu.c_cflag |= el->el_tty.t_t[QU_IO][MD_CTL].t_setmask; 1003 1004 el->el_tty.t_qu.c_lflag &= ~el->el_tty.t_t[QU_IO][MD_LIN].t_clrmask; 1005 el->el_tty.t_qu.c_lflag |= el->el_tty.t_t[QU_IO][MD_LIN].t_setmask; 1006 1007 if (tty_setty(el, &el->el_tty.t_qu) == -1) { 1008 #ifdef DEBUG_TTY 1009 (void) fprintf(el->el_errfile, "QuoteModeOn: tty_setty: %s\n", 1010 strerror(errno)); 1011 #endif /* DEBUG_TTY */ 1012 return (-1); 1013 } 1014 el->el_tty.t_mode = QU_IO; 1015 return (0); 1016 } 1017 1018 1019 /* tty_noquotemode(): 1020 * Turn off quote mode 1021 */ 1022 protected int 1023 tty_noquotemode(EditLine *el) 1024 { 1025 1026 if (el->el_tty.t_mode != QU_IO) 1027 return (0); 1028 if (tty_setty(el, &el->el_tty.t_ed) == -1) { 1029 #ifdef DEBUG_TTY 1030 (void) fprintf(el->el_errfile, "QuoteModeOff: tty_setty: %s\n", 1031 strerror(errno)); 1032 #endif /* DEBUG_TTY */ 1033 return (-1); 1034 } 1035 el->el_tty.t_mode = ED_IO; 1036 return (0); 1037 } 1038 1039 1040 /* tty_stty(): 1041 * Stty builtin 1042 */ 1043 protected int 1044 /*ARGSUSED*/ 1045 tty_stty(EditLine *el, int argc, char **argv) 1046 { 1047 const ttymodes_t *m; 1048 char x, *d; 1049 int aflag = 0; 1050 char *s; 1051 char *name; 1052 int z = EX_IO; 1053 1054 if (argv == NULL) 1055 return (-1); 1056 name = *argv++; 1057 1058 while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0') 1059 switch (argv[0][1]) { 1060 case 'a': 1061 aflag++; 1062 argv++; 1063 break; 1064 case 'd': 1065 argv++; 1066 z = ED_IO; 1067 break; 1068 case 'x': 1069 argv++; 1070 z = EX_IO; 1071 break; 1072 case 'q': 1073 argv++; 1074 z = QU_IO; 1075 break; 1076 default: 1077 (void) fprintf(el->el_errfile, 1078 "%s: Unknown switch `%c'.\n", 1079 name, argv[0][1]); 1080 return (-1); 1081 } 1082 1083 if (!argv || !*argv) { 1084 int i = -1; 1085 int len = 0, st = 0, cu; 1086 for (m = ttymodes; m->m_name; m++) { 1087 if (m->m_type != i) { 1088 (void) fprintf(el->el_outfile, "%s%s", 1089 i != -1 ? "\n" : "", 1090 el->el_tty.t_t[z][m->m_type].t_name); 1091 i = m->m_type; 1092 st = len = 1093 strlen(el->el_tty.t_t[z][m->m_type].t_name); 1094 } 1095 x = (el->el_tty.t_t[z][i].t_setmask & m->m_value) 1096 ? '+' : '\0'; 1097 x = (el->el_tty.t_t[z][i].t_clrmask & m->m_value) 1098 ? '-' : x; 1099 1100 if (x != '\0' || aflag) { 1101 1102 cu = strlen(m->m_name) + (x != '\0') + 1; 1103 1104 if (len + cu >= el->el_term.t_size.h) { 1105 (void) fprintf(el->el_outfile, "\n%*s", 1106 st, ""); 1107 len = st + cu; 1108 } else 1109 len += cu; 1110 1111 if (x != '\0') 1112 (void) fprintf(el->el_outfile, "%c%s ", 1113 x, m->m_name); 1114 else 1115 (void) fprintf(el->el_outfile, "%s ", 1116 m->m_name); 1117 } 1118 } 1119 (void) fprintf(el->el_outfile, "\n"); 1120 return (0); 1121 } 1122 while (argv && (s = *argv++)) { 1123 switch (*s) { 1124 case '+': 1125 case '-': 1126 x = *s++; 1127 break; 1128 default: 1129 x = '\0'; 1130 break; 1131 } 1132 d = s; 1133 for (m = ttymodes; m->m_name; m++) 1134 if (strcmp(m->m_name, d) == 0) 1135 break; 1136 1137 if (!m->m_name) { 1138 (void) fprintf(el->el_errfile, 1139 "%s: Invalid argument `%s'.\n", name, d); 1140 return (-1); 1141 } 1142 switch (x) { 1143 case '+': 1144 el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value; 1145 el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value; 1146 break; 1147 case '-': 1148 el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value; 1149 el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value; 1150 break; 1151 default: 1152 el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value; 1153 el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value; 1154 break; 1155 } 1156 } 1157 return (0); 1158 } 1159 1160 1161 #ifdef notyet 1162 /* tty_printchar(): 1163 * DEbugging routine to print the tty characters 1164 */ 1165 private void 1166 tty_printchar(EditLine *el, unsigned char *s) 1167 { 1168 ttyperm_t *m; 1169 int i; 1170 1171 for (i = 0; i < C_NCC; i++) { 1172 for (m = el->el_tty.t_t; m->m_name; m++) 1173 if (m->m_type == MD_CHAR && C_SH(i) == m->m_value) 1174 break; 1175 if (m->m_name) 1176 (void) fprintf(el->el_errfile, "%s ^%c ", 1177 m->m_name, s[i] + 'A' - 1); 1178 if (i % 5 == 0) 1179 (void) fprintf(el->el_errfile, "\n"); 1180 } 1181 (void) fprintf(el->el_errfile, "\n"); 1182 } 1183 #endif /* notyet */ 1184