Home | History | Annotate | Line # | Download | only in libedit
tty.c revision 1.9
      1 /*	$NetBSD: tty.c,v 1.9 1998/09/27 18:04:12 christos Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1992, 1993
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * This code is derived from software contributed to Berkeley by
      8  * Christos Zoulas of Cornell University.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     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. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *	This product includes software developed by the University of
     21  *	California, Berkeley and its contributors.
     22  * 4. Neither the name of the University nor the names of its contributors
     23  *    may be used to endorse or promote products derived from this software
     24  *    without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     36  * SUCH DAMAGE.
     37  */
     38 
     39 #include <sys/cdefs.h>
     40 #if !defined(lint) && !defined(SCCSID)
     41 #if 0
     42 static char sccsid[] = "@(#)tty.c	8.1 (Berkeley) 6/4/93";
     43 #else
     44 __RCSID("$NetBSD: tty.c,v 1.9 1998/09/27 18:04:12 christos Exp $");
     45 #endif
     46 #endif /* not lint && not SCCSID */
     47 
     48 /*
     49  * tty.c: tty interface stuff
     50  */
     51 #include "sys.h"
     52 #include "tty.h"
     53 #include "el.h"
     54 
     55 typedef struct ttymodes_t {
     56     char *m_name;
     57     u_int m_value;
     58     int   m_type;
     59 } ttymodes_t;
     60 
     61 typedef struct ttymap_t {
     62     int nch, och;		 /* Internal and termio rep of chars */
     63     el_action_t bind[3]; 	/* emacs, vi, and vi-cmd */
     64 } ttymap_t;
     65 
     66 
     67 private ttyperm_t ttyperm = {
     68     {
     69 	{ "iflag:", ICRNL, (INLCR|IGNCR) },
     70 	{ "oflag:", (OPOST|ONLCR), ONLRET },
     71 	{ "cflag:", 0, 0 },
     72 	{ "lflag:", (ISIG|ICANON|ECHO|ECHOE|ECHOCTL|IEXTEN),
     73 		    (NOFLSH|ECHONL|EXTPROC|FLUSHO) },
     74 	{ "chars:", 	0, 0 },
     75     },
     76     {
     77 	{ "iflag:", (INLCR|ICRNL), IGNCR },
     78 	{ "oflag:", (OPOST|ONLCR), ONLRET },
     79 	{ "cflag:", 0, 0 },
     80 	{ "lflag:", ISIG,
     81 		    (NOFLSH|ICANON|ECHO|ECHOK|ECHONL|EXTPROC|IEXTEN|FLUSHO) },
     82 	{ "chars:", (C_SH(C_MIN)|C_SH(C_TIME)|C_SH(C_SWTCH)|C_SH(C_DSWTCH)|
     83 		     C_SH(C_SUSP)|C_SH(C_DSUSP)|C_SH(C_EOL)|C_SH(C_DISCARD)|
     84 		     C_SH(C_PGOFF)|C_SH(C_PAGE)|C_SH(C_STATUS)), 0 }
     85     },
     86     {
     87 	{ "iflag:", 0, IXON | IXOFF },
     88 	{ "oflag:", 0, 0 },
     89 	{ "cflag:", 0, 0 },
     90 	{ "lflag:", 0, ISIG | IEXTEN },
     91 	{ "chars:", 0, 0 },
     92     }
     93 };
     94 
     95 private ttychar_t ttychar = {
     96     {
     97 	CINTR,		 CQUIT, 	 CERASE, 	   CKILL,
     98 	CEOF, 		 CEOL, 		 CEOL2, 	   CSWTCH,
     99 	CDSWTCH,	 CERASE2,	 CSTART, 	   CSTOP,
    100 	CWERASE, 	 CSUSP, 	 CDSUSP, 	   CREPRINT,
    101 	CDISCARD, 	 CLNEXT,	 CSTATUS,	   CPAGE,
    102 	CPGOFF,		 CKILL2, 	 CBRK, 		   CMIN,
    103 	CTIME
    104     },
    105     {
    106 	CINTR, 		 CQUIT, 	  CERASE, 	   CKILL,
    107 	_POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
    108 	_POSIX_VDISABLE, CERASE2,	  CSTART, 	   CSTOP,
    109 	_POSIX_VDISABLE, CSUSP,           _POSIX_VDISABLE, _POSIX_VDISABLE,
    110 	CDISCARD, 	 _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
    111 	_POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 1,
    112 	0
    113     },
    114     {
    115 	0,		 0,		  0,		   0,
    116 	0,		 0,		  0,		   0,
    117 	0,		 0,		  0,		   0,
    118 	0,		 0,		  0,		   0,
    119 	0,		 0,		  0,		   0,
    120 	0,		 0,		  0,		   0,
    121 	0
    122     }
    123 };
    124 
    125 private ttymap_t tty_map[] = {
    126 #ifdef VERASE
    127 	{ C_ERASE,   VERASE,
    128 	    { ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR } },
    129 #endif /* VERASE */
    130 #ifdef VERASE2
    131 	{ C_ERASE2,  VERASE2,
    132 	    { ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR } },
    133 #endif /* VERASE2 */
    134 #ifdef VKILL
    135     	{ C_KILL,    VKILL,
    136 	    { EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED } },
    137 #endif /* VKILL */
    138 #ifdef VKILL2
    139     	{ C_KILL2,   VKILL2,
    140 	    { EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED } },
    141 #endif /* VKILL2 */
    142 #ifdef VEOF
    143     	{ C_EOF,     VEOF,
    144 	    { EM_DELETE_OR_LIST, VI_LIST_OR_EOF, ED_UNASSIGNED } },
    145 #endif /* VEOF */
    146 #ifdef VWERASE
    147     	{ C_WERASE,  VWERASE,
    148 	    { ED_DELETE_PREV_WORD, ED_DELETE_PREV_WORD, ED_PREV_WORD } },
    149 #endif /* VWERASE */
    150 #ifdef VREPRINT
    151    	{ C_REPRINT, VREPRINT,
    152 	    { ED_REDISPLAY, ED_INSERT, ED_REDISPLAY } },
    153 #endif /* VREPRINT */
    154 #ifdef VLNEXT
    155     	{ C_LNEXT,   VLNEXT,
    156 	    { ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED } },
    157 #endif /* VLNEXT */
    158 	{ -1,	     -1,
    159 	    { ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED } }
    160     };
    161 
    162 private ttymodes_t ttymodes[] = {
    163 # ifdef	IGNBRK
    164     { "ignbrk",	IGNBRK,	MD_INP },
    165 # endif /* IGNBRK */
    166 # ifdef	BRKINT
    167     { "brkint",	BRKINT,	MD_INP },
    168 # endif /* BRKINT */
    169 # ifdef	IGNPAR
    170     { "ignpar",	IGNPAR,	MD_INP },
    171 # endif /* IGNPAR */
    172 # ifdef	PARMRK
    173     { "parmrk",	PARMRK,	MD_INP },
    174 # endif /* PARMRK */
    175 # ifdef	INPCK
    176     { "inpck",	INPCK,	MD_INP },
    177 # endif /* INPCK */
    178 # ifdef	ISTRIP
    179     { "istrip",	ISTRIP,	MD_INP },
    180 # endif /* ISTRIP */
    181 # ifdef	INLCR
    182     { "inlcr",	INLCR,	MD_INP },
    183 # endif /* INLCR */
    184 # ifdef	IGNCR
    185     { "igncr",	IGNCR,	MD_INP },
    186 # endif /* IGNCR */
    187 # ifdef	ICRNL
    188     { "icrnl",	ICRNL,	MD_INP },
    189 # endif /* ICRNL */
    190 # ifdef	IUCLC
    191     { "iuclc",	IUCLC,	MD_INP },
    192 # endif /* IUCLC */
    193 # ifdef	IXON
    194     { "ixon",	IXON,	MD_INP },
    195 # endif /* IXON */
    196 # ifdef	IXANY
    197     { "ixany",	IXANY,	MD_INP },
    198 # endif /* IXANY */
    199 # ifdef	IXOFF
    200     { "ixoff",	IXOFF,	MD_INP },
    201 # endif /* IXOFF */
    202 # ifdef  IMAXBEL
    203     { "imaxbel",IMAXBEL,MD_INP },
    204 # endif /* IMAXBEL */
    205 
    206 # ifdef	OPOST
    207     { "opost",	OPOST,	MD_OUT },
    208 # endif /* OPOST */
    209 # ifdef	OLCUC
    210     { "olcuc",	OLCUC,	MD_OUT },
    211 # endif /* OLCUC */
    212 # ifdef	ONLCR
    213     { "onlcr",	ONLCR,	MD_OUT },
    214 # endif /* ONLCR */
    215 # ifdef	OCRNL
    216     { "ocrnl",	OCRNL,	MD_OUT },
    217 # endif /* OCRNL */
    218 # ifdef	ONOCR
    219     { "onocr",	ONOCR,	MD_OUT },
    220 # endif /* ONOCR */
    221 # ifdef ONOEOT
    222     { "onoeot",	ONOEOT,	MD_OUT },
    223 # endif /* ONOEOT */
    224 # ifdef	ONLRET
    225     { "onlret",	ONLRET,	MD_OUT },
    226 # endif /* ONLRET */
    227 # ifdef	OFILL
    228     { "ofill",	OFILL,	MD_OUT },
    229 # endif /* OFILL */
    230 # ifdef	OFDEL
    231     { "ofdel",	OFDEL,	MD_OUT },
    232 # endif /* OFDEL */
    233 # ifdef	NLDLY
    234     { "nldly",	NLDLY,	MD_OUT },
    235 # endif /* NLDLY */
    236 # ifdef	CRDLY
    237     { "crdly",	CRDLY,	MD_OUT },
    238 # endif /* CRDLY */
    239 # ifdef	TABDLY
    240     { "tabdly",	TABDLY,	MD_OUT },
    241 # endif /* TABDLY */
    242 # ifdef	XTABS
    243     { "xtabs",	XTABS,	MD_OUT },
    244 # endif /* XTABS */
    245 # ifdef	BSDLY
    246     { "bsdly",	BSDLY,	MD_OUT },
    247 # endif /* BSDLY */
    248 # ifdef	VTDLY
    249     { "vtdly",	VTDLY,	MD_OUT },
    250 # endif /* VTDLY */
    251 # ifdef	FFDLY
    252     { "ffdly",	FFDLY,	MD_OUT },
    253 # endif /* FFDLY */
    254 # ifdef	PAGEOUT
    255     { "pageout",PAGEOUT,MD_OUT },
    256 # endif /* PAGEOUT */
    257 # ifdef	WRAP
    258     { "wrap",	WRAP,	MD_OUT },
    259 # endif /* WRAP */
    260 
    261 # ifdef	CIGNORE
    262     { "cignore",CIGNORE,MD_CTL },
    263 # endif /* CBAUD */
    264 # ifdef	CBAUD
    265     { "cbaud",	CBAUD,	MD_CTL },
    266 # endif /* CBAUD */
    267 # ifdef	CSTOPB
    268     { "cstopb",	CSTOPB,	MD_CTL },
    269 # endif /* CSTOPB */
    270 # ifdef	CREAD
    271     { "cread",	CREAD,	MD_CTL },
    272 # endif /* CREAD */
    273 # ifdef	PARENB
    274     { "parenb",	PARENB,	MD_CTL },
    275 # endif /* PARENB */
    276 # ifdef	PARODD
    277     { "parodd",	PARODD,	MD_CTL },
    278 # endif /* PARODD */
    279 # ifdef	HUPCL
    280     { "hupcl",	HUPCL,	MD_CTL },
    281 # endif /* HUPCL */
    282 # ifdef	CLOCAL
    283     { "clocal",	CLOCAL,	MD_CTL },
    284 # endif /* CLOCAL */
    285 # ifdef	LOBLK
    286     { "loblk",	LOBLK,	MD_CTL },
    287 # endif /* LOBLK */
    288 # ifdef	CIBAUD
    289     { "cibaud",	CIBAUD,	MD_CTL },
    290 # endif /* CIBAUD */
    291 # ifdef CRTSCTS
    292 #  ifdef CCTS_OFLOW
    293     { "ccts_oflow",CCTS_OFLOW,MD_CTL },
    294 #  else
    295     { "crtscts",CRTSCTS,MD_CTL },
    296 #  endif /* CCTS_OFLOW */
    297 # endif /* CRTSCTS */
    298 # ifdef CRTS_IFLOW
    299     { "crts_iflow",CRTS_IFLOW,MD_CTL },
    300 # endif /* CRTS_IFLOW */
    301 # ifdef CDTRCTS
    302     { "cdtrcts",CDTRCTS,MD_CTL },
    303 # endif /* CDTRCTS */
    304 # ifdef MDMBUF
    305     { "mdmbuf",	MDMBUF,	MD_CTL },
    306 # endif /* MDMBUF */
    307 # ifdef RCV1EN
    308     { "rcv1en",	RCV1EN,	MD_CTL },
    309 # endif /* RCV1EN */
    310 # ifdef XMT1EN
    311     { "xmt1en",	XMT1EN,	MD_CTL },
    312 # endif /* XMT1EN */
    313 
    314 # ifdef	ISIG
    315     { "isig",	ISIG,	MD_LIN },
    316 # endif /* ISIG */
    317 # ifdef	ICANON
    318     { "icanon",	ICANON,	MD_LIN },
    319 # endif /* ICANON */
    320 # ifdef	XCASE
    321     { "xcase",	XCASE,	MD_LIN },
    322 # endif /* XCASE */
    323 # ifdef	ECHO
    324     { "echo",	ECHO,	MD_LIN },
    325 # endif /* ECHO */
    326 # ifdef	ECHOE
    327     { "echoe",	ECHOE,	MD_LIN },
    328 # endif /* ECHOE */
    329 # ifdef	ECHOK
    330     { "echok",	ECHOK,	MD_LIN },
    331 # endif /* ECHOK */
    332 # ifdef	ECHONL
    333     { "echonl",	ECHONL,	MD_LIN },
    334 # endif /* ECHONL */
    335 # ifdef	NOFLSH
    336     { "noflsh",	NOFLSH,	MD_LIN },
    337 # endif /* NOFLSH */
    338 # ifdef	TOSTOP
    339     { "tostop",	TOSTOP,	MD_LIN },
    340 # endif /* TOSTOP */
    341 # ifdef	ECHOCTL
    342     { "echoctl",ECHOCTL,MD_LIN },
    343 # endif /* ECHOCTL */
    344 # ifdef	ECHOPRT
    345     { "echoprt",ECHOPRT,MD_LIN },
    346 # endif /* ECHOPRT */
    347 # ifdef	ECHOKE
    348     { "echoke",	ECHOKE,	MD_LIN },
    349 # endif /* ECHOKE */
    350 # ifdef	DEFECHO
    351     { "defecho",DEFECHO,MD_LIN },
    352 # endif /* DEFECHO */
    353 # ifdef	FLUSHO
    354     { "flusho",	FLUSHO,	MD_LIN },
    355 # endif /* FLUSHO */
    356 # ifdef	PENDIN
    357     { "pendin",	PENDIN,	MD_LIN },
    358 # endif /* PENDIN */
    359 # ifdef	IEXTEN
    360     { "iexten",	IEXTEN,	MD_LIN },
    361 # endif /* IEXTEN */
    362 # ifdef	NOKERNINFO
    363     { "nokerninfo",NOKERNINFO,MD_LIN },
    364 # endif /* NOKERNINFO */
    365 # ifdef	ALTWERASE
    366     { "altwerase",ALTWERASE,MD_LIN },
    367 # endif /* ALTWERASE */
    368 # ifdef	EXTPROC
    369     { "extproc",EXTPROC, MD_LIN },
    370 # endif /* EXTPROC */
    371 
    372 # if defined(VINTR)
    373     { "intr",		C_SH(C_INTR), 	MD_CHAR },
    374 # endif /* VINTR */
    375 # if defined(VQUIT)
    376     { "quit",		C_SH(C_QUIT), 	MD_CHAR },
    377 # endif /* VQUIT */
    378 # if defined(VERASE)
    379     { "erase",		C_SH(C_ERASE), 	MD_CHAR },
    380 # endif /* VERASE */
    381 # if defined(VKILL)
    382     { "kill",		C_SH(C_KILL), 	MD_CHAR },
    383 # endif /* VKILL */
    384 # if defined(VEOF)
    385     { "eof",		C_SH(C_EOF), 	MD_CHAR },
    386 # endif /* VEOF */
    387 # if defined(VEOL)
    388     { "eol",		C_SH(C_EOL), 	MD_CHAR },
    389 # endif /* VEOL */
    390 # if defined(VEOL2)
    391     { "eol2",		C_SH(C_EOL2), 	MD_CHAR },
    392 # endif  /* VEOL2 */
    393 # if defined(VSWTCH)
    394     { "swtch",		C_SH(C_SWTCH), 	MD_CHAR },
    395 # endif /* VSWTCH */
    396 # if defined(VDSWTCH)
    397     { "dswtch",		C_SH(C_DSWTCH),	MD_CHAR },
    398 # endif /* VDSWTCH */
    399 # if defined(VERASE2)
    400     { "erase2",		C_SH(C_ERASE2),	MD_CHAR },
    401 # endif /* VERASE2 */
    402 # if defined(VSTART)
    403     { "start",		C_SH(C_START), 	MD_CHAR },
    404 # endif /* VSTART */
    405 # if defined(VSTOP)
    406     { "stop",		C_SH(C_STOP), 	MD_CHAR },
    407 # endif /* VSTOP */
    408 # if defined(VWERASE)
    409     { "werase",		C_SH(C_WERASE),	MD_CHAR },
    410 # endif /* VWERASE */
    411 # if defined(VSUSP)
    412     { "susp",		C_SH(C_SUSP), 	MD_CHAR },
    413 # endif /* VSUSP */
    414 # if defined(VDSUSP)
    415     { "dsusp",		C_SH(C_DSUSP), 	MD_CHAR },
    416 # endif /* VDSUSP */
    417 # if defined(VREPRINT)
    418     { "reprint",	C_SH(C_REPRINT),MD_CHAR },
    419 # endif /* VREPRINT */
    420 # if defined(VDISCARD)
    421     { "discard",	C_SH(C_DISCARD),MD_CHAR },
    422 # endif /* VDISCARD */
    423 # if defined(VLNEXT)
    424     { "lnext",		C_SH(C_LNEXT), 	MD_CHAR },
    425 # endif /* VLNEXT */
    426 # if defined(VSTATUS)
    427     { "status",		C_SH(C_STATUS),	MD_CHAR },
    428 # endif /* VSTATUS */
    429 # if defined(VPAGE)
    430     { "page",		C_SH(C_PAGE), 	MD_CHAR },
    431 # endif /* VPAGE */
    432 # if defined(VPGOFF)
    433     { "pgoff",		C_SH(C_PGOFF), 	MD_CHAR },
    434 # endif /* VPGOFF */
    435 # if defined(VKILL2)
    436     { "kill2",		C_SH(C_KILL2), 	MD_CHAR },
    437 # endif /* VKILL2 */
    438 # if defined(VBRK)
    439     { "brk",		C_SH(C_BRK), 	MD_CHAR },
    440 # endif /* VBRK */
    441 # if defined(VMIN)
    442     { "min",		C_SH(C_MIN), 	MD_CHAR },
    443 # endif /* VMIN */
    444 # if defined(VTIME)
    445     { "time",		C_SH(C_TIME), 	MD_CHAR },
    446 # endif /* VTIME */
    447     { NULL, 0, -1 },
    448 };
    449 
    450 
    451 
    452 #define tty_getty(el, td) tcgetattr((el)->el_infd, (td))
    453 #define tty_setty(el, td) tcsetattr((el)->el_infd, TCSADRAIN, (td))
    454 
    455 #define tty__gettabs(td)     ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1)
    456 #define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8)
    457 #define tty__cooked_mode(td) ((td)->c_lflag & ICANON)
    458 
    459 private void    tty__getchar	__P((struct termios *, unsigned char *));
    460 private void    tty__setchar	__P((struct termios *, unsigned char *));
    461 private speed_t tty__getspeed	__P((struct termios *));
    462 private int     tty_setup	__P((EditLine *));
    463 
    464 #define t_qu t_ts
    465 
    466 
    467 /* tty_setup():
    468  *	Get the tty parameters and initialize the editing state
    469  */
    470 private int
    471 tty_setup(el)
    472     EditLine *el;
    473 {
    474     int rst = 1;
    475     if (tty_getty(el, &el->el_tty.t_ed) == -1) {
    476 #ifdef DEBUG_TTY
    477 	(void) fprintf(el->el_errfile,
    478 		       "tty_setup: tty_getty: %s\n", strerror(errno));
    479 #endif /* DEBUG_TTY */
    480 	return(-1);
    481     }
    482     el->el_tty.t_ts    = el->el_tty.t_ex = el->el_tty.t_ed;
    483 
    484     el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex);
    485     el->el_tty.t_tabs  = tty__gettabs(&el->el_tty.t_ex);
    486     el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex);
    487 
    488     el->el_tty.t_ex.c_iflag &= ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask;
    489     el->el_tty.t_ex.c_iflag |=  el->el_tty.t_t[EX_IO][MD_INP].t_setmask;
    490 
    491     el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask;
    492     el->el_tty.t_ex.c_oflag |=  el->el_tty.t_t[EX_IO][MD_OUT].t_setmask;
    493 
    494     el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask;
    495     el->el_tty.t_ex.c_cflag |=  el->el_tty.t_t[EX_IO][MD_CTL].t_setmask;
    496 
    497     el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask;
    498     el->el_tty.t_ex.c_lflag |=  el->el_tty.t_t[EX_IO][MD_LIN].t_setmask;
    499 
    500     /*
    501      * Reset the tty chars to reasonable defaults
    502      * If they are disabled, then enable them.
    503      */
    504     if (rst) {
    505         if (tty__cooked_mode(&el->el_tty.t_ts)) {
    506             tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
    507             /*
    508              * Don't affect CMIN and CTIME for the editor mode
    509              */
    510             for (rst = 0; rst < C_NCC - 2; rst++)
    511                 if (el->el_tty.t_c[TS_IO][rst] != el->el_tty.t_vdisable &&
    512                     el->el_tty.t_c[ED_IO][rst] != el->el_tty.t_vdisable)
    513                     el->el_tty.t_c[ED_IO][rst]  = el->el_tty.t_c[TS_IO][rst];
    514             for (rst = 0; rst < C_NCC; rst++)
    515                 if (el->el_tty.t_c[TS_IO][rst] != el->el_tty.t_vdisable)
    516                     el->el_tty.t_c[EX_IO][rst]  = el->el_tty.t_c[TS_IO][rst];
    517         }
    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) {
    520 #ifdef DEBUG_TTY
    521             (void) fprintf(el->el_errfile, "tty_setup: tty_setty: %s\n",
    522 			   strerror(errno));
    523 #endif /* DEBUG_TTY */
    524             return(-1);
    525         }
    526     }
    527     else
    528         tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
    529 
    530     el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask;
    531     el->el_tty.t_ed.c_iflag |=  el->el_tty.t_t[ED_IO][MD_INP].t_setmask;
    532 
    533     el->el_tty.t_ed.c_oflag &= ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask;
    534     el->el_tty.t_ed.c_oflag |=  el->el_tty.t_t[ED_IO][MD_OUT].t_setmask;
    535 
    536     el->el_tty.t_ed.c_cflag &= ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask;
    537     el->el_tty.t_ed.c_cflag |=  el->el_tty.t_t[ED_IO][MD_CTL].t_setmask;
    538 
    539     el->el_tty.t_ed.c_lflag &= ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask;
    540     el->el_tty.t_ed.c_lflag |=  el->el_tty.t_t[ED_IO][MD_LIN].t_setmask;
    541 
    542     tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
    543     tty_bind_char(el, 1);
    544     return 0;
    545 }
    546 
    547 protected int
    548 tty_init(el)
    549     EditLine *el;
    550 {
    551     el->el_tty.t_mode     = EX_IO;
    552     el->el_tty.t_vdisable = _POSIX_VDISABLE;
    553     (void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t));
    554     (void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t));
    555     return tty_setup(el);
    556 } /* end tty_init */
    557 
    558 
    559 /* tty_end():
    560  *	Restore the tty to its original settings
    561  */
    562 protected void
    563 /*ARGSUSED*/
    564 tty_end(el)
    565     EditLine *el;
    566 {
    567     /* XXX: Maybe reset to an initial state? */
    568 }
    569 
    570 
    571 /* tty__getspeed():
    572  *	Get the tty speed
    573  */
    574 private speed_t
    575 tty__getspeed(td)
    576     struct termios *td;
    577 {
    578     speed_t spd;
    579 
    580     if ((spd = cfgetispeed(td)) == 0)
    581 	spd = cfgetospeed(td);
    582     return spd;
    583 } /* end tty__getspeed */
    584 
    585 
    586 /* tty__getchar():
    587  *	Get the tty characters
    588  */
    589 private void
    590 tty__getchar(td, s)
    591     struct termios *td;
    592     unsigned char *s;
    593 {
    594 # ifdef VINTR
    595     s[C_INTR]	= td->c_cc[VINTR];
    596 # endif /* VINTR */
    597 # ifdef VQUIT
    598     s[C_QUIT]	= td->c_cc[VQUIT];
    599 # endif /* VQUIT */
    600 # ifdef VERASE
    601     s[C_ERASE]	= td->c_cc[VERASE];
    602 # endif /* VERASE */
    603 # ifdef VKILL
    604     s[C_KILL]	= td->c_cc[VKILL];
    605 # endif /* VKILL */
    606 # ifdef VEOF
    607     s[C_EOF]	= td->c_cc[VEOF];
    608 # endif /* VEOF */
    609 # ifdef VEOL
    610     s[C_EOL]	= td->c_cc[VEOL];
    611 # endif /* VEOL */
    612 # ifdef VEOL2
    613     s[C_EOL2]	= td->c_cc[VEOL2];
    614 # endif  /* VEOL2 */
    615 # ifdef VSWTCH
    616     s[C_SWTCH]	= td->c_cc[VSWTCH];
    617 # endif /* VSWTCH */
    618 # ifdef VDSWTCH
    619     s[C_DSWTCH]	= td->c_cc[VDSWTCH];
    620 # endif /* VDSWTCH */
    621 # ifdef VERASE2
    622     s[C_ERASE2]	= td->c_cc[VERASE2];
    623 # endif /* VERASE2 */
    624 # ifdef VSTART
    625     s[C_START]	= td->c_cc[VSTART];
    626 # endif /* VSTART */
    627 # ifdef VSTOP
    628     s[C_STOP]	= td->c_cc[VSTOP];
    629 # endif /* VSTOP */
    630 # ifdef VWERASE
    631     s[C_WERASE]	= td->c_cc[VWERASE];
    632 # endif /* VWERASE */
    633 # ifdef VSUSP
    634     s[C_SUSP]	= td->c_cc[VSUSP];
    635 # endif /* VSUSP */
    636 # ifdef VDSUSP
    637     s[C_DSUSP]	= td->c_cc[VDSUSP];
    638 # endif /* VDSUSP */
    639 # ifdef VREPRINT
    640     s[C_REPRINT]= td->c_cc[VREPRINT];
    641 # endif /* VREPRINT */
    642 # ifdef VDISCARD
    643     s[C_DISCARD]= td->c_cc[VDISCARD];
    644 # endif /* VDISCARD */
    645 # ifdef VLNEXT
    646     s[C_LNEXT]	= td->c_cc[VLNEXT];
    647 # endif /* VLNEXT */
    648 # ifdef VSTATUS
    649     s[C_STATUS]	= td->c_cc[VSTATUS];
    650 # endif /* VSTATUS */
    651 # ifdef VPAGE
    652     s[C_PAGE]	= td->c_cc[VPAGE];
    653 # endif /* VPAGE */
    654 # ifdef VPGOFF
    655     s[C_PGOFF]	= td->c_cc[VPGOFF];
    656 # endif /* VPGOFF */
    657 # ifdef VKILL2
    658     s[C_KILL2]	= td->c_cc[VKILL2];
    659 # endif /* KILL2 */
    660 # ifdef VMIN
    661     s[C_MIN]	= td->c_cc[VMIN];
    662 # endif /* VMIN */
    663 # ifdef VTIME
    664     s[C_TIME]	= td->c_cc[VTIME];
    665 # endif /* VTIME */
    666 } /* tty__getchar */
    667 
    668 
    669 /* tty__setchar():
    670  *	Set the tty characters
    671  */
    672 private void
    673 tty__setchar(td, s)
    674     struct termios *td;
    675     unsigned char *s;
    676 {
    677 # ifdef VINTR
    678     td->c_cc[VINTR]	= s[C_INTR];
    679 # endif /* VINTR */
    680 # ifdef VQUIT
    681     td->c_cc[VQUIT]	= s[C_QUIT];
    682 # endif /* VQUIT */
    683 # ifdef VERASE
    684     td->c_cc[VERASE]	= s[C_ERASE];
    685 # endif /* VERASE */
    686 # ifdef VKILL
    687     td->c_cc[VKILL]	= s[C_KILL];
    688 # endif /* VKILL */
    689 # ifdef VEOF
    690     td->c_cc[VEOF]	= s[C_EOF];
    691 # endif /* VEOF */
    692 # ifdef VEOL
    693     td->c_cc[VEOL]	= s[C_EOL];
    694 # endif /* VEOL */
    695 # ifdef VEOL2
    696     td->c_cc[VEOL2]	= s[C_EOL2];
    697 # endif  /* VEOL2 */
    698 # ifdef VSWTCH
    699     td->c_cc[VSWTCH]	= s[C_SWTCH];
    700 # endif /* VSWTCH */
    701 # ifdef VDSWTCH
    702     td->c_cc[VDSWTCH]	= s[C_DSWTCH];
    703 # endif /* VDSWTCH */
    704 # ifdef VERASE2
    705     td->c_cc[VERASE2]	= s[C_ERASE2];
    706 # endif /* VERASE2 */
    707 # ifdef VSTART
    708     td->c_cc[VSTART]	= s[C_START];
    709 # endif /* VSTART */
    710 # ifdef VSTOP
    711     td->c_cc[VSTOP]	= s[C_STOP];
    712 # endif /* VSTOP */
    713 # ifdef VWERASE
    714     td->c_cc[VWERASE]	= s[C_WERASE];
    715 # endif /* VWERASE */
    716 # ifdef VSUSP
    717     td->c_cc[VSUSP]	= s[C_SUSP];
    718 # endif /* VSUSP */
    719 # ifdef VDSUSP
    720     td->c_cc[VDSUSP]	= s[C_DSUSP];
    721 # endif /* VDSUSP */
    722 # ifdef VREPRINT
    723     td->c_cc[VREPRINT]	= s[C_REPRINT];
    724 # endif /* VREPRINT */
    725 # ifdef VDISCARD
    726     td->c_cc[VDISCARD]	= s[C_DISCARD];
    727 # endif /* VDISCARD */
    728 # ifdef VLNEXT
    729     td->c_cc[VLNEXT]	= s[C_LNEXT];
    730 # endif /* VLNEXT */
    731 # ifdef VSTATUS
    732     td->c_cc[VSTATUS]	= s[C_STATUS];
    733 # endif /* VSTATUS */
    734 # ifdef VPAGE
    735     td->c_cc[VPAGE]	= s[C_PAGE];
    736 # endif /* VPAGE */
    737 # ifdef VPGOFF
    738     td->c_cc[VPGOFF]	= s[C_PGOFF];
    739 # endif /* VPGOFF */
    740 # ifdef VKILL2
    741     td->c_cc[VKILL2]	= s[C_KILL2];
    742 # endif /* VKILL2 */
    743 # ifdef VMIN
    744     td->c_cc[VMIN]	= s[C_MIN];
    745 # endif /* VMIN */
    746 # ifdef VTIME
    747     td->c_cc[VTIME]	= s[C_TIME];
    748 # endif /* VTIME */
    749 } /* tty__setchar */
    750 
    751 
    752 /* tty_bind_char():
    753  *	Rebind the editline functions
    754  */
    755 protected void
    756 tty_bind_char(el, force)
    757     EditLine *el;
    758     int force;
    759 {
    760     unsigned char *t_n = el->el_tty.t_c[ED_IO];
    761     unsigned char *t_o = el->el_tty.t_ed.c_cc;
    762     char new[2], old[2];
    763     ttymap_t *tp;
    764     el_action_t  *dmap, *dalt, *map, *alt;
    765     new[1] = old[1] = '\0';
    766 
    767 
    768     map = el->el_map.key;
    769     alt = el->el_map.alt;
    770     if (el->el_map.type == MAP_VI) {
    771 	dmap = el->el_map.vii;
    772 	dalt = el->el_map.vic;
    773     }
    774     else {
    775 	dmap = el->el_map.emacs;
    776 	dalt = NULL;
    777     }
    778 
    779     for (tp = tty_map; tp->nch != -1; tp++) {
    780 	new[0] = t_n[tp->nch];
    781 	old[0] = t_o[tp->och];
    782 	if (new[0] == old[0] && !force)
    783 	    continue;
    784 	/* Put the old default binding back, and set the new binding */
    785 	key_clear(el, map, old);
    786 	map[(int)old[0]] = dmap[(int)old[0]];
    787 	key_clear(el, map, new);
    788 	/* MAP_VI == 1, MAP_EMACS == 0... */
    789 	map[(int)new[0]] = tp->bind[(int)el->el_map.type];
    790 	if (dalt) {
    791 	    key_clear(el, alt, old);
    792 	    alt[(int)old[0]] = dalt[(int)old[0]];
    793 	    key_clear(el, alt, new);
    794 	    alt[(int)new[0]] = tp->bind[(int)el->el_map.type+1];
    795 	}
    796     }
    797 }
    798 
    799 /* tty_rawmode():
    800  * 	Set terminal into 1 character at a time mode.
    801  */
    802 protected int
    803 tty_rawmode(el)
    804     EditLine *el;
    805 {
    806     if (el->el_tty.t_mode == ED_IO)
    807 	return (0);
    808 
    809     if (tty_getty(el, &el->el_tty.t_ts) == -1) {
    810 #ifdef DEBUG_TTY
    811 	(void) fprintf(el->el_errfile, "tty_rawmode: tty_getty: %s\n", strerror(errno));
    812 #endif /* DEBUG_TTY */
    813 	return(-1);
    814     }
    815 
    816     /*
    817      * We always keep up with the eight bit setting and the speed of the
    818      * tty. But only we only believe changes that are made to cooked mode!
    819      */
    820     el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts);
    821     el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts);
    822 
    823     if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed ||
    824 	tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) {
    825 	(void) cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed);
    826 	(void) cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed);
    827 	(void) cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed);
    828 	(void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed);
    829     }
    830 
    831     if (tty__cooked_mode(&el->el_tty.t_ts)) {
    832 	if (el->el_tty.t_ts.c_cflag != el->el_tty.t_ex.c_cflag) {
    833 	    el->el_tty.t_ex.c_cflag  = el->el_tty.t_ts.c_cflag;
    834 	    el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask;
    835 	    el->el_tty.t_ex.c_cflag |=  el->el_tty.t_t[EX_IO][MD_CTL].t_setmask;
    836 
    837 	    el->el_tty.t_ed.c_cflag  = el->el_tty.t_ts.c_cflag;
    838 	    el->el_tty.t_ed.c_cflag &= ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask;
    839 	    el->el_tty.t_ed.c_cflag |=  el->el_tty.t_t[ED_IO][MD_CTL].t_setmask;
    840 	}
    841 
    842 	if ((el->el_tty.t_ts.c_lflag != el->el_tty.t_ex.c_lflag) &&
    843 	    (el->el_tty.t_ts.c_lflag != el->el_tty.t_ed.c_lflag)) {
    844 	    el->el_tty.t_ex.c_lflag = el->el_tty.t_ts.c_lflag;
    845 	    el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask;
    846 	    el->el_tty.t_ex.c_lflag |=  el->el_tty.t_t[EX_IO][MD_LIN].t_setmask;
    847 
    848 	    el->el_tty.t_ed.c_lflag = el->el_tty.t_ts.c_lflag;
    849 	    el->el_tty.t_ed.c_lflag &= ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask;
    850 	    el->el_tty.t_ed.c_lflag |=  el->el_tty.t_t[ED_IO][MD_LIN].t_setmask;
    851 	}
    852 
    853 	if ((el->el_tty.t_ts.c_iflag != el->el_tty.t_ex.c_iflag) &&
    854 	    (el->el_tty.t_ts.c_iflag != el->el_tty.t_ed.c_iflag)) {
    855 	    el->el_tty.t_ex.c_iflag = el->el_tty.t_ts.c_iflag;
    856 	    el->el_tty.t_ex.c_iflag &= ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask;
    857 	    el->el_tty.t_ex.c_iflag |=  el->el_tty.t_t[EX_IO][MD_INP].t_setmask;
    858 
    859 	    el->el_tty.t_ed.c_iflag = el->el_tty.t_ts.c_iflag;
    860 	    el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask;
    861 	    el->el_tty.t_ed.c_iflag |=  el->el_tty.t_t[ED_IO][MD_INP].t_setmask;
    862 	}
    863 
    864 	if ((el->el_tty.t_ts.c_oflag != el->el_tty.t_ex.c_oflag) &&
    865 	    (el->el_tty.t_ts.c_oflag != el->el_tty.t_ed.c_oflag)) {
    866 	    el->el_tty.t_ex.c_oflag = el->el_tty.t_ts.c_oflag;
    867 	    el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask;
    868 	    el->el_tty.t_ex.c_oflag |=  el->el_tty.t_t[EX_IO][MD_OUT].t_setmask;
    869 
    870 	    el->el_tty.t_ed.c_oflag = el->el_tty.t_ts.c_oflag;
    871 	    el->el_tty.t_ed.c_oflag &= ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask;
    872 	    el->el_tty.t_ed.c_oflag |=  el->el_tty.t_t[ED_IO][MD_OUT].t_setmask;
    873 	}
    874 
    875 	if (tty__gettabs(&el->el_tty.t_ex) == 0)
    876 	    el->el_tty.t_tabs = 0;
    877 	else
    878 	    el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0;
    879 
    880 	{
    881 	    int i;
    882 
    883 	    tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
    884 	    /*
    885 	     * Check if the user made any changes.
    886 	     * If he did, then propagate the changes to the
    887 	     * edit and execute data structures.
    888 	     */
    889 	    for (i = 0; i < C_NCC; i++)
    890 		if (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i])
    891 		    break;
    892 
    893 	    if (i != C_NCC) {
    894 		/*
    895 		 * Propagate changes only to the unprotected chars
    896 		 * that have been modified just now.
    897 		 */
    898 		for (i = 0; i < C_NCC; i++) {
    899 		    if (!((el->el_tty.t_t[ED_IO][MD_CHAR].t_setmask & C_SH(i)))
    900 		      && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
    901 			el->el_tty.t_c[ED_IO][i] = el->el_tty.t_c[TS_IO][i];
    902 		    if (el->el_tty.t_t[ED_IO][MD_CHAR].t_clrmask & C_SH(i))
    903 			el->el_tty.t_c[ED_IO][i] = el->el_tty.t_vdisable;
    904 		}
    905 		tty_bind_char(el, 0);
    906 		tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
    907 
    908 		for (i = 0; i < C_NCC; i++) {
    909 		    if (!((el->el_tty.t_t[EX_IO][MD_CHAR].t_setmask & C_SH(i)))
    910 		      && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
    911 			el->el_tty.t_c[EX_IO][i] = el->el_tty.t_c[TS_IO][i];
    912 		    if (el->el_tty.t_t[EX_IO][MD_CHAR].t_clrmask & C_SH(i))
    913 			el->el_tty.t_c[EX_IO][i] = el->el_tty.t_vdisable;
    914 		}
    915 		tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
    916 	    }
    917 	}
    918     }
    919 
    920     if (tty_setty(el, &el->el_tty.t_ed) == -1) {
    921 #ifdef DEBUG_TTY
    922 	(void) fprintf(el->el_errfile, "tty_rawmode: tty_setty: %s\n",
    923 		       strerror(errno));
    924 #endif /* DEBUG_TTY */
    925 	return -1;
    926     }
    927     el->el_tty.t_mode = ED_IO;
    928     return (0);
    929 } /* end tty_rawmode */
    930 
    931 
    932 /* tty_cookedmode():
    933  *	Set the tty back to normal mode
    934  */
    935 protected int
    936 tty_cookedmode(el)
    937     EditLine *el;
    938 {				/* set tty in normal setup */
    939     if (el->el_tty.t_mode == EX_IO)
    940 	return (0);
    941 
    942     if (tty_setty(el, &el->el_tty.t_ex) == -1) {
    943 #ifdef DEBUG_TTY
    944 	(void) fprintf(el->el_errfile, "tty_cookedmode: tty_setty: %s\n",
    945 		       strerror(errno));
    946 #endif /* DEBUG_TTY */
    947 	return -1;
    948     }
    949     el->el_tty.t_mode = EX_IO;
    950     return (0);
    951 } /* end tty_cookedmode */
    952 
    953 
    954 /* tty_quotemode():
    955  *	Turn on quote mode
    956  */
    957 protected int
    958 tty_quotemode(el)
    959     EditLine *el;
    960 {
    961     if (el->el_tty.t_mode == QU_IO)
    962 	return 0;
    963 
    964     el->el_tty.t_qu = el->el_tty.t_ed;
    965 
    966     el->el_tty.t_qu.c_iflag &= ~el->el_tty.t_t[QU_IO][MD_INP].t_clrmask;
    967     el->el_tty.t_qu.c_iflag |=  el->el_tty.t_t[QU_IO][MD_INP].t_setmask;
    968 
    969     el->el_tty.t_qu.c_oflag &= ~el->el_tty.t_t[QU_IO][MD_OUT].t_clrmask;
    970     el->el_tty.t_qu.c_oflag |=  el->el_tty.t_t[QU_IO][MD_OUT].t_setmask;
    971 
    972     el->el_tty.t_qu.c_cflag &= ~el->el_tty.t_t[QU_IO][MD_CTL].t_clrmask;
    973     el->el_tty.t_qu.c_cflag |=  el->el_tty.t_t[QU_IO][MD_CTL].t_setmask;
    974 
    975     el->el_tty.t_qu.c_lflag &= ~el->el_tty.t_t[QU_IO][MD_LIN].t_clrmask;
    976     el->el_tty.t_qu.c_lflag |=  el->el_tty.t_t[QU_IO][MD_LIN].t_setmask;
    977 
    978     if (tty_setty(el, &el->el_tty.t_qu) == -1) {
    979 #ifdef DEBUG_TTY
    980 	(void) fprintf(el->el_errfile, "QuoteModeOn: tty_setty: %s\n",
    981 		       strerror(errno));
    982 #endif /* DEBUG_TTY */
    983 	return -1;
    984     }
    985     el->el_tty.t_mode = QU_IO;
    986     return 0;
    987 } /* end tty_quotemode */
    988 
    989 
    990 /* tty_noquotemode():
    991  *	Turn off quote mode
    992  */
    993 protected int
    994 tty_noquotemode(el)
    995     EditLine *el;
    996 {
    997     if (el->el_tty.t_mode != QU_IO)
    998 	return 0;
    999     if (tty_setty(el, &el->el_tty.t_ed) == -1) {
   1000 #ifdef DEBUG_TTY
   1001 	(void) fprintf(el->el_errfile, "QuoteModeOff: tty_setty: %s\n",
   1002 		       strerror(errno));
   1003 #endif /* DEBUG_TTY */
   1004 	return -1;
   1005     }
   1006     el->el_tty.t_mode = ED_IO;
   1007     return 0;
   1008 }
   1009 
   1010 /* tty_stty():
   1011  *	Stty builtin
   1012  */
   1013 protected int
   1014 /*ARGSUSED*/
   1015 tty_stty(el, argc, argv)
   1016     EditLine *el;
   1017     int argc;
   1018     char **argv;
   1019 {
   1020     ttymodes_t *m;
   1021     char x, *d;
   1022     int aflag = 0;
   1023     char *s;
   1024     char *name;
   1025     int z = EX_IO;
   1026 
   1027     if (argv == NULL)
   1028 	return -1;
   1029     name = *argv++;
   1030 
   1031     while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0')
   1032 	switch (argv[0][1]) {
   1033 	case 'a':
   1034 	    aflag++;
   1035 	    argv++;
   1036 	    break;
   1037 	case 'd':
   1038 	    argv++;
   1039 	    z = ED_IO;
   1040 	    break;
   1041 	case 'x':
   1042 	    argv++;
   1043 	    z = EX_IO;
   1044 	    break;
   1045 	case 'q':
   1046 	    argv++;
   1047 	    z = QU_IO;
   1048 	    break;
   1049 	default:
   1050 	    (void) fprintf(el->el_errfile, "%s: Unknown switch `%c'.\n",
   1051 			   name, argv[0][1]);
   1052 	    return -1;
   1053 	}
   1054 
   1055     if (!argv || !*argv) {
   1056 	int i = -1;
   1057 	int len = 0, st = 0, cu;
   1058 	for (m = ttymodes; m->m_name; m++) {
   1059 	    if (m->m_type != i) {
   1060 		(void) fprintf(el->el_outfile, "%s%s", i != -1 ? "\n" : "",
   1061 			el->el_tty.t_t[z][m->m_type].t_name);
   1062 		i = m->m_type;
   1063 		st = len = strlen(el->el_tty.t_t[z][m->m_type].t_name);
   1064 	    }
   1065 
   1066 	    x = (el->el_tty.t_t[z][i].t_setmask & m->m_value) ? '+' : '\0';
   1067 	    x = (el->el_tty.t_t[z][i].t_clrmask & m->m_value) ? '-' : x;
   1068 
   1069 	    if (x != '\0' || aflag) {
   1070 
   1071 		cu = strlen(m->m_name) + (x != '\0') + 1;
   1072 
   1073 		if (len + cu >= el->el_term.t_size.h) {
   1074 		    (void) fprintf(el->el_outfile, "\n%*s", st, "");
   1075 		    len = st + cu;
   1076 		}
   1077 		else
   1078 		    len += cu;
   1079 
   1080 		if (x != '\0')
   1081 		    (void) fprintf(el->el_outfile, "%c%s ", x, m->m_name);
   1082 		else
   1083 		    (void) fprintf(el->el_outfile, "%s ", m->m_name);
   1084 	    }
   1085 	}
   1086 	(void) fprintf(el->el_outfile, "\n");
   1087 	return 0;
   1088     }
   1089 
   1090     while (argv && (s = *argv++)) {
   1091 	switch (*s) {
   1092 	case '+':
   1093 	case '-':
   1094 	    x = *s++;
   1095 	    break;
   1096 	default:
   1097 	    x = '\0';
   1098 	    break;
   1099 	}
   1100 	d = s;
   1101 	for (m = ttymodes; m->m_name; m++)
   1102 	    if (strcmp(m->m_name, d) == 0)
   1103 		break;
   1104 
   1105 	if (!m->m_name)  {
   1106 	    (void) fprintf(el->el_errfile, "%s: Invalid argument `%s'.\n",
   1107 			   name, d);
   1108 	    return -1;
   1109 	}
   1110 
   1111 	switch (x) {
   1112 	case '+':
   1113 	    el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value;
   1114 	    el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
   1115 	    break;
   1116 	case '-':
   1117 	    el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
   1118 	    el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value;
   1119 	    break;
   1120 	default:
   1121 	    el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
   1122 	    el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
   1123 	    break;
   1124 	}
   1125     }
   1126     return 0;
   1127 } /* end tty_stty */
   1128 
   1129 
   1130 #ifdef notyet
   1131 /* tty_printchar():
   1132  *	DEbugging routine to print the tty characters
   1133  */
   1134 private void
   1135 tty_printchar(el, s)
   1136     EditLine *el;
   1137     unsigned char *s;
   1138 {
   1139     ttyperm_t *m;
   1140     int i;
   1141 
   1142     for (i = 0; i < C_NCC; i++) {
   1143 	for (m = el->el_tty.t_t; m->m_name; m++)
   1144 	    if (m->m_type == MD_CHAR && C_SH(i) == m->m_value)
   1145 		break;
   1146 	if (m->m_name)
   1147 	    (void) fprintf(el->el_errfile, "%s ^%c ", m->m_name, s[i] + 'A'-1);
   1148 	if (i % 5 == 0)
   1149 	    (void) fprintf(el->el_errfile, "\n");
   1150     }
   1151     (void) fprintf(el->el_errfile, "\n");
   1152 }
   1153 #endif /* notyet */
   1154