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