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