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