2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Christos Zoulas of Cornell University.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * @(#)tty.c 8.1 (Berkeley) 6/4/93
33 * $NetBSD: tty.c,v 1.25 2006/03/18 09:09:41 christos Exp $
34 * $DragonFly: src/lib/libedit/tty.c,v 1.5 2007/05/05 00:27:40 pavalos Exp $
40 * tty.c: tty interface stuff
46 typedef struct ttymodes_t
{
52 typedef struct ttymap_t
{
53 int nch
, och
; /* Internal and termio rep of chars */
54 el_action_t bind
[3]; /* emacs, vi, and vi-cmd */
58 private const ttyperm_t ttyperm
= {
60 {"iflag:", ICRNL
, (INLCR
| IGNCR
)},
61 {"oflag:", (OPOST
| ONLCR
), ONLRET
},
63 {"lflag:", (ISIG
| ICANON
| ECHO
| ECHOE
| ECHOCTL
| IEXTEN
),
64 (NOFLSH
| ECHONL
| EXTPROC
| FLUSHO
)},
68 {"iflag:", (INLCR
| ICRNL
), IGNCR
},
69 {"oflag:", (OPOST
| ONLCR
), ONLRET
},
72 (NOFLSH
| ICANON
| ECHO
| ECHOK
| ECHONL
| EXTPROC
| IEXTEN
| FLUSHO
)},
73 {"chars:", (C_SH(C_MIN
) | C_SH(C_TIME
) | C_SH(C_SWTCH
) | C_SH(C_DSWTCH
) |
74 C_SH(C_SUSP
) | C_SH(C_DSUSP
) | C_SH(C_EOL
) | C_SH(C_DISCARD
) |
75 C_SH(C_PGOFF
) | C_SH(C_PAGE
) | C_SH(C_STATUS
)), 0}
78 {"iflag:", 0, IXON
| IXOFF
| INLCR
| ICRNL
},
81 {"lflag:", 0, ISIG
| IEXTEN
},
86 private const ttychar_t ttychar
= {
88 CINTR
, CQUIT
, CERASE
, CKILL
,
89 CEOF
, CEOL
, CEOL2
, CSWTCH
,
90 CDSWTCH
, CERASE2
, CSTART
, CSTOP
,
91 CWERASE
, CSUSP
, CDSUSP
, CREPRINT
,
92 CDISCARD
, CLNEXT
, CSTATUS
, CPAGE
,
93 CPGOFF
, CKILL2
, CBRK
, CMIN
,
97 CINTR
, CQUIT
, CERASE
, CKILL
,
98 _POSIX_VDISABLE
, _POSIX_VDISABLE
, _POSIX_VDISABLE
, _POSIX_VDISABLE
,
99 _POSIX_VDISABLE
, CERASE2
, CSTART
, CSTOP
,
100 _POSIX_VDISABLE
, CSUSP
, _POSIX_VDISABLE
, _POSIX_VDISABLE
,
101 CDISCARD
, _POSIX_VDISABLE
, _POSIX_VDISABLE
, _POSIX_VDISABLE
,
102 _POSIX_VDISABLE
, _POSIX_VDISABLE
, _POSIX_VDISABLE
, 1,
116 private const ttymap_t tty_map
[] = {
119 {EM_DELETE_PREV_CHAR
, VI_DELETE_PREV_CHAR
, ED_PREV_CHAR
}},
123 {EM_DELETE_PREV_CHAR
, VI_DELETE_PREV_CHAR
, ED_PREV_CHAR
}},
127 {EM_KILL_LINE
, VI_KILL_LINE_PREV
, ED_UNASSIGNED
}},
131 {EM_KILL_LINE
, VI_KILL_LINE_PREV
, ED_UNASSIGNED
}},
135 {EM_DELETE_OR_LIST
, VI_LIST_OR_EOF
, ED_UNASSIGNED
}},
139 {ED_DELETE_PREV_WORD
, ED_DELETE_PREV_WORD
, ED_PREV_WORD
}},
142 {C_REPRINT
, VREPRINT
,
143 {ED_REDISPLAY
, ED_INSERT
, ED_REDISPLAY
}},
144 #endif /* VREPRINT */
147 {ED_QUOTED_INSERT
, ED_QUOTED_INSERT
, ED_UNASSIGNED
}},
150 {ED_UNASSIGNED
, ED_UNASSIGNED
, ED_UNASSIGNED
}}
153 private const ttymodes_t ttymodes
[] = {
155 {"ignbrk", IGNBRK
, MD_INP
},
158 {"brkint", BRKINT
, MD_INP
},
161 {"ignpar", IGNPAR
, MD_INP
},
164 {"parmrk", PARMRK
, MD_INP
},
167 {"inpck", INPCK
, MD_INP
},
170 {"istrip", ISTRIP
, MD_INP
},
173 {"inlcr", INLCR
, MD_INP
},
176 {"igncr", IGNCR
, MD_INP
},
179 {"icrnl", ICRNL
, MD_INP
},
182 {"iuclc", IUCLC
, MD_INP
},
185 {"ixon", IXON
, MD_INP
},
188 {"ixany", IXANY
, MD_INP
},
191 {"ixoff", IXOFF
, MD_INP
},
194 {"imaxbel", IMAXBEL
, MD_INP
},
198 {"opost", OPOST
, MD_OUT
},
201 {"olcuc", OLCUC
, MD_OUT
},
204 {"onlcr", ONLCR
, MD_OUT
},
207 {"ocrnl", OCRNL
, MD_OUT
},
210 {"onocr", ONOCR
, MD_OUT
},
213 {"onoeot", ONOEOT
, MD_OUT
},
216 {"onlret", ONLRET
, MD_OUT
},
219 {"ofill", OFILL
, MD_OUT
},
222 {"ofdel", OFDEL
, MD_OUT
},
225 {"nldly", NLDLY
, MD_OUT
},
228 {"crdly", CRDLY
, MD_OUT
},
231 {"tabdly", TABDLY
, MD_OUT
},
234 {"xtabs", XTABS
, MD_OUT
},
237 {"bsdly", BSDLY
, MD_OUT
},
240 {"vtdly", VTDLY
, MD_OUT
},
243 {"ffdly", FFDLY
, MD_OUT
},
246 {"pageout", PAGEOUT
, MD_OUT
},
249 {"wrap", WRAP
, MD_OUT
},
253 {"cignore", CIGNORE
, MD_CTL
},
256 {"cbaud", CBAUD
, MD_CTL
},
259 {"cstopb", CSTOPB
, MD_CTL
},
262 {"cread", CREAD
, MD_CTL
},
265 {"parenb", PARENB
, MD_CTL
},
268 {"parodd", PARODD
, MD_CTL
},
271 {"hupcl", HUPCL
, MD_CTL
},
274 {"clocal", CLOCAL
, MD_CTL
},
277 {"loblk", LOBLK
, MD_CTL
},
280 {"cibaud", CIBAUD
, MD_CTL
},
284 {"ccts_oflow", CCTS_OFLOW
, MD_CTL
},
286 {"crtscts", CRTSCTS
, MD_CTL
},
287 #endif /* CCTS_OFLOW */
290 {"crts_iflow", CRTS_IFLOW
, MD_CTL
},
291 #endif /* CRTS_IFLOW */
293 {"cdtrcts", CDTRCTS
, MD_CTL
},
296 {"mdmbuf", MDMBUF
, MD_CTL
},
299 {"rcv1en", RCV1EN
, MD_CTL
},
302 {"xmt1en", XMT1EN
, MD_CTL
},
306 {"isig", ISIG
, MD_LIN
},
309 {"icanon", ICANON
, MD_LIN
},
312 {"xcase", XCASE
, MD_LIN
},
315 {"echo", ECHO
, MD_LIN
},
318 {"echoe", ECHOE
, MD_LIN
},
321 {"echok", ECHOK
, MD_LIN
},
324 {"echonl", ECHONL
, MD_LIN
},
327 {"noflsh", NOFLSH
, MD_LIN
},
330 {"tostop", TOSTOP
, MD_LIN
},
333 {"echoctl", ECHOCTL
, MD_LIN
},
336 {"echoprt", ECHOPRT
, MD_LIN
},
339 {"echoke", ECHOKE
, MD_LIN
},
342 {"defecho", DEFECHO
, MD_LIN
},
345 {"flusho", FLUSHO
, MD_LIN
},
348 {"pendin", PENDIN
, MD_LIN
},
351 {"iexten", IEXTEN
, MD_LIN
},
354 {"nokerninfo", NOKERNINFO
, MD_LIN
},
355 #endif /* NOKERNINFO */
357 {"altwerase", ALTWERASE
, MD_LIN
},
358 #endif /* ALTWERASE */
360 {"extproc", EXTPROC
, MD_LIN
},
364 {"intr", C_SH(C_INTR
), MD_CHAR
},
367 {"quit", C_SH(C_QUIT
), MD_CHAR
},
370 {"erase", C_SH(C_ERASE
), MD_CHAR
},
373 {"kill", C_SH(C_KILL
), MD_CHAR
},
376 {"eof", C_SH(C_EOF
), MD_CHAR
},
379 {"eol", C_SH(C_EOL
), MD_CHAR
},
382 {"eol2", C_SH(C_EOL2
), MD_CHAR
},
385 {"swtch", C_SH(C_SWTCH
), MD_CHAR
},
388 {"dswtch", C_SH(C_DSWTCH
), MD_CHAR
},
391 {"erase2", C_SH(C_ERASE2
), MD_CHAR
},
394 {"start", C_SH(C_START
), MD_CHAR
},
397 {"stop", C_SH(C_STOP
), MD_CHAR
},
400 {"werase", C_SH(C_WERASE
), MD_CHAR
},
403 {"susp", C_SH(C_SUSP
), MD_CHAR
},
406 {"dsusp", C_SH(C_DSUSP
), MD_CHAR
},
408 #if defined(VREPRINT)
409 {"reprint", C_SH(C_REPRINT
), MD_CHAR
},
410 #endif /* VREPRINT */
411 #if defined(VDISCARD)
412 {"discard", C_SH(C_DISCARD
), MD_CHAR
},
413 #endif /* VDISCARD */
415 {"lnext", C_SH(C_LNEXT
), MD_CHAR
},
418 {"status", C_SH(C_STATUS
), MD_CHAR
},
421 {"page", C_SH(C_PAGE
), MD_CHAR
},
424 {"pgoff", C_SH(C_PGOFF
), MD_CHAR
},
427 {"kill2", C_SH(C_KILL2
), MD_CHAR
},
430 {"brk", C_SH(C_BRK
), MD_CHAR
},
433 {"min", C_SH(C_MIN
), MD_CHAR
},
436 {"time", C_SH(C_TIME
), MD_CHAR
},
443 #define tty_getty(el, td) tcgetattr((el)->el_infd, (td))
444 #define tty_setty(el, td) tcsetattr((el)->el_infd, TCSADRAIN, (td))
446 #define tty__gettabs(td) ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1)
447 #define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8)
448 #define tty__cooked_mode(td) ((td)->c_lflag & ICANON)
450 private int tty__getcharindex(int);
451 private void tty__getchar(struct termios
*, unsigned char *);
452 private void tty__setchar(struct termios
*, unsigned char *);
453 private speed_t
tty__getspeed(struct termios
*);
454 private int tty_setup(EditLine
*);
460 * Get the tty parameters and initialize the editing state
463 tty_setup(EditLine
*el
)
467 if (el
->el_flags
& EDIT_DISABLED
)
470 if (tty_getty(el
, &el
->el_tty
.t_ed
) == -1) {
472 (void) fprintf(el
->el_errfile
,
473 "tty_setup: tty_getty: %s\n", strerror(errno
));
474 #endif /* DEBUG_TTY */
477 el
->el_tty
.t_ts
= el
->el_tty
.t_ex
= el
->el_tty
.t_ed
;
479 el
->el_tty
.t_speed
= tty__getspeed(&el
->el_tty
.t_ex
);
480 el
->el_tty
.t_tabs
= tty__gettabs(&el
->el_tty
.t_ex
);
481 el
->el_tty
.t_eight
= tty__geteightbit(&el
->el_tty
.t_ex
);
483 el
->el_tty
.t_ex
.c_iflag
&= ~el
->el_tty
.t_t
[EX_IO
][MD_INP
].t_clrmask
;
484 el
->el_tty
.t_ex
.c_iflag
|= el
->el_tty
.t_t
[EX_IO
][MD_INP
].t_setmask
;
486 el
->el_tty
.t_ex
.c_oflag
&= ~el
->el_tty
.t_t
[EX_IO
][MD_OUT
].t_clrmask
;
487 el
->el_tty
.t_ex
.c_oflag
|= el
->el_tty
.t_t
[EX_IO
][MD_OUT
].t_setmask
;
489 el
->el_tty
.t_ex
.c_cflag
&= ~el
->el_tty
.t_t
[EX_IO
][MD_CTL
].t_clrmask
;
490 el
->el_tty
.t_ex
.c_cflag
|= el
->el_tty
.t_t
[EX_IO
][MD_CTL
].t_setmask
;
492 el
->el_tty
.t_ex
.c_lflag
&= ~el
->el_tty
.t_t
[EX_IO
][MD_LIN
].t_clrmask
;
493 el
->el_tty
.t_ex
.c_lflag
|= el
->el_tty
.t_t
[EX_IO
][MD_LIN
].t_setmask
;
496 * Reset the tty chars to reasonable defaults
497 * If they are disabled, then enable them.
500 if (tty__cooked_mode(&el
->el_tty
.t_ts
)) {
501 tty__getchar(&el
->el_tty
.t_ts
, el
->el_tty
.t_c
[TS_IO
]);
503 * Don't affect CMIN and CTIME for the editor mode
505 for (rst
= 0; rst
< C_NCC
- 2; rst
++)
506 if (el
->el_tty
.t_c
[TS_IO
][rst
] !=
507 el
->el_tty
.t_vdisable
508 && el
->el_tty
.t_c
[ED_IO
][rst
] !=
509 el
->el_tty
.t_vdisable
)
510 el
->el_tty
.t_c
[ED_IO
][rst
] =
511 el
->el_tty
.t_c
[TS_IO
][rst
];
512 for (rst
= 0; rst
< C_NCC
; rst
++)
513 if (el
->el_tty
.t_c
[TS_IO
][rst
] !=
514 el
->el_tty
.t_vdisable
)
515 el
->el_tty
.t_c
[EX_IO
][rst
] =
516 el
->el_tty
.t_c
[TS_IO
][rst
];
518 tty__setchar(&el
->el_tty
.t_ex
, el
->el_tty
.t_c
[EX_IO
]);
519 if (tty_setty(el
, &el
->el_tty
.t_ex
) == -1) {
521 (void) fprintf(el
->el_errfile
,
522 "tty_setup: tty_setty: %s\n",
524 #endif /* DEBUG_TTY */
530 tty__setchar(&el
->el_tty
.t_ex
, el
->el_tty
.t_c
[EX_IO
]);
533 el
->el_tty
.t_ed
.c_iflag
&= ~el
->el_tty
.t_t
[ED_IO
][MD_INP
].t_clrmask
;
534 el
->el_tty
.t_ed
.c_iflag
|= el
->el_tty
.t_t
[ED_IO
][MD_INP
].t_setmask
;
536 el
->el_tty
.t_ed
.c_oflag
&= ~el
->el_tty
.t_t
[ED_IO
][MD_OUT
].t_clrmask
;
537 el
->el_tty
.t_ed
.c_oflag
|= el
->el_tty
.t_t
[ED_IO
][MD_OUT
].t_setmask
;
539 el
->el_tty
.t_ed
.c_cflag
&= ~el
->el_tty
.t_t
[ED_IO
][MD_CTL
].t_clrmask
;
540 el
->el_tty
.t_ed
.c_cflag
|= el
->el_tty
.t_t
[ED_IO
][MD_CTL
].t_setmask
;
542 el
->el_tty
.t_ed
.c_lflag
&= ~el
->el_tty
.t_t
[ED_IO
][MD_LIN
].t_clrmask
;
543 el
->el_tty
.t_ed
.c_lflag
|= el
->el_tty
.t_t
[ED_IO
][MD_LIN
].t_setmask
;
545 tty__setchar(&el
->el_tty
.t_ed
, el
->el_tty
.t_c
[ED_IO
]);
546 tty_bind_char(el
, 1);
551 tty_init(EditLine
*el
)
554 el
->el_tty
.t_mode
= EX_IO
;
555 el
->el_tty
.t_vdisable
= _POSIX_VDISABLE
;
556 (void) memcpy(el
->el_tty
.t_t
, ttyperm
, sizeof(ttyperm_t
));
557 (void) memcpy(el
->el_tty
.t_c
, ttychar
, sizeof(ttychar_t
));
558 return (tty_setup(el
));
563 * Restore the tty to its original settings
567 tty_end(EditLine
*el
__attribute__((__unused__
)))
570 /* XXX: Maybe reset to an initial state? */
578 tty__getspeed(struct termios
*td
)
582 if ((spd
= cfgetispeed(td
)) == 0)
583 spd
= cfgetospeed(td
);
588 * Return the index of the asked char in the c_cc array
591 tty__getcharindex(int i
)
657 #endif /* VREPRINT */
661 #endif /* VDISCARD */
696 * Get the tty characters
699 tty__getchar(struct termios
*td
, unsigned char *s
)
703 s
[C_INTR
] = td
->c_cc
[VINTR
];
706 s
[C_QUIT
] = td
->c_cc
[VQUIT
];
709 s
[C_ERASE
] = td
->c_cc
[VERASE
];
712 s
[C_KILL
] = td
->c_cc
[VKILL
];
715 s
[C_EOF
] = td
->c_cc
[VEOF
];
718 s
[C_EOL
] = td
->c_cc
[VEOL
];
721 s
[C_EOL2
] = td
->c_cc
[VEOL2
];
724 s
[C_SWTCH
] = td
->c_cc
[VSWTCH
];
727 s
[C_DSWTCH
] = td
->c_cc
[VDSWTCH
];
730 s
[C_ERASE2
] = td
->c_cc
[VERASE2
];
733 s
[C_START
] = td
->c_cc
[VSTART
];
736 s
[C_STOP
] = td
->c_cc
[VSTOP
];
739 s
[C_WERASE
] = td
->c_cc
[VWERASE
];
742 s
[C_SUSP
] = td
->c_cc
[VSUSP
];
745 s
[C_DSUSP
] = td
->c_cc
[VDSUSP
];
748 s
[C_REPRINT
] = td
->c_cc
[VREPRINT
];
749 #endif /* VREPRINT */
751 s
[C_DISCARD
] = td
->c_cc
[VDISCARD
];
752 #endif /* VDISCARD */
754 s
[C_LNEXT
] = td
->c_cc
[VLNEXT
];
757 s
[C_STATUS
] = td
->c_cc
[VSTATUS
];
760 s
[C_PAGE
] = td
->c_cc
[VPAGE
];
763 s
[C_PGOFF
] = td
->c_cc
[VPGOFF
];
766 s
[C_KILL2
] = td
->c_cc
[VKILL2
];
769 s
[C_MIN
] = td
->c_cc
[VMIN
];
772 s
[C_TIME
] = td
->c_cc
[VTIME
];
778 * Set the tty characters
781 tty__setchar(struct termios
*td
, unsigned char *s
)
785 td
->c_cc
[VINTR
] = s
[C_INTR
];
788 td
->c_cc
[VQUIT
] = s
[C_QUIT
];
791 td
->c_cc
[VERASE
] = s
[C_ERASE
];
794 td
->c_cc
[VKILL
] = s
[C_KILL
];
797 td
->c_cc
[VEOF
] = s
[C_EOF
];
800 td
->c_cc
[VEOL
] = s
[C_EOL
];
803 td
->c_cc
[VEOL2
] = s
[C_EOL2
];
806 td
->c_cc
[VSWTCH
] = s
[C_SWTCH
];
809 td
->c_cc
[VDSWTCH
] = s
[C_DSWTCH
];
812 td
->c_cc
[VERASE2
] = s
[C_ERASE2
];
815 td
->c_cc
[VSTART
] = s
[C_START
];
818 td
->c_cc
[VSTOP
] = s
[C_STOP
];
821 td
->c_cc
[VWERASE
] = s
[C_WERASE
];
824 td
->c_cc
[VSUSP
] = s
[C_SUSP
];
827 td
->c_cc
[VDSUSP
] = s
[C_DSUSP
];
830 td
->c_cc
[VREPRINT
] = s
[C_REPRINT
];
831 #endif /* VREPRINT */
833 td
->c_cc
[VDISCARD
] = s
[C_DISCARD
];
834 #endif /* VDISCARD */
836 td
->c_cc
[VLNEXT
] = s
[C_LNEXT
];
839 td
->c_cc
[VSTATUS
] = s
[C_STATUS
];
842 td
->c_cc
[VPAGE
] = s
[C_PAGE
];
845 td
->c_cc
[VPGOFF
] = s
[C_PGOFF
];
848 td
->c_cc
[VKILL2
] = s
[C_KILL2
];
851 td
->c_cc
[VMIN
] = s
[C_MIN
];
854 td
->c_cc
[VTIME
] = s
[C_TIME
];
860 * Rebind the editline functions
863 tty_bind_char(EditLine
*el
, int force
)
866 unsigned char *t_n
= el
->el_tty
.t_c
[ED_IO
];
867 unsigned char *t_o
= el
->el_tty
.t_ed
.c_cc
;
868 unsigned char new[2], old
[2];
870 el_action_t
*map
, *alt
;
871 const el_action_t
*dmap
, *dalt
;
872 new[1] = old
[1] = '\0';
874 map
= el
->el_map
.key
;
875 alt
= el
->el_map
.alt
;
876 if (el
->el_map
.type
== MAP_VI
) {
877 dmap
= el
->el_map
.vii
;
878 dalt
= el
->el_map
.vic
;
880 dmap
= el
->el_map
.emacs
;
884 for (tp
= tty_map
; tp
->nch
!= -1; tp
++) {
885 new[0] = t_n
[tp
->nch
];
886 old
[0] = t_o
[tp
->och
];
887 if (new[0] == old
[0] && !force
)
889 /* Put the old default binding back, and set the new binding */
890 key_clear(el
, map
, (char *)old
);
891 map
[old
[0]] = dmap
[old
[0]];
892 key_clear(el
, map
, (char *)new);
893 /* MAP_VI == 1, MAP_EMACS == 0... */
894 map
[new[0]] = tp
->bind
[el
->el_map
.type
];
896 key_clear(el
, alt
, (char *)old
);
897 alt
[old
[0]] = dalt
[old
[0]];
898 key_clear(el
, alt
, (char *)new);
899 alt
[new[0]] = tp
->bind
[el
->el_map
.type
+ 1];
906 * Set terminal into 1 character at a time mode.
909 tty_rawmode(EditLine
*el
)
912 if (el
->el_tty
.t_mode
== ED_IO
|| el
->el_tty
.t_mode
== QU_IO
)
915 if (el
->el_flags
& EDIT_DISABLED
)
918 if (tty_getty(el
, &el
->el_tty
.t_ts
) == -1) {
920 (void) fprintf(el
->el_errfile
, "tty_rawmode: tty_getty: %s\n",
922 #endif /* DEBUG_TTY */
926 * We always keep up with the eight bit setting and the speed of the
927 * tty. But only we only believe changes that are made to cooked mode!
929 el
->el_tty
.t_eight
= tty__geteightbit(&el
->el_tty
.t_ts
);
930 el
->el_tty
.t_speed
= tty__getspeed(&el
->el_tty
.t_ts
);
932 if (tty__getspeed(&el
->el_tty
.t_ex
) != el
->el_tty
.t_speed
||
933 tty__getspeed(&el
->el_tty
.t_ed
) != el
->el_tty
.t_speed
) {
934 (void) cfsetispeed(&el
->el_tty
.t_ex
, el
->el_tty
.t_speed
);
935 (void) cfsetospeed(&el
->el_tty
.t_ex
, el
->el_tty
.t_speed
);
936 (void) cfsetispeed(&el
->el_tty
.t_ed
, el
->el_tty
.t_speed
);
937 (void) cfsetospeed(&el
->el_tty
.t_ed
, el
->el_tty
.t_speed
);
939 if (tty__cooked_mode(&el
->el_tty
.t_ts
)) {
940 if (el
->el_tty
.t_ts
.c_cflag
!= el
->el_tty
.t_ex
.c_cflag
) {
941 el
->el_tty
.t_ex
.c_cflag
=
942 el
->el_tty
.t_ts
.c_cflag
;
943 el
->el_tty
.t_ex
.c_cflag
&=
944 ~el
->el_tty
.t_t
[EX_IO
][MD_CTL
].t_clrmask
;
945 el
->el_tty
.t_ex
.c_cflag
|=
946 el
->el_tty
.t_t
[EX_IO
][MD_CTL
].t_setmask
;
948 el
->el_tty
.t_ed
.c_cflag
=
949 el
->el_tty
.t_ts
.c_cflag
;
950 el
->el_tty
.t_ed
.c_cflag
&=
951 ~el
->el_tty
.t_t
[ED_IO
][MD_CTL
].t_clrmask
;
952 el
->el_tty
.t_ed
.c_cflag
|=
953 el
->el_tty
.t_t
[ED_IO
][MD_CTL
].t_setmask
;
955 if ((el
->el_tty
.t_ts
.c_lflag
!= el
->el_tty
.t_ex
.c_lflag
) &&
956 (el
->el_tty
.t_ts
.c_lflag
!= el
->el_tty
.t_ed
.c_lflag
)) {
957 el
->el_tty
.t_ex
.c_lflag
=
958 el
->el_tty
.t_ts
.c_lflag
;
959 el
->el_tty
.t_ex
.c_lflag
&=
960 ~el
->el_tty
.t_t
[EX_IO
][MD_LIN
].t_clrmask
;
961 el
->el_tty
.t_ex
.c_lflag
|=
962 el
->el_tty
.t_t
[EX_IO
][MD_LIN
].t_setmask
;
964 el
->el_tty
.t_ed
.c_lflag
=
965 el
->el_tty
.t_ts
.c_lflag
;
966 el
->el_tty
.t_ed
.c_lflag
&=
967 ~el
->el_tty
.t_t
[ED_IO
][MD_LIN
].t_clrmask
;
968 el
->el_tty
.t_ed
.c_lflag
|=
969 el
->el_tty
.t_t
[ED_IO
][MD_LIN
].t_setmask
;
971 if ((el
->el_tty
.t_ts
.c_iflag
!= el
->el_tty
.t_ex
.c_iflag
) &&
972 (el
->el_tty
.t_ts
.c_iflag
!= el
->el_tty
.t_ed
.c_iflag
)) {
973 el
->el_tty
.t_ex
.c_iflag
=
974 el
->el_tty
.t_ts
.c_iflag
;
975 el
->el_tty
.t_ex
.c_iflag
&=
976 ~el
->el_tty
.t_t
[EX_IO
][MD_INP
].t_clrmask
;
977 el
->el_tty
.t_ex
.c_iflag
|=
978 el
->el_tty
.t_t
[EX_IO
][MD_INP
].t_setmask
;
980 el
->el_tty
.t_ed
.c_iflag
=
981 el
->el_tty
.t_ts
.c_iflag
;
982 el
->el_tty
.t_ed
.c_iflag
&=
983 ~el
->el_tty
.t_t
[ED_IO
][MD_INP
].t_clrmask
;
984 el
->el_tty
.t_ed
.c_iflag
|=
985 el
->el_tty
.t_t
[ED_IO
][MD_INP
].t_setmask
;
987 if ((el
->el_tty
.t_ts
.c_oflag
!= el
->el_tty
.t_ex
.c_oflag
) &&
988 (el
->el_tty
.t_ts
.c_oflag
!= el
->el_tty
.t_ed
.c_oflag
)) {
989 el
->el_tty
.t_ex
.c_oflag
=
990 el
->el_tty
.t_ts
.c_oflag
;
991 el
->el_tty
.t_ex
.c_oflag
&=
992 ~el
->el_tty
.t_t
[EX_IO
][MD_OUT
].t_clrmask
;
993 el
->el_tty
.t_ex
.c_oflag
|=
994 el
->el_tty
.t_t
[EX_IO
][MD_OUT
].t_setmask
;
996 el
->el_tty
.t_ed
.c_oflag
=
997 el
->el_tty
.t_ts
.c_oflag
;
998 el
->el_tty
.t_ed
.c_oflag
&=
999 ~el
->el_tty
.t_t
[ED_IO
][MD_OUT
].t_clrmask
;
1000 el
->el_tty
.t_ed
.c_oflag
|=
1001 el
->el_tty
.t_t
[ED_IO
][MD_OUT
].t_setmask
;
1003 if (tty__gettabs(&el
->el_tty
.t_ex
) == 0)
1004 el
->el_tty
.t_tabs
= 0;
1006 el
->el_tty
.t_tabs
= EL_CAN_TAB
? 1 : 0;
1011 tty__getchar(&el
->el_tty
.t_ts
, el
->el_tty
.t_c
[TS_IO
]);
1013 * Check if the user made any changes.
1014 * If he did, then propagate the changes to the
1015 * edit and execute data structures.
1017 for (i
= 0; i
< C_NCC
; i
++)
1018 if (el
->el_tty
.t_c
[TS_IO
][i
] !=
1019 el
->el_tty
.t_c
[EX_IO
][i
])
1024 * Propagate changes only to the unprotected
1025 * chars that have been modified just now.
1027 for (i
= 0; i
< C_NCC
; i
++) {
1028 if (!((el
->el_tty
.t_t
[ED_IO
][MD_CHAR
].t_setmask
& C_SH(i
)))
1029 && (el
->el_tty
.t_c
[TS_IO
][i
] != el
->el_tty
.t_c
[EX_IO
][i
]))
1030 el
->el_tty
.t_c
[ED_IO
][i
] = el
->el_tty
.t_c
[TS_IO
][i
];
1031 if (el
->el_tty
.t_t
[ED_IO
][MD_CHAR
].t_clrmask
& C_SH(i
))
1032 el
->el_tty
.t_c
[ED_IO
][i
] = el
->el_tty
.t_vdisable
;
1034 tty_bind_char(el
, 0);
1035 tty__setchar(&el
->el_tty
.t_ed
, el
->el_tty
.t_c
[ED_IO
]);
1037 for (i
= 0; i
< C_NCC
; i
++) {
1038 if (!((el
->el_tty
.t_t
[EX_IO
][MD_CHAR
].t_setmask
& C_SH(i
)))
1039 && (el
->el_tty
.t_c
[TS_IO
][i
] != el
->el_tty
.t_c
[EX_IO
][i
]))
1040 el
->el_tty
.t_c
[EX_IO
][i
] = el
->el_tty
.t_c
[TS_IO
][i
];
1041 if (el
->el_tty
.t_t
[EX_IO
][MD_CHAR
].t_clrmask
& C_SH(i
))
1042 el
->el_tty
.t_c
[EX_IO
][i
] = el
->el_tty
.t_vdisable
;
1044 tty__setchar(&el
->el_tty
.t_ex
, el
->el_tty
.t_c
[EX_IO
]);
1048 if (tty_setty(el
, &el
->el_tty
.t_ed
) == -1) {
1050 (void) fprintf(el
->el_errfile
, "tty_rawmode: tty_setty: %s\n",
1052 #endif /* DEBUG_TTY */
1055 el
->el_tty
.t_mode
= ED_IO
;
1060 /* tty_cookedmode():
1061 * Set the tty back to normal mode
1064 tty_cookedmode(EditLine
*el
)
1065 { /* set tty in normal setup */
1067 if (el
->el_tty
.t_mode
== EX_IO
)
1070 if (el
->el_flags
& EDIT_DISABLED
)
1073 if (tty_setty(el
, &el
->el_tty
.t_ex
) == -1) {
1075 (void) fprintf(el
->el_errfile
,
1076 "tty_cookedmode: tty_setty: %s\n",
1078 #endif /* DEBUG_TTY */
1081 el
->el_tty
.t_mode
= EX_IO
;
1087 * Turn on quote mode
1090 tty_quotemode(EditLine
*el
)
1092 if (el
->el_tty
.t_mode
== QU_IO
)
1095 el
->el_tty
.t_qu
= el
->el_tty
.t_ed
;
1097 el
->el_tty
.t_qu
.c_iflag
&= ~el
->el_tty
.t_t
[QU_IO
][MD_INP
].t_clrmask
;
1098 el
->el_tty
.t_qu
.c_iflag
|= el
->el_tty
.t_t
[QU_IO
][MD_INP
].t_setmask
;
1100 el
->el_tty
.t_qu
.c_oflag
&= ~el
->el_tty
.t_t
[QU_IO
][MD_OUT
].t_clrmask
;
1101 el
->el_tty
.t_qu
.c_oflag
|= el
->el_tty
.t_t
[QU_IO
][MD_OUT
].t_setmask
;
1103 el
->el_tty
.t_qu
.c_cflag
&= ~el
->el_tty
.t_t
[QU_IO
][MD_CTL
].t_clrmask
;
1104 el
->el_tty
.t_qu
.c_cflag
|= el
->el_tty
.t_t
[QU_IO
][MD_CTL
].t_setmask
;
1106 el
->el_tty
.t_qu
.c_lflag
&= ~el
->el_tty
.t_t
[QU_IO
][MD_LIN
].t_clrmask
;
1107 el
->el_tty
.t_qu
.c_lflag
|= el
->el_tty
.t_t
[QU_IO
][MD_LIN
].t_setmask
;
1109 if (tty_setty(el
, &el
->el_tty
.t_qu
) == -1) {
1111 (void) fprintf(el
->el_errfile
, "QuoteModeOn: tty_setty: %s\n",
1113 #endif /* DEBUG_TTY */
1116 el
->el_tty
.t_mode
= QU_IO
;
1121 /* tty_noquotemode():
1122 * Turn off quote mode
1125 tty_noquotemode(EditLine
*el
)
1128 if (el
->el_tty
.t_mode
!= QU_IO
)
1130 if (tty_setty(el
, &el
->el_tty
.t_ed
) == -1) {
1132 (void) fprintf(el
->el_errfile
, "QuoteModeOff: tty_setty: %s\n",
1134 #endif /* DEBUG_TTY */
1137 el
->el_tty
.t_mode
= ED_IO
;
1147 tty_stty(EditLine
*el
, int argc
__attribute__((__unused__
)), const char **argv
)
1149 const ttymodes_t
*m
;
1154 struct termios
*tios
= &el
->el_tty
.t_ex
;
1161 while (argv
&& *argv
&& argv
[0][0] == '-' && argv
[0][2] == '\0')
1162 switch (argv
[0][1]) {
1169 tios
= &el
->el_tty
.t_ed
;
1174 tios
= &el
->el_tty
.t_ex
;
1179 tios
= &el
->el_tty
.t_ts
;
1183 (void) fprintf(el
->el_errfile
,
1184 "%s: Unknown switch `%c'.\n",
1189 if (!argv
|| !*argv
) {
1191 int 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
);
1199 strlen(el
->el_tty
.t_t
[z
][m
->m_type
].t_name
);
1202 x
= (el
->el_tty
.t_t
[z
][i
].t_setmask
& m
->m_value
)
1204 x
= (el
->el_tty
.t_t
[z
][i
].t_clrmask
& m
->m_value
)
1210 if (x
!= '\0' || aflag
) {
1212 cu
= strlen(m
->m_name
) + (x
!= '\0') + 1;
1214 if (len
+ cu
>= el
->el_term
.t_size
.h
) {
1215 (void) fprintf(el
->el_outfile
, "\n%*s",
1222 (void) fprintf(el
->el_outfile
, "%c%s ",
1225 (void) fprintf(el
->el_outfile
, "%s ",
1229 (void) fprintf(el
->el_outfile
, "\n");
1232 while (argv
&& (s
= *argv
++)) {
1245 for (m
= ttymodes
; m
->m_name
; m
++)
1246 if ((p
? strncmp(m
->m_name
, d
, (size_t)(p
- d
)) :
1247 strcmp(m
->m_name
, d
)) == 0 &&
1248 (p
== NULL
|| m
->m_type
== MD_CHAR
))
1252 (void) fprintf(el
->el_errfile
,
1253 "%s: Invalid argument `%s'.\n", name
, d
);
1257 int c
= ffs((int)m
->m_value
);
1258 int v
= *++p
? parse__escape((const char **) &p
) :
1259 el
->el_tty
.t_vdisable
;
1261 c
= tty__getcharindex(c
);
1268 el
->el_tty
.t_t
[z
][m
->m_type
].t_setmask
|= m
->m_value
;
1269 el
->el_tty
.t_t
[z
][m
->m_type
].t_clrmask
&= ~m
->m_value
;
1272 el
->el_tty
.t_t
[z
][m
->m_type
].t_setmask
&= ~m
->m_value
;
1273 el
->el_tty
.t_t
[z
][m
->m_type
].t_clrmask
|= m
->m_value
;
1276 el
->el_tty
.t_t
[z
][m
->m_type
].t_setmask
&= ~m
->m_value
;
1277 el
->el_tty
.t_t
[z
][m
->m_type
].t_clrmask
&= ~m
->m_value
;
1287 * DEbugging routine to print the tty characters
1290 tty_printchar(EditLine
*el
, unsigned char *s
)
1295 for (i
= 0; i
< C_NCC
; i
++) {
1296 for (m
= el
->el_tty
.t_t
; m
->m_name
; m
++)
1297 if (m
->m_type
== MD_CHAR
&& C_SH(i
) == m
->m_value
)
1300 (void) fprintf(el
->el_errfile
, "%s ^%c ",
1301 m
->m_name
, s
[i
] + 'A' - 1);
1303 (void) fprintf(el
->el_errfile
, "\n");
1305 (void) fprintf(el
->el_errfile
, "\n");