2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Christos Zoulas of Cornell University.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 #if !defined(lint) && !defined(SCCSID)
38 static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) 6/4/93";
39 #endif /* not lint && not SCCSID */
42 * tty.c: tty interface stuff
48 typedef struct ttymodes_t {
54 typedef struct ttymap_t {
55 int nch, och; /* Internal and termio rep of chars */
56 el_action_t bind[3]; /* emacs, vi, and vi-cmd */
60 private ttyperm_t ttyperm = {
62 { "iflag:", ICRNL, (INLCR|IGNCR) },
63 { "oflag:", (OPOST|ONLCR), ONLRET },
65 { "lflag:", (ISIG|ICANON|ECHO|ECHOE|ECHOCTL|IEXTEN),
66 (NOFLSH|ECHONL|EXTPROC|FLUSHO) },
70 { "iflag:", (INLCR|ICRNL), IGNCR },
71 { "oflag:", (OPOST|ONLCR), ONLRET },
74 (NOFLSH|ICANON|ECHO|ECHOK|ECHONL|EXTPROC|IEXTEN|FLUSHO) },
75 { "chars:", (C_SH(C_MIN)|C_SH(C_TIME)|C_SH(C_SWTCH)|C_SH(C_DSWTCH)|
76 C_SH(C_SUSP)|C_SH(C_DSUSP)|C_SH(C_EOL)|C_SH(C_DISCARD)|
77 C_SH(C_PGOFF)|C_SH(C_PAGE)|C_SH(C_STATUS)), 0 }
80 { "iflag:", 0, IXON | IXOFF | INLCR | ICRNL },
83 { "lflag:", 0, ISIG | IEXTEN },
88 private ttychar_t ttychar = {
90 CINTR, CQUIT, CERASE, CKILL,
91 CEOF, CEOL, CEOL2, CSWTCH,
92 CDSWTCH, CERASE2, CSTART, CSTOP,
93 CWERASE, CSUSP, CDSUSP, CREPRINT,
94 CDISCARD, CLNEXT, CSTATUS, CPAGE,
95 CPGOFF, CKILL2, CBRK, CMIN,
99 CINTR, CQUIT, CERASE, CKILL,
100 _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
101 _POSIX_VDISABLE, CERASE2, CSTART, CSTOP,
102 _POSIX_VDISABLE, CSUSP, _POSIX_VDISABLE, _POSIX_VDISABLE,
103 CDISCARD, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
104 _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 1,
118 private ttymap_t tty_map[] = {
121 { ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR } },
125 { ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR } },
129 { EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED } },
133 { EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED } },
137 { EM_DELETE_OR_LIST, VI_LIST_OR_EOF, ED_UNASSIGNED } },
141 { ED_DELETE_PREV_WORD, ED_DELETE_PREV_WORD, ED_PREV_WORD } },
144 { C_REPRINT, VREPRINT,
145 { ED_REDISPLAY, ED_INSERT, ED_REDISPLAY } },
146 #endif /* VREPRINT */
149 { ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED } },
152 { ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED } }
155 private ttymodes_t ttymodes[] = {
157 { "ignbrk", IGNBRK, M_INP },
160 { "brkint", BRKINT, M_INP },
163 { "ignpar", IGNPAR, M_INP },
166 { "parmrk", PARMRK, M_INP },
169 { "inpck", INPCK, M_INP },
172 { "istrip", ISTRIP, M_INP },
175 { "inlcr", INLCR, M_INP },
178 { "igncr", IGNCR, M_INP },
181 { "icrnl", ICRNL, M_INP },
184 { "iuclc", IUCLC, M_INP },
187 { "ixon", IXON, M_INP },
190 { "ixany", IXANY, M_INP },
193 { "ixoff", IXOFF, M_INP },
196 { "imaxbel",IMAXBEL,M_INP },
197 # endif /* IMAXBEL */
200 { "opost", OPOST, M_OUT },
203 { "olcuc", OLCUC, M_OUT },
206 { "onlcr", ONLCR, M_OUT },
209 { "ocrnl", OCRNL, M_OUT },
212 { "onocr", ONOCR, M_OUT },
215 { "onoeot", ONOEOT, M_OUT },
218 { "onlret", ONLRET, M_OUT },
221 { "ofill", OFILL, M_OUT },
224 { "ofdel", OFDEL, M_OUT },
227 { "nldly", NLDLY, M_OUT },
230 { "crdly", CRDLY, M_OUT },
233 { "tabdly", TABDLY, M_OUT },
236 { "xtabs", XTABS, M_OUT },
239 { "bsdly", BSDLY, M_OUT },
242 { "vtdly", VTDLY, M_OUT },
245 { "ffdly", FFDLY, M_OUT },
248 { "pageout",PAGEOUT,M_OUT },
249 # endif /* PAGEOUT */
251 { "wrap", WRAP, M_OUT },
255 { "cignore",CIGNORE,M_CTL },
258 { "cbaud", CBAUD, M_CTL },
261 { "cstopb", CSTOPB, M_CTL },
264 { "cread", CREAD, M_CTL },
267 { "parenb", PARENB, M_CTL },
270 { "parodd", PARODD, M_CTL },
273 { "hupcl", HUPCL, M_CTL },
276 { "clocal", CLOCAL, M_CTL },
279 { "loblk", LOBLK, M_CTL },
282 { "cibaud", CIBAUD, M_CTL },
286 { "ccts_oflow",CCTS_OFLOW,M_CTL },
288 { "crtscts",CRTSCTS,M_CTL },
289 # endif /* CCTS_OFLOW */
290 # endif /* CRTSCTS */
292 { "crts_iflow",CRTS_IFLOW,M_CTL },
293 # endif /* CRTS_IFLOW */
295 { "mdmbuf", MDMBUF, M_CTL },
298 { "rcv1en", RCV1EN, M_CTL },
301 { "xmt1en", XMT1EN, M_CTL },
305 { "isig", ISIG, M_LIN },
308 { "icanon", ICANON, M_LIN },
311 { "xcase", XCASE, M_LIN },
314 { "echo", ECHO, M_LIN },
317 { "echoe", ECHOE, M_LIN },
320 { "echok", ECHOK, M_LIN },
323 { "echonl", ECHONL, M_LIN },
326 { "noflsh", NOFLSH, M_LIN },
329 { "tostop", TOSTOP, M_LIN },
332 { "echoctl",ECHOCTL,M_LIN },
333 # endif /* ECHOCTL */
335 { "echoprt",ECHOPRT,M_LIN },
336 # endif /* ECHOPRT */
338 { "echoke", ECHOKE, M_LIN },
341 { "defecho",DEFECHO,M_LIN },
342 # endif /* DEFECHO */
344 { "flusho", FLUSHO, M_LIN },
347 { "pendin", PENDIN, M_LIN },
350 { "iexten", IEXTEN, M_LIN },
353 { "nokerninfo",NOKERNINFO,M_LIN },
354 # endif /* NOKERNINFO */
356 { "altwerase",ALTWERASE,M_LIN },
357 # endif /* ALTWERASE */
359 { "extproc",EXTPROC, M_LIN },
360 # endif /* EXTPROC */
363 { "intr", C_SH(C_INTR), M_CHAR },
366 { "quit", C_SH(C_QUIT), M_CHAR },
369 { "erase", C_SH(C_ERASE), M_CHAR },
372 { "kill", C_SH(C_KILL), M_CHAR },
375 { "eof", C_SH(C_EOF), M_CHAR },
378 { "eol", C_SH(C_EOL), M_CHAR },
381 { "eol2", C_SH(C_EOL2), M_CHAR },
384 { "swtch", C_SH(C_SWTCH), M_CHAR },
386 # if defined(VDSWTCH)
387 { "dswtch", C_SH(C_DSWTCH), M_CHAR },
388 # endif /* VDSWTCH */
389 # if defined(VERASE2)
390 { "erase2", C_SH(C_ERASE2), M_CHAR },
391 # endif /* VERASE2 */
393 { "start", C_SH(C_START), M_CHAR },
396 { "stop", C_SH(C_STOP), M_CHAR },
398 # if defined(VWERASE)
399 { "werase", C_SH(C_WERASE), M_CHAR },
400 # endif /* VWERASE */
402 { "susp", C_SH(C_SUSP), M_CHAR },
405 { "dsusp", C_SH(C_DSUSP), M_CHAR },
407 # if defined(VREPRINT)
408 { "reprint", C_SH(C_REPRINT),M_CHAR },
409 # endif /* VREPRINT */
410 # if defined(VDISCARD)
411 { "discard", C_SH(C_DISCARD),M_CHAR },
412 # endif /* VDISCARD */
414 { "lnext", C_SH(C_LNEXT), M_CHAR },
416 # if defined(VSTATUS)
417 { "status", C_SH(C_STATUS), M_CHAR },
418 # endif /* VSTATUS */
420 { "page", C_SH(C_PAGE), M_CHAR },
423 { "pgoff", C_SH(C_PGOFF), M_CHAR },
426 { "kill2", C_SH(C_KILL2), M_CHAR },
429 { "brk", C_SH(C_BRK), M_CHAR },
432 { "min", C_SH(C_MIN), M_CHAR },
435 { "time", C_SH(C_TIME), M_CHAR },
442 #define tty_getty(el, td) tcgetattr((el)->el_infd, (td))
443 #define tty_setty(el, td) tcsetattr((el)->el_infd, TCSADRAIN, (td))
445 #define tty__gettabs(td) ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1)
446 #define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8)
447 #define tty__cooked_mode(td) ((td)->c_lflag & ICANON)
449 private void tty__getchar __P((struct termios *, unsigned char *));
450 private void tty__setchar __P((struct termios *, unsigned char *));
451 private speed_t tty__getspeed __P((struct termios *));
452 private int tty_setup __P((EditLine *));
458 * Get the tty parameters and initialize the editing state
465 if (tty_getty(el, &el->el_tty.t_ed) == -1) {
467 (void) fprintf(el->el_errfile,
468 "tty_setup: tty_getty: %s\n", strerror(errno));
469 #endif /* DEBUG_TTY */
472 el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed;
474 el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex);
475 el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex);
476 el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex);
478 el->el_tty.t_ex.c_iflag &= ~el->el_tty.t_t[EX_IO][M_INP].t_clrmask;
479 el->el_tty.t_ex.c_iflag |= el->el_tty.t_t[EX_IO][M_INP].t_setmask;
481 el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][M_OUT].t_clrmask;
482 el->el_tty.t_ex.c_oflag |= el->el_tty.t_t[EX_IO][M_OUT].t_setmask;
484 el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][M_CTL].t_clrmask;
485 el->el_tty.t_ex.c_cflag |= el->el_tty.t_t[EX_IO][M_CTL].t_setmask;
487 el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][M_LIN].t_clrmask;
488 el->el_tty.t_ex.c_lflag |= el->el_tty.t_t[EX_IO][M_LIN].t_setmask;
491 * Reset the tty chars to reasonable defaults
492 * If they are disabled, then enable them.
495 if (tty__cooked_mode(&el->el_tty.t_ts)) {
496 tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
498 * Don't affect CMIN and CTIME for the editor mode
500 for (rst = 0; rst < C_NCC - 2; rst++)
501 if (el->el_tty.t_c[TS_IO][rst] != el->el_tty.t_vdisable &&
502 el->el_tty.t_c[ED_IO][rst] != el->el_tty.t_vdisable)
503 el->el_tty.t_c[ED_IO][rst] = el->el_tty.t_c[TS_IO][rst];
504 for (rst = 0; rst < C_NCC; rst++)
505 if (el->el_tty.t_c[TS_IO][rst] != el->el_tty.t_vdisable &&
506 el->el_tty.t_c[EX_IO][rst] != el->el_tty.t_vdisable)
507 el->el_tty.t_c[EX_IO][rst] = el->el_tty.t_c[TS_IO][rst];
509 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
510 if (tty_setty(el, &el->el_tty.t_ex) == -1) {
512 (void) fprintf(el->el_errfile, "tty_setup: tty_setty: %s\n",
514 #endif /* DEBUG_TTY */
519 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
521 el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][M_INP].t_clrmask;
522 el->el_tty.t_ed.c_iflag |= el->el_tty.t_t[ED_IO][M_INP].t_setmask;
524 el->el_tty.t_ed.c_oflag &= ~el->el_tty.t_t[ED_IO][M_OUT].t_clrmask;
525 el->el_tty.t_ed.c_oflag |= el->el_tty.t_t[ED_IO][M_OUT].t_setmask;
527 el->el_tty.t_ed.c_cflag &= ~el->el_tty.t_t[ED_IO][M_CTL].t_clrmask;
528 el->el_tty.t_ed.c_cflag |= el->el_tty.t_t[ED_IO][M_CTL].t_setmask;
530 el->el_tty.t_ed.c_lflag &= ~el->el_tty.t_t[ED_IO][M_LIN].t_clrmask;
531 el->el_tty.t_ed.c_lflag |= el->el_tty.t_t[ED_IO][M_LIN].t_setmask;
533 tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
541 el->el_tty.t_mode = EX_IO;
542 el->el_tty.t_vdisable = _POSIX_VDISABLE;
543 (void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t));
544 (void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t));
545 return tty_setup(el);
550 * Restore the tty to its original settings
557 /* XXX: Maybe reset to an initial state? */
570 if ((spd = cfgetispeed(td)) == 0)
571 spd = cfgetospeed(td);
573 } /* end tty__getspeed */
577 * Get the tty characters
585 s[C_INTR] = td->c_cc[VINTR];
588 s[C_QUIT] = td->c_cc[VQUIT];
591 s[C_ERASE] = td->c_cc[VERASE];
594 s[C_KILL] = td->c_cc[VKILL];
597 s[C_EOF] = td->c_cc[VEOF];
600 s[C_EOL] = td->c_cc[VEOL];
603 s[C_EOL2] = td->c_cc[VEOL2];
606 s[C_SWTCH] = td->c_cc[VSWTCH];
609 s[C_DSWTCH] = td->c_cc[VDSWTCH];
610 # endif /* VDSWTCH */
612 s[C_ERASE2] = td->c_cc[VERASE2];
613 # endif /* VERASE2 */
615 s[C_START] = td->c_cc[VSTART];
618 s[C_STOP] = td->c_cc[VSTOP];
621 s[C_WERASE] = td->c_cc[VWERASE];
622 # endif /* VWERASE */
624 s[C_SUSP] = td->c_cc[VSUSP];
627 s[C_DSUSP] = td->c_cc[VDSUSP];
630 s[C_REPRINT]= td->c_cc[VREPRINT];
631 # endif /* VREPRINT */
633 s[C_DISCARD]= td->c_cc[VDISCARD];
634 # endif /* VDISCARD */
636 s[C_LNEXT] = td->c_cc[VLNEXT];
639 s[C_STATUS] = td->c_cc[VSTATUS];
640 # endif /* VSTATUS */
642 s[C_PAGE] = td->c_cc[VPAGE];
645 s[C_PGOFF] = td->c_cc[VPGOFF];
648 s[C_KILL2] = td->c_cc[VKILL2];
651 s[C_MIN] = td->c_cc[VMIN];
654 s[C_TIME] = td->c_cc[VTIME];
660 * Set the tty characters
668 td->c_cc[VINTR] = s[C_INTR];
671 td->c_cc[VQUIT] = s[C_QUIT];
674 td->c_cc[VERASE] = s[C_ERASE];
677 td->c_cc[VKILL] = s[C_KILL];
680 td->c_cc[VEOF] = s[C_EOF];
683 td->c_cc[VEOL] = s[C_EOL];
686 td->c_cc[VEOL2] = s[C_EOL2];
689 td->c_cc[VSWTCH] = s[C_SWTCH];
692 td->c_cc[VDSWTCH] = s[C_DSWTCH];
693 # endif /* VDSWTCH */
695 td->c_cc[VERASE2] = s[C_ERASE2];
696 # endif /* VERASE2 */
698 td->c_cc[VSTART] = s[C_START];
701 td->c_cc[VSTOP] = s[C_STOP];
704 td->c_cc[VWERASE] = s[C_WERASE];
705 # endif /* VWERASE */
707 td->c_cc[VSUSP] = s[C_SUSP];
710 td->c_cc[VDSUSP] = s[C_DSUSP];
713 td->c_cc[VREPRINT] = s[C_REPRINT];
714 # endif /* VREPRINT */
716 td->c_cc[VDISCARD] = s[C_DISCARD];
717 # endif /* VDISCARD */
719 td->c_cc[VLNEXT] = s[C_LNEXT];
722 td->c_cc[VSTATUS] = s[C_STATUS];
723 # endif /* VSTATUS */
725 td->c_cc[VPAGE] = s[C_PAGE];
728 td->c_cc[VPGOFF] = s[C_PGOFF];
731 td->c_cc[VKILL2] = s[C_KILL2];
734 td->c_cc[VMIN] = s[C_MIN];
737 td->c_cc[VTIME] = s[C_TIME];
743 * Rebind the editline functions
746 tty_bind_char(el, force)
750 unsigned char *t_n = el->el_tty.t_c[ED_IO];
751 unsigned char *t_o = el->el_tty.t_ed.c_cc;
754 el_action_t *dmap, *dalt, *map, *alt;
755 new[1] = old[1] = '\0';
758 map = el->el_map.key;
759 alt = el->el_map.alt;
760 if (el->el_map.type == MAP_VI) {
761 dmap = el->el_map.vii;
762 dalt = el->el_map.vic;
765 dmap = el->el_map.emacs;
769 for (tp = tty_map; tp->nch != -1; tp++) {
770 new[0] = t_n[tp->nch];
771 old[0] = t_o[tp->och];
772 if (new[0] == old[0] && !force)
774 /* Put the old default binding back, and set the new binding */
775 key_clear(el, map, old);
776 map[old[0]] = dmap[old[0]];
777 key_clear(el, map, new);
778 /* MAP_VI == 1, MAP_EMACS == 0... */
779 map[new[0]] = tp->bind[el->el_map.type];
781 key_clear(el, alt, old);
782 alt[old[0]] = dalt[old[0]];
783 key_clear(el, alt, new);
784 alt[new[0]] = tp->bind[el->el_map.type+1];
790 * Set terminal into 1 character at a time mode.
796 if (el->el_tty.t_mode == ED_IO || el->el_tty.t_mode == QU_IO)
799 if (tty_getty(el, &el->el_tty.t_ts) == -1) {
801 (void) fprintf(el->el_errfile, "tty_rawmode: tty_getty: %s\n", strerror(errno));
802 #endif /* DEBUG_TTY */
807 * We always keep up with the eight bit setting and the speed of the
808 * tty. But only we only believe changes that are made to cooked mode!
810 el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts);
811 el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts);
813 if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed ||
814 tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) {
815 (void) cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed);
816 (void) cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed);
817 (void) cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed);
818 (void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed);
821 if (tty__cooked_mode(&el->el_tty.t_ts)) {
822 if (el->el_tty.t_ts.c_cflag != el->el_tty.t_ex.c_cflag) {
823 el->el_tty.t_ex.c_cflag = el->el_tty.t_ts.c_cflag;
824 el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][M_CTL].t_clrmask;
825 el->el_tty.t_ex.c_cflag |= el->el_tty.t_t[EX_IO][M_CTL].t_setmask;
827 el->el_tty.t_ed.c_cflag = el->el_tty.t_ts.c_cflag;
828 el->el_tty.t_ed.c_cflag &= ~el->el_tty.t_t[ED_IO][M_CTL].t_clrmask;
829 el->el_tty.t_ed.c_cflag |= el->el_tty.t_t[ED_IO][M_CTL].t_setmask;
832 if ((el->el_tty.t_ts.c_lflag != el->el_tty.t_ex.c_lflag) &&
833 (el->el_tty.t_ts.c_lflag != el->el_tty.t_ed.c_lflag)) {
834 el->el_tty.t_ex.c_lflag = el->el_tty.t_ts.c_lflag;
835 el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][M_LIN].t_clrmask;
836 el->el_tty.t_ex.c_lflag |= el->el_tty.t_t[EX_IO][M_LIN].t_setmask;
838 el->el_tty.t_ed.c_lflag = el->el_tty.t_ts.c_lflag;
839 el->el_tty.t_ed.c_lflag &= ~el->el_tty.t_t[ED_IO][M_LIN].t_clrmask;
840 el->el_tty.t_ed.c_lflag |= el->el_tty.t_t[ED_IO][M_LIN].t_setmask;
843 if ((el->el_tty.t_ts.c_iflag != el->el_tty.t_ex.c_iflag) &&
844 (el->el_tty.t_ts.c_iflag != el->el_tty.t_ed.c_iflag)) {
845 el->el_tty.t_ex.c_iflag = el->el_tty.t_ts.c_iflag;
846 el->el_tty.t_ex.c_iflag &= ~el->el_tty.t_t[EX_IO][M_INP].t_clrmask;
847 el->el_tty.t_ex.c_iflag |= el->el_tty.t_t[EX_IO][M_INP].t_setmask;
849 el->el_tty.t_ed.c_iflag = el->el_tty.t_ts.c_iflag;
850 el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][M_INP].t_clrmask;
851 el->el_tty.t_ed.c_iflag |= el->el_tty.t_t[ED_IO][M_INP].t_setmask;
854 if ((el->el_tty.t_ts.c_oflag != el->el_tty.t_ex.c_oflag) &&
855 (el->el_tty.t_ts.c_oflag != el->el_tty.t_ed.c_oflag)) {
856 el->el_tty.t_ex.c_oflag = el->el_tty.t_ts.c_oflag;
857 el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][M_OUT].t_clrmask;
858 el->el_tty.t_ex.c_oflag |= el->el_tty.t_t[EX_IO][M_OUT].t_setmask;
860 el->el_tty.t_ed.c_oflag = el->el_tty.t_ts.c_oflag;
861 el->el_tty.t_ed.c_oflag &= ~el->el_tty.t_t[ED_IO][M_OUT].t_clrmask;
862 el->el_tty.t_ed.c_oflag |= el->el_tty.t_t[ED_IO][M_OUT].t_setmask;
865 if (tty__gettabs(&el->el_tty.t_ex) == 0)
866 el->el_tty.t_tabs = 0;
868 el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0;
873 tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
875 * Check if the user made any changes.
876 * If he did, then propagate the changes to the
877 * edit and execute data structures.
879 for (i = 0; i < C_NCC; i++)
880 if (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i])
885 * Propagate changes only to the unprotected chars
886 * that have been modified just now.
888 for (i = 0; i < C_NCC; i++) {
889 if (!((el->el_tty.t_t[ED_IO][M_CHAR].t_setmask & C_SH(i)))
890 && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
891 el->el_tty.t_c[ED_IO][i] = el->el_tty.t_c[TS_IO][i];
892 if (el->el_tty.t_t[ED_IO][M_CHAR].t_clrmask & C_SH(i))
893 el->el_tty.t_c[ED_IO][i] = el->el_tty.t_vdisable;
895 tty_bind_char(el, 0);
896 tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
898 for (i = 0; i < C_NCC; i++) {
899 if (!((el->el_tty.t_t[EX_IO][M_CHAR].t_setmask & C_SH(i)))
900 && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
901 el->el_tty.t_c[EX_IO][i] = el->el_tty.t_c[TS_IO][i];
902 if (el->el_tty.t_t[EX_IO][M_CHAR].t_clrmask & C_SH(i))
903 el->el_tty.t_c[EX_IO][i] = el->el_tty.t_vdisable;
905 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
911 if (tty_setty(el, &el->el_tty.t_ed) == -1) {
913 (void) fprintf(el->el_errfile, "tty_rawmode: tty_setty: %s\n",
915 #endif /* DEBUG_TTY */
918 el->el_tty.t_mode = ED_IO;
920 } /* end tty_rawmode */
924 * Set the tty back to normal mode
929 { /* set tty in normal setup */
930 if (el->el_tty.t_mode == EX_IO)
933 if (tty_setty(el, &el->el_tty.t_ex) == -1) {
935 (void) fprintf(el->el_errfile, "tty_cookedmode: tty_setty: %s\n",
937 #endif /* DEBUG_TTY */
940 el->el_tty.t_mode = EX_IO;
942 } /* end tty_cookedmode */
952 if (el->el_tty.t_mode == QU_IO)
955 el->el_tty.t_qu = el->el_tty.t_ed;
957 el->el_tty.t_qu.c_iflag &= ~el->el_tty.t_t[QU_IO][M_INP].t_clrmask;
958 el->el_tty.t_qu.c_iflag |= el->el_tty.t_t[QU_IO][M_INP].t_setmask;
960 el->el_tty.t_qu.c_oflag &= ~el->el_tty.t_t[QU_IO][M_OUT].t_clrmask;
961 el->el_tty.t_qu.c_oflag |= el->el_tty.t_t[QU_IO][M_OUT].t_setmask;
963 el->el_tty.t_qu.c_cflag &= ~el->el_tty.t_t[QU_IO][M_CTL].t_clrmask;
964 el->el_tty.t_qu.c_cflag |= el->el_tty.t_t[QU_IO][M_CTL].t_setmask;
966 el->el_tty.t_qu.c_lflag &= ~el->el_tty.t_t[QU_IO][M_LIN].t_clrmask;
967 el->el_tty.t_qu.c_lflag |= el->el_tty.t_t[QU_IO][M_LIN].t_setmask;
969 if (tty_setty(el, &el->el_tty.t_qu) == -1) {
971 (void) fprintf(el->el_errfile, "QuoteModeOn: tty_setty: %s\n",
973 #endif /* DEBUG_TTY */
976 el->el_tty.t_mode = QU_IO;
978 } /* end tty_quotemode */
981 /* tty_noquotemode():
982 * Turn off quote mode
988 if (el->el_tty.t_mode != QU_IO)
990 if (tty_setty(el, &el->el_tty.t_ed) == -1) {
992 (void) fprintf(el->el_errfile, "QuoteModeOff: tty_setty: %s\n",
994 #endif /* DEBUG_TTY */
997 el->el_tty.t_mode = ED_IO;
1006 tty_stty(el, argc, argv)
1022 while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0')
1023 switch (argv[0][1]) {
1041 (void) fprintf(el->el_errfile, "%s: Unknown switch `%c'.\n",
1046 if (!argv || !*argv) {
1048 int len = 0, st = 0, cu;
1049 for (m = ttymodes; m->m_name; m++) {
1050 if (m->m_type != i) {
1051 (void) fprintf(el->el_outfile, "%s%s", i != -1 ? "\n" : "",
1052 el->el_tty.t_t[z][m->m_type].t_name);
1054 st = len = strlen(el->el_tty.t_t[z][m->m_type].t_name);
1057 x = (el->el_tty.t_t[z][i].t_setmask & m->m_value) ? '+' : '\0';
1058 x = (el->el_tty.t_t[z][i].t_clrmask & m->m_value) ? '-' : x;
1060 if (x != '\0' || aflag) {
1062 cu = strlen(m->m_name) + (x != '\0') + 1;
1064 if (len + cu >= el->el_term.t_size.h) {
1065 (void) fprintf(el->el_outfile, "\n%*s", st, "");
1072 (void) fprintf(el->el_outfile, "%c%s ", x, m->m_name);
1074 (void) fprintf(el->el_outfile, "%s ", m->m_name);
1077 (void) fprintf(el->el_outfile, "\n");
1081 while (argv && (s = *argv++)) {
1092 for (m = ttymodes; m->m_name; m++)
1093 if (strcmp(m->m_name, d) == 0)
1097 (void) fprintf(el->el_errfile, "%s: Invalid argument `%s'.\n",
1104 el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value;
1105 el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
1108 el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
1109 el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value;
1112 el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
1113 el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
1118 } /* end tty_stty */
1123 * DEbugging routine to print the tty characters
1126 tty_printchar(el, s)
1133 for (i = 0; i < C_NCC; i++) {
1134 for (m = el->el_tty.t_t; m->m_name; m++)
1135 if (m->m_type == M_CHAR && C_SH(i) == m->m_value)
1138 (void) fprintf(el->el_errfile, "%s ^%c ", m->m_name, s[i] + 'A'-1);
1140 (void) fprintf(el->el_errfile, "\n");
1142 (void) fprintf(el->el_errfile, "\n");