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