Home | History | Annotate | Line # | Download | only in libedit
tty.c revision 1.7
      1 /*	$NetBSD: tty.c,v 1.7 1998/03/30 01:30:14 mrg 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.7 1998/03/30 01:30:14 mrg 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,	M_INP },
    165 # endif /* IGNBRK */
    166 # ifdef	BRKINT
    167     { "brkint",	BRKINT,	M_INP },
    168 # endif /* BRKINT */
    169 # ifdef	IGNPAR
    170     { "ignpar",	IGNPAR,	M_INP },
    171 # endif /* IGNPAR */
    172 # ifdef	PARMRK
    173     { "parmrk",	PARMRK,	M_INP },
    174 # endif /* PARMRK */
    175 # ifdef	INPCK
    176     { "inpck",	INPCK,	M_INP },
    177 # endif /* INPCK */
    178 # ifdef	ISTRIP
    179     { "istrip",	ISTRIP,	M_INP },
    180 # endif /* ISTRIP */
    181 # ifdef	INLCR
    182     { "inlcr",	INLCR,	M_INP },
    183 # endif /* INLCR */
    184 # ifdef	IGNCR
    185     { "igncr",	IGNCR,	M_INP },
    186 # endif /* IGNCR */
    187 # ifdef	ICRNL
    188     { "icrnl",	ICRNL,	M_INP },
    189 # endif /* ICRNL */
    190 # ifdef	IUCLC
    191     { "iuclc",	IUCLC,	M_INP },
    192 # endif /* IUCLC */
    193 # ifdef	IXON
    194     { "ixon",	IXON,	M_INP },
    195 # endif /* IXON */
    196 # ifdef	IXANY
    197     { "ixany",	IXANY,	M_INP },
    198 # endif /* IXANY */
    199 # ifdef	IXOFF
    200     { "ixoff",	IXOFF,	M_INP },
    201 # endif /* IXOFF */
    202 # ifdef  IMAXBEL
    203     { "imaxbel",IMAXBEL,M_INP },
    204 # endif /* IMAXBEL */
    205 
    206 # ifdef	OPOST
    207     { "opost",	OPOST,	M_OUT },
    208 # endif /* OPOST */
    209 # ifdef	OLCUC
    210     { "olcuc",	OLCUC,	M_OUT },
    211 # endif /* OLCUC */
    212 # ifdef	ONLCR
    213     { "onlcr",	ONLCR,	M_OUT },
    214 # endif /* ONLCR */
    215 # ifdef	OCRNL
    216     { "ocrnl",	OCRNL,	M_OUT },
    217 # endif /* OCRNL */
    218 # ifdef	ONOCR
    219     { "onocr",	ONOCR,	M_OUT },
    220 # endif /* ONOCR */
    221 # ifdef ONOEOT
    222     { "onoeot",	ONOEOT,	M_OUT },
    223 # endif /* ONOEOT */
    224 # ifdef	ONLRET
    225     { "onlret",	ONLRET,	M_OUT },
    226 # endif /* ONLRET */
    227 # ifdef	OFILL
    228     { "ofill",	OFILL,	M_OUT },
    229 # endif /* OFILL */
    230 # ifdef	OFDEL
    231     { "ofdel",	OFDEL,	M_OUT },
    232 # endif /* OFDEL */
    233 # ifdef	NLDLY
    234     { "nldly",	NLDLY,	M_OUT },
    235 # endif /* NLDLY */
    236 # ifdef	CRDLY
    237     { "crdly",	CRDLY,	M_OUT },
    238 # endif /* CRDLY */
    239 # ifdef	TABDLY
    240     { "tabdly",	TABDLY,	M_OUT },
    241 # endif /* TABDLY */
    242 # ifdef	XTABS
    243     { "xtabs",	XTABS,	M_OUT },
    244 # endif /* XTABS */
    245 # ifdef	BSDLY
    246     { "bsdly",	BSDLY,	M_OUT },
    247 # endif /* BSDLY */
    248 # ifdef	VTDLY
    249     { "vtdly",	VTDLY,	M_OUT },
    250 # endif /* VTDLY */
    251 # ifdef	FFDLY
    252     { "ffdly",	FFDLY,	M_OUT },
    253 # endif /* FFDLY */
    254 # ifdef	PAGEOUT
    255     { "pageout",PAGEOUT,M_OUT },
    256 # endif /* PAGEOUT */
    257 # ifdef	WRAP
    258     { "wrap",	WRAP,	M_OUT },
    259 # endif /* WRAP */
    260 
    261 # ifdef	CIGNORE
    262     { "cignore",CIGNORE,M_CTL },
    263 # endif /* CBAUD */
    264 # ifdef	CBAUD
    265     { "cbaud",	CBAUD,	M_CTL },
    266 # endif /* CBAUD */
    267 # ifdef	CSTOPB
    268     { "cstopb",	CSTOPB,	M_CTL },
    269 # endif /* CSTOPB */
    270 # ifdef	CREAD
    271     { "cread",	CREAD,	M_CTL },
    272 # endif /* CREAD */
    273 # ifdef	PARENB
    274     { "parenb",	PARENB,	M_CTL },
    275 # endif /* PARENB */
    276 # ifdef	PARODD
    277     { "parodd",	PARODD,	M_CTL },
    278 # endif /* PARODD */
    279 # ifdef	HUPCL
    280     { "hupcl",	HUPCL,	M_CTL },
    281 # endif /* HUPCL */
    282 # ifdef	CLOCAL
    283     { "clocal",	CLOCAL,	M_CTL },
    284 # endif /* CLOCAL */
    285 # ifdef	LOBLK
    286     { "loblk",	LOBLK,	M_CTL },
    287 # endif /* LOBLK */
    288 # ifdef	CIBAUD
    289     { "cibaud",	CIBAUD,	M_CTL },
    290 # endif /* CIBAUD */
    291 # ifdef CRTSCTS
    292 #  ifdef CCTS_OFLOW
    293     { "ccts_oflow",CCTS_OFLOW,M_CTL },
    294 #  else
    295     { "crtscts",CRTSCTS,M_CTL },
    296 #  endif /* CCTS_OFLOW */
    297 # endif /* CRTSCTS */
    298 # ifdef CRTS_IFLOW
    299     { "crts_iflow",CRTS_IFLOW,M_CTL },
    300 # endif /* CRTS_IFLOW */
    301 # ifdef CDTRCTS
    302     { "cdtrcts",CDTRCTS,M_CTL },
    303 # endif /* CDTRCTS */
    304 # ifdef MDMBUF
    305     { "mdmbuf",	MDMBUF,	M_CTL },
    306 # endif /* MDMBUF */
    307 # ifdef RCV1EN
    308     { "rcv1en",	RCV1EN,	M_CTL },
    309 # endif /* RCV1EN */
    310 # ifdef XMT1EN
    311     { "xmt1en",	XMT1EN,	M_CTL },
    312 # endif /* XMT1EN */
    313 
    314 # ifdef	ISIG
    315     { "isig",	ISIG,	M_LIN },
    316 # endif /* ISIG */
    317 # ifdef	ICANON
    318     { "icanon",	ICANON,	M_LIN },
    319 # endif /* ICANON */
    320 # ifdef	XCASE
    321     { "xcase",	XCASE,	M_LIN },
    322 # endif /* XCASE */
    323 # ifdef	ECHO
    324     { "echo",	ECHO,	M_LIN },
    325 # endif /* ECHO */
    326 # ifdef	ECHOE
    327     { "echoe",	ECHOE,	M_LIN },
    328 # endif /* ECHOE */
    329 # ifdef	ECHOK
    330     { "echok",	ECHOK,	M_LIN },
    331 # endif /* ECHOK */
    332 # ifdef	ECHONL
    333     { "echonl",	ECHONL,	M_LIN },
    334 # endif /* ECHONL */
    335 # ifdef	NOFLSH
    336     { "noflsh",	NOFLSH,	M_LIN },
    337 # endif /* NOFLSH */
    338 # ifdef	TOSTOP
    339     { "tostop",	TOSTOP,	M_LIN },
    340 # endif /* TOSTOP */
    341 # ifdef	ECHOCTL
    342     { "echoctl",ECHOCTL,M_LIN },
    343 # endif /* ECHOCTL */
    344 # ifdef	ECHOPRT
    345     { "echoprt",ECHOPRT,M_LIN },
    346 # endif /* ECHOPRT */
    347 # ifdef	ECHOKE
    348     { "echoke",	ECHOKE,	M_LIN },
    349 # endif /* ECHOKE */
    350 # ifdef	DEFECHO
    351     { "defecho",DEFECHO,M_LIN },
    352 # endif /* DEFECHO */
    353 # ifdef	FLUSHO
    354     { "flusho",	FLUSHO,	M_LIN },
    355 # endif /* FLUSHO */
    356 # ifdef	PENDIN
    357     { "pendin",	PENDIN,	M_LIN },
    358 # endif /* PENDIN */
    359 # ifdef	IEXTEN
    360     { "iexten",	IEXTEN,	M_LIN },
    361 # endif /* IEXTEN */
    362 # ifdef	NOKERNINFO
    363     { "nokerninfo",NOKERNINFO,M_LIN },
    364 # endif /* NOKERNINFO */
    365 # ifdef	ALTWERASE
    366     { "altwerase",ALTWERASE,M_LIN },
    367 # endif /* ALTWERASE */
    368 # ifdef	EXTPROC
    369     { "extproc",EXTPROC, M_LIN },
    370 # endif /* EXTPROC */
    371 
    372 # if defined(VINTR)
    373     { "intr",		C_SH(C_INTR), 	M_CHAR },
    374 # endif /* VINTR */
    375 # if defined(VQUIT)
    376     { "quit",		C_SH(C_QUIT), 	M_CHAR },
    377 # endif /* VQUIT */
    378 # if defined(VERASE)
    379     { "erase",		C_SH(C_ERASE), 	M_CHAR },
    380 # endif /* VERASE */
    381 # if defined(VKILL)
    382     { "kill",		C_SH(C_KILL), 	M_CHAR },
    383 # endif /* VKILL */
    384 # if defined(VEOF)
    385     { "eof",		C_SH(C_EOF), 	M_CHAR },
    386 # endif /* VEOF */
    387 # if defined(VEOL)
    388     { "eol",		C_SH(C_EOL), 	M_CHAR },
    389 # endif /* VEOL */
    390 # if defined(VEOL2)
    391     { "eol2",		C_SH(C_EOL2), 	M_CHAR },
    392 # endif  /* VEOL2 */
    393 # if defined(VSWTCH)
    394     { "swtch",		C_SH(C_SWTCH), 	M_CHAR },
    395 # endif /* VSWTCH */
    396 # if defined(VDSWTCH)
    397     { "dswtch",		C_SH(C_DSWTCH),	M_CHAR },
    398 # endif /* VDSWTCH */
    399 # if defined(VERASE2)
    400     { "erase2",		C_SH(C_ERASE2),	M_CHAR },
    401 # endif /* VERASE2 */
    402 # if defined(VSTART)
    403     { "start",		C_SH(C_START), 	M_CHAR },
    404 # endif /* VSTART */
    405 # if defined(VSTOP)
    406     { "stop",		C_SH(C_STOP), 	M_CHAR },
    407 # endif /* VSTOP */
    408 # if defined(VWERASE)
    409     { "werase",		C_SH(C_WERASE),	M_CHAR },
    410 # endif /* VWERASE */
    411 # if defined(VSUSP)
    412     { "susp",		C_SH(C_SUSP), 	M_CHAR },
    413 # endif /* VSUSP */
    414 # if defined(VDSUSP)
    415     { "dsusp",		C_SH(C_DSUSP), 	M_CHAR },
    416 # endif /* VDSUSP */
    417 # if defined(VREPRINT)
    418     { "reprint",	C_SH(C_REPRINT),M_CHAR },
    419 # endif /* VREPRINT */
    420 # if defined(VDISCARD)
    421     { "discard",	C_SH(C_DISCARD),M_CHAR },
    422 # endif /* VDISCARD */
    423 # if defined(VLNEXT)
    424     { "lnext",		C_SH(C_LNEXT), 	M_CHAR },
    425 # endif /* VLNEXT */
    426 # if defined(VSTATUS)
    427     { "status",		C_SH(C_STATUS),	M_CHAR },
    428 # endif /* VSTATUS */
    429 # if defined(VPAGE)
    430     { "page",		C_SH(C_PAGE), 	M_CHAR },
    431 # endif /* VPAGE */
    432 # if defined(VPGOFF)
    433     { "pgoff",		C_SH(C_PGOFF), 	M_CHAR },
    434 # endif /* VPGOFF */
    435 # if defined(VKILL2)
    436     { "kill2",		C_SH(C_KILL2), 	M_CHAR },
    437 # endif /* VKILL2 */
    438 # if defined(VBRK)
    439     { "brk",		C_SH(C_BRK), 	M_CHAR },
    440 # endif /* VBRK */
    441 # if defined(VMIN)
    442     { "min",		C_SH(C_MIN), 	M_CHAR },
    443 # endif /* VMIN */
    444 # if defined(VTIME)
    445     { "time",		C_SH(C_TIME), 	M_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][M_INP].t_clrmask;
    489     el->el_tty.t_ex.c_iflag |=  el->el_tty.t_t[EX_IO][M_INP].t_setmask;
    490 
    491     el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][M_OUT].t_clrmask;
    492     el->el_tty.t_ex.c_oflag |=  el->el_tty.t_t[EX_IO][M_OUT].t_setmask;
    493 
    494     el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][M_CTL].t_clrmask;
    495     el->el_tty.t_ex.c_cflag |=  el->el_tty.t_t[EX_IO][M_CTL].t_setmask;
    496 
    497     el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][M_LIN].t_clrmask;
    498     el->el_tty.t_ex.c_lflag |=  el->el_tty.t_t[EX_IO][M_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][M_INP].t_clrmask;
    531     el->el_tty.t_ed.c_iflag |=  el->el_tty.t_t[ED_IO][M_INP].t_setmask;
    532 
    533     el->el_tty.t_ed.c_oflag &= ~el->el_tty.t_t[ED_IO][M_OUT].t_clrmask;
    534     el->el_tty.t_ed.c_oflag |=  el->el_tty.t_t[ED_IO][M_OUT].t_setmask;
    535 
    536     el->el_tty.t_ed.c_cflag &= ~el->el_tty.t_t[ED_IO][M_CTL].t_clrmask;
    537     el->el_tty.t_ed.c_cflag |=  el->el_tty.t_t[ED_IO][M_CTL].t_setmask;
    538 
    539     el->el_tty.t_ed.c_lflag &= ~el->el_tty.t_t[ED_IO][M_LIN].t_clrmask;
    540     el->el_tty.t_ed.c_lflag |=  el->el_tty.t_t[ED_IO][M_LIN].t_setmask;
    541 
    542     tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
    543     return 0;
    544 }
    545 
    546 protected int
    547 tty_init(el)
    548     EditLine *el;
    549 {
    550     el->el_tty.t_mode     = EX_IO;
    551     el->el_tty.t_vdisable = _POSIX_VDISABLE;
    552     (void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t));
    553     (void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t));
    554     return tty_setup(el);
    555 } /* end tty_init */
    556 
    557 
    558 /* tty_end():
    559  *	Restore the tty to its original settings
    560  */
    561 protected void
    562 /*ARGSUSED*/
    563 tty_end(el)
    564     EditLine *el;
    565 {
    566     /* XXX: Maybe reset to an initial state? */
    567 }
    568 
    569 
    570 /* tty__getspeed():
    571  *	Get the tty speed
    572  */
    573 private speed_t
    574 tty__getspeed(td)
    575     struct termios *td;
    576 {
    577     speed_t spd;
    578 
    579     if ((spd = cfgetispeed(td)) == 0)
    580 	spd = cfgetospeed(td);
    581     return spd;
    582 } /* end tty__getspeed */
    583 
    584 
    585 /* tty__getchar():
    586  *	Get the tty characters
    587  */
    588 private void
    589 tty__getchar(td, s)
    590     struct termios *td;
    591     unsigned char *s;
    592 {
    593 # ifdef VINTR
    594     s[C_INTR]	= td->c_cc[VINTR];
    595 # endif /* VINTR */
    596 # ifdef VQUIT
    597     s[C_QUIT]	= td->c_cc[VQUIT];
    598 # endif /* VQUIT */
    599 # ifdef VERASE
    600     s[C_ERASE]	= td->c_cc[VERASE];
    601 # endif /* VERASE */
    602 # ifdef VKILL
    603     s[C_KILL]	= td->c_cc[VKILL];
    604 # endif /* VKILL */
    605 # ifdef VEOF
    606     s[C_EOF]	= td->c_cc[VEOF];
    607 # endif /* VEOF */
    608 # ifdef VEOL
    609     s[C_EOL]	= td->c_cc[VEOL];
    610 # endif /* VEOL */
    611 # ifdef VEOL2
    612     s[C_EOL2]	= td->c_cc[VEOL2];
    613 # endif  /* VEOL2 */
    614 # ifdef VSWTCH
    615     s[C_SWTCH]	= td->c_cc[VSWTCH];
    616 # endif /* VSWTCH */
    617 # ifdef VDSWTCH
    618     s[C_DSWTCH]	= td->c_cc[VDSWTCH];
    619 # endif /* VDSWTCH */
    620 # ifdef VERASE2
    621     s[C_ERASE2]	= td->c_cc[VERASE2];
    622 # endif /* VERASE2 */
    623 # ifdef VSTART
    624     s[C_START]	= td->c_cc[VSTART];
    625 # endif /* VSTART */
    626 # ifdef VSTOP
    627     s[C_STOP]	= td->c_cc[VSTOP];
    628 # endif /* VSTOP */
    629 # ifdef VWERASE
    630     s[C_WERASE]	= td->c_cc[VWERASE];
    631 # endif /* VWERASE */
    632 # ifdef VSUSP
    633     s[C_SUSP]	= td->c_cc[VSUSP];
    634 # endif /* VSUSP */
    635 # ifdef VDSUSP
    636     s[C_DSUSP]	= td->c_cc[VDSUSP];
    637 # endif /* VDSUSP */
    638 # ifdef VREPRINT
    639     s[C_REPRINT]= td->c_cc[VREPRINT];
    640 # endif /* VREPRINT */
    641 # ifdef VDISCARD
    642     s[C_DISCARD]= td->c_cc[VDISCARD];
    643 # endif /* VDISCARD */
    644 # ifdef VLNEXT
    645     s[C_LNEXT]	= td->c_cc[VLNEXT];
    646 # endif /* VLNEXT */
    647 # ifdef VSTATUS
    648     s[C_STATUS]	= td->c_cc[VSTATUS];
    649 # endif /* VSTATUS */
    650 # ifdef VPAGE
    651     s[C_PAGE]	= td->c_cc[VPAGE];
    652 # endif /* VPAGE */
    653 # ifdef VPGOFF
    654     s[C_PGOFF]	= td->c_cc[VPGOFF];
    655 # endif /* VPGOFF */
    656 # ifdef VKILL2
    657     s[C_KILL2]	= td->c_cc[VKILL2];
    658 # endif /* KILL2 */
    659 # ifdef VMIN
    660     s[C_MIN]	= td->c_cc[VMIN];
    661 # endif /* VMIN */
    662 # ifdef VTIME
    663     s[C_TIME]	= td->c_cc[VTIME];
    664 # endif /* VTIME */
    665 } /* tty__getchar */
    666 
    667 
    668 /* tty__setchar():
    669  *	Set the tty characters
    670  */
    671 private void
    672 tty__setchar(td, s)
    673     struct termios *td;
    674     unsigned char *s;
    675 {
    676 # ifdef VINTR
    677     td->c_cc[VINTR]	= s[C_INTR];
    678 # endif /* VINTR */
    679 # ifdef VQUIT
    680     td->c_cc[VQUIT]	= s[C_QUIT];
    681 # endif /* VQUIT */
    682 # ifdef VERASE
    683     td->c_cc[VERASE]	= s[C_ERASE];
    684 # endif /* VERASE */
    685 # ifdef VKILL
    686     td->c_cc[VKILL]	= s[C_KILL];
    687 # endif /* VKILL */
    688 # ifdef VEOF
    689     td->c_cc[VEOF]	= s[C_EOF];
    690 # endif /* VEOF */
    691 # ifdef VEOL
    692     td->c_cc[VEOL]	= s[C_EOL];
    693 # endif /* VEOL */
    694 # ifdef VEOL2
    695     td->c_cc[VEOL2]	= s[C_EOL2];
    696 # endif  /* VEOL2 */
    697 # ifdef VSWTCH
    698     td->c_cc[VSWTCH]	= s[C_SWTCH];
    699 # endif /* VSWTCH */
    700 # ifdef VDSWTCH
    701     td->c_cc[VDSWTCH]	= s[C_DSWTCH];
    702 # endif /* VDSWTCH */
    703 # ifdef VERASE2
    704     td->c_cc[VERASE2]	= s[C_ERASE2];
    705 # endif /* VERASE2 */
    706 # ifdef VSTART
    707     td->c_cc[VSTART]	= s[C_START];
    708 # endif /* VSTART */
    709 # ifdef VSTOP
    710     td->c_cc[VSTOP]	= s[C_STOP];
    711 # endif /* VSTOP */
    712 # ifdef VWERASE
    713     td->c_cc[VWERASE]	= s[C_WERASE];
    714 # endif /* VWERASE */
    715 # ifdef VSUSP
    716     td->c_cc[VSUSP]	= s[C_SUSP];
    717 # endif /* VSUSP */
    718 # ifdef VDSUSP
    719     td->c_cc[VDSUSP]	= s[C_DSUSP];
    720 # endif /* VDSUSP */
    721 # ifdef VREPRINT
    722     td->c_cc[VREPRINT]	= s[C_REPRINT];
    723 # endif /* VREPRINT */
    724 # ifdef VDISCARD
    725     td->c_cc[VDISCARD]	= s[C_DISCARD];
    726 # endif /* VDISCARD */
    727 # ifdef VLNEXT
    728     td->c_cc[VLNEXT]	= s[C_LNEXT];
    729 # endif /* VLNEXT */
    730 # ifdef VSTATUS
    731     td->c_cc[VSTATUS]	= s[C_STATUS];
    732 # endif /* VSTATUS */
    733 # ifdef VPAGE
    734     td->c_cc[VPAGE]	= s[C_PAGE];
    735 # endif /* VPAGE */
    736 # ifdef VPGOFF
    737     td->c_cc[VPGOFF]	= s[C_PGOFF];
    738 # endif /* VPGOFF */
    739 # ifdef VKILL2
    740     td->c_cc[VKILL2]	= s[C_KILL2];
    741 # endif /* VKILL2 */
    742 # ifdef VMIN
    743     td->c_cc[VMIN]	= s[C_MIN];
    744 # endif /* VMIN */
    745 # ifdef VTIME
    746     td->c_cc[VTIME]	= s[C_TIME];
    747 # endif /* VTIME */
    748 } /* tty__setchar */
    749 
    750 
    751 /* tty_bind_char():
    752  *	Rebind the editline functions
    753  */
    754 protected void
    755 tty_bind_char(el, force)
    756     EditLine *el;
    757     int force;
    758 {
    759     unsigned char *t_n = el->el_tty.t_c[ED_IO];
    760     unsigned char *t_o = el->el_tty.t_ed.c_cc;
    761     char new[2], old[2];
    762     ttymap_t *tp;
    763     el_action_t  *dmap, *dalt, *map, *alt;
    764     new[1] = old[1] = '\0';
    765 
    766 
    767     map = el->el_map.key;
    768     alt = el->el_map.alt;
    769     if (el->el_map.type == MAP_VI) {
    770 	dmap = el->el_map.vii;
    771 	dalt = el->el_map.vic;
    772     }
    773     else {
    774 	dmap = el->el_map.emacs;
    775 	dalt = NULL;
    776     }
    777 
    778     for (tp = tty_map; tp->nch != -1; tp++) {
    779 	new[0] = t_n[tp->nch];
    780 	old[0] = t_o[tp->och];
    781 	if (new[0] == old[0] && !force)
    782 	    continue;
    783 	/* Put the old default binding back, and set the new binding */
    784 	key_clear(el, map, old);
    785 	map[(int)old[0]] = dmap[(int)old[0]];
    786 	key_clear(el, map, new);
    787 	/* MAP_VI == 1, MAP_EMACS == 0... */
    788 	map[(int)new[0]] = tp->bind[(int)el->el_map.type];
    789 	if (dalt) {
    790 	    key_clear(el, alt, old);
    791 	    alt[(int)old[0]] = dalt[(int)old[0]];
    792 	    key_clear(el, alt, new);
    793 	    alt[(int)new[0]] = tp->bind[(int)el->el_map.type+1];
    794 	}
    795     }
    796 }
    797 
    798 /* tty_rawmode():
    799  * 	Set terminal into 1 character at a time mode.
    800  */
    801 protected int
    802 tty_rawmode(el)
    803     EditLine *el;
    804 {
    805     if (el->el_tty.t_mode == ED_IO)
    806 	return (0);
    807 
    808     if (tty_getty(el, &el->el_tty.t_ts) == -1) {
    809 #ifdef DEBUG_TTY
    810 	(void) fprintf(el->el_errfile, "tty_rawmode: tty_getty: %s\n", strerror(errno));
    811 #endif /* DEBUG_TTY */
    812 	return(-1);
    813     }
    814 
    815     /*
    816      * We always keep up with the eight bit setting and the speed of the
    817      * tty. But only we only believe changes that are made to cooked mode!
    818      */
    819     el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts);
    820     el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts);
    821 
    822     if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed ||
    823 	tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) {
    824 	(void) cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed);
    825 	(void) cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed);
    826 	(void) cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed);
    827 	(void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed);
    828     }
    829 
    830     if (tty__cooked_mode(&el->el_tty.t_ts)) {
    831 	if (el->el_tty.t_ts.c_cflag != el->el_tty.t_ex.c_cflag) {
    832 	    el->el_tty.t_ex.c_cflag  = el->el_tty.t_ts.c_cflag;
    833 	    el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][M_CTL].t_clrmask;
    834 	    el->el_tty.t_ex.c_cflag |=  el->el_tty.t_t[EX_IO][M_CTL].t_setmask;
    835 
    836 	    el->el_tty.t_ed.c_cflag  = el->el_tty.t_ts.c_cflag;
    837 	    el->el_tty.t_ed.c_cflag &= ~el->el_tty.t_t[ED_IO][M_CTL].t_clrmask;
    838 	    el->el_tty.t_ed.c_cflag |=  el->el_tty.t_t[ED_IO][M_CTL].t_setmask;
    839 	}
    840 
    841 	if ((el->el_tty.t_ts.c_lflag != el->el_tty.t_ex.c_lflag) &&
    842 	    (el->el_tty.t_ts.c_lflag != el->el_tty.t_ed.c_lflag)) {
    843 	    el->el_tty.t_ex.c_lflag = el->el_tty.t_ts.c_lflag;
    844 	    el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][M_LIN].t_clrmask;
    845 	    el->el_tty.t_ex.c_lflag |=  el->el_tty.t_t[EX_IO][M_LIN].t_setmask;
    846 
    847 	    el->el_tty.t_ed.c_lflag = el->el_tty.t_ts.c_lflag;
    848 	    el->el_tty.t_ed.c_lflag &= ~el->el_tty.t_t[ED_IO][M_LIN].t_clrmask;
    849 	    el->el_tty.t_ed.c_lflag |=  el->el_tty.t_t[ED_IO][M_LIN].t_setmask;
    850 	}
    851 
    852 	if ((el->el_tty.t_ts.c_iflag != el->el_tty.t_ex.c_iflag) &&
    853 	    (el->el_tty.t_ts.c_iflag != el->el_tty.t_ed.c_iflag)) {
    854 	    el->el_tty.t_ex.c_iflag = el->el_tty.t_ts.c_iflag;
    855 	    el->el_tty.t_ex.c_iflag &= ~el->el_tty.t_t[EX_IO][M_INP].t_clrmask;
    856 	    el->el_tty.t_ex.c_iflag |=  el->el_tty.t_t[EX_IO][M_INP].t_setmask;
    857 
    858 	    el->el_tty.t_ed.c_iflag = el->el_tty.t_ts.c_iflag;
    859 	    el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][M_INP].t_clrmask;
    860 	    el->el_tty.t_ed.c_iflag |=  el->el_tty.t_t[ED_IO][M_INP].t_setmask;
    861 	}
    862 
    863 	if ((el->el_tty.t_ts.c_oflag != el->el_tty.t_ex.c_oflag) &&
    864 	    (el->el_tty.t_ts.c_oflag != el->el_tty.t_ed.c_oflag)) {
    865 	    el->el_tty.t_ex.c_oflag = el->el_tty.t_ts.c_oflag;
    866 	    el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][M_OUT].t_clrmask;
    867 	    el->el_tty.t_ex.c_oflag |=  el->el_tty.t_t[EX_IO][M_OUT].t_setmask;
    868 
    869 	    el->el_tty.t_ed.c_oflag = el->el_tty.t_ts.c_oflag;
    870 	    el->el_tty.t_ed.c_oflag &= ~el->el_tty.t_t[ED_IO][M_OUT].t_clrmask;
    871 	    el->el_tty.t_ed.c_oflag |=  el->el_tty.t_t[ED_IO][M_OUT].t_setmask;
    872 	}
    873 
    874 	if (tty__gettabs(&el->el_tty.t_ex) == 0)
    875 	    el->el_tty.t_tabs = 0;
    876 	else
    877 	    el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0;
    878 
    879 	{
    880 	    int i;
    881 
    882 	    tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
    883 	    /*
    884 	     * Check if the user made any changes.
    885 	     * If he did, then propagate the changes to the
    886 	     * edit and execute data structures.
    887 	     */
    888 	    for (i = 0; i < C_NCC; i++)
    889 		if (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i])
    890 		    break;
    891 
    892 	    if (i != C_NCC) {
    893 		/*
    894 		 * Propagate changes only to the unprotected chars
    895 		 * that have been modified just now.
    896 		 */
    897 		for (i = 0; i < C_NCC; i++) {
    898 		    if (!((el->el_tty.t_t[ED_IO][M_CHAR].t_setmask & C_SH(i)))
    899 		      && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
    900 			el->el_tty.t_c[ED_IO][i] = el->el_tty.t_c[TS_IO][i];
    901 		    if (el->el_tty.t_t[ED_IO][M_CHAR].t_clrmask & C_SH(i))
    902 			el->el_tty.t_c[ED_IO][i] = el->el_tty.t_vdisable;
    903 		}
    904 		tty_bind_char(el, 0);
    905 		tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
    906 
    907 		for (i = 0; i < C_NCC; i++) {
    908 		    if (!((el->el_tty.t_t[EX_IO][M_CHAR].t_setmask & C_SH(i)))
    909 		      && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
    910 			el->el_tty.t_c[EX_IO][i] = el->el_tty.t_c[TS_IO][i];
    911 		    if (el->el_tty.t_t[EX_IO][M_CHAR].t_clrmask & C_SH(i))
    912 			el->el_tty.t_c[EX_IO][i] = el->el_tty.t_vdisable;
    913 		}
    914 		tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
    915 	    }
    916 	}
    917     }
    918 
    919     if (tty_setty(el, &el->el_tty.t_ed) == -1) {
    920 #ifdef DEBUG_TTY
    921 	(void) fprintf(el->el_errfile, "tty_rawmode: tty_setty: %s\n",
    922 		       strerror(errno));
    923 #endif /* DEBUG_TTY */
    924 	return -1;
    925     }
    926     el->el_tty.t_mode = ED_IO;
    927     return (0);
    928 } /* end tty_rawmode */
    929 
    930 
    931 /* tty_cookedmode():
    932  *	Set the tty back to normal mode
    933  */
    934 protected int
    935 tty_cookedmode(el)
    936     EditLine *el;
    937 {				/* set tty in normal setup */
    938     if (el->el_tty.t_mode == EX_IO)
    939 	return (0);
    940 
    941     if (tty_setty(el, &el->el_tty.t_ex) == -1) {
    942 #ifdef DEBUG_TTY
    943 	(void) fprintf(el->el_errfile, "tty_cookedmode: tty_setty: %s\n",
    944 		       strerror(errno));
    945 #endif /* DEBUG_TTY */
    946 	return -1;
    947     }
    948     el->el_tty.t_mode = EX_IO;
    949     return (0);
    950 } /* end tty_cookedmode */
    951 
    952 
    953 /* tty_quotemode():
    954  *	Turn on quote mode
    955  */
    956 protected int
    957 tty_quotemode(el)
    958     EditLine *el;
    959 {
    960     if (el->el_tty.t_mode == QU_IO)
    961 	return 0;
    962 
    963     el->el_tty.t_qu = el->el_tty.t_ed;
    964 
    965     el->el_tty.t_qu.c_iflag &= ~el->el_tty.t_t[QU_IO][M_INP].t_clrmask;
    966     el->el_tty.t_qu.c_iflag |=  el->el_tty.t_t[QU_IO][M_INP].t_setmask;
    967 
    968     el->el_tty.t_qu.c_oflag &= ~el->el_tty.t_t[QU_IO][M_OUT].t_clrmask;
    969     el->el_tty.t_qu.c_oflag |=  el->el_tty.t_t[QU_IO][M_OUT].t_setmask;
    970 
    971     el->el_tty.t_qu.c_cflag &= ~el->el_tty.t_t[QU_IO][M_CTL].t_clrmask;
    972     el->el_tty.t_qu.c_cflag |=  el->el_tty.t_t[QU_IO][M_CTL].t_setmask;
    973 
    974     el->el_tty.t_qu.c_lflag &= ~el->el_tty.t_t[QU_IO][M_LIN].t_clrmask;
    975     el->el_tty.t_qu.c_lflag |=  el->el_tty.t_t[QU_IO][M_LIN].t_setmask;
    976 
    977     if (tty_setty(el, &el->el_tty.t_qu) == -1) {
    978 #ifdef DEBUG_TTY
    979 	(void) fprintf(el->el_errfile, "QuoteModeOn: tty_setty: %s\n",
    980 		       strerror(errno));
    981 #endif /* DEBUG_TTY */
    982 	return -1;
    983     }
    984     el->el_tty.t_mode = QU_IO;
    985     return 0;
    986 } /* end tty_quotemode */
    987 
    988 
    989 /* tty_noquotemode():
    990  *	Turn off quote mode
    991  */
    992 protected int
    993 tty_noquotemode(el)
    994     EditLine *el;
    995 {
    996     if (el->el_tty.t_mode != QU_IO)
    997 	return 0;
    998     if (tty_setty(el, &el->el_tty.t_ed) == -1) {
    999 #ifdef DEBUG_TTY
   1000 	(void) fprintf(el->el_errfile, "QuoteModeOff: tty_setty: %s\n",
   1001 		       strerror(errno));
   1002 #endif /* DEBUG_TTY */
   1003 	return -1;
   1004     }
   1005     el->el_tty.t_mode = ED_IO;
   1006     return 0;
   1007 }
   1008 
   1009 /* tty_stty():
   1010  *	Stty builtin
   1011  */
   1012 protected int
   1013 /*ARGSUSED*/
   1014 tty_stty(el, argc, argv)
   1015     EditLine *el;
   1016     int argc;
   1017     char **argv;
   1018 {
   1019     ttymodes_t *m;
   1020     char x, *d;
   1021     int aflag = 0;
   1022     char *s;
   1023     char *name;
   1024     int z = EX_IO;
   1025 
   1026     if (argv == NULL)
   1027 	return -1;
   1028     name = *argv++;
   1029 
   1030     while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0')
   1031 	switch (argv[0][1]) {
   1032 	case 'a':
   1033 	    aflag++;
   1034 	    argv++;
   1035 	    break;
   1036 	case 'd':
   1037 	    argv++;
   1038 	    z = ED_IO;
   1039 	    break;
   1040 	case 'x':
   1041 	    argv++;
   1042 	    z = EX_IO;
   1043 	    break;
   1044 	case 'q':
   1045 	    argv++;
   1046 	    z = QU_IO;
   1047 	    break;
   1048 	default:
   1049 	    (void) fprintf(el->el_errfile, "%s: Unknown switch `%c'.\n",
   1050 			   name, argv[0][1]);
   1051 	    return -1;
   1052 	}
   1053 
   1054     if (!argv || !*argv) {
   1055 	int i = -1;
   1056 	int len = 0, st = 0, cu;
   1057 	for (m = ttymodes; m->m_name; m++) {
   1058 	    if (m->m_type != i) {
   1059 		(void) fprintf(el->el_outfile, "%s%s", i != -1 ? "\n" : "",
   1060 			el->el_tty.t_t[z][m->m_type].t_name);
   1061 		i = m->m_type;
   1062 		st = len = strlen(el->el_tty.t_t[z][m->m_type].t_name);
   1063 	    }
   1064 
   1065 	    x = (el->el_tty.t_t[z][i].t_setmask & m->m_value) ? '+' : '\0';
   1066 	    x = (el->el_tty.t_t[z][i].t_clrmask & m->m_value) ? '-' : x;
   1067 
   1068 	    if (x != '\0' || aflag) {
   1069 
   1070 		cu = strlen(m->m_name) + (x != '\0') + 1;
   1071 
   1072 		if (len + cu >= el->el_term.t_size.h) {
   1073 		    (void) fprintf(el->el_outfile, "\n%*s", st, "");
   1074 		    len = st + cu;
   1075 		}
   1076 		else
   1077 		    len += cu;
   1078 
   1079 		if (x != '\0')
   1080 		    (void) fprintf(el->el_outfile, "%c%s ", x, m->m_name);
   1081 		else
   1082 		    (void) fprintf(el->el_outfile, "%s ", m->m_name);
   1083 	    }
   1084 	}
   1085 	(void) fprintf(el->el_outfile, "\n");
   1086 	return 0;
   1087     }
   1088 
   1089     while (argv && (s = *argv++)) {
   1090 	switch (*s) {
   1091 	case '+':
   1092 	case '-':
   1093 	    x = *s++;
   1094 	    break;
   1095 	default:
   1096 	    x = '\0';
   1097 	    break;
   1098 	}
   1099 	d = s;
   1100 	for (m = ttymodes; m->m_name; m++)
   1101 	    if (strcmp(m->m_name, d) == 0)
   1102 		break;
   1103 
   1104 	if (!m->m_name)  {
   1105 	    (void) fprintf(el->el_errfile, "%s: Invalid argument `%s'.\n",
   1106 			   name, d);
   1107 	    return -1;
   1108 	}
   1109 
   1110 	switch (x) {
   1111 	case '+':
   1112 	    el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value;
   1113 	    el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
   1114 	    break;
   1115 	case '-':
   1116 	    el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
   1117 	    el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value;
   1118 	    break;
   1119 	default:
   1120 	    el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
   1121 	    el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
   1122 	    break;
   1123 	}
   1124     }
   1125     return 0;
   1126 } /* end tty_stty */
   1127 
   1128 
   1129 #ifdef notyet
   1130 /* tty_printchar():
   1131  *	DEbugging routine to print the tty characters
   1132  */
   1133 private void
   1134 tty_printchar(el, s)
   1135     EditLine *el;
   1136     unsigned char *s;
   1137 {
   1138     ttyperm_t *m;
   1139     int i;
   1140 
   1141     for (i = 0; i < C_NCC; i++) {
   1142 	for (m = el->el_tty.t_t; m->m_name; m++)
   1143 	    if (m->m_type == M_CHAR && C_SH(i) == m->m_value)
   1144 		break;
   1145 	if (m->m_name)
   1146 	    (void) fprintf(el->el_errfile, "%s ^%c ", m->m_name, s[i] + 'A'-1);
   1147 	if (i % 5 == 0)
   1148 	    (void) fprintf(el->el_errfile, "\n");
   1149     }
   1150     (void) fprintf(el->el_errfile, "\n");
   1151 }
   1152 #endif /* notyet */
   1153