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