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. 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.
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
32 * @(#)tty.c 8.1 (Berkeley) 6/4/93
33 * $NetBSD: tty.c,v 1.25 2006/03/18 09:09:41 christos Exp $
34 * $DragonFly: src/lib/libedit/tty.c,v 1.5 2007/05/05 00:27:40 pavalos Exp $
40 * tty.c: tty interface stuff
46 typedef struct ttymodes_t {
52 typedef struct ttymap_t {
53 int nch, och; /* Internal and termio rep of chars */
54 el_action_t bind[3]; /* emacs, vi, and vi-cmd */
58 private const ttyperm_t ttyperm = {
60 {"iflag:", ICRNL, (INLCR | IGNCR)},
61 {"oflag:", (OPOST | ONLCR), ONLRET},
63 {"lflag:", (ISIG | ICANON | ECHO | ECHOE | ECHOCTL | IEXTEN),
64 (NOFLSH | ECHONL | EXTPROC | FLUSHO)},
68 {"iflag:", (INLCR | ICRNL), IGNCR},
69 {"oflag:", (OPOST | ONLCR), ONLRET},
72 (NOFLSH | ICANON | ECHO | ECHOK | ECHONL | EXTPROC | IEXTEN | FLUSHO)},
73 {"chars:", (C_SH(C_MIN) | C_SH(C_TIME) | C_SH(C_SWTCH) | C_SH(C_DSWTCH) |
74 C_SH(C_SUSP) | C_SH(C_DSUSP) | C_SH(C_EOL) | C_SH(C_DISCARD) |
75 C_SH(C_PGOFF) | C_SH(C_PAGE) | C_SH(C_STATUS)), 0}
78 {"iflag:", 0, IXON | IXOFF | INLCR | ICRNL},
81 {"lflag:", 0, ISIG | IEXTEN},
86 private const ttychar_t ttychar = {
88 CINTR, CQUIT, CERASE, CKILL,
89 CEOF, CEOL, CEOL2, CSWTCH,
90 CDSWTCH, CERASE2, CSTART, CSTOP,
91 CWERASE, CSUSP, CDSUSP, CREPRINT,
92 CDISCARD, CLNEXT, CSTATUS, CPAGE,
93 CPGOFF, CKILL2, CBRK, CMIN,
97 CINTR, CQUIT, CERASE, CKILL,
98 _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
99 _POSIX_VDISABLE, CERASE2, CSTART, CSTOP,
100 _POSIX_VDISABLE, CSUSP, _POSIX_VDISABLE, _POSIX_VDISABLE,
101 CDISCARD, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
102 _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 1,
116 private const ttymap_t tty_map[] = {
119 {EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
123 {EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
127 {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
131 {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
135 {EM_DELETE_OR_LIST, VI_LIST_OR_EOF, ED_UNASSIGNED}},
139 {ED_DELETE_PREV_WORD, ED_DELETE_PREV_WORD, ED_PREV_WORD}},
142 {C_REPRINT, VREPRINT,
143 {ED_REDISPLAY, ED_INSERT, ED_REDISPLAY}},
144 #endif /* VREPRINT */
147 {ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED}},
150 {ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED}}
153 private const ttymodes_t ttymodes[] = {
155 {"ignbrk", IGNBRK, MD_INP},
158 {"brkint", BRKINT, MD_INP},
161 {"ignpar", IGNPAR, MD_INP},
164 {"parmrk", PARMRK, MD_INP},
167 {"inpck", INPCK, MD_INP},
170 {"istrip", ISTRIP, MD_INP},
173 {"inlcr", INLCR, MD_INP},
176 {"igncr", IGNCR, MD_INP},
179 {"icrnl", ICRNL, MD_INP},
182 {"iuclc", IUCLC, MD_INP},
185 {"ixon", IXON, MD_INP},
188 {"ixany", IXANY, MD_INP},
191 {"ixoff", IXOFF, MD_INP},
194 {"imaxbel", IMAXBEL, MD_INP},
198 {"opost", OPOST, MD_OUT},
201 {"olcuc", OLCUC, MD_OUT},
204 {"onlcr", ONLCR, MD_OUT},
207 {"ocrnl", OCRNL, MD_OUT},
210 {"onocr", ONOCR, MD_OUT},
213 {"onoeot", ONOEOT, MD_OUT},
216 {"onlret", ONLRET, MD_OUT},
219 {"ofill", OFILL, MD_OUT},
222 {"ofdel", OFDEL, MD_OUT},
225 {"nldly", NLDLY, MD_OUT},
228 {"crdly", CRDLY, MD_OUT},
231 {"tabdly", TABDLY, MD_OUT},
234 {"xtabs", XTABS, MD_OUT},
237 {"bsdly", BSDLY, MD_OUT},
240 {"vtdly", VTDLY, MD_OUT},
243 {"ffdly", FFDLY, MD_OUT},
246 {"pageout", PAGEOUT, MD_OUT},
249 {"wrap", WRAP, MD_OUT},
253 {"cignore", CIGNORE, MD_CTL},
256 {"cbaud", CBAUD, MD_CTL},
259 {"cstopb", CSTOPB, MD_CTL},
262 {"cread", CREAD, MD_CTL},
265 {"parenb", PARENB, MD_CTL},
268 {"parodd", PARODD, MD_CTL},
271 {"hupcl", HUPCL, MD_CTL},
274 {"clocal", CLOCAL, MD_CTL},
277 {"loblk", LOBLK, MD_CTL},
280 {"cibaud", CIBAUD, MD_CTL},
284 {"ccts_oflow", CCTS_OFLOW, MD_CTL},
286 {"crtscts", CRTSCTS, MD_CTL},
287 #endif /* CCTS_OFLOW */
290 {"crts_iflow", CRTS_IFLOW, MD_CTL},
291 #endif /* CRTS_IFLOW */
293 {"cdtrcts", CDTRCTS, MD_CTL},
296 {"mdmbuf", MDMBUF, MD_CTL},
299 {"rcv1en", RCV1EN, MD_CTL},
302 {"xmt1en", XMT1EN, MD_CTL},
306 {"isig", ISIG, MD_LIN},
309 {"icanon", ICANON, MD_LIN},
312 {"xcase", XCASE, MD_LIN},
315 {"echo", ECHO, MD_LIN},
318 {"echoe", ECHOE, MD_LIN},
321 {"echok", ECHOK, MD_LIN},
324 {"echonl", ECHONL, MD_LIN},
327 {"noflsh", NOFLSH, MD_LIN},
330 {"tostop", TOSTOP, MD_LIN},
333 {"echoctl", ECHOCTL, MD_LIN},
336 {"echoprt", ECHOPRT, MD_LIN},
339 {"echoke", ECHOKE, MD_LIN},
342 {"defecho", DEFECHO, MD_LIN},
345 {"flusho", FLUSHO, MD_LIN},
348 {"pendin", PENDIN, MD_LIN},
351 {"iexten", IEXTEN, MD_LIN},
354 {"nokerninfo", NOKERNINFO, MD_LIN},
355 #endif /* NOKERNINFO */
357 {"altwerase", ALTWERASE, MD_LIN},
358 #endif /* ALTWERASE */
360 {"extproc", EXTPROC, MD_LIN},
364 {"intr", C_SH(C_INTR), MD_CHAR},
367 {"quit", C_SH(C_QUIT), MD_CHAR},
370 {"erase", C_SH(C_ERASE), MD_CHAR},
373 {"kill", C_SH(C_KILL), MD_CHAR},
376 {"eof", C_SH(C_EOF), MD_CHAR},
379 {"eol", C_SH(C_EOL), MD_CHAR},
382 {"eol2", C_SH(C_EOL2), MD_CHAR},
385 {"swtch", C_SH(C_SWTCH), MD_CHAR},
388 {"dswtch", C_SH(C_DSWTCH), MD_CHAR},
391 {"erase2", C_SH(C_ERASE2), MD_CHAR},
394 {"start", C_SH(C_START), MD_CHAR},
397 {"stop", C_SH(C_STOP), MD_CHAR},
400 {"werase", C_SH(C_WERASE), MD_CHAR},
403 {"susp", C_SH(C_SUSP), MD_CHAR},
406 {"dsusp", C_SH(C_DSUSP), MD_CHAR},
408 #if defined(VREPRINT)
409 {"reprint", C_SH(C_REPRINT), MD_CHAR},
410 #endif /* VREPRINT */
411 #if defined(VDISCARD)
412 {"discard", C_SH(C_DISCARD), MD_CHAR},
413 #endif /* VDISCARD */
415 {"lnext", C_SH(C_LNEXT), MD_CHAR},
418 {"status", C_SH(C_STATUS), MD_CHAR},
421 {"page", C_SH(C_PAGE), MD_CHAR},
424 {"pgoff", C_SH(C_PGOFF), MD_CHAR},
427 {"kill2", C_SH(C_KILL2), MD_CHAR},
430 {"brk", C_SH(C_BRK), MD_CHAR},
433 {"min", C_SH(C_MIN), MD_CHAR},
436 {"time", C_SH(C_TIME), MD_CHAR},
443 #define tty_getty(el, td) tcgetattr((el)->el_infd, (td))
444 #define tty_setty(el, td) tcsetattr((el)->el_infd, TCSADRAIN, (td))
446 #define tty__gettabs(td) ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1)
447 #define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8)
448 #define tty__cooked_mode(td) ((td)->c_lflag & ICANON)
450 private int tty__getcharindex(int);
451 private void tty__getchar(struct termios *, unsigned char *);
452 private void tty__setchar(struct termios *, unsigned char *);
453 private speed_t tty__getspeed(struct termios *);
454 private int tty_setup(EditLine *);
460 * Get the tty parameters and initialize the editing state
463 tty_setup(EditLine *el)
467 if (el->el_flags & EDIT_DISABLED)
470 if (tty_getty(el, &el->el_tty.t_ed) == -1) {
472 (void) fprintf(el->el_errfile,
473 "tty_setup: tty_getty: %s\n", strerror(errno));
474 #endif /* DEBUG_TTY */
477 el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed;
479 el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex);
480 el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex);
481 el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex);
483 el->el_tty.t_ex.c_iflag &= ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask;
484 el->el_tty.t_ex.c_iflag |= el->el_tty.t_t[EX_IO][MD_INP].t_setmask;
486 el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask;
487 el->el_tty.t_ex.c_oflag |= el->el_tty.t_t[EX_IO][MD_OUT].t_setmask;
489 el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask;
490 el->el_tty.t_ex.c_cflag |= el->el_tty.t_t[EX_IO][MD_CTL].t_setmask;
492 el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask;
493 el->el_tty.t_ex.c_lflag |= el->el_tty.t_t[EX_IO][MD_LIN].t_setmask;
496 * Reset the tty chars to reasonable defaults
497 * If they are disabled, then enable them.
500 if (tty__cooked_mode(&el->el_tty.t_ts)) {
501 tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
503 * Don't affect CMIN and CTIME for the editor mode
505 for (rst = 0; rst < C_NCC - 2; rst++)
506 if (el->el_tty.t_c[TS_IO][rst] !=
507 el->el_tty.t_vdisable
508 && el->el_tty.t_c[ED_IO][rst] !=
509 el->el_tty.t_vdisable)
510 el->el_tty.t_c[ED_IO][rst] =
511 el->el_tty.t_c[TS_IO][rst];
512 for (rst = 0; rst < C_NCC; rst++)
513 if (el->el_tty.t_c[TS_IO][rst] !=
514 el->el_tty.t_vdisable)
515 el->el_tty.t_c[EX_IO][rst] =
516 el->el_tty.t_c[TS_IO][rst];
518 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
519 if (tty_setty(el, &el->el_tty.t_ex) == -1) {
521 (void) fprintf(el->el_errfile,
522 "tty_setup: tty_setty: %s\n",
524 #endif /* DEBUG_TTY */
530 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
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;
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;
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;
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;
545 tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
546 tty_bind_char(el, 1);
551 tty_init(EditLine *el)
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));
563 * Restore the tty to its original settings
567 tty_end(EditLine *el __attribute__((__unused__)))
570 /* XXX: Maybe reset to an initial state? */
578 tty__getspeed(struct termios *td)
582 if ((spd = cfgetispeed(td)) == 0)
583 spd = cfgetospeed(td);
588 * Return the index of the asked char in the c_cc array
591 tty__getcharindex(int i)
657 #endif /* VREPRINT */
661 #endif /* VDISCARD */
696 * Get the tty characters
699 tty__getchar(struct termios *td, unsigned char *s)
703 s[C_INTR] = td->c_cc[VINTR];
706 s[C_QUIT] = td->c_cc[VQUIT];
709 s[C_ERASE] = td->c_cc[VERASE];
712 s[C_KILL] = td->c_cc[VKILL];
715 s[C_EOF] = td->c_cc[VEOF];
718 s[C_EOL] = td->c_cc[VEOL];
721 s[C_EOL2] = td->c_cc[VEOL2];
724 s[C_SWTCH] = td->c_cc[VSWTCH];
727 s[C_DSWTCH] = td->c_cc[VDSWTCH];
730 s[C_ERASE2] = td->c_cc[VERASE2];
733 s[C_START] = td->c_cc[VSTART];
736 s[C_STOP] = td->c_cc[VSTOP];
739 s[C_WERASE] = td->c_cc[VWERASE];
742 s[C_SUSP] = td->c_cc[VSUSP];
745 s[C_DSUSP] = td->c_cc[VDSUSP];
748 s[C_REPRINT] = td->c_cc[VREPRINT];
749 #endif /* VREPRINT */
751 s[C_DISCARD] = td->c_cc[VDISCARD];
752 #endif /* VDISCARD */
754 s[C_LNEXT] = td->c_cc[VLNEXT];
757 s[C_STATUS] = td->c_cc[VSTATUS];
760 s[C_PAGE] = td->c_cc[VPAGE];
763 s[C_PGOFF] = td->c_cc[VPGOFF];
766 s[C_KILL2] = td->c_cc[VKILL2];
769 s[C_MIN] = td->c_cc[VMIN];
772 s[C_TIME] = td->c_cc[VTIME];
778 * Set the tty characters
781 tty__setchar(struct termios *td, unsigned char *s)
785 td->c_cc[VINTR] = s[C_INTR];
788 td->c_cc[VQUIT] = s[C_QUIT];
791 td->c_cc[VERASE] = s[C_ERASE];
794 td->c_cc[VKILL] = s[C_KILL];
797 td->c_cc[VEOF] = s[C_EOF];
800 td->c_cc[VEOL] = s[C_EOL];
803 td->c_cc[VEOL2] = s[C_EOL2];
806 td->c_cc[VSWTCH] = s[C_SWTCH];
809 td->c_cc[VDSWTCH] = s[C_DSWTCH];
812 td->c_cc[VERASE2] = s[C_ERASE2];
815 td->c_cc[VSTART] = s[C_START];
818 td->c_cc[VSTOP] = s[C_STOP];
821 td->c_cc[VWERASE] = s[C_WERASE];
824 td->c_cc[VSUSP] = s[C_SUSP];
827 td->c_cc[VDSUSP] = s[C_DSUSP];
830 td->c_cc[VREPRINT] = s[C_REPRINT];
831 #endif /* VREPRINT */
833 td->c_cc[VDISCARD] = s[C_DISCARD];
834 #endif /* VDISCARD */
836 td->c_cc[VLNEXT] = s[C_LNEXT];
839 td->c_cc[VSTATUS] = s[C_STATUS];
842 td->c_cc[VPAGE] = s[C_PAGE];
845 td->c_cc[VPGOFF] = s[C_PGOFF];
848 td->c_cc[VKILL2] = s[C_KILL2];
851 td->c_cc[VMIN] = s[C_MIN];
854 td->c_cc[VTIME] = s[C_TIME];
860 * Rebind the editline functions
863 tty_bind_char(EditLine *el, int force)
866 unsigned char *t_n = el->el_tty.t_c[ED_IO];
867 unsigned char *t_o = el->el_tty.t_ed.c_cc;
868 unsigned char new[2], old[2];
870 el_action_t *map, *alt;
871 const el_action_t *dmap, *dalt;
872 new[1] = old[1] = '\0';
874 map = el->el_map.key;
875 alt = el->el_map.alt;
876 if (el->el_map.type == MAP_VI) {
877 dmap = el->el_map.vii;
878 dalt = el->el_map.vic;
880 dmap = el->el_map.emacs;
884 for (tp = tty_map; tp->nch != -1; tp++) {
885 new[0] = t_n[tp->nch];
886 old[0] = t_o[tp->och];
887 if (new[0] == old[0] && !force)
889 /* Put the old default binding back, and set the new binding */
890 key_clear(el, map, (char *)old);
891 map[old[0]] = dmap[old[0]];
892 key_clear(el, map, (char *)new);
893 /* MAP_VI == 1, MAP_EMACS == 0... */
894 map[new[0]] = tp->bind[el->el_map.type];
896 key_clear(el, alt, (char *)old);
897 alt[old[0]] = dalt[old[0]];
898 key_clear(el, alt, (char *)new);
899 alt[new[0]] = tp->bind[el->el_map.type + 1];
906 * Set terminal into 1 character at a time mode.
909 tty_rawmode(EditLine *el)
912 if (el->el_tty.t_mode == ED_IO || el->el_tty.t_mode == QU_IO)
915 if (el->el_flags & EDIT_DISABLED)
918 if (tty_getty(el, &el->el_tty.t_ts) == -1) {
920 (void) fprintf(el->el_errfile, "tty_rawmode: tty_getty: %s\n",
922 #endif /* DEBUG_TTY */
926 * We always keep up with the eight bit setting and the speed of the
927 * tty. But only we only believe changes that are made to cooked mode!
929 el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts);
930 el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts);
932 if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed ||
933 tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) {
934 (void) cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed);
935 (void) cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed);
936 (void) cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed);
937 (void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed);
939 if (tty__cooked_mode(&el->el_tty.t_ts)) {
940 if (el->el_tty.t_ts.c_cflag != el->el_tty.t_ex.c_cflag) {
941 el->el_tty.t_ex.c_cflag =
942 el->el_tty.t_ts.c_cflag;
943 el->el_tty.t_ex.c_cflag &=
944 ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask;
945 el->el_tty.t_ex.c_cflag |=
946 el->el_tty.t_t[EX_IO][MD_CTL].t_setmask;
948 el->el_tty.t_ed.c_cflag =
949 el->el_tty.t_ts.c_cflag;
950 el->el_tty.t_ed.c_cflag &=
951 ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask;
952 el->el_tty.t_ed.c_cflag |=
953 el->el_tty.t_t[ED_IO][MD_CTL].t_setmask;
955 if ((el->el_tty.t_ts.c_lflag != el->el_tty.t_ex.c_lflag) &&
956 (el->el_tty.t_ts.c_lflag != el->el_tty.t_ed.c_lflag)) {
957 el->el_tty.t_ex.c_lflag =
958 el->el_tty.t_ts.c_lflag;
959 el->el_tty.t_ex.c_lflag &=
960 ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask;
961 el->el_tty.t_ex.c_lflag |=
962 el->el_tty.t_t[EX_IO][MD_LIN].t_setmask;
964 el->el_tty.t_ed.c_lflag =
965 el->el_tty.t_ts.c_lflag;
966 el->el_tty.t_ed.c_lflag &=
967 ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask;
968 el->el_tty.t_ed.c_lflag |=
969 el->el_tty.t_t[ED_IO][MD_LIN].t_setmask;
971 if ((el->el_tty.t_ts.c_iflag != el->el_tty.t_ex.c_iflag) &&
972 (el->el_tty.t_ts.c_iflag != el->el_tty.t_ed.c_iflag)) {
973 el->el_tty.t_ex.c_iflag =
974 el->el_tty.t_ts.c_iflag;
975 el->el_tty.t_ex.c_iflag &=
976 ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask;
977 el->el_tty.t_ex.c_iflag |=
978 el->el_tty.t_t[EX_IO][MD_INP].t_setmask;
980 el->el_tty.t_ed.c_iflag =
981 el->el_tty.t_ts.c_iflag;
982 el->el_tty.t_ed.c_iflag &=
983 ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask;
984 el->el_tty.t_ed.c_iflag |=
985 el->el_tty.t_t[ED_IO][MD_INP].t_setmask;
987 if ((el->el_tty.t_ts.c_oflag != el->el_tty.t_ex.c_oflag) &&
988 (el->el_tty.t_ts.c_oflag != el->el_tty.t_ed.c_oflag)) {
989 el->el_tty.t_ex.c_oflag =
990 el->el_tty.t_ts.c_oflag;
991 el->el_tty.t_ex.c_oflag &=
992 ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask;
993 el->el_tty.t_ex.c_oflag |=
994 el->el_tty.t_t[EX_IO][MD_OUT].t_setmask;
996 el->el_tty.t_ed.c_oflag =
997 el->el_tty.t_ts.c_oflag;
998 el->el_tty.t_ed.c_oflag &=
999 ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask;
1000 el->el_tty.t_ed.c_oflag |=
1001 el->el_tty.t_t[ED_IO][MD_OUT].t_setmask;
1003 if (tty__gettabs(&el->el_tty.t_ex) == 0)
1004 el->el_tty.t_tabs = 0;
1006 el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0;
1011 tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
1013 * Check if the user made any changes.
1014 * If he did, then propagate the changes to the
1015 * edit and execute data structures.
1017 for (i = 0; i < C_NCC; i++)
1018 if (el->el_tty.t_c[TS_IO][i] !=
1019 el->el_tty.t_c[EX_IO][i])
1024 * Propagate changes only to the unprotected
1025 * chars that have been modified just now.
1027 for (i = 0; i < C_NCC; i++) {
1028 if (!((el->el_tty.t_t[ED_IO][MD_CHAR].t_setmask & C_SH(i)))
1029 && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
1030 el->el_tty.t_c[ED_IO][i] = el->el_tty.t_c[TS_IO][i];
1031 if (el->el_tty.t_t[ED_IO][MD_CHAR].t_clrmask & C_SH(i))
1032 el->el_tty.t_c[ED_IO][i] = el->el_tty.t_vdisable;
1034 tty_bind_char(el, 0);
1035 tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
1037 for (i = 0; i < C_NCC; i++) {
1038 if (!((el->el_tty.t_t[EX_IO][MD_CHAR].t_setmask & C_SH(i)))
1039 && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
1040 el->el_tty.t_c[EX_IO][i] = el->el_tty.t_c[TS_IO][i];
1041 if (el->el_tty.t_t[EX_IO][MD_CHAR].t_clrmask & C_SH(i))
1042 el->el_tty.t_c[EX_IO][i] = el->el_tty.t_vdisable;
1044 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
1048 if (tty_setty(el, &el->el_tty.t_ed) == -1) {
1050 (void) fprintf(el->el_errfile, "tty_rawmode: tty_setty: %s\n",
1052 #endif /* DEBUG_TTY */
1055 el->el_tty.t_mode = ED_IO;
1060 /* tty_cookedmode():
1061 * Set the tty back to normal mode
1064 tty_cookedmode(EditLine *el)
1065 { /* set tty in normal setup */
1067 if (el->el_tty.t_mode == EX_IO)
1070 if (el->el_flags & EDIT_DISABLED)
1073 if (tty_setty(el, &el->el_tty.t_ex) == -1) {
1075 (void) fprintf(el->el_errfile,
1076 "tty_cookedmode: tty_setty: %s\n",
1078 #endif /* DEBUG_TTY */
1081 el->el_tty.t_mode = EX_IO;
1087 * Turn on quote mode
1090 tty_quotemode(EditLine *el)
1092 if (el->el_tty.t_mode == QU_IO)
1095 el->el_tty.t_qu = el->el_tty.t_ed;
1097 el->el_tty.t_qu.c_iflag &= ~el->el_tty.t_t[QU_IO][MD_INP].t_clrmask;
1098 el->el_tty.t_qu.c_iflag |= el->el_tty.t_t[QU_IO][MD_INP].t_setmask;
1100 el->el_tty.t_qu.c_oflag &= ~el->el_tty.t_t[QU_IO][MD_OUT].t_clrmask;
1101 el->el_tty.t_qu.c_oflag |= el->el_tty.t_t[QU_IO][MD_OUT].t_setmask;
1103 el->el_tty.t_qu.c_cflag &= ~el->el_tty.t_t[QU_IO][MD_CTL].t_clrmask;
1104 el->el_tty.t_qu.c_cflag |= el->el_tty.t_t[QU_IO][MD_CTL].t_setmask;
1106 el->el_tty.t_qu.c_lflag &= ~el->el_tty.t_t[QU_IO][MD_LIN].t_clrmask;
1107 el->el_tty.t_qu.c_lflag |= el->el_tty.t_t[QU_IO][MD_LIN].t_setmask;
1109 if (tty_setty(el, &el->el_tty.t_qu) == -1) {
1111 (void) fprintf(el->el_errfile, "QuoteModeOn: tty_setty: %s\n",
1113 #endif /* DEBUG_TTY */
1116 el->el_tty.t_mode = QU_IO;
1121 /* tty_noquotemode():
1122 * Turn off quote mode
1125 tty_noquotemode(EditLine *el)
1128 if (el->el_tty.t_mode != QU_IO)
1130 if (tty_setty(el, &el->el_tty.t_ed) == -1) {
1132 (void) fprintf(el->el_errfile, "QuoteModeOff: tty_setty: %s\n",
1134 #endif /* DEBUG_TTY */
1137 el->el_tty.t_mode = ED_IO;
1147 tty_stty(EditLine *el, int argc __attribute__((__unused__)), const char **argv)
1149 const ttymodes_t *m;
1154 struct termios *tios = &el->el_tty.t_ex;
1161 while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0')
1162 switch (argv[0][1]) {
1169 tios = &el->el_tty.t_ed;
1174 tios = &el->el_tty.t_ex;
1179 tios = &el->el_tty.t_ts;
1183 (void) fprintf(el->el_errfile,
1184 "%s: Unknown switch `%c'.\n",
1189 if (!argv || !*argv) {
1191 int len = 0, st = 0, cu;
1192 for (m = ttymodes; m->m_name; m++) {
1193 if (m->m_type != i) {
1194 (void) fprintf(el->el_outfile, "%s%s",
1195 i != -1 ? "\n" : "",
1196 el->el_tty.t_t[z][m->m_type].t_name);
1199 strlen(el->el_tty.t_t[z][m->m_type].t_name);
1202 x = (el->el_tty.t_t[z][i].t_setmask & m->m_value)
1204 x = (el->el_tty.t_t[z][i].t_clrmask & m->m_value)
1210 if (x != '\0' || aflag) {
1212 cu = strlen(m->m_name) + (x != '\0') + 1;
1214 if (len + cu >= el->el_term.t_size.h) {
1215 (void) fprintf(el->el_outfile, "\n%*s",
1222 (void) fprintf(el->el_outfile, "%c%s ",
1225 (void) fprintf(el->el_outfile, "%s ",
1229 (void) fprintf(el->el_outfile, "\n");
1232 while (argv && (s = *argv++)) {
1245 for (m = ttymodes; m->m_name; m++)
1246 if ((p ? strncmp(m->m_name, d, (size_t)(p - d)) :
1247 strcmp(m->m_name, d)) == 0 &&
1248 (p == NULL || m->m_type == MD_CHAR))
1252 (void) fprintf(el->el_errfile,
1253 "%s: Invalid argument `%s'.\n", name, d);
1257 int c = ffs((int)m->m_value);
1258 int v = *++p ? parse__escape((const char **) &p) :
1259 el->el_tty.t_vdisable;
1261 c = tty__getcharindex(c);
1268 el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value;
1269 el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
1272 el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
1273 el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value;
1276 el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
1277 el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
1287 * DEbugging routine to print the tty characters
1290 tty_printchar(EditLine *el, unsigned char *s)
1295 for (i = 0; i < C_NCC; i++) {
1296 for (m = el->el_tty.t_t; m->m_name; m++)
1297 if (m->m_type == MD_CHAR && C_SH(i) == m->m_value)
1300 (void) fprintf(el->el_errfile, "%s ^%c ",
1301 m->m_name, s[i] + 'A' - 1);
1303 (void) fprintf(el->el_errfile, "\n");
1305 (void) fprintf(el->el_errfile, "\n");