tty.c revision 1.62 1 /* $NetBSD: tty.c,v 1.62 2016/04/11 00:50:13 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.62 2016/04/11 00:50:13 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 if (el->el_flags & EDIT_DISABLED)
502 return 0;
503
504 if (el->el_tty.t_initialized)
505 return -1;
506
507 if (!isatty(el->el_outfd)) {
508 #ifdef DEBUG_TTY
509 (void) fprintf(el->el_errfile, "%s: isatty: %s\n", __func__,
510 strerror(errno));
511 #endif /* DEBUG_TTY */
512 return -1;
513 }
514 if (tty_getty(el, &el->el_tty.t_or) == -1) {
515 #ifdef DEBUG_TTY
516 (void) fprintf(el->el_errfile, "%s: tty_getty: %s\n", __func__,
517 strerror(errno));
518 #endif /* DEBUG_TTY */
519 return -1;
520 }
521 el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed = el->el_tty.t_or;
522
523 el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex);
524 el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex);
525 el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex);
526
527 tty_setup_flags(el, &el->el_tty.t_ex, EX_IO);
528
529 /*
530 * Reset the tty chars to reasonable defaults
531 * If they are disabled, then enable them.
532 */
533 if (rst) {
534 if (tty__cooked_mode(&el->el_tty.t_ts)) {
535 tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
536 /*
537 * Don't affect CMIN and CTIME for the editor mode
538 */
539 for (rst = 0; rst < C_NCC - 2; rst++)
540 if (el->el_tty.t_c[TS_IO][rst] !=
541 el->el_tty.t_vdisable
542 && el->el_tty.t_c[ED_IO][rst] !=
543 el->el_tty.t_vdisable)
544 el->el_tty.t_c[ED_IO][rst] =
545 el->el_tty.t_c[TS_IO][rst];
546 for (rst = 0; rst < C_NCC; rst++)
547 if (el->el_tty.t_c[TS_IO][rst] !=
548 el->el_tty.t_vdisable)
549 el->el_tty.t_c[EX_IO][rst] =
550 el->el_tty.t_c[TS_IO][rst];
551 }
552 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
553 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) {
554 #ifdef DEBUG_TTY
555 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n",
556 __func__, strerror(errno));
557 #endif /* DEBUG_TTY */
558 return -1;
559 }
560 }
561
562 tty_setup_flags(el, &el->el_tty.t_ed, ED_IO);
563
564 tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
565 tty_bind_char(el, 1);
566 el->el_tty.t_initialized = 1;
567 return 0;
568 }
569
570 protected int
571 tty_init(EditLine *el)
572 {
573
574 el->el_tty.t_mode = EX_IO;
575 el->el_tty.t_vdisable = _POSIX_VDISABLE;
576 el->el_tty.t_initialized = 0;
577 (void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t));
578 (void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t));
579 return tty_setup(el);
580 }
581
582
583 /* tty_end():
584 * Restore the tty to its original settings
585 */
586 protected void
587 /*ARGSUSED*/
588 tty_end(EditLine *el)
589 {
590 if (el->el_flags & EDIT_DISABLED)
591 return;
592
593 if (!el->el_tty.t_initialized)
594 return;
595
596 if (tty_setty(el, TCSAFLUSH, &el->el_tty.t_or) == -1) {
597 #ifdef DEBUG_TTY
598 (void) fprintf(el->el_errfile,
599 "%s: tty_setty: %s\n", __func__, strerror(errno));
600 #endif /* DEBUG_TTY */
601 }
602 }
603
604
605 /* tty__getspeed():
606 * Get the tty speed
607 */
608 private speed_t
609 tty__getspeed(struct termios *td)
610 {
611 speed_t spd;
612
613 if ((spd = cfgetispeed(td)) == 0)
614 spd = cfgetospeed(td);
615 return spd;
616 }
617
618 /* tty__getspeed():
619 * Return the index of the asked char in the c_cc array
620 */
621 private int
622 tty__getcharindex(int i)
623 {
624 switch (i) {
625 #ifdef VINTR
626 case C_INTR:
627 return VINTR;
628 #endif /* VINTR */
629 #ifdef VQUIT
630 case C_QUIT:
631 return VQUIT;
632 #endif /* VQUIT */
633 #ifdef VERASE
634 case C_ERASE:
635 return VERASE;
636 #endif /* VERASE */
637 #ifdef VKILL
638 case C_KILL:
639 return VKILL;
640 #endif /* VKILL */
641 #ifdef VEOF
642 case C_EOF:
643 return VEOF;
644 #endif /* VEOF */
645 #ifdef VEOL
646 case C_EOL:
647 return VEOL;
648 #endif /* VEOL */
649 #ifdef VEOL2
650 case C_EOL2:
651 return VEOL2;
652 #endif /* VEOL2 */
653 #ifdef VSWTCH
654 case C_SWTCH:
655 return VSWTCH;
656 #endif /* VSWTCH */
657 #ifdef VDSWTCH
658 case C_DSWTCH:
659 return VDSWTCH;
660 #endif /* VDSWTCH */
661 #ifdef VERASE2
662 case C_ERASE2:
663 return VERASE2;
664 #endif /* VERASE2 */
665 #ifdef VSTART
666 case C_START:
667 return VSTART;
668 #endif /* VSTART */
669 #ifdef VSTOP
670 case C_STOP:
671 return VSTOP;
672 #endif /* VSTOP */
673 #ifdef VWERASE
674 case C_WERASE:
675 return VWERASE;
676 #endif /* VWERASE */
677 #ifdef VSUSP
678 case C_SUSP:
679 return VSUSP;
680 #endif /* VSUSP */
681 #ifdef VDSUSP
682 case C_DSUSP:
683 return VDSUSP;
684 #endif /* VDSUSP */
685 #ifdef VREPRINT
686 case C_REPRINT:
687 return VREPRINT;
688 #endif /* VREPRINT */
689 #ifdef VDISCARD
690 case C_DISCARD:
691 return VDISCARD;
692 #endif /* VDISCARD */
693 #ifdef VLNEXT
694 case C_LNEXT:
695 return VLNEXT;
696 #endif /* VLNEXT */
697 #ifdef VSTATUS
698 case C_STATUS:
699 return VSTATUS;
700 #endif /* VSTATUS */
701 #ifdef VPAGE
702 case C_PAGE:
703 return VPAGE;
704 #endif /* VPAGE */
705 #ifdef VPGOFF
706 case C_PGOFF:
707 return VPGOFF;
708 #endif /* VPGOFF */
709 #ifdef VKILL2
710 case C_KILL2:
711 return VKILL2;
712 #endif /* KILL2 */
713 #ifdef VMIN
714 case C_MIN:
715 return VMIN;
716 #endif /* VMIN */
717 #ifdef VTIME
718 case C_TIME:
719 return VTIME;
720 #endif /* VTIME */
721 default:
722 return -1;
723 }
724 }
725
726 /* tty__getchar():
727 * Get the tty characters
728 */
729 private void
730 tty__getchar(struct termios *td, unsigned char *s)
731 {
732
733 #ifdef VINTR
734 s[C_INTR] = td->c_cc[VINTR];
735 #endif /* VINTR */
736 #ifdef VQUIT
737 s[C_QUIT] = td->c_cc[VQUIT];
738 #endif /* VQUIT */
739 #ifdef VERASE
740 s[C_ERASE] = td->c_cc[VERASE];
741 #endif /* VERASE */
742 #ifdef VKILL
743 s[C_KILL] = td->c_cc[VKILL];
744 #endif /* VKILL */
745 #ifdef VEOF
746 s[C_EOF] = td->c_cc[VEOF];
747 #endif /* VEOF */
748 #ifdef VEOL
749 s[C_EOL] = td->c_cc[VEOL];
750 #endif /* VEOL */
751 #ifdef VEOL2
752 s[C_EOL2] = td->c_cc[VEOL2];
753 #endif /* VEOL2 */
754 #ifdef VSWTCH
755 s[C_SWTCH] = td->c_cc[VSWTCH];
756 #endif /* VSWTCH */
757 #ifdef VDSWTCH
758 s[C_DSWTCH] = td->c_cc[VDSWTCH];
759 #endif /* VDSWTCH */
760 #ifdef VERASE2
761 s[C_ERASE2] = td->c_cc[VERASE2];
762 #endif /* VERASE2 */
763 #ifdef VSTART
764 s[C_START] = td->c_cc[VSTART];
765 #endif /* VSTART */
766 #ifdef VSTOP
767 s[C_STOP] = td->c_cc[VSTOP];
768 #endif /* VSTOP */
769 #ifdef VWERASE
770 s[C_WERASE] = td->c_cc[VWERASE];
771 #endif /* VWERASE */
772 #ifdef VSUSP
773 s[C_SUSP] = td->c_cc[VSUSP];
774 #endif /* VSUSP */
775 #ifdef VDSUSP
776 s[C_DSUSP] = td->c_cc[VDSUSP];
777 #endif /* VDSUSP */
778 #ifdef VREPRINT
779 s[C_REPRINT] = td->c_cc[VREPRINT];
780 #endif /* VREPRINT */
781 #ifdef VDISCARD
782 s[C_DISCARD] = td->c_cc[VDISCARD];
783 #endif /* VDISCARD */
784 #ifdef VLNEXT
785 s[C_LNEXT] = td->c_cc[VLNEXT];
786 #endif /* VLNEXT */
787 #ifdef VSTATUS
788 s[C_STATUS] = td->c_cc[VSTATUS];
789 #endif /* VSTATUS */
790 #ifdef VPAGE
791 s[C_PAGE] = td->c_cc[VPAGE];
792 #endif /* VPAGE */
793 #ifdef VPGOFF
794 s[C_PGOFF] = td->c_cc[VPGOFF];
795 #endif /* VPGOFF */
796 #ifdef VKILL2
797 s[C_KILL2] = td->c_cc[VKILL2];
798 #endif /* KILL2 */
799 #ifdef VMIN
800 s[C_MIN] = td->c_cc[VMIN];
801 #endif /* VMIN */
802 #ifdef VTIME
803 s[C_TIME] = td->c_cc[VTIME];
804 #endif /* VTIME */
805 } /* tty__getchar */
806
807
808 /* tty__setchar():
809 * Set the tty characters
810 */
811 private void
812 tty__setchar(struct termios *td, unsigned char *s)
813 {
814
815 #ifdef VINTR
816 td->c_cc[VINTR] = s[C_INTR];
817 #endif /* VINTR */
818 #ifdef VQUIT
819 td->c_cc[VQUIT] = s[C_QUIT];
820 #endif /* VQUIT */
821 #ifdef VERASE
822 td->c_cc[VERASE] = s[C_ERASE];
823 #endif /* VERASE */
824 #ifdef VKILL
825 td->c_cc[VKILL] = s[C_KILL];
826 #endif /* VKILL */
827 #ifdef VEOF
828 td->c_cc[VEOF] = s[C_EOF];
829 #endif /* VEOF */
830 #ifdef VEOL
831 td->c_cc[VEOL] = s[C_EOL];
832 #endif /* VEOL */
833 #ifdef VEOL2
834 td->c_cc[VEOL2] = s[C_EOL2];
835 #endif /* VEOL2 */
836 #ifdef VSWTCH
837 td->c_cc[VSWTCH] = s[C_SWTCH];
838 #endif /* VSWTCH */
839 #ifdef VDSWTCH
840 td->c_cc[VDSWTCH] = s[C_DSWTCH];
841 #endif /* VDSWTCH */
842 #ifdef VERASE2
843 td->c_cc[VERASE2] = s[C_ERASE2];
844 #endif /* VERASE2 */
845 #ifdef VSTART
846 td->c_cc[VSTART] = s[C_START];
847 #endif /* VSTART */
848 #ifdef VSTOP
849 td->c_cc[VSTOP] = s[C_STOP];
850 #endif /* VSTOP */
851 #ifdef VWERASE
852 td->c_cc[VWERASE] = s[C_WERASE];
853 #endif /* VWERASE */
854 #ifdef VSUSP
855 td->c_cc[VSUSP] = s[C_SUSP];
856 #endif /* VSUSP */
857 #ifdef VDSUSP
858 td->c_cc[VDSUSP] = s[C_DSUSP];
859 #endif /* VDSUSP */
860 #ifdef VREPRINT
861 td->c_cc[VREPRINT] = s[C_REPRINT];
862 #endif /* VREPRINT */
863 #ifdef VDISCARD
864 td->c_cc[VDISCARD] = s[C_DISCARD];
865 #endif /* VDISCARD */
866 #ifdef VLNEXT
867 td->c_cc[VLNEXT] = s[C_LNEXT];
868 #endif /* VLNEXT */
869 #ifdef VSTATUS
870 td->c_cc[VSTATUS] = s[C_STATUS];
871 #endif /* VSTATUS */
872 #ifdef VPAGE
873 td->c_cc[VPAGE] = s[C_PAGE];
874 #endif /* VPAGE */
875 #ifdef VPGOFF
876 td->c_cc[VPGOFF] = s[C_PGOFF];
877 #endif /* VPGOFF */
878 #ifdef VKILL2
879 td->c_cc[VKILL2] = s[C_KILL2];
880 #endif /* VKILL2 */
881 #ifdef VMIN
882 td->c_cc[VMIN] = s[C_MIN];
883 #endif /* VMIN */
884 #ifdef VTIME
885 td->c_cc[VTIME] = s[C_TIME];
886 #endif /* VTIME */
887 } /* tty__setchar */
888
889
890 /* tty_bind_char():
891 * Rebind the editline functions
892 */
893 protected void
894 tty_bind_char(EditLine *el, int force)
895 {
896
897 unsigned char *t_n = el->el_tty.t_c[ED_IO];
898 unsigned char *t_o = el->el_tty.t_ed.c_cc;
899 wchar_t new[2], old[2];
900 const ttymap_t *tp;
901 el_action_t *map, *alt;
902 const el_action_t *dmap, *dalt;
903 new[1] = old[1] = '\0';
904
905 map = el->el_map.key;
906 alt = el->el_map.alt;
907 if (el->el_map.type == MAP_VI) {
908 dmap = el->el_map.vii;
909 dalt = el->el_map.vic;
910 } else {
911 dmap = el->el_map.emacs;
912 dalt = NULL;
913 }
914
915 for (tp = tty_map; tp->nch != (wint_t)-1; tp++) {
916 new[0] = (wchar_t)t_n[tp->nch];
917 old[0] = (wchar_t)t_o[tp->och];
918 if (new[0] == old[0] && !force)
919 continue;
920 /* Put the old default binding back, and set the new binding */
921 keymacro_clear(el, map, old);
922 map[(unsigned char)old[0]] = dmap[(unsigned char)old[0]];
923 keymacro_clear(el, map, new);
924 /* MAP_VI == 1, MAP_EMACS == 0... */
925 map[(unsigned char)new[0]] = tp->bind[el->el_map.type];
926 if (dalt) {
927 keymacro_clear(el, alt, old);
928 alt[(unsigned char)old[0]] =
929 dalt[(unsigned char)old[0]];
930 keymacro_clear(el, alt, new);
931 alt[(unsigned char)new[0]] =
932 tp->bind[el->el_map.type + 1];
933 }
934 }
935 }
936
937
938 private tcflag_t *
939 tty__get_flag(struct termios *t, int kind) {
940 switch (kind) {
941 case MD_INP:
942 return &t->c_iflag;
943 case MD_OUT:
944 return &t->c_oflag;
945 case MD_CTL:
946 return &t->c_cflag;
947 case MD_LIN:
948 return &t->c_lflag;
949 default:
950 abort();
951 /*NOTREACHED*/
952 }
953 }
954
955
956 private tcflag_t
957 tty_update_flag(EditLine *el, tcflag_t f, int mode, int kind)
958 {
959 f &= ~el->el_tty.t_t[mode][kind].t_clrmask;
960 f |= el->el_tty.t_t[mode][kind].t_setmask;
961 return f;
962 }
963
964
965 private void
966 tty_update_flags(EditLine *el, int kind)
967 {
968 tcflag_t *tt, *ed, *ex;
969 tt = tty__get_flag(&el->el_tty.t_ts, kind);
970 ed = tty__get_flag(&el->el_tty.t_ed, kind);
971 ex = tty__get_flag(&el->el_tty.t_ex, kind);
972
973 if (*tt != *ex && (kind != MD_CTL || *tt != *ed)) {
974 *ed = tty_update_flag(el, *tt, ED_IO, kind);
975 *ex = tty_update_flag(el, *tt, EX_IO, kind);
976 }
977 }
978
979
980 private void
981 tty_update_char(EditLine *el, int mode, int c) {
982 if (!((el->el_tty.t_t[mode][MD_CHAR].t_setmask & C_SH(c)))
983 && (el->el_tty.t_c[TS_IO][c] != el->el_tty.t_c[EX_IO][c]))
984 el->el_tty.t_c[mode][c] = el->el_tty.t_c[TS_IO][c];
985 if (el->el_tty.t_t[mode][MD_CHAR].t_clrmask & C_SH(c))
986 el->el_tty.t_c[mode][c] = el->el_tty.t_vdisable;
987 }
988
989
990 /* tty_rawmode():
991 * Set terminal into 1 character at a time mode.
992 */
993 protected int
994 tty_rawmode(EditLine *el)
995 {
996
997 if (el->el_tty.t_mode == ED_IO || el->el_tty.t_mode == QU_IO)
998 return 0;
999
1000 if (el->el_flags & EDIT_DISABLED)
1001 return 0;
1002
1003 if (tty_getty(el, &el->el_tty.t_ts) == -1) {
1004 #ifdef DEBUG_TTY
1005 (void) fprintf(el->el_errfile, "%s: tty_getty: %s\n", __func__,
1006 strerror(errno));
1007 #endif /* DEBUG_TTY */
1008 return -1;
1009 }
1010 /*
1011 * We always keep up with the eight bit setting and the speed of the
1012 * tty. But we only believe changes that are made to cooked mode!
1013 */
1014 el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts);
1015 el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts);
1016
1017 if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed ||
1018 tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) {
1019 (void) cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed);
1020 (void) cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed);
1021 (void) cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed);
1022 (void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed);
1023 }
1024 if (tty__cooked_mode(&el->el_tty.t_ts)) {
1025 int i;
1026
1027 for (i = MD_INP; i <= MD_LIN; i++)
1028 tty_update_flags(el, i);
1029
1030 if (tty__gettabs(&el->el_tty.t_ex) == 0)
1031 el->el_tty.t_tabs = 0;
1032 else
1033 el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0;
1034
1035 tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
1036 /*
1037 * Check if the user made any changes.
1038 * If he did, then propagate the changes to the
1039 * edit and execute data structures.
1040 */
1041 for (i = 0; i < C_NCC; i++)
1042 if (el->el_tty.t_c[TS_IO][i] !=
1043 el->el_tty.t_c[EX_IO][i])
1044 break;
1045
1046 if (i != C_NCC) {
1047 /*
1048 * Propagate changes only to the unprotected
1049 * chars that have been modified just now.
1050 */
1051 for (i = 0; i < C_NCC; i++)
1052 tty_update_char(el, ED_IO, i);
1053
1054 tty_bind_char(el, 0);
1055 tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
1056
1057 for (i = 0; i < C_NCC; i++)
1058 tty_update_char(el, EX_IO, i);
1059
1060 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
1061 }
1062 }
1063 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) {
1064 #ifdef DEBUG_TTY
1065 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1066 strerror(errno));
1067 #endif /* DEBUG_TTY */
1068 return -1;
1069 }
1070 el->el_tty.t_mode = ED_IO;
1071 return 0;
1072 }
1073
1074
1075 /* tty_cookedmode():
1076 * Set the tty back to normal mode
1077 */
1078 protected int
1079 tty_cookedmode(EditLine *el)
1080 { /* set tty in normal setup */
1081
1082 if (el->el_tty.t_mode == EX_IO)
1083 return 0;
1084
1085 if (el->el_flags & EDIT_DISABLED)
1086 return 0;
1087
1088 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) {
1089 #ifdef DEBUG_TTY
1090 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1091 strerror(errno));
1092 #endif /* DEBUG_TTY */
1093 return -1;
1094 }
1095 el->el_tty.t_mode = EX_IO;
1096 return 0;
1097 }
1098
1099
1100 /* tty_quotemode():
1101 * Turn on quote mode
1102 */
1103 protected int
1104 tty_quotemode(EditLine *el)
1105 {
1106 if (el->el_tty.t_mode == QU_IO)
1107 return 0;
1108
1109 el->el_tty.t_qu = el->el_tty.t_ed;
1110
1111 tty_setup_flags(el, &el->el_tty.t_qu, QU_IO);
1112
1113 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_qu) == -1) {
1114 #ifdef DEBUG_TTY
1115 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1116 strerror(errno));
1117 #endif /* DEBUG_TTY */
1118 return -1;
1119 }
1120 el->el_tty.t_mode = QU_IO;
1121 return 0;
1122 }
1123
1124
1125 /* tty_noquotemode():
1126 * Turn off quote mode
1127 */
1128 protected int
1129 tty_noquotemode(EditLine *el)
1130 {
1131
1132 if (el->el_tty.t_mode != QU_IO)
1133 return 0;
1134 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) {
1135 #ifdef DEBUG_TTY
1136 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1137 strerror(errno));
1138 #endif /* DEBUG_TTY */
1139 return -1;
1140 }
1141 el->el_tty.t_mode = ED_IO;
1142 return 0;
1143 }
1144
1145
1146 /* tty_stty():
1147 * Stty builtin
1148 */
1149 protected int
1150 /*ARGSUSED*/
1151 tty_stty(EditLine *el, int argc __attribute__((__unused__)),
1152 const wchar_t **argv)
1153 {
1154 const ttymodes_t *m;
1155 char x;
1156 int aflag = 0;
1157 const wchar_t *s, *d;
1158 char name[EL_BUFSIZ];
1159 struct termios *tios = &el->el_tty.t_ex;
1160 int z = EX_IO;
1161
1162 if (argv == NULL)
1163 return -1;
1164 strncpy(name, ct_encode_string(*argv++, &el->el_scratch), sizeof(name));
1165 name[sizeof(name) - 1] = '\0';
1166
1167 while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0')
1168 switch (argv[0][1]) {
1169 case 'a':
1170 aflag++;
1171 argv++;
1172 break;
1173 case 'd':
1174 argv++;
1175 tios = &el->el_tty.t_ed;
1176 z = ED_IO;
1177 break;
1178 case 'x':
1179 argv++;
1180 tios = &el->el_tty.t_ex;
1181 z = EX_IO;
1182 break;
1183 case 'q':
1184 argv++;
1185 tios = &el->el_tty.t_ts;
1186 z = QU_IO;
1187 break;
1188 default:
1189 (void) fprintf(el->el_errfile,
1190 "%s: Unknown switch `%lc'.\n",
1191 name, (wint_t)argv[0][1]);
1192 return -1;
1193 }
1194
1195 if (!argv || !*argv) {
1196 int i = -1;
1197 size_t len = 0, st = 0, cu;
1198 for (m = ttymodes; m->m_name; m++) {
1199 if (m->m_type != i) {
1200 (void) fprintf(el->el_outfile, "%s%s",
1201 i != -1 ? "\n" : "",
1202 el->el_tty.t_t[z][m->m_type].t_name);
1203 i = m->m_type;
1204 st = len =
1205 strlen(el->el_tty.t_t[z][m->m_type].t_name);
1206 }
1207 if (i != -1) {
1208 x = (el->el_tty.t_t[z][i].t_setmask & m->m_value)
1209 ? '+' : '\0';
1210
1211 if (el->el_tty.t_t[z][i].t_clrmask & m->m_value)
1212 x = '-';
1213 } else {
1214 x = '\0';
1215 }
1216
1217 if (x != '\0' || aflag) {
1218
1219 cu = strlen(m->m_name) + (x != '\0') + 1;
1220
1221 if (len + cu >=
1222 (size_t)el->el_terminal.t_size.h) {
1223 (void) fprintf(el->el_outfile, "\n%*s",
1224 (int)st, "");
1225 len = st + cu;
1226 } else
1227 len += cu;
1228
1229 if (x != '\0')
1230 (void) fprintf(el->el_outfile, "%c%s ",
1231 x, m->m_name);
1232 else
1233 (void) fprintf(el->el_outfile, "%s ",
1234 m->m_name);
1235 }
1236 }
1237 (void) fprintf(el->el_outfile, "\n");
1238 return 0;
1239 }
1240 while (argv && (s = *argv++)) {
1241 const wchar_t *p;
1242 switch (*s) {
1243 case '+':
1244 case '-':
1245 x = (char)*s++;
1246 break;
1247 default:
1248 x = '\0';
1249 break;
1250 }
1251 d = s;
1252 p = wcschr(s, L'=');
1253 for (m = ttymodes; m->m_name; m++)
1254 if ((p ? strncmp(m->m_name, ct_encode_string(d,
1255 &el->el_scratch), (size_t)(p - d)) :
1256 strcmp(m->m_name, ct_encode_string(d,
1257 &el->el_scratch))) == 0 &&
1258 (p == NULL || m->m_type == MD_CHAR))
1259 break;
1260
1261 if (!m->m_name) {
1262 (void) fprintf(el->el_errfile,
1263 "%s: Invalid argument `%ls'.\n", name, d);
1264 return -1;
1265 }
1266 if (p) {
1267 int c = ffs((int)m->m_value);
1268 int v = *++p ? parse__escape(&p) :
1269 el->el_tty.t_vdisable;
1270 assert(c != 0);
1271 c--;
1272 c = tty__getcharindex(c);
1273 assert(c != -1);
1274 tios->c_cc[c] = (cc_t)v;
1275 continue;
1276 }
1277 switch (x) {
1278 case '+':
1279 el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value;
1280 el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
1281 break;
1282 case '-':
1283 el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
1284 el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value;
1285 break;
1286 default:
1287 el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
1288 el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
1289 break;
1290 }
1291 }
1292
1293 tty_setup_flags(el, tios, z);
1294 if (el->el_tty.t_mode == z) {
1295 if (tty_setty(el, TCSADRAIN, tios) == -1) {
1296 #ifdef DEBUG_TTY
1297 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n",
1298 __func__, strerror(errno));
1299 #endif /* DEBUG_TTY */
1300 return -1;
1301 }
1302 }
1303
1304 return 0;
1305 }
1306
1307
1308 #ifdef notyet
1309 /* tty_printchar():
1310 * DEbugging routine to print the tty characters
1311 */
1312 private void
1313 tty_printchar(EditLine *el, unsigned char *s)
1314 {
1315 ttyperm_t *m;
1316 int i;
1317
1318 for (i = 0; i < C_NCC; i++) {
1319 for (m = el->el_tty.t_t; m->m_name; m++)
1320 if (m->m_type == MD_CHAR && C_SH(i) == m->m_value)
1321 break;
1322 if (m->m_name)
1323 (void) fprintf(el->el_errfile, "%s ^%c ",
1324 m->m_name, s[i] + 'A' - 1);
1325 if (i % 5 == 0)
1326 (void) fprintf(el->el_errfile, "\n");
1327 }
1328 (void) fprintf(el->el_errfile, "\n");
1329 }
1330 #endif /* notyet */
1331
1332
1333 private void
1334 tty_setup_flags(EditLine *el, struct termios *tios, int mode)
1335 {
1336 int kind;
1337 for (kind = MD_INP; kind <= MD_LIN; kind++) {
1338 tcflag_t *f = tty__get_flag(tios, kind);
1339 *f = tty_update_flag(el, *f, mode, kind);
1340 }
1341 }
1342