1 /* $NetBSD: tty.c,v 1.47 2015/05/14 10:44:15 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.47 2015/05/14 10:44:15 christos Exp $");
42 #endif /* not lint && not SCCSID */
43 #include <sys/cdefs.h>
44 __FBSDID("$FreeBSD$");
47 * tty.c: tty interface stuff
51 #include <unistd.h> /* for isatty */
52 #include <strings.h> /* for ffs */
53 #include <stdlib.h> /* for abort */
57 typedef struct ttymodes_t {
63 typedef struct ttymap_t {
64 Int nch, och; /* Internal and termio rep of chars */
65 el_action_t bind[3]; /* emacs, vi, and vi-cmd */
69 private const ttyperm_t ttyperm = {
71 {"iflag:", ICRNL, (INLCR | IGNCR)},
72 {"oflag:", (OPOST | ONLCR), ONLRET},
74 {"lflag:", (ISIG | ICANON | ECHO | ECHOE | ECHOCTL | IEXTEN),
75 (NOFLSH | ECHONL | EXTPROC | FLUSHO)},
79 {"iflag:", (INLCR | ICRNL), IGNCR},
80 {"oflag:", (OPOST | ONLCR), ONLRET},
83 (NOFLSH | ICANON | ECHO | ECHOK | ECHONL | EXTPROC | IEXTEN | FLUSHO)},
84 {"chars:", (C_SH(C_MIN) | C_SH(C_TIME) | C_SH(C_SWTCH) | C_SH(C_DSWTCH) |
85 C_SH(C_SUSP) | C_SH(C_DSUSP) | C_SH(C_EOL) | C_SH(C_DISCARD) |
86 C_SH(C_PGOFF) | C_SH(C_PAGE) | C_SH(C_STATUS)), 0}
89 {"iflag:", 0, IXON | IXOFF | INLCR | ICRNL},
92 {"lflag:", 0, ISIG | IEXTEN},
97 private const ttychar_t ttychar = {
99 CINTR, CQUIT, CERASE, CKILL,
100 CEOF, CEOL, CEOL2, CSWTCH,
101 CDSWTCH, CERASE2, CSTART, CSTOP,
102 CWERASE, CSUSP, CDSUSP, CREPRINT,
103 CDISCARD, CLNEXT, CSTATUS, CPAGE,
104 CPGOFF, CKILL2, CBRK, CMIN,
108 CINTR, CQUIT, CERASE, CKILL,
109 _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
110 _POSIX_VDISABLE, CERASE2, CSTART, CSTOP,
111 _POSIX_VDISABLE, CSUSP, _POSIX_VDISABLE, _POSIX_VDISABLE,
112 CDISCARD, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
113 _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 1,
127 private const ttymap_t tty_map[] = {
130 {EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
134 {EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
138 {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
142 {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
146 {EM_DELETE_OR_LIST, VI_LIST_OR_EOF, ED_UNASSIGNED}},
150 {ED_DELETE_PREV_WORD, ED_DELETE_PREV_WORD, ED_PREV_WORD}},
153 {C_REPRINT, VREPRINT,
154 {ED_REDISPLAY, ED_INSERT, ED_REDISPLAY}},
155 #endif /* VREPRINT */
158 {ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED}},
161 {ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED}}
164 private const ttymodes_t ttymodes[] = {
166 {"ignbrk", IGNBRK, MD_INP},
169 {"brkint", BRKINT, MD_INP},
172 {"ignpar", IGNPAR, MD_INP},
175 {"parmrk", PARMRK, MD_INP},
178 {"inpck", INPCK, MD_INP},
181 {"istrip", ISTRIP, MD_INP},
184 {"inlcr", INLCR, MD_INP},
187 {"igncr", IGNCR, MD_INP},
190 {"icrnl", ICRNL, MD_INP},
193 {"iuclc", IUCLC, MD_INP},
196 {"ixon", IXON, MD_INP},
199 {"ixany", IXANY, MD_INP},
202 {"ixoff", IXOFF, MD_INP},
205 {"imaxbel", IMAXBEL, MD_INP},
209 {"opost", OPOST, MD_OUT},
212 {"olcuc", OLCUC, MD_OUT},
215 {"onlcr", ONLCR, MD_OUT},
218 {"ocrnl", OCRNL, MD_OUT},
221 {"onocr", ONOCR, MD_OUT},
224 {"onoeot", ONOEOT, MD_OUT},
227 {"onlret", ONLRET, MD_OUT},
230 {"ofill", OFILL, MD_OUT},
233 {"ofdel", OFDEL, MD_OUT},
236 {"nldly", NLDLY, MD_OUT},
239 {"crdly", CRDLY, MD_OUT},
242 {"tabdly", TABDLY, MD_OUT},
245 {"xtabs", XTABS, MD_OUT},
248 {"bsdly", BSDLY, MD_OUT},
251 {"vtdly", VTDLY, MD_OUT},
254 {"ffdly", FFDLY, MD_OUT},
257 {"pageout", PAGEOUT, MD_OUT},
260 {"wrap", WRAP, MD_OUT},
264 {"cignore", CIGNORE, MD_CTL},
267 {"cbaud", CBAUD, MD_CTL},
270 {"cstopb", CSTOPB, MD_CTL},
273 {"cread", CREAD, MD_CTL},
276 {"parenb", PARENB, MD_CTL},
279 {"parodd", PARODD, MD_CTL},
282 {"hupcl", HUPCL, MD_CTL},
285 {"clocal", CLOCAL, MD_CTL},
288 {"loblk", LOBLK, MD_CTL},
291 {"cibaud", CIBAUD, MD_CTL},
295 {"ccts_oflow", CCTS_OFLOW, MD_CTL},
297 {"crtscts", CRTSCTS, MD_CTL},
298 #endif /* CCTS_OFLOW */
301 {"crts_iflow", CRTS_IFLOW, MD_CTL},
302 #endif /* CRTS_IFLOW */
304 {"cdtrcts", CDTRCTS, MD_CTL},
307 {"mdmbuf", MDMBUF, MD_CTL},
310 {"rcv1en", RCV1EN, MD_CTL},
313 {"xmt1en", XMT1EN, MD_CTL},
317 {"isig", ISIG, MD_LIN},
320 {"icanon", ICANON, MD_LIN},
323 {"xcase", XCASE, MD_LIN},
326 {"echo", ECHO, MD_LIN},
329 {"echoe", ECHOE, MD_LIN},
332 {"echok", ECHOK, MD_LIN},
335 {"echonl", ECHONL, MD_LIN},
338 {"noflsh", NOFLSH, MD_LIN},
341 {"tostop", TOSTOP, MD_LIN},
344 {"echoctl", ECHOCTL, MD_LIN},
347 {"echoprt", ECHOPRT, MD_LIN},
350 {"echoke", ECHOKE, MD_LIN},
353 {"defecho", DEFECHO, MD_LIN},
356 {"flusho", FLUSHO, MD_LIN},
359 {"pendin", PENDIN, MD_LIN},
362 {"iexten", IEXTEN, MD_LIN},
365 {"nokerninfo", NOKERNINFO, MD_LIN},
366 #endif /* NOKERNINFO */
368 {"altwerase", ALTWERASE, MD_LIN},
369 #endif /* ALTWERASE */
371 {"extproc", EXTPROC, MD_LIN},
375 {"intr", C_SH(C_INTR), MD_CHAR},
378 {"quit", C_SH(C_QUIT), MD_CHAR},
381 {"erase", C_SH(C_ERASE), MD_CHAR},
384 {"kill", C_SH(C_KILL), MD_CHAR},
387 {"eof", C_SH(C_EOF), MD_CHAR},
390 {"eol", C_SH(C_EOL), MD_CHAR},
393 {"eol2", C_SH(C_EOL2), MD_CHAR},
396 {"swtch", C_SH(C_SWTCH), MD_CHAR},
399 {"dswtch", C_SH(C_DSWTCH), MD_CHAR},
402 {"erase2", C_SH(C_ERASE2), MD_CHAR},
405 {"start", C_SH(C_START), MD_CHAR},
408 {"stop", C_SH(C_STOP), MD_CHAR},
411 {"werase", C_SH(C_WERASE), MD_CHAR},
414 {"susp", C_SH(C_SUSP), MD_CHAR},
417 {"dsusp", C_SH(C_DSUSP), MD_CHAR},
419 #if defined(VREPRINT)
420 {"reprint", C_SH(C_REPRINT), MD_CHAR},
421 #endif /* VREPRINT */
422 #if defined(VDISCARD)
423 {"discard", C_SH(C_DISCARD), MD_CHAR},
424 #endif /* VDISCARD */
426 {"lnext", C_SH(C_LNEXT), MD_CHAR},
429 {"status", C_SH(C_STATUS), MD_CHAR},
432 {"page", C_SH(C_PAGE), MD_CHAR},
435 {"pgoff", C_SH(C_PGOFF), MD_CHAR},
438 {"kill2", C_SH(C_KILL2), MD_CHAR},
441 {"brk", C_SH(C_BRK), MD_CHAR},
444 {"min", C_SH(C_MIN), MD_CHAR},
447 {"time", C_SH(C_TIME), MD_CHAR},
454 #define tty__gettabs(td) ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1)
455 #define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8)
456 #define tty__cooked_mode(td) ((td)->c_lflag & ICANON)
458 private int tty_getty(EditLine *, struct termios *);
459 private int tty_setty(EditLine *, int, const struct termios *);
460 private int tty__getcharindex(int);
461 private void tty__getchar(struct termios *, unsigned char *);
462 private void tty__setchar(struct termios *, unsigned char *);
463 private speed_t tty__getspeed(struct termios *);
464 private int tty_setup(EditLine *);
465 private void tty_setup_flags(EditLine *, struct termios *, int);
470 * Wrapper for tcgetattr to handle EINTR
473 tty_getty(EditLine *el, struct termios *t)
476 while ((rv = tcgetattr(el->el_infd, t)) == -1 && errno == EINTR)
482 * Wrapper for tcsetattr to handle EINTR
485 tty_setty(EditLine *el, int action, const struct termios *t)
488 while ((rv = tcsetattr(el->el_infd, action, t)) == -1 && errno == EINTR)
494 * Get the tty parameters and initialize the editing state
497 tty_setup(EditLine *el)
501 if (el->el_flags & EDIT_DISABLED)
504 if (!isatty(el->el_outfd)) {
506 (void) fprintf(el->el_errfile, "%s: isatty: %s\n", __func__,
508 #endif /* DEBUG_TTY */
511 if (tty_getty(el, &el->el_tty.t_or) == -1) {
513 (void) fprintf(el->el_errfile, "%s: tty_getty: %s\n", __func__,
515 #endif /* DEBUG_TTY */
518 el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed = el->el_tty.t_or;
520 el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex);
521 el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex);
522 el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex);
524 tty_setup_flags(el, &el->el_tty.t_ex, EX_IO);
527 * Reset the tty chars to reasonable defaults
528 * If they are disabled, then enable them.
531 if (tty__cooked_mode(&el->el_tty.t_ts)) {
532 tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
534 * Don't affect CMIN and CTIME for the editor mode
536 for (rst = 0; rst < C_NCC - 2; rst++)
537 if (el->el_tty.t_c[TS_IO][rst] !=
538 el->el_tty.t_vdisable
539 && el->el_tty.t_c[ED_IO][rst] !=
540 el->el_tty.t_vdisable)
541 el->el_tty.t_c[ED_IO][rst] =
542 el->el_tty.t_c[TS_IO][rst];
543 for (rst = 0; rst < C_NCC; rst++)
544 if (el->el_tty.t_c[TS_IO][rst] !=
545 el->el_tty.t_vdisable)
546 el->el_tty.t_c[EX_IO][rst] =
547 el->el_tty.t_c[TS_IO][rst];
549 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
550 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) {
552 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n",
553 __func__, strerror(errno));
554 #endif /* DEBUG_TTY */
559 tty_setup_flags(el, &el->el_tty.t_ed, ED_IO);
561 tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
562 tty_bind_char(el, 1);
567 tty_init(EditLine *el)
570 el->el_tty.t_mode = EX_IO;
571 el->el_tty.t_vdisable = _POSIX_VDISABLE;
572 (void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t));
573 (void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t));
574 return tty_setup(el);
579 * Restore the tty to its original settings
583 tty_end(EditLine *el)
585 if (tty_setty(el, TCSAFLUSH, &el->el_tty.t_or) == -1) {
587 (void) fprintf(el->el_errfile,
588 "%s: tty_setty: %s\n", __func__, strerror(errno));
589 #endif /* DEBUG_TTY */
598 tty__getspeed(struct termios *td)
602 if ((spd = cfgetispeed(td)) == 0)
603 spd = cfgetospeed(td);
608 * Return the index of the asked char in the c_cc array
611 tty__getcharindex(int i)
677 #endif /* VREPRINT */
681 #endif /* VDISCARD */
716 * Get the tty characters
719 tty__getchar(struct termios *td, unsigned char *s)
723 s[C_INTR] = td->c_cc[VINTR];
726 s[C_QUIT] = td->c_cc[VQUIT];
729 s[C_ERASE] = td->c_cc[VERASE];
732 s[C_KILL] = td->c_cc[VKILL];
735 s[C_EOF] = td->c_cc[VEOF];
738 s[C_EOL] = td->c_cc[VEOL];
741 s[C_EOL2] = td->c_cc[VEOL2];
744 s[C_SWTCH] = td->c_cc[VSWTCH];
747 s[C_DSWTCH] = td->c_cc[VDSWTCH];
750 s[C_ERASE2] = td->c_cc[VERASE2];
753 s[C_START] = td->c_cc[VSTART];
756 s[C_STOP] = td->c_cc[VSTOP];
759 s[C_WERASE] = td->c_cc[VWERASE];
762 s[C_SUSP] = td->c_cc[VSUSP];
765 s[C_DSUSP] = td->c_cc[VDSUSP];
768 s[C_REPRINT] = td->c_cc[VREPRINT];
769 #endif /* VREPRINT */
771 s[C_DISCARD] = td->c_cc[VDISCARD];
772 #endif /* VDISCARD */
774 s[C_LNEXT] = td->c_cc[VLNEXT];
777 s[C_STATUS] = td->c_cc[VSTATUS];
780 s[C_PAGE] = td->c_cc[VPAGE];
783 s[C_PGOFF] = td->c_cc[VPGOFF];
786 s[C_KILL2] = td->c_cc[VKILL2];
789 s[C_MIN] = td->c_cc[VMIN];
792 s[C_TIME] = td->c_cc[VTIME];
798 * Set the tty characters
801 tty__setchar(struct termios *td, unsigned char *s)
805 td->c_cc[VINTR] = s[C_INTR];
808 td->c_cc[VQUIT] = s[C_QUIT];
811 td->c_cc[VERASE] = s[C_ERASE];
814 td->c_cc[VKILL] = s[C_KILL];
817 td->c_cc[VEOF] = s[C_EOF];
820 td->c_cc[VEOL] = s[C_EOL];
823 td->c_cc[VEOL2] = s[C_EOL2];
826 td->c_cc[VSWTCH] = s[C_SWTCH];
829 td->c_cc[VDSWTCH] = s[C_DSWTCH];
832 td->c_cc[VERASE2] = s[C_ERASE2];
835 td->c_cc[VSTART] = s[C_START];
838 td->c_cc[VSTOP] = s[C_STOP];
841 td->c_cc[VWERASE] = s[C_WERASE];
844 td->c_cc[VSUSP] = s[C_SUSP];
847 td->c_cc[VDSUSP] = s[C_DSUSP];
850 td->c_cc[VREPRINT] = s[C_REPRINT];
851 #endif /* VREPRINT */
853 td->c_cc[VDISCARD] = s[C_DISCARD];
854 #endif /* VDISCARD */
856 td->c_cc[VLNEXT] = s[C_LNEXT];
859 td->c_cc[VSTATUS] = s[C_STATUS];
862 td->c_cc[VPAGE] = s[C_PAGE];
865 td->c_cc[VPGOFF] = s[C_PGOFF];
868 td->c_cc[VKILL2] = s[C_KILL2];
871 td->c_cc[VMIN] = s[C_MIN];
874 td->c_cc[VTIME] = s[C_TIME];
880 * Rebind the editline functions
883 tty_bind_char(EditLine *el, int force)
886 unsigned char *t_n = el->el_tty.t_c[ED_IO];
887 unsigned char *t_o = el->el_tty.t_ed.c_cc;
890 el_action_t *map, *alt;
891 const el_action_t *dmap, *dalt;
892 new[1] = old[1] = '\0';
894 map = el->el_map.key;
895 alt = el->el_map.alt;
896 if (el->el_map.type == MAP_VI) {
897 dmap = el->el_map.vii;
898 dalt = el->el_map.vic;
900 dmap = el->el_map.emacs;
904 for (tp = tty_map; tp->nch != (Int)-1; tp++) {
905 new[0] = t_n[tp->nch];
906 old[0] = t_o[tp->och];
907 if (new[0] == old[0] && !force)
909 /* Put the old default binding back, and set the new binding */
910 keymacro_clear(el, map, old);
911 map[UC(old[0])] = dmap[UC(old[0])];
912 keymacro_clear(el, map, new);
913 /* MAP_VI == 1, MAP_EMACS == 0... */
914 map[UC(new[0])] = tp->bind[el->el_map.type];
916 keymacro_clear(el, alt, old);
917 alt[UC(old[0])] = dalt[UC(old[0])];
918 keymacro_clear(el, alt, new);
919 alt[UC(new[0])] = tp->bind[el->el_map.type + 1];
926 tty__get_flag(struct termios *t, int kind) {
944 tty_update_flag(EditLine *el, tcflag_t f, int mode, int kind)
946 f &= ~el->el_tty.t_t[mode][kind].t_clrmask;
947 f |= el->el_tty.t_t[mode][kind].t_setmask;
953 tty_update_flags(EditLine *el, int kind)
955 tcflag_t *tt, *ed, *ex;
956 tt = tty__get_flag(&el->el_tty.t_ts, kind);
957 ed = tty__get_flag(&el->el_tty.t_ed, kind);
958 ex = tty__get_flag(&el->el_tty.t_ex, kind);
960 if (*tt != *ex && (kind != MD_CTL || *tt != *ed)) {
961 *ed = tty_update_flag(el, *tt, ED_IO, kind);
962 *ex = tty_update_flag(el, *tt, EX_IO, kind);
968 tty_update_char(EditLine *el, int mode, int c) {
969 if (!((el->el_tty.t_t[mode][MD_CHAR].t_setmask & C_SH(c)))
970 && (el->el_tty.t_c[TS_IO][c] != el->el_tty.t_c[EX_IO][c]))
971 el->el_tty.t_c[mode][c] = el->el_tty.t_c[TS_IO][c];
972 if (el->el_tty.t_t[mode][MD_CHAR].t_clrmask & C_SH(c))
973 el->el_tty.t_c[mode][c] = el->el_tty.t_vdisable;
978 * Set terminal into 1 character at a time mode.
981 tty_rawmode(EditLine *el)
984 if (el->el_tty.t_mode == ED_IO || el->el_tty.t_mode == QU_IO)
987 if (el->el_flags & EDIT_DISABLED)
990 if (tty_getty(el, &el->el_tty.t_ts) == -1) {
992 (void) fprintf(el->el_errfile, "%s: tty_getty: %s\n", __func__,
994 #endif /* DEBUG_TTY */
998 * We always keep up with the eight bit setting and the speed of the
999 * tty. But we only believe changes that are made to cooked mode!
1001 el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts);
1002 el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts);
1004 if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed ||
1005 tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) {
1006 (void) cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed);
1007 (void) cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed);
1008 (void) cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed);
1009 (void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed);
1011 if (tty__cooked_mode(&el->el_tty.t_ts)) {
1014 for (i = MD_INP; i <= MD_LIN; i++)
1015 tty_update_flags(el, i);
1017 if (tty__gettabs(&el->el_tty.t_ex) == 0)
1018 el->el_tty.t_tabs = 0;
1020 el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0;
1022 tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
1024 * Check if the user made any changes.
1025 * If he did, then propagate the changes to the
1026 * edit and execute data structures.
1028 for (i = 0; i < C_NCC; i++)
1029 if (el->el_tty.t_c[TS_IO][i] !=
1030 el->el_tty.t_c[EX_IO][i])
1035 * Propagate changes only to the unprotected
1036 * chars that have been modified just now.
1038 for (i = 0; i < C_NCC; i++)
1039 tty_update_char(el, ED_IO, i);
1041 tty_bind_char(el, 0);
1042 tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
1044 for (i = 0; i < C_NCC; i++)
1045 tty_update_char(el, EX_IO, i);
1047 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
1050 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) {
1052 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1054 #endif /* DEBUG_TTY */
1057 el->el_tty.t_mode = ED_IO;
1062 /* tty_cookedmode():
1063 * Set the tty back to normal mode
1066 tty_cookedmode(EditLine *el)
1067 { /* set tty in normal setup */
1069 if (el->el_tty.t_mode == EX_IO)
1072 if (el->el_flags & EDIT_DISABLED)
1075 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) {
1077 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1079 #endif /* DEBUG_TTY */
1082 el->el_tty.t_mode = EX_IO;
1088 * Turn on quote mode
1091 tty_quotemode(EditLine *el)
1093 if (el->el_tty.t_mode == QU_IO)
1096 el->el_tty.t_qu = el->el_tty.t_ed;
1098 tty_setup_flags(el, &el->el_tty.t_qu, QU_IO);
1100 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_qu) == -1) {
1102 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1104 #endif /* DEBUG_TTY */
1107 el->el_tty.t_mode = QU_IO;
1112 /* tty_noquotemode():
1113 * Turn off quote mode
1116 tty_noquotemode(EditLine *el)
1119 if (el->el_tty.t_mode != QU_IO)
1121 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) {
1123 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1125 #endif /* DEBUG_TTY */
1128 el->el_tty.t_mode = ED_IO;
1138 tty_stty(EditLine *el, int argc __attribute__((__unused__)), const Char **argv)
1140 const ttymodes_t *m;
1144 char name[EL_BUFSIZ];
1145 struct termios *tios = &el->el_tty.t_ex;
1150 strncpy(name, ct_encode_string(*argv++, &el->el_scratch), sizeof(name));
1151 name[sizeof(name) - 1] = '\0';
1153 while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0')
1154 switch (argv[0][1]) {
1161 tios = &el->el_tty.t_ed;
1166 tios = &el->el_tty.t_ex;
1171 tios = &el->el_tty.t_ts;
1175 (void) fprintf(el->el_errfile,
1176 "%s: Unknown switch `" FCHAR "'.\n",
1177 name, (Int)argv[0][1]);
1181 if (!argv || !*argv) {
1183 size_t len = 0, st = 0, cu;
1184 for (m = ttymodes; m->m_name; m++) {
1185 if (m->m_type != i) {
1186 (void) fprintf(el->el_outfile, "%s%s",
1187 i != -1 ? "\n" : "",
1188 el->el_tty.t_t[z][m->m_type].t_name);
1191 strlen(el->el_tty.t_t[z][m->m_type].t_name);
1194 x = (el->el_tty.t_t[z][i].t_setmask & m->m_value)
1197 if (el->el_tty.t_t[z][i].t_clrmask & m->m_value)
1203 if (x != '\0' || aflag) {
1205 cu = strlen(m->m_name) + (x != '\0') + 1;
1208 (size_t)el->el_terminal.t_size.h) {
1209 (void) fprintf(el->el_outfile, "\n%*s",
1216 (void) fprintf(el->el_outfile, "%c%s ",
1219 (void) fprintf(el->el_outfile, "%s ",
1223 (void) fprintf(el->el_outfile, "\n");
1226 while (argv && (s = *argv++)) {
1239 for (m = ttymodes; m->m_name; m++)
1240 if ((p ? strncmp(m->m_name, ct_encode_string(d,
1241 &el->el_scratch), (size_t)(p - d)) :
1242 strcmp(m->m_name, ct_encode_string(d,
1243 &el->el_scratch))) == 0 &&
1244 (p == NULL || m->m_type == MD_CHAR))
1248 (void) fprintf(el->el_errfile,
1249 "%s: Invalid argument `" FSTR "'.\n", name, d);
1253 int c = ffs((int)m->m_value);
1254 int v = *++p ? parse__escape(&p) :
1255 el->el_tty.t_vdisable;
1258 c = tty__getcharindex(c);
1260 tios->c_cc[c] = (cc_t)v;
1265 el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value;
1266 el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
1269 el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
1270 el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value;
1273 el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
1274 el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
1279 tty_setup_flags(el, tios, z);
1280 if (el->el_tty.t_mode == z) {
1281 if (tty_setty(el, TCSADRAIN, tios) == -1) {
1283 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n",
1284 __func__, strerror(errno));
1285 #endif /* DEBUG_TTY */
1296 * DEbugging routine to print the tty characters
1299 tty_printchar(EditLine *el, unsigned char *s)
1304 for (i = 0; i < C_NCC; i++) {
1305 for (m = el->el_tty.t_t; m->m_name; m++)
1306 if (m->m_type == MD_CHAR && C_SH(i) == m->m_value)
1309 (void) fprintf(el->el_errfile, "%s ^%c ",
1310 m->m_name, s[i] + 'A' - 1);
1312 (void) fprintf(el->el_errfile, "\n");
1314 (void) fprintf(el->el_errfile, "\n");
1320 tty_setup_flags(EditLine *el, struct termios *tios, int mode)
1323 for (kind = MD_INP; kind <= MD_LIN; kind++) {
1324 tcflag_t *f = tty__get_flag(tios, kind);
1325 *f = tty_update_flag(el, *f, mode, kind);