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