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