1 /* $NetBSD: tty.c,v 1.59 2016/03/22 01:34:32 christos Exp $ */
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * Christos Zoulas of Cornell University.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #if !defined(lint) && !defined(SCCSID)
38 static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) 6/4/93";
40 __RCSID("$NetBSD: tty.c,v 1.59 2016/03/22 01:34:32 christos Exp $");
42 #endif /* not lint && not SCCSID */
43 #include <sys/cdefs.h>
44 __FBSDID("$FreeBSD$");
47 * tty.c: tty interface stuff
51 #include <stdlib.h> /* for abort */
53 #include <strings.h> /* for ffs */
54 #include <unistd.h> /* for isatty */
59 typedef struct ttymodes_t {
65 typedef struct ttymap_t {
66 wint_t nch, och; /* Internal and termio rep of chars */
67 el_action_t bind[3]; /* emacs, vi, and vi-cmd */
71 private const ttyperm_t ttyperm = {
73 {"iflag:", ICRNL, (INLCR | IGNCR)},
74 {"oflag:", (OPOST | ONLCR), ONLRET},
76 {"lflag:", (ISIG | ICANON | ECHO | ECHOE | ECHOCTL | IEXTEN),
77 (NOFLSH | ECHONL | EXTPROC | FLUSHO)},
81 {"iflag:", (INLCR | ICRNL), IGNCR},
82 {"oflag:", (OPOST | ONLCR), ONLRET},
85 (NOFLSH | ICANON | ECHO | ECHOK | ECHONL | EXTPROC | IEXTEN | FLUSHO)},
86 {"chars:", (C_SH(C_MIN) | C_SH(C_TIME) | C_SH(C_SWTCH) | C_SH(C_DSWTCH) |
87 C_SH(C_SUSP) | C_SH(C_DSUSP) | C_SH(C_EOL) | C_SH(C_DISCARD) |
88 C_SH(C_PGOFF) | C_SH(C_PAGE) | C_SH(C_STATUS)), 0}
91 {"iflag:", 0, IXON | IXOFF | INLCR | ICRNL},
94 {"lflag:", 0, ISIG | IEXTEN},
99 private const ttychar_t ttychar = {
101 CINTR, CQUIT, CERASE, CKILL,
102 CEOF, CEOL, CEOL2, CSWTCH,
103 CDSWTCH, CERASE2, CSTART, CSTOP,
104 CWERASE, CSUSP, CDSUSP, CREPRINT,
105 CDISCARD, CLNEXT, CSTATUS, CPAGE,
106 CPGOFF, CKILL2, CBRK, CMIN,
110 CINTR, CQUIT, CERASE, CKILL,
111 _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
112 _POSIX_VDISABLE, CERASE2, CSTART, CSTOP,
113 _POSIX_VDISABLE, CSUSP, _POSIX_VDISABLE, _POSIX_VDISABLE,
114 CDISCARD, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
115 _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 1,
129 private const ttymap_t tty_map[] = {
132 {EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
136 {EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
140 {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
144 {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
148 {EM_DELETE_OR_LIST, VI_LIST_OR_EOF, ED_UNASSIGNED}},
152 {ED_DELETE_PREV_WORD, ED_DELETE_PREV_WORD, ED_PREV_WORD}},
155 {C_REPRINT, VREPRINT,
156 {ED_REDISPLAY, ED_INSERT, ED_REDISPLAY}},
157 #endif /* VREPRINT */
160 {ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED}},
162 {(wint_t)-1, (wint_t)-1,
163 {ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED}}
166 private const ttymodes_t ttymodes[] = {
168 {"ignbrk", IGNBRK, MD_INP},
171 {"brkint", BRKINT, MD_INP},
174 {"ignpar", IGNPAR, MD_INP},
177 {"parmrk", PARMRK, MD_INP},
180 {"inpck", INPCK, MD_INP},
183 {"istrip", ISTRIP, MD_INP},
186 {"inlcr", INLCR, MD_INP},
189 {"igncr", IGNCR, MD_INP},
192 {"icrnl", ICRNL, MD_INP},
195 {"iuclc", IUCLC, MD_INP},
198 {"ixon", IXON, MD_INP},
201 {"ixany", IXANY, MD_INP},
204 {"ixoff", IXOFF, MD_INP},
207 {"imaxbel", IMAXBEL, MD_INP},
211 {"opost", OPOST, MD_OUT},
214 {"olcuc", OLCUC, MD_OUT},
217 {"onlcr", ONLCR, MD_OUT},
220 {"ocrnl", OCRNL, MD_OUT},
223 {"onocr", ONOCR, MD_OUT},
226 {"onoeot", ONOEOT, MD_OUT},
229 {"onlret", ONLRET, MD_OUT},
232 {"ofill", OFILL, MD_OUT},
235 {"ofdel", OFDEL, MD_OUT},
238 {"nldly", NLDLY, MD_OUT},
241 {"crdly", CRDLY, MD_OUT},
244 {"tabdly", TABDLY, MD_OUT},
247 {"xtabs", XTABS, MD_OUT},
250 {"bsdly", BSDLY, MD_OUT},
253 {"vtdly", VTDLY, MD_OUT},
256 {"ffdly", FFDLY, MD_OUT},
259 {"pageout", PAGEOUT, MD_OUT},
262 {"wrap", WRAP, MD_OUT},
266 {"cignore", CIGNORE, MD_CTL},
269 {"cbaud", CBAUD, MD_CTL},
272 {"cstopb", CSTOPB, MD_CTL},
275 {"cread", CREAD, MD_CTL},
278 {"parenb", PARENB, MD_CTL},
281 {"parodd", PARODD, MD_CTL},
284 {"hupcl", HUPCL, MD_CTL},
287 {"clocal", CLOCAL, MD_CTL},
290 {"loblk", LOBLK, MD_CTL},
293 {"cibaud", CIBAUD, MD_CTL},
297 {"ccts_oflow", CCTS_OFLOW, MD_CTL},
299 {"crtscts", CRTSCTS, MD_CTL},
300 #endif /* CCTS_OFLOW */
303 {"crts_iflow", CRTS_IFLOW, MD_CTL},
304 #endif /* CRTS_IFLOW */
306 {"cdtrcts", CDTRCTS, MD_CTL},
309 {"mdmbuf", MDMBUF, MD_CTL},
312 {"rcv1en", RCV1EN, MD_CTL},
315 {"xmt1en", XMT1EN, MD_CTL},
319 {"isig", ISIG, MD_LIN},
322 {"icanon", ICANON, MD_LIN},
325 {"xcase", XCASE, MD_LIN},
328 {"echo", ECHO, MD_LIN},
331 {"echoe", ECHOE, MD_LIN},
334 {"echok", ECHOK, MD_LIN},
337 {"echonl", ECHONL, MD_LIN},
340 {"noflsh", NOFLSH, MD_LIN},
343 {"tostop", TOSTOP, MD_LIN},
346 {"echoctl", ECHOCTL, MD_LIN},
349 {"echoprt", ECHOPRT, MD_LIN},
352 {"echoke", ECHOKE, MD_LIN},
355 {"defecho", DEFECHO, MD_LIN},
358 {"flusho", FLUSHO, MD_LIN},
361 {"pendin", PENDIN, MD_LIN},
364 {"iexten", IEXTEN, MD_LIN},
367 {"nokerninfo", NOKERNINFO, MD_LIN},
368 #endif /* NOKERNINFO */
370 {"altwerase", ALTWERASE, MD_LIN},
371 #endif /* ALTWERASE */
373 {"extproc", EXTPROC, MD_LIN},
377 {"intr", C_SH(C_INTR), MD_CHAR},
380 {"quit", C_SH(C_QUIT), MD_CHAR},
383 {"erase", C_SH(C_ERASE), MD_CHAR},
386 {"kill", C_SH(C_KILL), MD_CHAR},
389 {"eof", C_SH(C_EOF), MD_CHAR},
392 {"eol", C_SH(C_EOL), MD_CHAR},
395 {"eol2", C_SH(C_EOL2), MD_CHAR},
398 {"swtch", C_SH(C_SWTCH), MD_CHAR},
401 {"dswtch", C_SH(C_DSWTCH), MD_CHAR},
404 {"erase2", C_SH(C_ERASE2), MD_CHAR},
407 {"start", C_SH(C_START), MD_CHAR},
410 {"stop", C_SH(C_STOP), MD_CHAR},
413 {"werase", C_SH(C_WERASE), MD_CHAR},
416 {"susp", C_SH(C_SUSP), MD_CHAR},
419 {"dsusp", C_SH(C_DSUSP), MD_CHAR},
421 #if defined(VREPRINT)
422 {"reprint", C_SH(C_REPRINT), MD_CHAR},
423 #endif /* VREPRINT */
424 #if defined(VDISCARD)
425 {"discard", C_SH(C_DISCARD), MD_CHAR},
426 #endif /* VDISCARD */
428 {"lnext", C_SH(C_LNEXT), MD_CHAR},
431 {"status", C_SH(C_STATUS), MD_CHAR},
434 {"page", C_SH(C_PAGE), MD_CHAR},
437 {"pgoff", C_SH(C_PGOFF), MD_CHAR},
440 {"kill2", C_SH(C_KILL2), MD_CHAR},
443 {"brk", C_SH(C_BRK), MD_CHAR},
446 {"min", C_SH(C_MIN), MD_CHAR},
449 {"time", C_SH(C_TIME), MD_CHAR},
456 #define tty__gettabs(td) ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1)
457 #define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8)
458 #define tty__cooked_mode(td) ((td)->c_lflag & ICANON)
460 private int tty_getty(EditLine *, struct termios *);
461 private int tty_setty(EditLine *, int, const struct termios *);
462 private int tty__getcharindex(int);
463 private void tty__getchar(struct termios *, unsigned char *);
464 private void tty__setchar(struct termios *, unsigned char *);
465 private speed_t tty__getspeed(struct termios *);
466 private int tty_setup(EditLine *);
467 private void tty_setup_flags(EditLine *, struct termios *, int);
472 * Wrapper for tcgetattr to handle EINTR
475 tty_getty(EditLine *el, struct termios *t)
478 while ((rv = tcgetattr(el->el_infd, t)) == -1 && errno == EINTR)
484 * Wrapper for tcsetattr to handle EINTR
487 tty_setty(EditLine *el, int action, const struct termios *t)
490 while ((rv = tcsetattr(el->el_infd, action, t)) == -1 && errno == EINTR)
496 * Get the tty parameters and initialize the editing state
499 tty_setup(EditLine *el)
503 if (el->el_flags & EDIT_DISABLED)
506 if (el->el_tty.t_initialized)
509 if (!isatty(el->el_outfd)) {
511 (void) fprintf(el->el_errfile, "%s: isatty: %s\n", __func__,
513 #endif /* DEBUG_TTY */
516 if (tty_getty(el, &el->el_tty.t_or) == -1) {
518 (void) fprintf(el->el_errfile, "%s: tty_getty: %s\n", __func__,
520 #endif /* DEBUG_TTY */
523 el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed = el->el_tty.t_or;
525 el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex);
526 el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex);
527 el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex);
529 tty_setup_flags(el, &el->el_tty.t_ex, EX_IO);
532 * Reset the tty chars to reasonable defaults
533 * If they are disabled, then enable them.
536 if (tty__cooked_mode(&el->el_tty.t_ts)) {
537 tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
539 * Don't affect CMIN and CTIME for the editor mode
541 for (rst = 0; rst < C_NCC - 2; rst++)
542 if (el->el_tty.t_c[TS_IO][rst] !=
543 el->el_tty.t_vdisable
544 && el->el_tty.t_c[ED_IO][rst] !=
545 el->el_tty.t_vdisable)
546 el->el_tty.t_c[ED_IO][rst] =
547 el->el_tty.t_c[TS_IO][rst];
548 for (rst = 0; rst < C_NCC; rst++)
549 if (el->el_tty.t_c[TS_IO][rst] !=
550 el->el_tty.t_vdisable)
551 el->el_tty.t_c[EX_IO][rst] =
552 el->el_tty.t_c[TS_IO][rst];
554 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
555 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) {
557 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n",
558 __func__, strerror(errno));
559 #endif /* DEBUG_TTY */
564 tty_setup_flags(el, &el->el_tty.t_ed, ED_IO);
566 tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
567 tty_bind_char(el, 1);
568 el->el_tty.t_initialized = 1;
573 tty_init(EditLine *el)
576 el->el_tty.t_mode = EX_IO;
577 el->el_tty.t_vdisable = _POSIX_VDISABLE;
578 el->el_tty.t_initialized = 0;
579 (void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t));
580 (void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t));
581 return tty_setup(el);
586 * Restore the tty to its original settings
590 tty_end(EditLine *el)
592 if (el->el_flags & EDIT_DISABLED)
595 if (!el->el_tty.t_initialized)
598 if (tty_setty(el, TCSAFLUSH, &el->el_tty.t_or) == -1) {
600 (void) fprintf(el->el_errfile,
601 "%s: tty_setty: %s\n", __func__, strerror(errno));
602 #endif /* DEBUG_TTY */
611 tty__getspeed(struct termios *td)
615 if ((spd = cfgetispeed(td)) == 0)
616 spd = cfgetospeed(td);
621 * Return the index of the asked char in the c_cc array
624 tty__getcharindex(int i)
690 #endif /* VREPRINT */
694 #endif /* VDISCARD */
729 * Get the tty characters
732 tty__getchar(struct termios *td, unsigned char *s)
736 s[C_INTR] = td->c_cc[VINTR];
739 s[C_QUIT] = td->c_cc[VQUIT];
742 s[C_ERASE] = td->c_cc[VERASE];
745 s[C_KILL] = td->c_cc[VKILL];
748 s[C_EOF] = td->c_cc[VEOF];
751 s[C_EOL] = td->c_cc[VEOL];
754 s[C_EOL2] = td->c_cc[VEOL2];
757 s[C_SWTCH] = td->c_cc[VSWTCH];
760 s[C_DSWTCH] = td->c_cc[VDSWTCH];
763 s[C_ERASE2] = td->c_cc[VERASE2];
766 s[C_START] = td->c_cc[VSTART];
769 s[C_STOP] = td->c_cc[VSTOP];
772 s[C_WERASE] = td->c_cc[VWERASE];
775 s[C_SUSP] = td->c_cc[VSUSP];
778 s[C_DSUSP] = td->c_cc[VDSUSP];
781 s[C_REPRINT] = td->c_cc[VREPRINT];
782 #endif /* VREPRINT */
784 s[C_DISCARD] = td->c_cc[VDISCARD];
785 #endif /* VDISCARD */
787 s[C_LNEXT] = td->c_cc[VLNEXT];
790 s[C_STATUS] = td->c_cc[VSTATUS];
793 s[C_PAGE] = td->c_cc[VPAGE];
796 s[C_PGOFF] = td->c_cc[VPGOFF];
799 s[C_KILL2] = td->c_cc[VKILL2];
802 s[C_MIN] = td->c_cc[VMIN];
805 s[C_TIME] = td->c_cc[VTIME];
811 * Set the tty characters
814 tty__setchar(struct termios *td, unsigned char *s)
818 td->c_cc[VINTR] = s[C_INTR];
821 td->c_cc[VQUIT] = s[C_QUIT];
824 td->c_cc[VERASE] = s[C_ERASE];
827 td->c_cc[VKILL] = s[C_KILL];
830 td->c_cc[VEOF] = s[C_EOF];
833 td->c_cc[VEOL] = s[C_EOL];
836 td->c_cc[VEOL2] = s[C_EOL2];
839 td->c_cc[VSWTCH] = s[C_SWTCH];
842 td->c_cc[VDSWTCH] = s[C_DSWTCH];
845 td->c_cc[VERASE2] = s[C_ERASE2];
848 td->c_cc[VSTART] = s[C_START];
851 td->c_cc[VSTOP] = s[C_STOP];
854 td->c_cc[VWERASE] = s[C_WERASE];
857 td->c_cc[VSUSP] = s[C_SUSP];
860 td->c_cc[VDSUSP] = s[C_DSUSP];
863 td->c_cc[VREPRINT] = s[C_REPRINT];
864 #endif /* VREPRINT */
866 td->c_cc[VDISCARD] = s[C_DISCARD];
867 #endif /* VDISCARD */
869 td->c_cc[VLNEXT] = s[C_LNEXT];
872 td->c_cc[VSTATUS] = s[C_STATUS];
875 td->c_cc[VPAGE] = s[C_PAGE];
878 td->c_cc[VPGOFF] = s[C_PGOFF];
881 td->c_cc[VKILL2] = s[C_KILL2];
884 td->c_cc[VMIN] = s[C_MIN];
887 td->c_cc[VTIME] = s[C_TIME];
893 * Rebind the editline functions
896 tty_bind_char(EditLine *el, int force)
899 unsigned char *t_n = el->el_tty.t_c[ED_IO];
900 unsigned char *t_o = el->el_tty.t_ed.c_cc;
903 el_action_t *map, *alt;
904 const el_action_t *dmap, *dalt;
905 new[1] = old[1] = '\0';
907 map = el->el_map.key;
908 alt = el->el_map.alt;
909 if (el->el_map.type == MAP_VI) {
910 dmap = el->el_map.vii;
911 dalt = el->el_map.vic;
913 dmap = el->el_map.emacs;
917 for (tp = tty_map; tp->nch != (wint_t)-1; tp++) {
918 new[0] = (Char)t_n[tp->nch];
919 old[0] = (Char)t_o[tp->och];
920 if (new[0] == old[0] && !force)
922 /* Put the old default binding back, and set the new binding */
923 keymacro_clear(el, map, old);
924 map[UC(old[0])] = dmap[UC(old[0])];
925 keymacro_clear(el, map, new);
926 /* MAP_VI == 1, MAP_EMACS == 0... */
927 map[UC(new[0])] = tp->bind[el->el_map.type];
929 keymacro_clear(el, alt, old);
930 alt[UC(old[0])] = dalt[UC(old[0])];
931 keymacro_clear(el, alt, new);
932 alt[UC(new[0])] = tp->bind[el->el_map.type + 1];
939 tty__get_flag(struct termios *t, int kind) {
957 tty_update_flag(EditLine *el, tcflag_t f, int mode, int kind)
959 f &= ~el->el_tty.t_t[mode][kind].t_clrmask;
960 f |= el->el_tty.t_t[mode][kind].t_setmask;
966 tty_update_flags(EditLine *el, int kind)
968 tcflag_t *tt, *ed, *ex;
969 tt = tty__get_flag(&el->el_tty.t_ts, kind);
970 ed = tty__get_flag(&el->el_tty.t_ed, kind);
971 ex = tty__get_flag(&el->el_tty.t_ex, kind);
973 if (*tt != *ex && (kind != MD_CTL || *tt != *ed)) {
974 *ed = tty_update_flag(el, *tt, ED_IO, kind);
975 *ex = tty_update_flag(el, *tt, EX_IO, kind);
981 tty_update_char(EditLine *el, int mode, int c) {
982 if (!((el->el_tty.t_t[mode][MD_CHAR].t_setmask & C_SH(c)))
983 && (el->el_tty.t_c[TS_IO][c] != el->el_tty.t_c[EX_IO][c]))
984 el->el_tty.t_c[mode][c] = el->el_tty.t_c[TS_IO][c];
985 if (el->el_tty.t_t[mode][MD_CHAR].t_clrmask & C_SH(c))
986 el->el_tty.t_c[mode][c] = el->el_tty.t_vdisable;
991 * Set terminal into 1 character at a time mode.
994 tty_rawmode(EditLine *el)
997 if (el->el_tty.t_mode == ED_IO || el->el_tty.t_mode == QU_IO)
1000 if (el->el_flags & EDIT_DISABLED)
1003 if (tty_getty(el, &el->el_tty.t_ts) == -1) {
1005 (void) fprintf(el->el_errfile, "%s: tty_getty: %s\n", __func__,
1007 #endif /* DEBUG_TTY */
1011 * We always keep up with the eight bit setting and the speed of the
1012 * tty. But we only believe changes that are made to cooked mode!
1014 el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts);
1015 el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts);
1017 if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed ||
1018 tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) {
1019 (void) cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed);
1020 (void) cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed);
1021 (void) cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed);
1022 (void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed);
1024 if (tty__cooked_mode(&el->el_tty.t_ts)) {
1027 for (i = MD_INP; i <= MD_LIN; i++)
1028 tty_update_flags(el, i);
1030 if (tty__gettabs(&el->el_tty.t_ex) == 0)
1031 el->el_tty.t_tabs = 0;
1033 el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0;
1035 tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
1037 * Check if the user made any changes.
1038 * If he did, then propagate the changes to the
1039 * edit and execute data structures.
1041 for (i = 0; i < C_NCC; i++)
1042 if (el->el_tty.t_c[TS_IO][i] !=
1043 el->el_tty.t_c[EX_IO][i])
1048 * Propagate changes only to the unprotected
1049 * chars that have been modified just now.
1051 for (i = 0; i < C_NCC; i++)
1052 tty_update_char(el, ED_IO, i);
1054 tty_bind_char(el, 0);
1055 tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
1057 for (i = 0; i < C_NCC; i++)
1058 tty_update_char(el, EX_IO, i);
1060 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
1063 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) {
1065 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1067 #endif /* DEBUG_TTY */
1070 el->el_tty.t_mode = ED_IO;
1075 /* tty_cookedmode():
1076 * Set the tty back to normal mode
1079 tty_cookedmode(EditLine *el)
1080 { /* set tty in normal setup */
1082 if (el->el_tty.t_mode == EX_IO)
1085 if (el->el_flags & EDIT_DISABLED)
1088 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) {
1090 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1092 #endif /* DEBUG_TTY */
1095 el->el_tty.t_mode = EX_IO;
1101 * Turn on quote mode
1104 tty_quotemode(EditLine *el)
1106 if (el->el_tty.t_mode == QU_IO)
1109 el->el_tty.t_qu = el->el_tty.t_ed;
1111 tty_setup_flags(el, &el->el_tty.t_qu, QU_IO);
1113 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_qu) == -1) {
1115 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1117 #endif /* DEBUG_TTY */
1120 el->el_tty.t_mode = QU_IO;
1125 /* tty_noquotemode():
1126 * Turn off quote mode
1129 tty_noquotemode(EditLine *el)
1132 if (el->el_tty.t_mode != QU_IO)
1134 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) {
1136 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1138 #endif /* DEBUG_TTY */
1141 el->el_tty.t_mode = ED_IO;
1151 tty_stty(EditLine *el, int argc __attribute__((__unused__)), const Char **argv)
1153 const ttymodes_t *m;
1157 char name[EL_BUFSIZ];
1158 struct termios *tios = &el->el_tty.t_ex;
1163 strncpy(name, ct_encode_string(*argv++, &el->el_scratch), sizeof(name));
1164 name[sizeof(name) - 1] = '\0';
1166 while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0')
1167 switch (argv[0][1]) {
1174 tios = &el->el_tty.t_ed;
1179 tios = &el->el_tty.t_ex;
1184 tios = &el->el_tty.t_ts;
1188 (void) fprintf(el->el_errfile,
1189 "%s: Unknown switch `%lc'.\n",
1190 name, (wint_t)argv[0][1]);
1194 if (!argv || !*argv) {
1196 size_t len = 0, st = 0, cu;
1197 for (m = ttymodes; m->m_name; m++) {
1198 if (m->m_type != i) {
1199 (void) fprintf(el->el_outfile, "%s%s",
1200 i != -1 ? "\n" : "",
1201 el->el_tty.t_t[z][m->m_type].t_name);
1204 strlen(el->el_tty.t_t[z][m->m_type].t_name);
1207 x = (el->el_tty.t_t[z][i].t_setmask & m->m_value)
1210 if (el->el_tty.t_t[z][i].t_clrmask & m->m_value)
1216 if (x != '\0' || aflag) {
1218 cu = strlen(m->m_name) + (x != '\0') + 1;
1221 (size_t)el->el_terminal.t_size.h) {
1222 (void) fprintf(el->el_outfile, "\n%*s",
1229 (void) fprintf(el->el_outfile, "%c%s ",
1232 (void) fprintf(el->el_outfile, "%s ",
1236 (void) fprintf(el->el_outfile, "\n");
1239 while (argv && (s = *argv++)) {
1252 for (m = ttymodes; m->m_name; m++)
1253 if ((p ? strncmp(m->m_name, ct_encode_string(d,
1254 &el->el_scratch), (size_t)(p - d)) :
1255 strcmp(m->m_name, ct_encode_string(d,
1256 &el->el_scratch))) == 0 &&
1257 (p == NULL || m->m_type == MD_CHAR))
1261 (void) fprintf(el->el_errfile,
1262 "%s: Invalid argument `" FSTR "'.\n", name, d);
1266 int c = ffs((int)m->m_value);
1267 int v = *++p ? parse__escape(&p) :
1268 el->el_tty.t_vdisable;
1271 c = tty__getcharindex(c);
1273 tios->c_cc[c] = (cc_t)v;
1278 el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value;
1279 el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
1282 el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
1283 el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value;
1286 el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
1287 el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
1292 tty_setup_flags(el, tios, z);
1293 if (el->el_tty.t_mode == z) {
1294 if (tty_setty(el, TCSADRAIN, tios) == -1) {
1296 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n",
1297 __func__, strerror(errno));
1298 #endif /* DEBUG_TTY */
1309 * DEbugging routine to print the tty characters
1312 tty_printchar(EditLine *el, unsigned char *s)
1317 for (i = 0; i < C_NCC; i++) {
1318 for (m = el->el_tty.t_t; m->m_name; m++)
1319 if (m->m_type == MD_CHAR && C_SH(i) == m->m_value)
1322 (void) fprintf(el->el_errfile, "%s ^%c ",
1323 m->m_name, s[i] + 'A' - 1);
1325 (void) fprintf(el->el_errfile, "\n");
1327 (void) fprintf(el->el_errfile, "\n");
1333 tty_setup_flags(EditLine *el, struct termios *tios, int mode)
1336 for (kind = MD_INP; kind <= MD_LIN; kind++) {
1337 tcflag_t *f = tty__get_flag(tios, kind);
1338 *f = tty_update_flag(el, *f, mode, kind);