xref: /netbsd-src/lib/libedit/tty.c (revision d9158b13b5dfe46201430699a3f7a235ecf28df3)
1 /*-
2  * Copyright (c) 1992, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Christos Zoulas of Cornell University.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by the University of
19  *	California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  */
36 
37 #if !defined(lint) && !defined(SCCSID)
38 static char sccsid[] = "@(#)tty.c	8.1 (Berkeley) 6/4/93";
39 #endif /* not lint && not SCCSID */
40 
41 /*
42  * tty.c: tty interface stuff
43  */
44 #include "sys.h"
45 #include "tty.h"
46 #include "el.h"
47 
48 typedef struct ttymodes_t {
49     char *m_name;
50     int   m_value;
51     int   m_type;
52 } ttymodes_t;
53 
54 typedef struct ttymap_t {
55     int nch, och;		 /* Internal and termio rep of chars */
56     el_action_t bind[3]; 	/* emacs, vi, and vi-cmd */
57 } ttymap_t;
58 
59 
60 private ttyperm_t ttyperm = {
61     {
62 	{ "iflag:", ICRNL, (INLCR|IGNCR) },
63 	{ "oflag:", (OPOST|ONLCR), ONLRET },
64 	{ "cflag:", 0, 0 },
65 	{ "lflag:", (ISIG|ICANON|ECHO|ECHOE|ECHOCTL|IEXTEN),
66 		    (NOFLSH|ECHONL|EXTPROC|FLUSHO) },
67 	{ "chars:", 	0, 0 },
68     },
69     {
70 	{ "iflag:", (INLCR|ICRNL), IGNCR },
71 	{ "oflag:", (OPOST|ONLCR), ONLRET },
72 	{ "cflag:", 0, 0 },
73 	{ "lflag:", ISIG,
74 		    (NOFLSH|ICANON|ECHO|ECHOK|ECHONL|EXTPROC|IEXTEN|FLUSHO) },
75 	{ "chars:", (C_SH(C_MIN)|C_SH(C_TIME)|C_SH(C_SWTCH)|C_SH(C_DSWTCH)|
76 		     C_SH(C_SUSP)|C_SH(C_DSUSP)|C_SH(C_EOL)|C_SH(C_DISCARD)|
77 		     C_SH(C_PGOFF)|C_SH(C_PAGE)|C_SH(C_STATUS)), 0 }
78     },
79     {
80 	{ "iflag:", 0, IXON | IXOFF },
81 	{ "oflag:", 0, 0 },
82 	{ "cflag:", 0, 0 },
83 	{ "lflag:", 0, ISIG | IEXTEN },
84 	{ "chars:", 0, 0 },
85     }
86 };
87 
88 private ttychar_t ttychar = {
89     {
90 	CINTR,		 CQUIT, 	 CERASE, 	   CKILL,
91 	CEOF, 		 CEOL, 		 CEOL2, 	   CSWTCH,
92 	CDSWTCH,	 CERASE2,	 CSTART, 	   CSTOP,
93 	CWERASE, 	 CSUSP, 	 CDSUSP, 	   CREPRINT,
94 	CDISCARD, 	 CLNEXT,	 CSTATUS,	   CPAGE,
95 	CPGOFF,		 CKILL2, 	 CBRK, 		   CMIN,
96 	CTIME
97     },
98     {
99 	CINTR, 		 CQUIT, 	  CERASE, 	   CKILL,
100 	_POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
101 	_POSIX_VDISABLE, CERASE2,	  CSTART, 	   CSTOP,
102 	_POSIX_VDISABLE, CSUSP,           _POSIX_VDISABLE, _POSIX_VDISABLE,
103 	CDISCARD, 	 _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
104 	_POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 1,
105 	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 
118 private 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 
155 private 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 
449 private void    tty__getchar	__P((struct termios *, unsigned char *));
450 private void    tty__setchar	__P((struct termios *, unsigned char *));
451 private speed_t tty__getspeed	__P((struct termios *));
452 private 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  */
460 private int
461 tty_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 
537 protected int
538 tty_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  */
552 protected void
553 /*ARGSUSED*/
554 tty_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  */
564 private speed_t
565 tty__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  */
579 private void
580 tty__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  */
662 private void
663 tty__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  */
745 protected void
746 tty_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  */
792 protected int
793 tty_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  */
926 protected int
927 tty_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  */
948 protected int
949 tty_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  */
984 protected int
985 tty_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  */
1004 protected int
1005 /*ARGSUSED*/
1006 tty_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  */
1125 private void
1126 tty_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