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