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