1
/* $NetBSD: tty.c,v 1.15 2001/05/17 01:02:17 christos Exp $ */
4
* Copyright (c) 1992, 1993
5
* The Regents of the University of California. All rights reserved.
7
* This code is derived from software contributed to Berkeley by
8
* Christos Zoulas of Cornell University.
10
* Redistribution and use in source and binary forms, with or without
11
* modification, are permitted provided that the following conditions
13
* 1. Redistributions of source code must retain the above copyright
14
* notice, this list of conditions and the following disclaimer.
15
* 2. Redistributions in binary form must reproduce the above copyright
16
* notice, this list of conditions and the following disclaimer in the
17
* documentation and/or other materials provided with the distribution.
18
* 3. All advertising materials mentioning features or use of this software
19
* must display the following acknowledgement:
20
* This product includes software developed by the University of
21
* California, Berkeley and its contributors.
22
* 4. Neither the name of the University nor the names of its contributors
23
* may be used to endorse or promote products derived from this software
24
* without specific prior written permission.
26
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40
#if !defined(lint) && !defined(SCCSID)
42
static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) 6/4/93";
44
__RCSID("$NetBSD: tty.c,v 1.15 2001/05/17 01:02:17 christos Exp $");
46
#endif /* not lint && not SCCSID */
49
* tty.c: tty interface stuff
55
typedef struct ttymodes_t {
61
typedef struct ttymap_t {
62
int nch, och; /* Internal and termio rep of chars */
63
el_action_t bind[3]; /* emacs, vi, and vi-cmd */
67
private const ttyperm_t ttyperm = {
69
{"iflag:", ICRNL, (INLCR | IGNCR)},
70
{"oflag:", (OPOST | ONLCR), ONLRET},
72
{"lflag:", (ISIG | ICANON | ECHO | ECHOE | ECHOCTL | IEXTEN),
73
(NOFLSH | ECHONL | EXTPROC | FLUSHO)},
77
{"iflag:", (INLCR | ICRNL), IGNCR},
78
{"oflag:", (OPOST | ONLCR), ONLRET},
81
(NOFLSH | ICANON | ECHO | ECHOK | ECHONL | EXTPROC | IEXTEN | FLUSHO)},
82
{"chars:", (C_SH(C_MIN) | C_SH(C_TIME) | C_SH(C_SWTCH) | C_SH(C_DSWTCH) |
83
C_SH(C_SUSP) | C_SH(C_DSUSP) | C_SH(C_EOL) | C_SH(C_DISCARD) |
84
C_SH(C_PGOFF) | C_SH(C_PAGE) | C_SH(C_STATUS)), 0}
87
{"iflag:", 0, IXON | IXOFF | INLCR | ICRNL},
90
{"lflag:", 0, ISIG | IEXTEN},
95
private const ttychar_t ttychar = {
97
CINTR, CQUIT, CERASE, CKILL,
98
CEOF, CEOL, CEOL2, CSWTCH,
99
CDSWTCH, CERASE2, CSTART, CSTOP,
100
CWERASE, CSUSP, CDSUSP, CREPRINT,
101
CDISCARD, CLNEXT, CSTATUS, CPAGE,
102
CPGOFF, CKILL2, CBRK, CMIN,
106
CINTR, CQUIT, CERASE, CKILL,
107
_POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
108
_POSIX_VDISABLE, CERASE2, CSTART, CSTOP,
109
_POSIX_VDISABLE, CSUSP, _POSIX_VDISABLE, _POSIX_VDISABLE,
110
CDISCARD, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
111
_POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 1,
125
private const ttymap_t tty_map[] = {
128
{ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
132
{ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
136
{EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
140
{EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
144
{EM_DELETE_OR_LIST, VI_LIST_OR_EOF, ED_UNASSIGNED}},
148
{ED_DELETE_PREV_WORD, ED_DELETE_PREV_WORD, ED_PREV_WORD}},
151
{C_REPRINT, VREPRINT,
152
{ED_REDISPLAY, ED_INSERT, ED_REDISPLAY}},
153
#endif /* VREPRINT */
156
{ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED}},
159
{ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED}}
162
private const ttymodes_t ttymodes[] = {
164
{"ignbrk", IGNBRK, MD_INP},
167
{"brkint", BRKINT, MD_INP},
170
{"ignpar", IGNPAR, MD_INP},
173
{"parmrk", PARMRK, MD_INP},
176
{"inpck", INPCK, MD_INP},
179
{"istrip", ISTRIP, MD_INP},
182
{"inlcr", INLCR, MD_INP},
185
{"igncr", IGNCR, MD_INP},
188
{"icrnl", ICRNL, MD_INP},
191
{"iuclc", IUCLC, MD_INP},
194
{"ixon", IXON, MD_INP},
197
{"ixany", IXANY, MD_INP},
200
{"ixoff", IXOFF, MD_INP},
203
{"imaxbel", IMAXBEL, MD_INP},
207
{"opost", OPOST, MD_OUT},
210
{"olcuc", OLCUC, MD_OUT},
213
{"onlcr", ONLCR, MD_OUT},
216
{"ocrnl", OCRNL, MD_OUT},
219
{"onocr", ONOCR, MD_OUT},
222
{"onoeot", ONOEOT, MD_OUT},
225
{"onlret", ONLRET, MD_OUT},
228
{"ofill", OFILL, MD_OUT},
231
{"ofdel", OFDEL, MD_OUT},
234
{"nldly", NLDLY, MD_OUT},
237
{"crdly", CRDLY, MD_OUT},
240
{"tabdly", TABDLY, MD_OUT},
243
{"xtabs", XTABS, MD_OUT},
246
{"bsdly", BSDLY, MD_OUT},
249
{"vtdly", VTDLY, MD_OUT},
252
{"ffdly", FFDLY, MD_OUT},
255
{"pageout", PAGEOUT, MD_OUT},
258
{"wrap", WRAP, MD_OUT},
262
{"cignore", CIGNORE, MD_CTL},
265
{"cbaud", CBAUD, MD_CTL},
268
{"cstopb", CSTOPB, MD_CTL},
271
{"cread", CREAD, MD_CTL},
274
{"parenb", PARENB, MD_CTL},
277
{"parodd", PARODD, MD_CTL},
280
{"hupcl", HUPCL, MD_CTL},
283
{"clocal", CLOCAL, MD_CTL},
286
{"loblk", LOBLK, MD_CTL},
289
{"cibaud", CIBAUD, MD_CTL},
293
{"ccts_oflow", CCTS_OFLOW, MD_CTL},
295
{"crtscts", CRTSCTS, MD_CTL},
296
#endif /* CCTS_OFLOW */
299
{"crts_iflow", CRTS_IFLOW, MD_CTL},
300
#endif /* CRTS_IFLOW */
302
{"cdtrcts", CDTRCTS, MD_CTL},
305
{"mdmbuf", MDMBUF, MD_CTL},
308
{"rcv1en", RCV1EN, MD_CTL},
311
{"xmt1en", XMT1EN, MD_CTL},
315
{"isig", ISIG, MD_LIN},
318
{"icanon", ICANON, MD_LIN},
321
{"xcase", XCASE, MD_LIN},
324
{"echo", ECHO, MD_LIN},
327
{"echoe", ECHOE, MD_LIN},
330
{"echok", ECHOK, MD_LIN},
333
{"echonl", ECHONL, MD_LIN},
336
{"noflsh", NOFLSH, MD_LIN},
339
{"tostop", TOSTOP, MD_LIN},
342
{"echoctl", ECHOCTL, MD_LIN},
345
{"echoprt", ECHOPRT, MD_LIN},
348
{"echoke", ECHOKE, MD_LIN},
351
{"defecho", DEFECHO, MD_LIN},
354
{"flusho", FLUSHO, MD_LIN},
357
{"pendin", PENDIN, MD_LIN},
360
{"iexten", IEXTEN, MD_LIN},
363
{"nokerninfo", NOKERNINFO, MD_LIN},
364
#endif /* NOKERNINFO */
366
{"altwerase", ALTWERASE, MD_LIN},
367
#endif /* ALTWERASE */
369
{"extproc", EXTPROC, MD_LIN},
373
{"intr", C_SH(C_INTR), MD_CHAR},
376
{"quit", C_SH(C_QUIT), MD_CHAR},
379
{"erase", C_SH(C_ERASE), MD_CHAR},
382
{"kill", C_SH(C_KILL), MD_CHAR},
385
{"eof", C_SH(C_EOF), MD_CHAR},
388
{"eol", C_SH(C_EOL), MD_CHAR},
391
{"eol2", C_SH(C_EOL2), MD_CHAR},
394
{"swtch", C_SH(C_SWTCH), MD_CHAR},
397
{"dswtch", C_SH(C_DSWTCH), MD_CHAR},
400
{"erase2", C_SH(C_ERASE2), MD_CHAR},
403
{"start", C_SH(C_START), MD_CHAR},
406
{"stop", C_SH(C_STOP), MD_CHAR},
409
{"werase", C_SH(C_WERASE), MD_CHAR},
412
{"susp", C_SH(C_SUSP), MD_CHAR},
415
{"dsusp", C_SH(C_DSUSP), MD_CHAR},
417
#if defined(VREPRINT)
418
{"reprint", C_SH(C_REPRINT), MD_CHAR},
419
#endif /* VREPRINT */
420
#if defined(VDISCARD)
421
{"discard", C_SH(C_DISCARD), MD_CHAR},
422
#endif /* VDISCARD */
424
{"lnext", C_SH(C_LNEXT), MD_CHAR},
427
{"status", C_SH(C_STATUS), MD_CHAR},
430
{"page", C_SH(C_PAGE), MD_CHAR},
433
{"pgoff", C_SH(C_PGOFF), MD_CHAR},
436
{"kill2", C_SH(C_KILL2), MD_CHAR},
439
{"brk", C_SH(C_BRK), MD_CHAR},
442
{"min", C_SH(C_MIN), MD_CHAR},
445
{"time", C_SH(C_TIME), MD_CHAR},
452
#define tty_getty(el, td) tcgetattr((el)->el_infd, (td))
453
#define tty_setty(el, td) tcsetattr((el)->el_infd, TCSADRAIN, (td))
455
#define tty__gettabs(td) ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1)
456
#define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8)
457
#define tty__cooked_mode(td) ((td)->c_lflag & ICANON)
459
private void tty__getchar(struct termios *, unsigned char *);
460
private void tty__setchar(struct termios *, unsigned char *);
461
private speed_t tty__getspeed(struct termios *);
462
private int tty_setup(EditLine *);
468
* Get the tty parameters and initialize the editing state
471
tty_setup(EditLine *el)
475
if (el->el_flags & EDIT_DISABLED)
478
if (tty_getty(el, &el->el_tty.t_ed) == -1) {
480
(void) fprintf(el->el_errfile,
481
"tty_setup: tty_getty: %s\n", strerror(errno));
482
#endif /* DEBUG_TTY */
485
el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed;
487
el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex);
488
el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex);
489
el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex);
491
el->el_tty.t_ex.c_iflag &= ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask;
492
el->el_tty.t_ex.c_iflag |= el->el_tty.t_t[EX_IO][MD_INP].t_setmask;
494
el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask;
495
el->el_tty.t_ex.c_oflag |= el->el_tty.t_t[EX_IO][MD_OUT].t_setmask;
497
el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask;
498
el->el_tty.t_ex.c_cflag |= el->el_tty.t_t[EX_IO][MD_CTL].t_setmask;
500
el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask;
501
el->el_tty.t_ex.c_lflag |= el->el_tty.t_t[EX_IO][MD_LIN].t_setmask;
504
* Reset the tty chars to reasonable defaults
505
* If they are disabled, then enable them.
508
if (tty__cooked_mode(&el->el_tty.t_ts)) {
509
tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
511
* Don't affect CMIN and CTIME for the editor mode
513
for (rst = 0; rst < C_NCC - 2; rst++)
514
if (el->el_tty.t_c[TS_IO][rst] !=
515
el->el_tty.t_vdisable
516
&& el->el_tty.t_c[ED_IO][rst] !=
517
el->el_tty.t_vdisable)
518
el->el_tty.t_c[ED_IO][rst] =
519
el->el_tty.t_c[TS_IO][rst];
520
for (rst = 0; rst < C_NCC; rst++)
521
if (el->el_tty.t_c[TS_IO][rst] !=
522
el->el_tty.t_vdisable)
523
el->el_tty.t_c[EX_IO][rst] =
524
el->el_tty.t_c[TS_IO][rst];
526
tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
527
if (tty_setty(el, &el->el_tty.t_ex) == -1) {
529
(void) fprintf(el->el_errfile,
530
"tty_setup: tty_setty: %s\n",
532
#endif /* DEBUG_TTY */
536
tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
538
el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask;
539
el->el_tty.t_ed.c_iflag |= el->el_tty.t_t[ED_IO][MD_INP].t_setmask;
541
el->el_tty.t_ed.c_oflag &= ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask;
542
el->el_tty.t_ed.c_oflag |= el->el_tty.t_t[ED_IO][MD_OUT].t_setmask;
544
el->el_tty.t_ed.c_cflag &= ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask;
545
el->el_tty.t_ed.c_cflag |= el->el_tty.t_t[ED_IO][MD_CTL].t_setmask;
547
el->el_tty.t_ed.c_lflag &= ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask;
548
el->el_tty.t_ed.c_lflag |= el->el_tty.t_t[ED_IO][MD_LIN].t_setmask;
550
tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
551
tty_bind_char(el, 1);
556
tty_init(EditLine *el)
559
el->el_tty.t_mode = EX_IO;
560
el->el_tty.t_vdisable = _POSIX_VDISABLE;
561
(void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t));
562
(void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t));
563
return (tty_setup(el));
568
* Restore the tty to its original settings
572
tty_end(EditLine *el __attribute__((unused)))
575
/* XXX: Maybe reset to an initial state? */
583
tty__getspeed(struct termios *td)
587
if ((spd = cfgetispeed(td)) == 0)
588
spd = cfgetospeed(td);
594
* Get the tty characters
597
tty__getchar(struct termios *td, unsigned char *s)
601
s[C_INTR] = td->c_cc[VINTR];
604
s[C_QUIT] = td->c_cc[VQUIT];
607
s[C_ERASE] = td->c_cc[VERASE];
610
s[C_KILL] = td->c_cc[VKILL];
613
s[C_EOF] = td->c_cc[VEOF];
616
s[C_EOL] = td->c_cc[VEOL];
619
s[C_EOL2] = td->c_cc[VEOL2];
622
s[C_SWTCH] = td->c_cc[VSWTCH];
625
s[C_DSWTCH] = td->c_cc[VDSWTCH];
628
s[C_ERASE2] = td->c_cc[VERASE2];
631
s[C_START] = td->c_cc[VSTART];
634
s[C_STOP] = td->c_cc[VSTOP];
637
s[C_WERASE] = td->c_cc[VWERASE];
640
s[C_SUSP] = td->c_cc[VSUSP];
643
s[C_DSUSP] = td->c_cc[VDSUSP];
646
s[C_REPRINT] = td->c_cc[VREPRINT];
647
#endif /* VREPRINT */
649
s[C_DISCARD] = td->c_cc[VDISCARD];
650
#endif /* VDISCARD */
652
s[C_LNEXT] = td->c_cc[VLNEXT];
655
s[C_STATUS] = td->c_cc[VSTATUS];
658
s[C_PAGE] = td->c_cc[VPAGE];
661
s[C_PGOFF] = td->c_cc[VPGOFF];
664
s[C_KILL2] = td->c_cc[VKILL2];
667
s[C_MIN] = td->c_cc[VMIN];
670
s[C_TIME] = td->c_cc[VTIME];
676
* Set the tty characters
679
tty__setchar(struct termios *td, unsigned char *s)
683
td->c_cc[VINTR] = s[C_INTR];
686
td->c_cc[VQUIT] = s[C_QUIT];
689
td->c_cc[VERASE] = s[C_ERASE];
692
td->c_cc[VKILL] = s[C_KILL];
695
td->c_cc[VEOF] = s[C_EOF];
698
td->c_cc[VEOL] = s[C_EOL];
701
td->c_cc[VEOL2] = s[C_EOL2];
704
td->c_cc[VSWTCH] = s[C_SWTCH];
707
td->c_cc[VDSWTCH] = s[C_DSWTCH];
710
td->c_cc[VERASE2] = s[C_ERASE2];
713
td->c_cc[VSTART] = s[C_START];
716
td->c_cc[VSTOP] = s[C_STOP];
719
td->c_cc[VWERASE] = s[C_WERASE];
722
td->c_cc[VSUSP] = s[C_SUSP];
725
td->c_cc[VDSUSP] = s[C_DSUSP];
728
td->c_cc[VREPRINT] = s[C_REPRINT];
729
#endif /* VREPRINT */
731
td->c_cc[VDISCARD] = s[C_DISCARD];
732
#endif /* VDISCARD */
734
td->c_cc[VLNEXT] = s[C_LNEXT];
737
td->c_cc[VSTATUS] = s[C_STATUS];
740
td->c_cc[VPAGE] = s[C_PAGE];
743
td->c_cc[VPGOFF] = s[C_PGOFF];
746
td->c_cc[VKILL2] = s[C_KILL2];
749
td->c_cc[VMIN] = s[C_MIN];
752
td->c_cc[VTIME] = s[C_TIME];
758
* Rebind the editline functions
761
tty_bind_char(EditLine *el, int force)
764
unsigned char *t_n = el->el_tty.t_c[ED_IO];
765
unsigned char *t_o = el->el_tty.t_ed.c_cc;
766
unsigned char new[2], old[2];
768
el_action_t *map, *alt;
769
const el_action_t *dmap, *dalt;
770
new[1] = old[1] = '\0';
772
map = el->el_map.key;
773
alt = el->el_map.alt;
774
if (el->el_map.type == MAP_VI) {
775
dmap = el->el_map.vii;
776
dalt = el->el_map.vic;
778
dmap = el->el_map.emacs;
782
for (tp = tty_map; tp->nch != -1; tp++) {
783
new[0] = t_n[tp->nch];
784
old[0] = t_o[tp->och];
785
if (new[0] == old[0] && !force)
787
/* Put the old default binding back, and set the new binding */
788
key_clear(el, map, (char *)old);
789
map[old[0]] = dmap[old[0]];
790
key_clear(el, map, (char *)new);
791
/* MAP_VI == 1, MAP_EMACS == 0... */
792
map[new[0]] = tp->bind[el->el_map.type];
794
key_clear(el, alt, (char *)old);
795
alt[old[0]] = dalt[old[0]];
796
key_clear(el, alt, (char *)new);
797
alt[new[0]] = tp->bind[el->el_map.type + 1];
804
* Set terminal into 1 character at a time mode.
807
tty_rawmode(EditLine *el)
810
if (el->el_tty.t_mode == ED_IO || el->el_tty.t_mode == QU_IO)
813
if (el->el_flags & EDIT_DISABLED)
816
if (tty_getty(el, &el->el_tty.t_ts) == -1) {
818
(void) fprintf(el->el_errfile, "tty_rawmode: tty_getty: %s\n",
820
#endif /* DEBUG_TTY */
824
* We always keep up with the eight bit setting and the speed of the
825
* tty. But only we only believe changes that are made to cooked mode!
827
el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts);
828
el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts);
830
if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed ||
831
tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) {
832
(void) cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed);
833
(void) cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed);
834
(void) cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed);
835
(void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed);
837
if (tty__cooked_mode(&el->el_tty.t_ts)) {
838
if (el->el_tty.t_ts.c_cflag != el->el_tty.t_ex.c_cflag) {
839
el->el_tty.t_ex.c_cflag =
840
el->el_tty.t_ts.c_cflag;
841
el->el_tty.t_ex.c_cflag &=
842
~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask;
843
el->el_tty.t_ex.c_cflag |=
844
el->el_tty.t_t[EX_IO][MD_CTL].t_setmask;
846
el->el_tty.t_ed.c_cflag =
847
el->el_tty.t_ts.c_cflag;
848
el->el_tty.t_ed.c_cflag &=
849
~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask;
850
el->el_tty.t_ed.c_cflag |=
851
el->el_tty.t_t[ED_IO][MD_CTL].t_setmask;
853
if ((el->el_tty.t_ts.c_lflag != el->el_tty.t_ex.c_lflag) &&
854
(el->el_tty.t_ts.c_lflag != el->el_tty.t_ed.c_lflag)) {
855
el->el_tty.t_ex.c_lflag =
856
el->el_tty.t_ts.c_lflag;
857
el->el_tty.t_ex.c_lflag &=
858
~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask;
859
el->el_tty.t_ex.c_lflag |=
860
el->el_tty.t_t[EX_IO][MD_LIN].t_setmask;
862
el->el_tty.t_ed.c_lflag =
863
el->el_tty.t_ts.c_lflag;
864
el->el_tty.t_ed.c_lflag &=
865
~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask;
866
el->el_tty.t_ed.c_lflag |=
867
el->el_tty.t_t[ED_IO][MD_LIN].t_setmask;
869
if ((el->el_tty.t_ts.c_iflag != el->el_tty.t_ex.c_iflag) &&
870
(el->el_tty.t_ts.c_iflag != el->el_tty.t_ed.c_iflag)) {
871
el->el_tty.t_ex.c_iflag =
872
el->el_tty.t_ts.c_iflag;
873
el->el_tty.t_ex.c_iflag &=
874
~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask;
875
el->el_tty.t_ex.c_iflag |=
876
el->el_tty.t_t[EX_IO][MD_INP].t_setmask;
878
el->el_tty.t_ed.c_iflag =
879
el->el_tty.t_ts.c_iflag;
880
el->el_tty.t_ed.c_iflag &=
881
~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask;
882
el->el_tty.t_ed.c_iflag |=
883
el->el_tty.t_t[ED_IO][MD_INP].t_setmask;
885
if ((el->el_tty.t_ts.c_oflag != el->el_tty.t_ex.c_oflag) &&
886
(el->el_tty.t_ts.c_oflag != el->el_tty.t_ed.c_oflag)) {
887
el->el_tty.t_ex.c_oflag =
888
el->el_tty.t_ts.c_oflag;
889
el->el_tty.t_ex.c_oflag &=
890
~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask;
891
el->el_tty.t_ex.c_oflag |=
892
el->el_tty.t_t[EX_IO][MD_OUT].t_setmask;
894
el->el_tty.t_ed.c_oflag =
895
el->el_tty.t_ts.c_oflag;
896
el->el_tty.t_ed.c_oflag &=
897
~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask;
898
el->el_tty.t_ed.c_oflag |=
899
el->el_tty.t_t[ED_IO][MD_OUT].t_setmask;
901
if (tty__gettabs(&el->el_tty.t_ex) == 0)
902
el->el_tty.t_tabs = 0;
904
el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0;
909
tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
911
* Check if the user made any changes.
912
* If he did, then propagate the changes to the
913
* edit and execute data structures.
915
for (i = 0; i < C_NCC; i++)
916
if (el->el_tty.t_c[TS_IO][i] !=
917
el->el_tty.t_c[EX_IO][i])
922
* Propagate changes only to the unprotected
923
* chars that have been modified just now.
925
for (i = 0; i < C_NCC; i++) {
926
if (!((el->el_tty.t_t[ED_IO][MD_CHAR].t_setmask & C_SH(i)))
927
&& (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
928
el->el_tty.t_c[ED_IO][i] = el->el_tty.t_c[TS_IO][i];
929
if (el->el_tty.t_t[ED_IO][MD_CHAR].t_clrmask & C_SH(i))
930
el->el_tty.t_c[ED_IO][i] = el->el_tty.t_vdisable;
932
tty_bind_char(el, 0);
933
tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
935
for (i = 0; i < C_NCC; i++) {
936
if (!((el->el_tty.t_t[EX_IO][MD_CHAR].t_setmask & C_SH(i)))
937
&& (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
938
el->el_tty.t_c[EX_IO][i] = el->el_tty.t_c[TS_IO][i];
939
if (el->el_tty.t_t[EX_IO][MD_CHAR].t_clrmask & C_SH(i))
940
el->el_tty.t_c[EX_IO][i] = el->el_tty.t_vdisable;
942
tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
946
if (tty_setty(el, &el->el_tty.t_ed) == -1) {
948
(void) fprintf(el->el_errfile, "tty_rawmode: tty_setty: %s\n",
950
#endif /* DEBUG_TTY */
953
el->el_tty.t_mode = ED_IO;
959
* Set the tty back to normal mode
962
tty_cookedmode(EditLine *el)
963
{ /* set tty in normal setup */
965
if (el->el_tty.t_mode == EX_IO)
968
if (el->el_flags & EDIT_DISABLED)
971
if (tty_setty(el, &el->el_tty.t_ex) == -1) {
973
(void) fprintf(el->el_errfile,
974
"tty_cookedmode: tty_setty: %s\n",
976
#endif /* DEBUG_TTY */
979
el->el_tty.t_mode = EX_IO;
988
tty_quotemode(EditLine *el)
990
if (el->el_tty.t_mode == QU_IO)
993
el->el_tty.t_qu = el->el_tty.t_ed;
995
el->el_tty.t_qu.c_iflag &= ~el->el_tty.t_t[QU_IO][MD_INP].t_clrmask;
996
el->el_tty.t_qu.c_iflag |= el->el_tty.t_t[QU_IO][MD_INP].t_setmask;
998
el->el_tty.t_qu.c_oflag &= ~el->el_tty.t_t[QU_IO][MD_OUT].t_clrmask;
999
el->el_tty.t_qu.c_oflag |= el->el_tty.t_t[QU_IO][MD_OUT].t_setmask;
1001
el->el_tty.t_qu.c_cflag &= ~el->el_tty.t_t[QU_IO][MD_CTL].t_clrmask;
1002
el->el_tty.t_qu.c_cflag |= el->el_tty.t_t[QU_IO][MD_CTL].t_setmask;
1004
el->el_tty.t_qu.c_lflag &= ~el->el_tty.t_t[QU_IO][MD_LIN].t_clrmask;
1005
el->el_tty.t_qu.c_lflag |= el->el_tty.t_t[QU_IO][MD_LIN].t_setmask;
1007
if (tty_setty(el, &el->el_tty.t_qu) == -1) {
1009
(void) fprintf(el->el_errfile, "QuoteModeOn: tty_setty: %s\n",
1011
#endif /* DEBUG_TTY */
1014
el->el_tty.t_mode = QU_IO;
1019
/* tty_noquotemode():
1020
* Turn off quote mode
1023
tty_noquotemode(EditLine *el)
1026
if (el->el_tty.t_mode != QU_IO)
1028
if (tty_setty(el, &el->el_tty.t_ed) == -1) {
1030
(void) fprintf(el->el_errfile, "QuoteModeOff: tty_setty: %s\n",
1032
#endif /* DEBUG_TTY */
1035
el->el_tty.t_mode = ED_IO;
1045
tty_stty(EditLine *el, int argc __attribute__((unused)), const char **argv)
1047
const ttymodes_t *m;
1059
while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0')
1060
switch (argv[0][1]) {
1078
(void) fprintf(el->el_errfile,
1079
"%s: Unknown switch `%c'.\n",
1084
if (!argv || !*argv) {
1086
int len = 0, st = 0, cu;
1087
for (m = ttymodes; m->m_name; m++) {
1088
if (m->m_type != i) {
1089
(void) fprintf(el->el_outfile, "%s%s",
1090
i != -1 ? "\n" : "",
1091
el->el_tty.t_t[z][m->m_type].t_name);
1094
strlen(el->el_tty.t_t[z][m->m_type].t_name);
1096
x = (el->el_tty.t_t[z][i].t_setmask & m->m_value)
1098
x = (el->el_tty.t_t[z][i].t_clrmask & m->m_value)
1101
if (x != '\0' || aflag) {
1103
cu = strlen(m->m_name) + (x != '\0') + 1;
1105
if (len + cu >= el->el_term.t_size.h) {
1106
(void) fprintf(el->el_outfile, "\n%*s",
1113
(void) fprintf(el->el_outfile, "%c%s ",
1116
(void) fprintf(el->el_outfile, "%s ",
1120
(void) fprintf(el->el_outfile, "\n");
1123
while (argv && (s = *argv++)) {
1134
for (m = ttymodes; m->m_name; m++)
1135
if (strcmp(m->m_name, d) == 0)
1139
(void) fprintf(el->el_errfile,
1140
"%s: Invalid argument `%s'.\n", name, d);
1145
el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value;
1146
el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
1149
el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
1150
el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value;
1153
el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
1154
el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
1164
* DEbugging routine to print the tty characters
1167
tty_printchar(EditLine *el, unsigned char *s)
1172
for (i = 0; i < C_NCC; i++) {
1173
for (m = el->el_tty.t_t; m->m_name; m++)
1174
if (m->m_type == MD_CHAR && C_SH(i) == m->m_value)
1177
(void) fprintf(el->el_errfile, "%s ^%c ",
1178
m->m_name, s[i] + 'A' - 1);
1180
(void) fprintf(el->el_errfile, "\n");
1182
(void) fprintf(el->el_errfile, "\n");