Home | History | Annotate | Line # | Download | only in libedit
tty.c revision 1.12
      1 /*	$NetBSD: tty.c,v 1.12 1999/08/02 01:01:56 sommerfeld 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.12 1999/08/02 01:01:56 sommerfeld 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 | INLCR | ICRNL },
     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 
    476     if (el->el_flags & EDIT_DISABLED)
    477 	return (0);
    478 
    479     if (tty_getty(el, &el->el_tty.t_ed) == -1) {
    480 #ifdef DEBUG_TTY
    481 	(void) fprintf(el->el_errfile,
    482 		       "tty_setup: tty_getty: %s\n", strerror(errno));
    483 #endif /* DEBUG_TTY */
    484 	return(-1);
    485     }
    486     el->el_tty.t_ts    = el->el_tty.t_ex = el->el_tty.t_ed;
    487 
    488     el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex);
    489     el->el_tty.t_tabs  = tty__gettabs(&el->el_tty.t_ex);
    490     el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex);
    491 
    492     el->el_tty.t_ex.c_iflag &= ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask;
    493     el->el_tty.t_ex.c_iflag |=  el->el_tty.t_t[EX_IO][MD_INP].t_setmask;
    494 
    495     el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask;
    496     el->el_tty.t_ex.c_oflag |=  el->el_tty.t_t[EX_IO][MD_OUT].t_setmask;
    497 
    498     el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask;
    499     el->el_tty.t_ex.c_cflag |=  el->el_tty.t_t[EX_IO][MD_CTL].t_setmask;
    500 
    501     el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask;
    502     el->el_tty.t_ex.c_lflag |=  el->el_tty.t_t[EX_IO][MD_LIN].t_setmask;
    503 
    504     /*
    505      * Reset the tty chars to reasonable defaults
    506      * If they are disabled, then enable them.
    507      */
    508     if (rst) {
    509         if (tty__cooked_mode(&el->el_tty.t_ts)) {
    510             tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
    511             /*
    512              * Don't affect CMIN and CTIME for the editor mode
    513              */
    514             for (rst = 0; rst < C_NCC - 2; rst++)
    515                 if (el->el_tty.t_c[TS_IO][rst] != el->el_tty.t_vdisable &&
    516                     el->el_tty.t_c[ED_IO][rst] != el->el_tty.t_vdisable)
    517                     el->el_tty.t_c[ED_IO][rst]  = el->el_tty.t_c[TS_IO][rst];
    518             for (rst = 0; rst < C_NCC; rst++)
    519                 if (el->el_tty.t_c[TS_IO][rst] != el->el_tty.t_vdisable)
    520                     el->el_tty.t_c[EX_IO][rst]  = el->el_tty.t_c[TS_IO][rst];
    521         }
    522         tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
    523         if (tty_setty(el, &el->el_tty.t_ex) == -1) {
    524 #ifdef DEBUG_TTY
    525             (void) fprintf(el->el_errfile, "tty_setup: tty_setty: %s\n",
    526 			   strerror(errno));
    527 #endif /* DEBUG_TTY */
    528             return(-1);
    529         }
    530     }
    531     else
    532         tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
    533 
    534     el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask;
    535     el->el_tty.t_ed.c_iflag |=  el->el_tty.t_t[ED_IO][MD_INP].t_setmask;
    536 
    537     el->el_tty.t_ed.c_oflag &= ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask;
    538     el->el_tty.t_ed.c_oflag |=  el->el_tty.t_t[ED_IO][MD_OUT].t_setmask;
    539 
    540     el->el_tty.t_ed.c_cflag &= ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask;
    541     el->el_tty.t_ed.c_cflag |=  el->el_tty.t_t[ED_IO][MD_CTL].t_setmask;
    542 
    543     el->el_tty.t_ed.c_lflag &= ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask;
    544     el->el_tty.t_ed.c_lflag |=  el->el_tty.t_t[ED_IO][MD_LIN].t_setmask;
    545 
    546     tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
    547     tty_bind_char(el, 1);
    548     return 0;
    549 }
    550 
    551 protected int
    552 tty_init(el)
    553     EditLine *el;
    554 {
    555     el->el_tty.t_mode     = EX_IO;
    556     el->el_tty.t_vdisable = _POSIX_VDISABLE;
    557     (void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t));
    558     (void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t));
    559     return tty_setup(el);
    560 } /* end tty_init */
    561 
    562 
    563 /* tty_end():
    564  *	Restore the tty to its original settings
    565  */
    566 protected void
    567 /*ARGSUSED*/
    568 tty_end(el)
    569     EditLine *el;
    570 {
    571     /* XXX: Maybe reset to an initial state? */
    572 }
    573 
    574 
    575 /* tty__getspeed():
    576  *	Get the tty speed
    577  */
    578 private speed_t
    579 tty__getspeed(td)
    580     struct termios *td;
    581 {
    582     speed_t spd;
    583 
    584     if ((spd = cfgetispeed(td)) == 0)
    585 	spd = cfgetospeed(td);
    586     return spd;
    587 } /* end tty__getspeed */
    588 
    589 
    590 /* tty__getchar():
    591  *	Get the tty characters
    592  */
    593 private void
    594 tty__getchar(td, s)
    595     struct termios *td;
    596     unsigned char *s;
    597 {
    598 # ifdef VINTR
    599     s[C_INTR]	= td->c_cc[VINTR];
    600 # endif /* VINTR */
    601 # ifdef VQUIT
    602     s[C_QUIT]	= td->c_cc[VQUIT];
    603 # endif /* VQUIT */
    604 # ifdef VERASE
    605     s[C_ERASE]	= td->c_cc[VERASE];
    606 # endif /* VERASE */
    607 # ifdef VKILL
    608     s[C_KILL]	= td->c_cc[VKILL];
    609 # endif /* VKILL */
    610 # ifdef VEOF
    611     s[C_EOF]	= td->c_cc[VEOF];
    612 # endif /* VEOF */
    613 # ifdef VEOL
    614     s[C_EOL]	= td->c_cc[VEOL];
    615 # endif /* VEOL */
    616 # ifdef VEOL2
    617     s[C_EOL2]	= td->c_cc[VEOL2];
    618 # endif  /* VEOL2 */
    619 # ifdef VSWTCH
    620     s[C_SWTCH]	= td->c_cc[VSWTCH];
    621 # endif /* VSWTCH */
    622 # ifdef VDSWTCH
    623     s[C_DSWTCH]	= td->c_cc[VDSWTCH];
    624 # endif /* VDSWTCH */
    625 # ifdef VERASE2
    626     s[C_ERASE2]	= td->c_cc[VERASE2];
    627 # endif /* VERASE2 */
    628 # ifdef VSTART
    629     s[C_START]	= td->c_cc[VSTART];
    630 # endif /* VSTART */
    631 # ifdef VSTOP
    632     s[C_STOP]	= td->c_cc[VSTOP];
    633 # endif /* VSTOP */
    634 # ifdef VWERASE
    635     s[C_WERASE]	= td->c_cc[VWERASE];
    636 # endif /* VWERASE */
    637 # ifdef VSUSP
    638     s[C_SUSP]	= td->c_cc[VSUSP];
    639 # endif /* VSUSP */
    640 # ifdef VDSUSP
    641     s[C_DSUSP]	= td->c_cc[VDSUSP];
    642 # endif /* VDSUSP */
    643 # ifdef VREPRINT
    644     s[C_REPRINT]= td->c_cc[VREPRINT];
    645 # endif /* VREPRINT */
    646 # ifdef VDISCARD
    647     s[C_DISCARD]= td->c_cc[VDISCARD];
    648 # endif /* VDISCARD */
    649 # ifdef VLNEXT
    650     s[C_LNEXT]	= td->c_cc[VLNEXT];
    651 # endif /* VLNEXT */
    652 # ifdef VSTATUS
    653     s[C_STATUS]	= td->c_cc[VSTATUS];
    654 # endif /* VSTATUS */
    655 # ifdef VPAGE
    656     s[C_PAGE]	= td->c_cc[VPAGE];
    657 # endif /* VPAGE */
    658 # ifdef VPGOFF
    659     s[C_PGOFF]	= td->c_cc[VPGOFF];
    660 # endif /* VPGOFF */
    661 # ifdef VKILL2
    662     s[C_KILL2]	= td->c_cc[VKILL2];
    663 # endif /* KILL2 */
    664 # ifdef VMIN
    665     s[C_MIN]	= td->c_cc[VMIN];
    666 # endif /* VMIN */
    667 # ifdef VTIME
    668     s[C_TIME]	= td->c_cc[VTIME];
    669 # endif /* VTIME */
    670 } /* tty__getchar */
    671 
    672 
    673 /* tty__setchar():
    674  *	Set the tty characters
    675  */
    676 private void
    677 tty__setchar(td, s)
    678     struct termios *td;
    679     unsigned char *s;
    680 {
    681 # ifdef VINTR
    682     td->c_cc[VINTR]	= s[C_INTR];
    683 # endif /* VINTR */
    684 # ifdef VQUIT
    685     td->c_cc[VQUIT]	= s[C_QUIT];
    686 # endif /* VQUIT */
    687 # ifdef VERASE
    688     td->c_cc[VERASE]	= s[C_ERASE];
    689 # endif /* VERASE */
    690 # ifdef VKILL
    691     td->c_cc[VKILL]	= s[C_KILL];
    692 # endif /* VKILL */
    693 # ifdef VEOF
    694     td->c_cc[VEOF]	= s[C_EOF];
    695 # endif /* VEOF */
    696 # ifdef VEOL
    697     td->c_cc[VEOL]	= s[C_EOL];
    698 # endif /* VEOL */
    699 # ifdef VEOL2
    700     td->c_cc[VEOL2]	= s[C_EOL2];
    701 # endif  /* VEOL2 */
    702 # ifdef VSWTCH
    703     td->c_cc[VSWTCH]	= s[C_SWTCH];
    704 # endif /* VSWTCH */
    705 # ifdef VDSWTCH
    706     td->c_cc[VDSWTCH]	= s[C_DSWTCH];
    707 # endif /* VDSWTCH */
    708 # ifdef VERASE2
    709     td->c_cc[VERASE2]	= s[C_ERASE2];
    710 # endif /* VERASE2 */
    711 # ifdef VSTART
    712     td->c_cc[VSTART]	= s[C_START];
    713 # endif /* VSTART */
    714 # ifdef VSTOP
    715     td->c_cc[VSTOP]	= s[C_STOP];
    716 # endif /* VSTOP */
    717 # ifdef VWERASE
    718     td->c_cc[VWERASE]	= s[C_WERASE];
    719 # endif /* VWERASE */
    720 # ifdef VSUSP
    721     td->c_cc[VSUSP]	= s[C_SUSP];
    722 # endif /* VSUSP */
    723 # ifdef VDSUSP
    724     td->c_cc[VDSUSP]	= s[C_DSUSP];
    725 # endif /* VDSUSP */
    726 # ifdef VREPRINT
    727     td->c_cc[VREPRINT]	= s[C_REPRINT];
    728 # endif /* VREPRINT */
    729 # ifdef VDISCARD
    730     td->c_cc[VDISCARD]	= s[C_DISCARD];
    731 # endif /* VDISCARD */
    732 # ifdef VLNEXT
    733     td->c_cc[VLNEXT]	= s[C_LNEXT];
    734 # endif /* VLNEXT */
    735 # ifdef VSTATUS
    736     td->c_cc[VSTATUS]	= s[C_STATUS];
    737 # endif /* VSTATUS */
    738 # ifdef VPAGE
    739     td->c_cc[VPAGE]	= s[C_PAGE];
    740 # endif /* VPAGE */
    741 # ifdef VPGOFF
    742     td->c_cc[VPGOFF]	= s[C_PGOFF];
    743 # endif /* VPGOFF */
    744 # ifdef VKILL2
    745     td->c_cc[VKILL2]	= s[C_KILL2];
    746 # endif /* VKILL2 */
    747 # ifdef VMIN
    748     td->c_cc[VMIN]	= s[C_MIN];
    749 # endif /* VMIN */
    750 # ifdef VTIME
    751     td->c_cc[VTIME]	= s[C_TIME];
    752 # endif /* VTIME */
    753 } /* tty__setchar */
    754 
    755 
    756 /* tty_bind_char():
    757  *	Rebind the editline functions
    758  */
    759 protected void
    760 tty_bind_char(el, force)
    761     EditLine *el;
    762     int force;
    763 {
    764     unsigned char *t_n = el->el_tty.t_c[ED_IO];
    765     unsigned char *t_o = el->el_tty.t_ed.c_cc;
    766     char new[2], old[2];
    767     ttymap_t *tp;
    768     el_action_t  *dmap, *dalt, *map, *alt;
    769     new[1] = old[1] = '\0';
    770 
    771 
    772     map = el->el_map.key;
    773     alt = el->el_map.alt;
    774     if (el->el_map.type == MAP_VI) {
    775 	dmap = el->el_map.vii;
    776 	dalt = el->el_map.vic;
    777     }
    778     else {
    779 	dmap = el->el_map.emacs;
    780 	dalt = NULL;
    781     }
    782 
    783     for (tp = tty_map; tp->nch != -1; tp++) {
    784 	new[0] = t_n[tp->nch];
    785 	old[0] = t_o[tp->och];
    786 	if (new[0] == old[0] && !force)
    787 	    continue;
    788 	/* Put the old default binding back, and set the new binding */
    789 	key_clear(el, map, old);
    790 	map[(int)old[0]] = dmap[(int)old[0]];
    791 	key_clear(el, map, new);
    792 	/* MAP_VI == 1, MAP_EMACS == 0... */
    793 	map[(int)new[0]] = tp->bind[(int)el->el_map.type];
    794 	if (dalt) {
    795 	    key_clear(el, alt, old);
    796 	    alt[(int)old[0]] = dalt[(int)old[0]];
    797 	    key_clear(el, alt, new);
    798 	    alt[(int)new[0]] = tp->bind[(int)el->el_map.type+1];
    799 	}
    800     }
    801 }
    802 
    803 /* tty_rawmode():
    804  * 	Set terminal into 1 character at a time mode.
    805  */
    806 protected int
    807 tty_rawmode(el)
    808     EditLine *el;
    809 {
    810     if (el->el_tty.t_mode == ED_IO || el->el_tty.t_mode == QU_IO)
    811 	return (0);
    812 
    813     if (el->el_flags & EDIT_DISABLED)
    814 	return (0);
    815 
    816     if (tty_getty(el, &el->el_tty.t_ts) == -1) {
    817 #ifdef DEBUG_TTY
    818 	(void) fprintf(el->el_errfile, "tty_rawmode: tty_getty: %s\n", strerror(errno));
    819 #endif /* DEBUG_TTY */
    820 	return(-1);
    821     }
    822 
    823     /*
    824      * We always keep up with the eight bit setting and the speed of the
    825      * tty. But only we only believe changes that are made to cooked mode!
    826      */
    827     el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts);
    828     el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts);
    829 
    830     if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed ||
    831 	tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) {
    832 	(void) cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed);
    833 	(void) cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed);
    834 	(void) cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed);
    835 	(void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed);
    836     }
    837 
    838     if (tty__cooked_mode(&el->el_tty.t_ts)) {
    839 	if (el->el_tty.t_ts.c_cflag != el->el_tty.t_ex.c_cflag) {
    840 	    el->el_tty.t_ex.c_cflag  = el->el_tty.t_ts.c_cflag;
    841 	    el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask;
    842 	    el->el_tty.t_ex.c_cflag |=  el->el_tty.t_t[EX_IO][MD_CTL].t_setmask;
    843 
    844 	    el->el_tty.t_ed.c_cflag  = el->el_tty.t_ts.c_cflag;
    845 	    el->el_tty.t_ed.c_cflag &= ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask;
    846 	    el->el_tty.t_ed.c_cflag |=  el->el_tty.t_t[ED_IO][MD_CTL].t_setmask;
    847 	}
    848 
    849 	if ((el->el_tty.t_ts.c_lflag != el->el_tty.t_ex.c_lflag) &&
    850 	    (el->el_tty.t_ts.c_lflag != el->el_tty.t_ed.c_lflag)) {
    851 	    el->el_tty.t_ex.c_lflag = el->el_tty.t_ts.c_lflag;
    852 	    el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask;
    853 	    el->el_tty.t_ex.c_lflag |=  el->el_tty.t_t[EX_IO][MD_LIN].t_setmask;
    854 
    855 	    el->el_tty.t_ed.c_lflag = el->el_tty.t_ts.c_lflag;
    856 	    el->el_tty.t_ed.c_lflag &= ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask;
    857 	    el->el_tty.t_ed.c_lflag |=  el->el_tty.t_t[ED_IO][MD_LIN].t_setmask;
    858 	}
    859 
    860 	if ((el->el_tty.t_ts.c_iflag != el->el_tty.t_ex.c_iflag) &&
    861 	    (el->el_tty.t_ts.c_iflag != el->el_tty.t_ed.c_iflag)) {
    862 	    el->el_tty.t_ex.c_iflag = el->el_tty.t_ts.c_iflag;
    863 	    el->el_tty.t_ex.c_iflag &= ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask;
    864 	    el->el_tty.t_ex.c_iflag |=  el->el_tty.t_t[EX_IO][MD_INP].t_setmask;
    865 
    866 	    el->el_tty.t_ed.c_iflag = el->el_tty.t_ts.c_iflag;
    867 	    el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask;
    868 	    el->el_tty.t_ed.c_iflag |=  el->el_tty.t_t[ED_IO][MD_INP].t_setmask;
    869 	}
    870 
    871 	if ((el->el_tty.t_ts.c_oflag != el->el_tty.t_ex.c_oflag) &&
    872 	    (el->el_tty.t_ts.c_oflag != el->el_tty.t_ed.c_oflag)) {
    873 	    el->el_tty.t_ex.c_oflag = el->el_tty.t_ts.c_oflag;
    874 	    el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask;
    875 	    el->el_tty.t_ex.c_oflag |=  el->el_tty.t_t[EX_IO][MD_OUT].t_setmask;
    876 
    877 	    el->el_tty.t_ed.c_oflag = el->el_tty.t_ts.c_oflag;
    878 	    el->el_tty.t_ed.c_oflag &= ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask;
    879 	    el->el_tty.t_ed.c_oflag |=  el->el_tty.t_t[ED_IO][MD_OUT].t_setmask;
    880 	}
    881 
    882 	if (tty__gettabs(&el->el_tty.t_ex) == 0)
    883 	    el->el_tty.t_tabs = 0;
    884 	else
    885 	    el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0;
    886 
    887 	{
    888 	    int i;
    889 
    890 	    tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
    891 	    /*
    892 	     * Check if the user made any changes.
    893 	     * If he did, then propagate the changes to the
    894 	     * edit and execute data structures.
    895 	     */
    896 	    for (i = 0; i < C_NCC; i++)
    897 		if (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i])
    898 		    break;
    899 
    900 	    if (i != C_NCC) {
    901 		/*
    902 		 * Propagate changes only to the unprotected chars
    903 		 * that have been modified just now.
    904 		 */
    905 		for (i = 0; i < C_NCC; i++) {
    906 		    if (!((el->el_tty.t_t[ED_IO][MD_CHAR].t_setmask & C_SH(i)))
    907 		      && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
    908 			el->el_tty.t_c[ED_IO][i] = el->el_tty.t_c[TS_IO][i];
    909 		    if (el->el_tty.t_t[ED_IO][MD_CHAR].t_clrmask & C_SH(i))
    910 			el->el_tty.t_c[ED_IO][i] = el->el_tty.t_vdisable;
    911 		}
    912 		tty_bind_char(el, 0);
    913 		tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
    914 
    915 		for (i = 0; i < C_NCC; i++) {
    916 		    if (!((el->el_tty.t_t[EX_IO][MD_CHAR].t_setmask & C_SH(i)))
    917 		      && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
    918 			el->el_tty.t_c[EX_IO][i] = el->el_tty.t_c[TS_IO][i];
    919 		    if (el->el_tty.t_t[EX_IO][MD_CHAR].t_clrmask & C_SH(i))
    920 			el->el_tty.t_c[EX_IO][i] = el->el_tty.t_vdisable;
    921 		}
    922 		tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
    923 	    }
    924 	}
    925     }
    926 
    927     if (tty_setty(el, &el->el_tty.t_ed) == -1) {
    928 #ifdef DEBUG_TTY
    929 	(void) fprintf(el->el_errfile, "tty_rawmode: tty_setty: %s\n",
    930 		       strerror(errno));
    931 #endif /* DEBUG_TTY */
    932 	return -1;
    933     }
    934     el->el_tty.t_mode = ED_IO;
    935     return (0);
    936 } /* end tty_rawmode */
    937 
    938 
    939 /* tty_cookedmode():
    940  *	Set the tty back to normal mode
    941  */
    942 protected int
    943 tty_cookedmode(el)
    944     EditLine *el;
    945 {				/* set tty in normal setup */
    946     if (el->el_tty.t_mode == EX_IO)
    947 	return (0);
    948 
    949     if (el->el_flags & EDIT_DISABLED)
    950 	return (0);
    951 
    952     if (tty_setty(el, &el->el_tty.t_ex) == -1) {
    953 #ifdef DEBUG_TTY
    954 	(void) fprintf(el->el_errfile, "tty_cookedmode: tty_setty: %s\n",
    955 		       strerror(errno));
    956 #endif /* DEBUG_TTY */
    957 	return -1;
    958     }
    959     el->el_tty.t_mode = EX_IO;
    960     return (0);
    961 } /* end tty_cookedmode */
    962 
    963 
    964 /* tty_quotemode():
    965  *	Turn on quote mode
    966  */
    967 protected int
    968 tty_quotemode(el)
    969     EditLine *el;
    970 {
    971     if (el->el_tty.t_mode == QU_IO)
    972 	return 0;
    973 
    974     el->el_tty.t_qu = el->el_tty.t_ed;
    975 
    976     el->el_tty.t_qu.c_iflag &= ~el->el_tty.t_t[QU_IO][MD_INP].t_clrmask;
    977     el->el_tty.t_qu.c_iflag |=  el->el_tty.t_t[QU_IO][MD_INP].t_setmask;
    978 
    979     el->el_tty.t_qu.c_oflag &= ~el->el_tty.t_t[QU_IO][MD_OUT].t_clrmask;
    980     el->el_tty.t_qu.c_oflag |=  el->el_tty.t_t[QU_IO][MD_OUT].t_setmask;
    981 
    982     el->el_tty.t_qu.c_cflag &= ~el->el_tty.t_t[QU_IO][MD_CTL].t_clrmask;
    983     el->el_tty.t_qu.c_cflag |=  el->el_tty.t_t[QU_IO][MD_CTL].t_setmask;
    984 
    985     el->el_tty.t_qu.c_lflag &= ~el->el_tty.t_t[QU_IO][MD_LIN].t_clrmask;
    986     el->el_tty.t_qu.c_lflag |=  el->el_tty.t_t[QU_IO][MD_LIN].t_setmask;
    987 
    988     if (tty_setty(el, &el->el_tty.t_qu) == -1) {
    989 #ifdef DEBUG_TTY
    990 	(void) fprintf(el->el_errfile, "QuoteModeOn: tty_setty: %s\n",
    991 		       strerror(errno));
    992 #endif /* DEBUG_TTY */
    993 	return -1;
    994     }
    995     el->el_tty.t_mode = QU_IO;
    996     return 0;
    997 } /* end tty_quotemode */
    998 
    999 
   1000 /* tty_noquotemode():
   1001  *	Turn off quote mode
   1002  */
   1003 protected int
   1004 tty_noquotemode(el)
   1005     EditLine *el;
   1006 {
   1007     if (el->el_tty.t_mode != QU_IO)
   1008 	return 0;
   1009     if (tty_setty(el, &el->el_tty.t_ed) == -1) {
   1010 #ifdef DEBUG_TTY
   1011 	(void) fprintf(el->el_errfile, "QuoteModeOff: tty_setty: %s\n",
   1012 		       strerror(errno));
   1013 #endif /* DEBUG_TTY */
   1014 	return -1;
   1015     }
   1016     el->el_tty.t_mode = ED_IO;
   1017     return 0;
   1018 }
   1019 
   1020 /* tty_stty():
   1021  *	Stty builtin
   1022  */
   1023 protected int
   1024 /*ARGSUSED*/
   1025 tty_stty(el, argc, argv)
   1026     EditLine *el;
   1027     int argc;
   1028     char **argv;
   1029 {
   1030     ttymodes_t *m;
   1031     char x, *d;
   1032     int aflag = 0;
   1033     char *s;
   1034     char *name;
   1035     int z = EX_IO;
   1036 
   1037     if (argv == NULL)
   1038 	return -1;
   1039     name = *argv++;
   1040 
   1041     while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0')
   1042 	switch (argv[0][1]) {
   1043 	case 'a':
   1044 	    aflag++;
   1045 	    argv++;
   1046 	    break;
   1047 	case 'd':
   1048 	    argv++;
   1049 	    z = ED_IO;
   1050 	    break;
   1051 	case 'x':
   1052 	    argv++;
   1053 	    z = EX_IO;
   1054 	    break;
   1055 	case 'q':
   1056 	    argv++;
   1057 	    z = QU_IO;
   1058 	    break;
   1059 	default:
   1060 	    (void) fprintf(el->el_errfile, "%s: Unknown switch `%c'.\n",
   1061 			   name, argv[0][1]);
   1062 	    return -1;
   1063 	}
   1064 
   1065     if (!argv || !*argv) {
   1066 	int i = -1;
   1067 	int len = 0, st = 0, cu;
   1068 	for (m = ttymodes; m->m_name; m++) {
   1069 	    if (m->m_type != i) {
   1070 		(void) fprintf(el->el_outfile, "%s%s", i != -1 ? "\n" : "",
   1071 			el->el_tty.t_t[z][m->m_type].t_name);
   1072 		i = m->m_type;
   1073 		st = len = strlen(el->el_tty.t_t[z][m->m_type].t_name);
   1074 	    }
   1075 
   1076 	    x = (el->el_tty.t_t[z][i].t_setmask & m->m_value) ? '+' : '\0';
   1077 	    x = (el->el_tty.t_t[z][i].t_clrmask & m->m_value) ? '-' : x;
   1078 
   1079 	    if (x != '\0' || aflag) {
   1080 
   1081 		cu = strlen(m->m_name) + (x != '\0') + 1;
   1082 
   1083 		if (len + cu >= el->el_term.t_size.h) {
   1084 		    (void) fprintf(el->el_outfile, "\n%*s", st, "");
   1085 		    len = st + cu;
   1086 		}
   1087 		else
   1088 		    len += cu;
   1089 
   1090 		if (x != '\0')
   1091 		    (void) fprintf(el->el_outfile, "%c%s ", x, m->m_name);
   1092 		else
   1093 		    (void) fprintf(el->el_outfile, "%s ", m->m_name);
   1094 	    }
   1095 	}
   1096 	(void) fprintf(el->el_outfile, "\n");
   1097 	return 0;
   1098     }
   1099 
   1100     while (argv && (s = *argv++)) {
   1101 	switch (*s) {
   1102 	case '+':
   1103 	case '-':
   1104 	    x = *s++;
   1105 	    break;
   1106 	default:
   1107 	    x = '\0';
   1108 	    break;
   1109 	}
   1110 	d = s;
   1111 	for (m = ttymodes; m->m_name; m++)
   1112 	    if (strcmp(m->m_name, d) == 0)
   1113 		break;
   1114 
   1115 	if (!m->m_name)  {
   1116 	    (void) fprintf(el->el_errfile, "%s: Invalid argument `%s'.\n",
   1117 			   name, d);
   1118 	    return -1;
   1119 	}
   1120 
   1121 	switch (x) {
   1122 	case '+':
   1123 	    el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value;
   1124 	    el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
   1125 	    break;
   1126 	case '-':
   1127 	    el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
   1128 	    el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value;
   1129 	    break;
   1130 	default:
   1131 	    el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
   1132 	    el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
   1133 	    break;
   1134 	}
   1135     }
   1136     return 0;
   1137 } /* end tty_stty */
   1138 
   1139 
   1140 #ifdef notyet
   1141 /* tty_printchar():
   1142  *	DEbugging routine to print the tty characters
   1143  */
   1144 private void
   1145 tty_printchar(el, s)
   1146     EditLine *el;
   1147     unsigned char *s;
   1148 {
   1149     ttyperm_t *m;
   1150     int i;
   1151 
   1152     for (i = 0; i < C_NCC; i++) {
   1153 	for (m = el->el_tty.t_t; m->m_name; m++)
   1154 	    if (m->m_type == MD_CHAR && C_SH(i) == m->m_value)
   1155 		break;
   1156 	if (m->m_name)
   1157 	    (void) fprintf(el->el_errfile, "%s ^%c ", m->m_name, s[i] + 'A'-1);
   1158 	if (i % 5 == 0)
   1159 	    (void) fprintf(el->el_errfile, "\n");
   1160     }
   1161     (void) fprintf(el->el_errfile, "\n");
   1162 }
   1163 #endif /* notyet */
   1164