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