summaryrefslogtreecommitdiff
path: root/lib/libedit/tty.c
diff options
context:
space:
mode:
authorRodney W. Grimes <rgrimes@FreeBSD.org>1994-05-27 05:00:24 +0000
committerRodney W. Grimes <rgrimes@FreeBSD.org>1994-05-27 05:00:24 +0000
commit58f0484fa251c266ede97b591b499fe3dd4f578e (patch)
tree41932a7161f4cd72005330a9c69747e7bab2ee5b /lib/libedit/tty.c
parentfb49e767ba942f74b1cee8814e085e5f2615ac53 (diff)
downloadsrc-test2-58f0484fa251c266ede97b591b499fe3dd4f578e.tar.gz
src-test2-58f0484fa251c266ede97b591b499fe3dd4f578e.zip
Notes
Diffstat (limited to 'lib/libedit/tty.c')
-rw-r--r--lib/libedit/tty.c1144
1 files changed, 1144 insertions, 0 deletions
diff --git a/lib/libedit/tty.c b/lib/libedit/tty.c
new file mode 100644
index 000000000000..ac99843b7746
--- /dev/null
+++ b/lib/libedit/tty.c
@@ -0,0 +1,1144 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Christos Zoulas of Cornell University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if !defined(lint) && !defined(SCCSID)
+static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint && not SCCSID */
+
+/*
+ * tty.c: tty interface stuff
+ */
+#include "sys.h"
+#include "tty.h"
+#include "el.h"
+
+typedef struct ttymodes_t {
+ char *m_name;
+ int m_value;
+ int m_type;
+} ttymodes_t;
+
+typedef struct ttymap_t {
+ int nch, och; /* Internal and termio rep of chars */
+ el_action_t bind[3]; /* emacs, vi, and vi-cmd */
+} ttymap_t;
+
+
+private ttyperm_t ttyperm = {
+ {
+ { "iflag:", ICRNL, (INLCR|IGNCR) },
+ { "oflag:", (OPOST|ONLCR), ONLRET },
+ { "cflag:", 0, 0 },
+ { "lflag:", (ISIG|ICANON|ECHO|ECHOE|ECHOCTL|IEXTEN),
+ (NOFLSH|ECHONL|EXTPROC|FLUSHO) },
+ { "chars:", 0, 0 },
+ },
+ {
+ { "iflag:", (INLCR|ICRNL), IGNCR },
+ { "oflag:", (OPOST|ONLCR), ONLRET },
+ { "cflag:", 0, 0 },
+ { "lflag:", ISIG,
+ (NOFLSH|ICANON|ECHO|ECHOK|ECHONL|EXTPROC|IEXTEN|FLUSHO) },
+ { "chars:", (C_SH(C_MIN)|C_SH(C_TIME)|C_SH(C_SWTCH)|C_SH(C_DSWTCH)|
+ C_SH(C_SUSP)|C_SH(C_DSUSP)|C_SH(C_EOL)|C_SH(C_DISCARD)|
+ C_SH(C_PGOFF)|C_SH(C_PAGE)|C_SH(C_STATUS)), 0 }
+ },
+ {
+ { "iflag:", 0, IXON | IXOFF },
+ { "oflag:", 0, 0 },
+ { "cflag:", 0, 0 },
+ { "lflag:", 0, ISIG | IEXTEN },
+ { "chars:", 0, 0 },
+ }
+};
+
+private ttychar_t ttychar = {
+ {
+ CINTR, CQUIT, CERASE, CKILL,
+ CEOF, CEOL, CEOL2, CSWTCH,
+ CDSWTCH, CERASE2, CSTART, CSTOP,
+ CWERASE, CSUSP, CDSUSP, CREPRINT,
+ CDISCARD, CLNEXT, CSTATUS, CPAGE,
+ CPGOFF, CKILL2, CBRK, CMIN,
+ CTIME
+ },
+ {
+ CINTR, CQUIT, CERASE, CKILL,
+ _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
+ _POSIX_VDISABLE, CERASE2, CSTART, CSTOP,
+ _POSIX_VDISABLE, CSUSP, _POSIX_VDISABLE, _POSIX_VDISABLE,
+ CDISCARD, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
+ _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 1,
+ 0
+ },
+ {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0
+ }
+};
+
+private ttymap_t tty_map[] = {
+#ifdef VERASE
+ { C_ERASE, VERASE,
+ { ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR } },
+#endif /* VERASE */
+#ifdef VERASE2
+ { C_ERASE2, VERASE2,
+ { ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR } },
+#endif /* VERASE2 */
+#ifdef VKILL
+ { C_KILL, VKILL,
+ { EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED } },
+#endif /* VKILL */
+#ifdef VKILL2
+ { C_KILL2, VKILL2,
+ { EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED } },
+#endif /* VKILL2 */
+#ifdef VEOF
+ { C_EOF, VEOF,
+ { EM_DELETE_OR_LIST, VI_LIST_OR_EOF, ED_UNASSIGNED } },
+#endif /* VEOF */
+#ifdef VWERASE
+ { C_WERASE, VWERASE,
+ { ED_DELETE_PREV_WORD, ED_DELETE_PREV_WORD, ED_PREV_WORD } },
+#endif /* VWERASE */
+#ifdef VREPRINT
+ { C_REPRINT, VREPRINT,
+ { ED_REDISPLAY, ED_INSERT, ED_REDISPLAY } },
+#endif /* VREPRINT */
+#ifdef VLNEXT
+ { C_LNEXT, VLNEXT,
+ { ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED } },
+#endif /* VLNEXT */
+ { -1, -1,
+ { ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED } }
+ };
+
+private ttymodes_t ttymodes[] = {
+# ifdef IGNBRK
+ { "ignbrk", IGNBRK, M_INP },
+# endif /* IGNBRK */
+# ifdef BRKINT
+ { "brkint", BRKINT, M_INP },
+# endif /* BRKINT */
+# ifdef IGNPAR
+ { "ignpar", IGNPAR, M_INP },
+# endif /* IGNPAR */
+# ifdef PARMRK
+ { "parmrk", PARMRK, M_INP },
+# endif /* PARMRK */
+# ifdef INPCK
+ { "inpck", INPCK, M_INP },
+# endif /* INPCK */
+# ifdef ISTRIP
+ { "istrip", ISTRIP, M_INP },
+# endif /* ISTRIP */
+# ifdef INLCR
+ { "inlcr", INLCR, M_INP },
+# endif /* INLCR */
+# ifdef IGNCR
+ { "igncr", IGNCR, M_INP },
+# endif /* IGNCR */
+# ifdef ICRNL
+ { "icrnl", ICRNL, M_INP },
+# endif /* ICRNL */
+# ifdef IUCLC
+ { "iuclc", IUCLC, M_INP },
+# endif /* IUCLC */
+# ifdef IXON
+ { "ixon", IXON, M_INP },
+# endif /* IXON */
+# ifdef IXANY
+ { "ixany", IXANY, M_INP },
+# endif /* IXANY */
+# ifdef IXOFF
+ { "ixoff", IXOFF, M_INP },
+# endif /* IXOFF */
+# ifdef IMAXBEL
+ { "imaxbel",IMAXBEL,M_INP },
+# endif /* IMAXBEL */
+
+# ifdef OPOST
+ { "opost", OPOST, M_OUT },
+# endif /* OPOST */
+# ifdef OLCUC
+ { "olcuc", OLCUC, M_OUT },
+# endif /* OLCUC */
+# ifdef ONLCR
+ { "onlcr", ONLCR, M_OUT },
+# endif /* ONLCR */
+# ifdef OCRNL
+ { "ocrnl", OCRNL, M_OUT },
+# endif /* OCRNL */
+# ifdef ONOCR
+ { "onocr", ONOCR, M_OUT },
+# endif /* ONOCR */
+# ifdef ONOEOT
+ { "onoeot", ONOEOT, M_OUT },
+# endif /* ONOEOT */
+# ifdef ONLRET
+ { "onlret", ONLRET, M_OUT },
+# endif /* ONLRET */
+# ifdef OFILL
+ { "ofill", OFILL, M_OUT },
+# endif /* OFILL */
+# ifdef OFDEL
+ { "ofdel", OFDEL, M_OUT },
+# endif /* OFDEL */
+# ifdef NLDLY
+ { "nldly", NLDLY, M_OUT },
+# endif /* NLDLY */
+# ifdef CRDLY
+ { "crdly", CRDLY, M_OUT },
+# endif /* CRDLY */
+# ifdef TABDLY
+ { "tabdly", TABDLY, M_OUT },
+# endif /* TABDLY */
+# ifdef XTABS
+ { "xtabs", XTABS, M_OUT },
+# endif /* XTABS */
+# ifdef BSDLY
+ { "bsdly", BSDLY, M_OUT },
+# endif /* BSDLY */
+# ifdef VTDLY
+ { "vtdly", VTDLY, M_OUT },
+# endif /* VTDLY */
+# ifdef FFDLY
+ { "ffdly", FFDLY, M_OUT },
+# endif /* FFDLY */
+# ifdef PAGEOUT
+ { "pageout",PAGEOUT,M_OUT },
+# endif /* PAGEOUT */
+# ifdef WRAP
+ { "wrap", WRAP, M_OUT },
+# endif /* WRAP */
+
+# ifdef CIGNORE
+ { "cignore",CIGNORE,M_CTL },
+# endif /* CBAUD */
+# ifdef CBAUD
+ { "cbaud", CBAUD, M_CTL },
+# endif /* CBAUD */
+# ifdef CSTOPB
+ { "cstopb", CSTOPB, M_CTL },
+# endif /* CSTOPB */
+# ifdef CREAD
+ { "cread", CREAD, M_CTL },
+# endif /* CREAD */
+# ifdef PARENB
+ { "parenb", PARENB, M_CTL },
+# endif /* PARENB */
+# ifdef PARODD
+ { "parodd", PARODD, M_CTL },
+# endif /* PARODD */
+# ifdef HUPCL
+ { "hupcl", HUPCL, M_CTL },
+# endif /* HUPCL */
+# ifdef CLOCAL
+ { "clocal", CLOCAL, M_CTL },
+# endif /* CLOCAL */
+# ifdef LOBLK
+ { "loblk", LOBLK, M_CTL },
+# endif /* LOBLK */
+# ifdef CIBAUD
+ { "cibaud", CIBAUD, M_CTL },
+# endif /* CIBAUD */
+# ifdef CRTSCTS
+# ifdef CCTS_OFLOW
+ { "ccts_oflow",CCTS_OFLOW,M_CTL },
+# else
+ { "crtscts",CRTSCTS,M_CTL },
+# endif /* CCTS_OFLOW */
+# endif /* CRTSCTS */
+# ifdef CRTS_IFLOW
+ { "crts_iflow",CRTS_IFLOW,M_CTL },
+# endif /* CRTS_IFLOW */
+# ifdef MDMBUF
+ { "mdmbuf", MDMBUF, M_CTL },
+# endif /* MDMBUF */
+# ifdef RCV1EN
+ { "rcv1en", RCV1EN, M_CTL },
+# endif /* RCV1EN */
+# ifdef XMT1EN
+ { "xmt1en", XMT1EN, M_CTL },
+# endif /* XMT1EN */
+
+# ifdef ISIG
+ { "isig", ISIG, M_LIN },
+# endif /* ISIG */
+# ifdef ICANON
+ { "icanon", ICANON, M_LIN },
+# endif /* ICANON */
+# ifdef XCASE
+ { "xcase", XCASE, M_LIN },
+# endif /* XCASE */
+# ifdef ECHO
+ { "echo", ECHO, M_LIN },
+# endif /* ECHO */
+# ifdef ECHOE
+ { "echoe", ECHOE, M_LIN },
+# endif /* ECHOE */
+# ifdef ECHOK
+ { "echok", ECHOK, M_LIN },
+# endif /* ECHOK */
+# ifdef ECHONL
+ { "echonl", ECHONL, M_LIN },
+# endif /* ECHONL */
+# ifdef NOFLSH
+ { "noflsh", NOFLSH, M_LIN },
+# endif /* NOFLSH */
+# ifdef TOSTOP
+ { "tostop", TOSTOP, M_LIN },
+# endif /* TOSTOP */
+# ifdef ECHOCTL
+ { "echoctl",ECHOCTL,M_LIN },
+# endif /* ECHOCTL */
+# ifdef ECHOPRT
+ { "echoprt",ECHOPRT,M_LIN },
+# endif /* ECHOPRT */
+# ifdef ECHOKE
+ { "echoke", ECHOKE, M_LIN },
+# endif /* ECHOKE */
+# ifdef DEFECHO
+ { "defecho",DEFECHO,M_LIN },
+# endif /* DEFECHO */
+# ifdef FLUSHO
+ { "flusho", FLUSHO, M_LIN },
+# endif /* FLUSHO */
+# ifdef PENDIN
+ { "pendin", PENDIN, M_LIN },
+# endif /* PENDIN */
+# ifdef IEXTEN
+ { "iexten", IEXTEN, M_LIN },
+# endif /* IEXTEN */
+# ifdef NOKERNINFO
+ { "nokerninfo",NOKERNINFO,M_LIN },
+# endif /* NOKERNINFO */
+# ifdef ALTWERASE
+ { "altwerase",ALTWERASE,M_LIN },
+# endif /* ALTWERASE */
+# ifdef EXTPROC
+ { "extproc",EXTPROC, M_LIN },
+# endif /* EXTPROC */
+
+# if defined(VINTR)
+ { "intr", C_SH(C_INTR), M_CHAR },
+# endif /* VINTR */
+# if defined(VQUIT)
+ { "quit", C_SH(C_QUIT), M_CHAR },
+# endif /* VQUIT */
+# if defined(VERASE)
+ { "erase", C_SH(C_ERASE), M_CHAR },
+# endif /* VERASE */
+# if defined(VKILL)
+ { "kill", C_SH(C_KILL), M_CHAR },
+# endif /* VKILL */
+# if defined(VEOF)
+ { "eof", C_SH(C_EOF), M_CHAR },
+# endif /* VEOF */
+# if defined(VEOL)
+ { "eol", C_SH(C_EOL), M_CHAR },
+# endif /* VEOL */
+# if defined(VEOL2)
+ { "eol2", C_SH(C_EOL2), M_CHAR },
+# endif /* VEOL2 */
+# if defined(VSWTCH)
+ { "swtch", C_SH(C_SWTCH), M_CHAR },
+# endif /* VSWTCH */
+# if defined(VDSWTCH)
+ { "dswtch", C_SH(C_DSWTCH), M_CHAR },
+# endif /* VDSWTCH */
+# if defined(VERASE2)
+ { "erase2", C_SH(C_ERASE2), M_CHAR },
+# endif /* VERASE2 */
+# if defined(VSTART)
+ { "start", C_SH(C_START), M_CHAR },
+# endif /* VSTART */
+# if defined(VSTOP)
+ { "stop", C_SH(C_STOP), M_CHAR },
+# endif /* VSTOP */
+# if defined(VWERASE)
+ { "werase", C_SH(C_WERASE), M_CHAR },
+# endif /* VWERASE */
+# if defined(VSUSP)
+ { "susp", C_SH(C_SUSP), M_CHAR },
+# endif /* VSUSP */
+# if defined(VDSUSP)
+ { "dsusp", C_SH(C_DSUSP), M_CHAR },
+# endif /* VDSUSP */
+# if defined(VREPRINT)
+ { "reprint", C_SH(C_REPRINT),M_CHAR },
+# endif /* VREPRINT */
+# if defined(VDISCARD)
+ { "discard", C_SH(C_DISCARD),M_CHAR },
+# endif /* VDISCARD */
+# if defined(VLNEXT)
+ { "lnext", C_SH(C_LNEXT), M_CHAR },
+# endif /* VLNEXT */
+# if defined(VSTATUS)
+ { "status", C_SH(C_STATUS), M_CHAR },
+# endif /* VSTATUS */
+# if defined(VPAGE)
+ { "page", C_SH(C_PAGE), M_CHAR },
+# endif /* VPAGE */
+# if defined(VPGOFF)
+ { "pgoff", C_SH(C_PGOFF), M_CHAR },
+# endif /* VPGOFF */
+# if defined(VKILL2)
+ { "kill2", C_SH(C_KILL2), M_CHAR },
+# endif /* VKILL2 */
+# if defined(VBRK)
+ { "brk", C_SH(C_BRK), M_CHAR },
+# endif /* VBRK */
+# if defined(VMIN)
+ { "min", C_SH(C_MIN), M_CHAR },
+# endif /* VMIN */
+# if defined(VTIME)
+ { "time", C_SH(C_TIME), M_CHAR },
+# endif /* VTIME */
+ { NULL, 0, -1 },
+};
+
+
+
+#define tty_getty(el, td) tcgetattr((el)->el_infd, (td))
+#define tty_setty(el, td) tcsetattr((el)->el_infd, TCSADRAIN, (td))
+
+#define tty__gettabs(td) ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1)
+#define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8)
+#define tty__cooked_mode(td) ((td)->c_lflag & ICANON)
+
+private void tty__getchar __P((struct termios *, unsigned char *));
+private void tty__setchar __P((struct termios *, unsigned char *));
+private speed_t tty__getspeed __P((struct termios *));
+private int tty_setup __P((EditLine *));
+
+#define t_qu t_ts
+
+
+/* tty_setup():
+ * Get the tty parameters and initialize the editing state
+ */
+private int
+tty_setup(el)
+ EditLine *el;
+{
+ int rst = 1;
+ if (tty_getty(el, &el->el_tty.t_ed) == -1) {
+#ifdef DEBUG_TTY
+ (void) fprintf(el->el_errfile,
+ "tty_setup: tty_getty: %s\n", strerror(errno));
+#endif /* DEBUG_TTY */
+ return(-1);
+ }
+ el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed;
+
+ el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex);
+ el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex);
+ el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex);
+
+ el->el_tty.t_ex.c_iflag &= ~el->el_tty.t_t[EX_IO][M_INP].t_clrmask;
+ el->el_tty.t_ex.c_iflag |= el->el_tty.t_t[EX_IO][M_INP].t_setmask;
+
+ el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][M_OUT].t_clrmask;
+ el->el_tty.t_ex.c_oflag |= el->el_tty.t_t[EX_IO][M_OUT].t_setmask;
+
+ el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][M_CTL].t_clrmask;
+ el->el_tty.t_ex.c_cflag |= el->el_tty.t_t[EX_IO][M_CTL].t_setmask;
+
+ el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][M_LIN].t_clrmask;
+ el->el_tty.t_ex.c_lflag |= el->el_tty.t_t[EX_IO][M_LIN].t_setmask;
+
+ /*
+ * Reset the tty chars to reasonable defaults
+ * If they are disabled, then enable them.
+ */
+ if (rst) {
+ if (tty__cooked_mode(&el->el_tty.t_ts)) {
+ tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
+ /*
+ * Don't affect CMIN and CTIME for the editor mode
+ */
+ for (rst = 0; rst < C_NCC - 2; rst++)
+ if (el->el_tty.t_c[TS_IO][rst] != el->el_tty.t_vdisable &&
+ el->el_tty.t_c[ED_IO][rst] != el->el_tty.t_vdisable)
+ el->el_tty.t_c[ED_IO][rst] = el->el_tty.t_c[TS_IO][rst];
+ for (rst = 0; rst < C_NCC; rst++)
+ if (el->el_tty.t_c[TS_IO][rst] != el->el_tty.t_vdisable &&
+ el->el_tty.t_c[EX_IO][rst] != el->el_tty.t_vdisable)
+ el->el_tty.t_c[EX_IO][rst] = el->el_tty.t_c[TS_IO][rst];
+ }
+ tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
+ if (tty_setty(el, &el->el_tty.t_ex) == -1) {
+#ifdef DEBUG_TTY
+ (void) fprintf(el->el_errfile, "tty_setup: tty_setty: %s\n",
+ strerror(errno));
+#endif /* DEBUG_TTY */
+ return(-1);
+ }
+ }
+ else
+ tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
+
+ el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][M_INP].t_clrmask;
+ el->el_tty.t_ed.c_iflag |= el->el_tty.t_t[ED_IO][M_INP].t_setmask;
+
+ el->el_tty.t_ed.c_oflag &= ~el->el_tty.t_t[ED_IO][M_OUT].t_clrmask;
+ el->el_tty.t_ed.c_oflag |= el->el_tty.t_t[ED_IO][M_OUT].t_setmask;
+
+ el->el_tty.t_ed.c_cflag &= ~el->el_tty.t_t[ED_IO][M_CTL].t_clrmask;
+ el->el_tty.t_ed.c_cflag |= el->el_tty.t_t[ED_IO][M_CTL].t_setmask;
+
+ el->el_tty.t_ed.c_lflag &= ~el->el_tty.t_t[ED_IO][M_LIN].t_clrmask;
+ el->el_tty.t_ed.c_lflag |= el->el_tty.t_t[ED_IO][M_LIN].t_setmask;
+
+ tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
+ return 0;
+}
+
+protected int
+tty_init(el)
+ EditLine *el;
+{
+ el->el_tty.t_mode = EX_IO;
+ el->el_tty.t_vdisable = _POSIX_VDISABLE;
+ (void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t));
+ (void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t));
+ return tty_setup(el);
+} /* end tty_init */
+
+
+/* tty_end():
+ * Restore the tty to its original settings
+ */
+protected void
+/*ARGSUSED*/
+tty_end(el)
+ EditLine *el;
+{
+ /* XXX: Maybe reset to an initial state? */
+}
+
+
+/* tty__getspeed():
+ * Get the tty speed
+ */
+private speed_t
+tty__getspeed(td)
+ struct termios *td;
+{
+ speed_t spd;
+
+ if ((spd = cfgetispeed(td)) == 0)
+ spd = cfgetospeed(td);
+ return spd;
+} /* end tty__getspeed */
+
+
+/* tty__getchar():
+ * Get the tty characters
+ */
+private void
+tty__getchar(td, s)
+ struct termios *td;
+ unsigned char *s;
+{
+# ifdef VINTR
+ s[C_INTR] = td->c_cc[VINTR];
+# endif /* VINTR */
+# ifdef VQUIT
+ s[C_QUIT] = td->c_cc[VQUIT];
+# endif /* VQUIT */
+# ifdef VERASE
+ s[C_ERASE] = td->c_cc[VERASE];
+# endif /* VERASE */
+# ifdef VKILL
+ s[C_KILL] = td->c_cc[VKILL];
+# endif /* VKILL */
+# ifdef VEOF
+ s[C_EOF] = td->c_cc[VEOF];
+# endif /* VEOF */
+# ifdef VEOL
+ s[C_EOL] = td->c_cc[VEOL];
+# endif /* VEOL */
+# ifdef VEOL2
+ s[C_EOL2] = td->c_cc[VEOL2];
+# endif /* VEOL2 */
+# ifdef VSWTCH
+ s[C_SWTCH] = td->c_cc[VSWTCH];
+# endif /* VSWTCH */
+# ifdef VDSWTCH
+ s[C_DSWTCH] = td->c_cc[VDSWTCH];
+# endif /* VDSWTCH */
+# ifdef VERASE2
+ s[C_ERASE2] = td->c_cc[VERASE2];
+# endif /* VERASE2 */
+# ifdef VSTART
+ s[C_START] = td->c_cc[VSTART];
+# endif /* VSTART */
+# ifdef VSTOP
+ s[C_STOP] = td->c_cc[VSTOP];
+# endif /* VSTOP */
+# ifdef VWERASE
+ s[C_WERASE] = td->c_cc[VWERASE];
+# endif /* VWERASE */
+# ifdef VSUSP
+ s[C_SUSP] = td->c_cc[VSUSP];
+# endif /* VSUSP */
+# ifdef VDSUSP
+ s[C_DSUSP] = td->c_cc[VDSUSP];
+# endif /* VDSUSP */
+# ifdef VREPRINT
+ s[C_REPRINT]= td->c_cc[VREPRINT];
+# endif /* VREPRINT */
+# ifdef VDISCARD
+ s[C_DISCARD]= td->c_cc[VDISCARD];
+# endif /* VDISCARD */
+# ifdef VLNEXT
+ s[C_LNEXT] = td->c_cc[VLNEXT];
+# endif /* VLNEXT */
+# ifdef VSTATUS
+ s[C_STATUS] = td->c_cc[VSTATUS];
+# endif /* VSTATUS */
+# ifdef VPAGE
+ s[C_PAGE] = td->c_cc[VPAGE];
+# endif /* VPAGE */
+# ifdef VPGOFF
+ s[C_PGOFF] = td->c_cc[VPGOFF];
+# endif /* VPGOFF */
+# ifdef VKILL2
+ s[C_KILL2] = td->c_cc[VKILL2];
+# endif /* KILL2 */
+# ifdef VMIN
+ s[C_MIN] = td->c_cc[VMIN];
+# endif /* VMIN */
+# ifdef VTIME
+ s[C_TIME] = td->c_cc[VTIME];
+# endif /* VTIME */
+} /* tty__getchar */
+
+
+/* tty__setchar():
+ * Set the tty characters
+ */
+private void
+tty__setchar(td, s)
+ struct termios *td;
+ unsigned char *s;
+{
+# ifdef VINTR
+ td->c_cc[VINTR] = s[C_INTR];
+# endif /* VINTR */
+# ifdef VQUIT
+ td->c_cc[VQUIT] = s[C_QUIT];
+# endif /* VQUIT */
+# ifdef VERASE
+ td->c_cc[VERASE] = s[C_ERASE];
+# endif /* VERASE */
+# ifdef VKILL
+ td->c_cc[VKILL] = s[C_KILL];
+# endif /* VKILL */
+# ifdef VEOF
+ td->c_cc[VEOF] = s[C_EOF];
+# endif /* VEOF */
+# ifdef VEOL
+ td->c_cc[VEOL] = s[C_EOL];
+# endif /* VEOL */
+# ifdef VEOL2
+ td->c_cc[VEOL2] = s[C_EOL2];
+# endif /* VEOL2 */
+# ifdef VSWTCH
+ td->c_cc[VSWTCH] = s[C_SWTCH];
+# endif /* VSWTCH */
+# ifdef VDSWTCH
+ td->c_cc[VDSWTCH] = s[C_DSWTCH];
+# endif /* VDSWTCH */
+# ifdef VERASE2
+ td->c_cc[VERASE2] = s[C_ERASE2];
+# endif /* VERASE2 */
+# ifdef VSTART
+ td->c_cc[VSTART] = s[C_START];
+# endif /* VSTART */
+# ifdef VSTOP
+ td->c_cc[VSTOP] = s[C_STOP];
+# endif /* VSTOP */
+# ifdef VWERASE
+ td->c_cc[VWERASE] = s[C_WERASE];
+# endif /* VWERASE */
+# ifdef VSUSP
+ td->c_cc[VSUSP] = s[C_SUSP];
+# endif /* VSUSP */
+# ifdef VDSUSP
+ td->c_cc[VDSUSP] = s[C_DSUSP];
+# endif /* VDSUSP */
+# ifdef VREPRINT
+ td->c_cc[VREPRINT] = s[C_REPRINT];
+# endif /* VREPRINT */
+# ifdef VDISCARD
+ td->c_cc[VDISCARD] = s[C_DISCARD];
+# endif /* VDISCARD */
+# ifdef VLNEXT
+ td->c_cc[VLNEXT] = s[C_LNEXT];
+# endif /* VLNEXT */
+# ifdef VSTATUS
+ td->c_cc[VSTATUS] = s[C_STATUS];
+# endif /* VSTATUS */
+# ifdef VPAGE
+ td->c_cc[VPAGE] = s[C_PAGE];
+# endif /* VPAGE */
+# ifdef VPGOFF
+ td->c_cc[VPGOFF] = s[C_PGOFF];
+# endif /* VPGOFF */
+# ifdef VKILL2
+ td->c_cc[VKILL2] = s[C_KILL2];
+# endif /* VKILL2 */
+# ifdef VMIN
+ td->c_cc[VMIN] = s[C_MIN];
+# endif /* VMIN */
+# ifdef VTIME
+ td->c_cc[VTIME] = s[C_TIME];
+# endif /* VTIME */
+} /* tty__setchar */
+
+
+/* tty_bind_char():
+ * Rebind the editline functions
+ */
+protected void
+tty_bind_char(el, force)
+ EditLine *el;
+ int force;
+{
+ unsigned char *t_n = el->el_tty.t_c[ED_IO];
+ unsigned char *t_o = el->el_tty.t_ed.c_cc;
+ char new[2], old[2];
+ ttymap_t *tp;
+ el_action_t *dmap, *dalt, *map, *alt;
+ new[1] = old[1] = '\0';
+
+
+ map = el->el_map.key;
+ alt = el->el_map.alt;
+ if (el->el_map.type == MAP_VI) {
+ dmap = el->el_map.vii;
+ dalt = el->el_map.vic;
+ }
+ else {
+ dmap = el->el_map.emacs;
+ dalt = NULL;
+ }
+
+ for (tp = tty_map; tp->nch != -1; tp++) {
+ new[0] = t_n[tp->nch];
+ old[0] = t_o[tp->och];
+ if (new[0] == old[0] && !force)
+ continue;
+ /* Put the old default binding back, and set the new binding */
+ key_clear(el, map, old);
+ map[old[0]] = dmap[old[0]];
+ key_clear(el, map, new);
+ /* MAP_VI == 1, MAP_EMACS == 0... */
+ map[new[0]] = tp->bind[el->el_map.type];
+ if (dalt) {
+ key_clear(el, alt, old);
+ alt[old[0]] = dalt[old[0]];
+ key_clear(el, alt, new);
+ alt[new[0]] = tp->bind[el->el_map.type+1];
+ }
+ }
+}
+
+/* tty_rawmode():
+ * Set terminal into 1 character at a time mode.
+ */
+protected int
+tty_rawmode(el)
+ EditLine *el;
+{
+ if (el->el_tty.t_mode == ED_IO)
+ return (0);
+
+ if (tty_getty(el, &el->el_tty.t_ts) == -1) {
+#ifdef DEBUG_TTY
+ (void) fprintf(el->el_errfile, "tty_rawmode: tty_getty: %s\n", strerror(errno));
+#endif /* DEBUG_TTY */
+ return(-1);
+ }
+
+ /*
+ * We always keep up with the eight bit setting and the speed of the
+ * tty. But only we only believe changes that are made to cooked mode!
+ */
+ el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts);
+ el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts);
+
+ if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed ||
+ tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) {
+ (void) cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed);
+ (void) cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed);
+ (void) cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed);
+ (void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed);
+ }
+
+ if (tty__cooked_mode(&el->el_tty.t_ts)) {
+ if (el->el_tty.t_ts.c_cflag != el->el_tty.t_ex.c_cflag) {
+ el->el_tty.t_ex.c_cflag = el->el_tty.t_ts.c_cflag;
+ el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][M_CTL].t_clrmask;
+ el->el_tty.t_ex.c_cflag |= el->el_tty.t_t[EX_IO][M_CTL].t_setmask;
+
+ el->el_tty.t_ed.c_cflag = el->el_tty.t_ts.c_cflag;
+ el->el_tty.t_ed.c_cflag &= ~el->el_tty.t_t[ED_IO][M_CTL].t_clrmask;
+ el->el_tty.t_ed.c_cflag |= el->el_tty.t_t[ED_IO][M_CTL].t_setmask;
+ }
+
+ if ((el->el_tty.t_ts.c_lflag != el->el_tty.t_ex.c_lflag) &&
+ (el->el_tty.t_ts.c_lflag != el->el_tty.t_ed.c_lflag)) {
+ el->el_tty.t_ex.c_lflag = el->el_tty.t_ts.c_lflag;
+ el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][M_LIN].t_clrmask;
+ el->el_tty.t_ex.c_lflag |= el->el_tty.t_t[EX_IO][M_LIN].t_setmask;
+
+ el->el_tty.t_ed.c_lflag = el->el_tty.t_ts.c_lflag;
+ el->el_tty.t_ed.c_lflag &= ~el->el_tty.t_t[ED_IO][M_LIN].t_clrmask;
+ el->el_tty.t_ed.c_lflag |= el->el_tty.t_t[ED_IO][M_LIN].t_setmask;
+ }
+
+ if ((el->el_tty.t_ts.c_iflag != el->el_tty.t_ex.c_iflag) &&
+ (el->el_tty.t_ts.c_iflag != el->el_tty.t_ed.c_iflag)) {
+ el->el_tty.t_ex.c_iflag = el->el_tty.t_ts.c_iflag;
+ el->el_tty.t_ex.c_iflag &= ~el->el_tty.t_t[EX_IO][M_INP].t_clrmask;
+ el->el_tty.t_ex.c_iflag |= el->el_tty.t_t[EX_IO][M_INP].t_setmask;
+
+ el->el_tty.t_ed.c_iflag = el->el_tty.t_ts.c_iflag;
+ el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][M_INP].t_clrmask;
+ el->el_tty.t_ed.c_iflag |= el->el_tty.t_t[ED_IO][M_INP].t_setmask;
+ }
+
+ if ((el->el_tty.t_ts.c_oflag != el->el_tty.t_ex.c_oflag) &&
+ (el->el_tty.t_ts.c_oflag != el->el_tty.t_ed.c_oflag)) {
+ el->el_tty.t_ex.c_oflag = el->el_tty.t_ts.c_oflag;
+ el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][M_OUT].t_clrmask;
+ el->el_tty.t_ex.c_oflag |= el->el_tty.t_t[EX_IO][M_OUT].t_setmask;
+
+ el->el_tty.t_ed.c_oflag = el->el_tty.t_ts.c_oflag;
+ el->el_tty.t_ed.c_oflag &= ~el->el_tty.t_t[ED_IO][M_OUT].t_clrmask;
+ el->el_tty.t_ed.c_oflag |= el->el_tty.t_t[ED_IO][M_OUT].t_setmask;
+ }
+
+ if (tty__gettabs(&el->el_tty.t_ex) == 0)
+ el->el_tty.t_tabs = 0;
+ else
+ el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0;
+
+ {
+ int i;
+
+ tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
+ /*
+ * Check if the user made any changes.
+ * If he did, then propagate the changes to the
+ * edit and execute data structures.
+ */
+ for (i = 0; i < C_NCC; i++)
+ if (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i])
+ break;
+
+ if (i != C_NCC) {
+ /*
+ * Propagate changes only to the unprotected chars
+ * that have been modified just now.
+ */
+ for (i = 0; i < C_NCC; i++) {
+ if (!((el->el_tty.t_t[ED_IO][M_CHAR].t_setmask & C_SH(i)))
+ && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
+ el->el_tty.t_c[ED_IO][i] = el->el_tty.t_c[TS_IO][i];
+ if (el->el_tty.t_t[ED_IO][M_CHAR].t_clrmask & C_SH(i))
+ el->el_tty.t_c[ED_IO][i] = el->el_tty.t_vdisable;
+ }
+ tty_bind_char(el, 0);
+ tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
+
+ for (i = 0; i < C_NCC; i++) {
+ if (!((el->el_tty.t_t[EX_IO][M_CHAR].t_setmask & C_SH(i)))
+ && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
+ el->el_tty.t_c[EX_IO][i] = el->el_tty.t_c[TS_IO][i];
+ if (el->el_tty.t_t[EX_IO][M_CHAR].t_clrmask & C_SH(i))
+ el->el_tty.t_c[EX_IO][i] = el->el_tty.t_vdisable;
+ }
+ tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
+ }
+
+ }
+ }
+
+ if (tty_setty(el, &el->el_tty.t_ed) == -1) {
+#ifdef DEBUG_TTY
+ (void) fprintf(el->el_errfile, "tty_rawmode: tty_setty: %s\n",
+ strerror(errno));
+#endif /* DEBUG_TTY */
+ return -1;
+ }
+ el->el_tty.t_mode = ED_IO;
+ return (0);
+} /* end tty_rawmode */
+
+
+/* tty_cookedmode():
+ * Set the tty back to normal mode
+ */
+protected int
+tty_cookedmode(el)
+ EditLine *el;
+{ /* set tty in normal setup */
+ if (el->el_tty.t_mode == EX_IO)
+ return (0);
+
+ if (tty_setty(el, &el->el_tty.t_ex) == -1) {
+#ifdef DEBUG_TTY
+ (void) fprintf(el->el_errfile, "tty_cookedmode: tty_setty: %s\n",
+ strerror(errno));
+#endif /* DEBUG_TTY */
+ return -1;
+ }
+ el->el_tty.t_mode = EX_IO;
+ return (0);
+} /* end tty_cookedmode */
+
+
+/* tty_quotemode():
+ * Turn on quote mode
+ */
+protected int
+tty_quotemode(el)
+ EditLine *el;
+{
+ if (el->el_tty.t_mode == QU_IO)
+ return 0;
+
+ el->el_tty.t_qu = el->el_tty.t_ed;
+
+ el->el_tty.t_qu.c_iflag &= ~el->el_tty.t_t[QU_IO][M_INP].t_clrmask;
+ el->el_tty.t_qu.c_iflag |= el->el_tty.t_t[QU_IO][M_INP].t_setmask;
+
+ el->el_tty.t_qu.c_oflag &= ~el->el_tty.t_t[QU_IO][M_OUT].t_clrmask;
+ el->el_tty.t_qu.c_oflag |= el->el_tty.t_t[QU_IO][M_OUT].t_setmask;
+
+ el->el_tty.t_qu.c_cflag &= ~el->el_tty.t_t[QU_IO][M_CTL].t_clrmask;
+ el->el_tty.t_qu.c_cflag |= el->el_tty.t_t[QU_IO][M_CTL].t_setmask;
+
+ el->el_tty.t_qu.c_lflag &= ~el->el_tty.t_t[QU_IO][M_LIN].t_clrmask;
+ el->el_tty.t_qu.c_lflag |= el->el_tty.t_t[QU_IO][M_LIN].t_setmask;
+
+ if (tty_setty(el, &el->el_tty.t_qu) == -1) {
+#ifdef DEBUG_TTY
+ (void) fprintf(el->el_errfile, "QuoteModeOn: tty_setty: %s\n",
+ strerror(errno));
+#endif /* DEBUG_TTY */
+ return -1;
+ }
+ el->el_tty.t_mode = QU_IO;
+ return 0;
+} /* end tty_quotemode */
+
+
+/* tty_noquotemode():
+ * Turn off quote mode
+ */
+protected int
+tty_noquotemode(el)
+ EditLine *el;
+{
+ if (el->el_tty.t_mode != QU_IO)
+ return 0;
+ if (tty_setty(el, &el->el_tty.t_ed) == -1) {
+#ifdef DEBUG_TTY
+ (void) fprintf(el->el_errfile, "QuoteModeOff: tty_setty: %s\n",
+ strerror(errno));
+#endif /* DEBUG_TTY */
+ return -1;
+ }
+ el->el_tty.t_mode = ED_IO;
+ return 0;
+}
+
+/* tty_stty():
+ * Stty builtin
+ */
+protected int
+/*ARGSUSED*/
+tty_stty(el, argc, argv)
+ EditLine *el;
+ int argc;
+ char **argv;
+{
+ ttymodes_t *m;
+ char x, *d;
+ int aflag = 0;
+ char *s;
+ char *name;
+ int z = EX_IO;
+
+ if (argv == NULL)
+ return -1;
+ name = *argv++;
+
+ while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0')
+ switch (argv[0][1]) {
+ case 'a':
+ aflag++;
+ argv++;
+ break;
+ case 'd':
+ argv++;
+ z = ED_IO;
+ break;
+ case 'x':
+ argv++;
+ z = EX_IO;
+ break;
+ case 'q':
+ argv++;
+ z = QU_IO;
+ break;
+ default:
+ (void) fprintf(el->el_errfile, "%s: Unknown switch `%c'.\n",
+ name, argv[0][1]);
+ return -1;
+ }
+
+ if (!argv || !*argv) {
+ int i = -1;
+ int len = 0, st = 0, cu;
+ for (m = ttymodes; m->m_name; m++) {
+ if (m->m_type != i) {
+ (void) fprintf(el->el_outfile, "%s%s", i != -1 ? "\n" : "",
+ el->el_tty.t_t[z][m->m_type].t_name);
+ i = m->m_type;
+ st = len = strlen(el->el_tty.t_t[z][m->m_type].t_name);
+ }
+
+ x = (el->el_tty.t_t[z][i].t_setmask & m->m_value) ? '+' : '\0';
+ x = (el->el_tty.t_t[z][i].t_clrmask & m->m_value) ? '-' : x;
+
+ if (x != '\0' || aflag) {
+
+ cu = strlen(m->m_name) + (x != '\0') + 1;
+
+ if (len + cu >= el->el_term.t_size.h) {
+ (void) fprintf(el->el_outfile, "\n%*s", st, "");
+ len = st + cu;
+ }
+ else
+ len += cu;
+
+ if (x != '\0')
+ (void) fprintf(el->el_outfile, "%c%s ", x, m->m_name);
+ else
+ (void) fprintf(el->el_outfile, "%s ", m->m_name);
+ }
+ }
+ (void) fprintf(el->el_outfile, "\n");
+ return 0;
+ }
+
+ while (argv && (s = *argv++)) {
+ switch (*s) {
+ case '+':
+ case '-':
+ x = *s++;
+ break;
+ default:
+ x = '\0';
+ break;
+ }
+ d = s;
+ for (m = ttymodes; m->m_name; m++)
+ if (strcmp(m->m_name, d) == 0)
+ break;
+
+ if (!m->m_name) {
+ (void) fprintf(el->el_errfile, "%s: Invalid argument `%s'.\n",
+ name, d);
+ return -1;
+ }
+
+ switch (x) {
+ case '+':
+ el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value;
+ el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
+ break;
+ case '-':
+ el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
+ el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value;
+ break;
+ default:
+ el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
+ el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
+ break;
+ }
+ }
+ return 0;
+} /* end tty_stty */
+
+
+#ifdef notyet
+/* tty_printchar():
+ * DEbugging routine to print the tty characters
+ */
+private void
+tty_printchar(el, s)
+ EditLine *el;
+ unsigned char *s;
+{
+ ttyperm_t *m;
+ int i;
+
+ for (i = 0; i < C_NCC; i++) {
+ for (m = el->el_tty.t_t; m->m_name; m++)
+ if (m->m_type == M_CHAR && C_SH(i) == m->m_value)
+ break;
+ if (m->m_name)
+ (void) fprintf(el->el_errfile, "%s ^%c ", m->m_name, s[i] + 'A'-1);
+ if (i % 5 == 0)
+ (void) fprintf(el->el_errfile, "\n");
+ }
+ (void) fprintf(el->el_errfile, "\n");
+}
+#endif /* notyet */