]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libedit/tty.c
unfinished sblive driver, playback/mixer only for now - not enabled in
[FreeBSD/FreeBSD.git] / lib / libedit / tty.c
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     u_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 | INLCR | ICRNL },
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 || el->el_tty.t_mode == QU_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 */