1 /* $NetBSD: tty.c,v 1.41 2011/10/04 15:27:04 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. 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.
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
36 #if !defined(lint) && !defined(SCCSID)
38 static char sccsid
[] = "@(#)tty.c 8.1 (Berkeley) 6/4/93";
41 #endif /* not lint && not SCCSID */
44 * tty.c: tty interface stuff
48 #include <unistd.h> /* for isatty */
49 #include <strings.h> /* for ffs */
53 typedef struct ttymodes_t
{
59 typedef struct ttymap_t
{
60 Int nch
, och
; /* Internal and termio rep of chars */
61 el_action_t bind
[3]; /* emacs, vi, and vi-cmd */
65 private const ttyperm_t ttyperm
= {
67 {"iflag:", ICRNL
, (INLCR
| IGNCR
)},
68 {"oflag:", (OPOST
| ONLCR
), ONLRET
},
70 {"lflag:", (ISIG
| ICANON
| ECHO
| ECHOE
| ECHOCTL
| IEXTEN
),
71 (NOFLSH
| ECHONL
| EXTPROC
| FLUSHO
)},
75 {"iflag:", (INLCR
| ICRNL
), IGNCR
},
76 {"oflag:", (OPOST
| ONLCR
), ONLRET
},
79 (NOFLSH
| ICANON
| ECHO
| ECHOK
| ECHONL
| EXTPROC
| IEXTEN
| FLUSHO
)},
80 {"chars:", (C_SH(C_MIN
) | C_SH(C_TIME
) | C_SH(C_SWTCH
) | C_SH(C_DSWTCH
) |
81 C_SH(C_SUSP
) | C_SH(C_DSUSP
) | C_SH(C_EOL
) | C_SH(C_DISCARD
) |
82 C_SH(C_PGOFF
) | C_SH(C_PAGE
) | C_SH(C_STATUS
)), 0}
85 {"iflag:", 0, IXON
| IXOFF
| INLCR
| ICRNL
},
88 {"lflag:", 0, ISIG
| IEXTEN
},
93 private const ttychar_t ttychar
= {
95 CINTR
, CQUIT
, CERASE
, CKILL
,
96 CEOF
, CEOL
, CEOL2
, CSWTCH
,
97 CDSWTCH
, CERASE2
, CSTART
, CSTOP
,
98 CWERASE
, CSUSP
, CDSUSP
, CREPRINT
,
99 CDISCARD
, CLNEXT
, CSTATUS
, CPAGE
,
100 CPGOFF
, CKILL2
, CBRK
, CMIN
,
104 CINTR
, CQUIT
, CERASE
, CKILL
,
105 _POSIX_VDISABLE
, _POSIX_VDISABLE
, _POSIX_VDISABLE
, _POSIX_VDISABLE
,
106 _POSIX_VDISABLE
, CERASE2
, CSTART
, CSTOP
,
107 _POSIX_VDISABLE
, CSUSP
, _POSIX_VDISABLE
, _POSIX_VDISABLE
,
108 CDISCARD
, _POSIX_VDISABLE
, _POSIX_VDISABLE
, _POSIX_VDISABLE
,
109 _POSIX_VDISABLE
, _POSIX_VDISABLE
, _POSIX_VDISABLE
, 1,
123 private const ttymap_t tty_map
[] = {
126 {EM_DELETE_PREV_CHAR
, VI_DELETE_PREV_CHAR
, ED_PREV_CHAR
}},
130 {EM_DELETE_PREV_CHAR
, VI_DELETE_PREV_CHAR
, ED_PREV_CHAR
}},
134 {EM_KILL_LINE
, VI_KILL_LINE_PREV
, ED_UNASSIGNED
}},
138 {EM_KILL_LINE
, VI_KILL_LINE_PREV
, ED_UNASSIGNED
}},
142 {EM_DELETE_OR_LIST
, VI_LIST_OR_EOF
, ED_UNASSIGNED
}},
146 {ED_DELETE_PREV_WORD
, ED_DELETE_PREV_WORD
, ED_PREV_WORD
}},
149 {C_REPRINT
, VREPRINT
,
150 {ED_REDISPLAY
, ED_INSERT
, ED_REDISPLAY
}},
151 #endif /* VREPRINT */
154 {ED_QUOTED_INSERT
, ED_QUOTED_INSERT
, ED_UNASSIGNED
}},
157 {ED_UNASSIGNED
, ED_UNASSIGNED
, ED_UNASSIGNED
}}
160 private const ttymodes_t ttymodes
[] = {
162 {"ignbrk", IGNBRK
, MD_INP
},
165 {"brkint", BRKINT
, MD_INP
},
168 {"ignpar", IGNPAR
, MD_INP
},
171 {"parmrk", PARMRK
, MD_INP
},
174 {"inpck", INPCK
, MD_INP
},
177 {"istrip", ISTRIP
, MD_INP
},
180 {"inlcr", INLCR
, MD_INP
},
183 {"igncr", IGNCR
, MD_INP
},
186 {"icrnl", ICRNL
, MD_INP
},
189 {"iuclc", IUCLC
, MD_INP
},
192 {"ixon", IXON
, MD_INP
},
195 {"ixany", IXANY
, MD_INP
},
198 {"ixoff", IXOFF
, MD_INP
},
201 {"imaxbel", IMAXBEL
, MD_INP
},
205 {"opost", OPOST
, MD_OUT
},
208 {"olcuc", OLCUC
, MD_OUT
},
211 {"onlcr", ONLCR
, MD_OUT
},
214 {"ocrnl", OCRNL
, MD_OUT
},
217 {"onocr", ONOCR
, MD_OUT
},
220 {"onoeot", ONOEOT
, MD_OUT
},
223 {"onlret", ONLRET
, MD_OUT
},
226 {"ofill", OFILL
, MD_OUT
},
229 {"ofdel", OFDEL
, MD_OUT
},
232 {"nldly", NLDLY
, MD_OUT
},
235 {"crdly", CRDLY
, MD_OUT
},
238 {"tabdly", TABDLY
, MD_OUT
},
241 {"xtabs", XTABS
, MD_OUT
},
244 {"bsdly", BSDLY
, MD_OUT
},
247 {"vtdly", VTDLY
, MD_OUT
},
250 {"ffdly", FFDLY
, MD_OUT
},
253 {"pageout", PAGEOUT
, MD_OUT
},
256 {"wrap", WRAP
, MD_OUT
},
260 {"cignore", CIGNORE
, MD_CTL
},
263 {"cbaud", CBAUD
, MD_CTL
},
266 {"cstopb", CSTOPB
, MD_CTL
},
269 {"cread", CREAD
, MD_CTL
},
272 {"parenb", PARENB
, MD_CTL
},
275 {"parodd", PARODD
, MD_CTL
},
278 {"hupcl", HUPCL
, MD_CTL
},
281 {"clocal", CLOCAL
, MD_CTL
},
284 {"loblk", LOBLK
, MD_CTL
},
287 {"cibaud", CIBAUD
, MD_CTL
},
291 {"ccts_oflow", CCTS_OFLOW
, MD_CTL
},
293 {"crtscts", CRTSCTS
, MD_CTL
},
294 #endif /* CCTS_OFLOW */
297 {"crts_iflow", CRTS_IFLOW
, MD_CTL
},
298 #endif /* CRTS_IFLOW */
300 {"cdtrcts", CDTRCTS
, MD_CTL
},
303 {"mdmbuf", MDMBUF
, MD_CTL
},
306 {"rcv1en", RCV1EN
, MD_CTL
},
309 {"xmt1en", XMT1EN
, MD_CTL
},
313 {"isig", ISIG
, MD_LIN
},
316 {"icanon", ICANON
, MD_LIN
},
319 {"xcase", XCASE
, MD_LIN
},
322 {"echo", ECHO
, MD_LIN
},
325 {"echoe", ECHOE
, MD_LIN
},
328 {"echok", ECHOK
, MD_LIN
},
331 {"echonl", ECHONL
, MD_LIN
},
334 {"noflsh", NOFLSH
, MD_LIN
},
337 {"tostop", TOSTOP
, MD_LIN
},
340 {"echoctl", ECHOCTL
, MD_LIN
},
343 {"echoprt", ECHOPRT
, MD_LIN
},
346 {"echoke", ECHOKE
, MD_LIN
},
349 {"defecho", DEFECHO
, MD_LIN
},
352 {"flusho", FLUSHO
, MD_LIN
},
355 {"pendin", PENDIN
, MD_LIN
},
358 {"iexten", IEXTEN
, MD_LIN
},
361 {"nokerninfo", NOKERNINFO
, MD_LIN
},
362 #endif /* NOKERNINFO */
364 {"altwerase", ALTWERASE
, MD_LIN
},
365 #endif /* ALTWERASE */
367 {"extproc", EXTPROC
, MD_LIN
},
371 {"intr", C_SH(C_INTR
), MD_CHAR
},
374 {"quit", C_SH(C_QUIT
), MD_CHAR
},
377 {"erase", C_SH(C_ERASE
), MD_CHAR
},
380 {"kill", C_SH(C_KILL
), MD_CHAR
},
383 {"eof", C_SH(C_EOF
), MD_CHAR
},
386 {"eol", C_SH(C_EOL
), MD_CHAR
},
389 {"eol2", C_SH(C_EOL2
), MD_CHAR
},
392 {"swtch", C_SH(C_SWTCH
), MD_CHAR
},
395 {"dswtch", C_SH(C_DSWTCH
), MD_CHAR
},
398 {"erase2", C_SH(C_ERASE2
), MD_CHAR
},
401 {"start", C_SH(C_START
), MD_CHAR
},
404 {"stop", C_SH(C_STOP
), MD_CHAR
},
407 {"werase", C_SH(C_WERASE
), MD_CHAR
},
410 {"susp", C_SH(C_SUSP
), MD_CHAR
},
413 {"dsusp", C_SH(C_DSUSP
), MD_CHAR
},
415 #if defined(VREPRINT)
416 {"reprint", C_SH(C_REPRINT
), MD_CHAR
},
417 #endif /* VREPRINT */
418 #if defined(VDISCARD)
419 {"discard", C_SH(C_DISCARD
), MD_CHAR
},
420 #endif /* VDISCARD */
422 {"lnext", C_SH(C_LNEXT
), MD_CHAR
},
425 {"status", C_SH(C_STATUS
), MD_CHAR
},
428 {"page", C_SH(C_PAGE
), MD_CHAR
},
431 {"pgoff", C_SH(C_PGOFF
), MD_CHAR
},
434 {"kill2", C_SH(C_KILL2
), MD_CHAR
},
437 {"brk", C_SH(C_BRK
), MD_CHAR
},
440 {"min", C_SH(C_MIN
), MD_CHAR
},
443 {"time", C_SH(C_TIME
), MD_CHAR
},
450 #define tty__gettabs(td) ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1)
451 #define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8)
452 #define tty__cooked_mode(td) ((td)->c_lflag & ICANON)
454 private int tty_getty(EditLine
*, struct termios
*);
455 private int tty_setty(EditLine
*, int, const struct termios
*);
456 private int tty__getcharindex(int);
457 private void tty__getchar(struct termios
*, unsigned char *);
458 private void tty__setchar(struct termios
*, unsigned char *);
459 private speed_t
tty__getspeed(struct termios
*);
460 private int tty_setup(EditLine
*);
465 * Wrapper for tcgetattr to handle EINTR
468 tty_getty(EditLine
*el
, struct termios
*t
)
471 while ((rv
= tcgetattr(el
->el_infd
, t
)) == -1 && errno
== EINTR
)
477 * Wrapper for tcsetattr to handle EINTR
480 tty_setty(EditLine
*el
, int action
, const struct termios
*t
)
483 while ((rv
= tcsetattr(el
->el_infd
, action
, t
)) == -1 && errno
== EINTR
)
489 * Get the tty parameters and initialize the editing state
492 tty_setup(EditLine
*el
)
496 if (el
->el_flags
& EDIT_DISABLED
)
499 if (!isatty(el
->el_outfd
)) {
501 (void) fprintf(el
->el_errfile
,
502 "tty_setup: isatty: %s\n", strerror(errno
));
503 #endif /* DEBUG_TTY */
506 if (tty_getty(el
, &el
->el_tty
.t_ed
) == -1) {
508 (void) fprintf(el
->el_errfile
,
509 "tty_setup: tty_getty: %s\n", strerror(errno
));
510 #endif /* DEBUG_TTY */
513 el
->el_tty
.t_ts
= el
->el_tty
.t_ex
= el
->el_tty
.t_ed
;
515 el
->el_tty
.t_speed
= tty__getspeed(&el
->el_tty
.t_ex
);
516 el
->el_tty
.t_tabs
= tty__gettabs(&el
->el_tty
.t_ex
);
517 el
->el_tty
.t_eight
= tty__geteightbit(&el
->el_tty
.t_ex
);
519 el
->el_tty
.t_ex
.c_iflag
&= ~el
->el_tty
.t_t
[EX_IO
][MD_INP
].t_clrmask
;
520 el
->el_tty
.t_ex
.c_iflag
|= el
->el_tty
.t_t
[EX_IO
][MD_INP
].t_setmask
;
522 el
->el_tty
.t_ex
.c_oflag
&= ~el
->el_tty
.t_t
[EX_IO
][MD_OUT
].t_clrmask
;
523 el
->el_tty
.t_ex
.c_oflag
|= el
->el_tty
.t_t
[EX_IO
][MD_OUT
].t_setmask
;
525 el
->el_tty
.t_ex
.c_cflag
&= ~el
->el_tty
.t_t
[EX_IO
][MD_CTL
].t_clrmask
;
526 el
->el_tty
.t_ex
.c_cflag
|= el
->el_tty
.t_t
[EX_IO
][MD_CTL
].t_setmask
;
528 el
->el_tty
.t_ex
.c_lflag
&= ~el
->el_tty
.t_t
[EX_IO
][MD_LIN
].t_clrmask
;
529 el
->el_tty
.t_ex
.c_lflag
|= el
->el_tty
.t_t
[EX_IO
][MD_LIN
].t_setmask
;
532 * Reset the tty chars to reasonable defaults
533 * If they are disabled, then enable them.
536 if (tty__cooked_mode(&el
->el_tty
.t_ts
)) {
537 tty__getchar(&el
->el_tty
.t_ts
, el
->el_tty
.t_c
[TS_IO
]);
539 * Don't affect CMIN and CTIME for the editor mode
541 for (rst
= 0; rst
< C_NCC
- 2; rst
++)
542 if (el
->el_tty
.t_c
[TS_IO
][rst
] !=
543 el
->el_tty
.t_vdisable
544 && el
->el_tty
.t_c
[ED_IO
][rst
] !=
545 el
->el_tty
.t_vdisable
)
546 el
->el_tty
.t_c
[ED_IO
][rst
] =
547 el
->el_tty
.t_c
[TS_IO
][rst
];
548 for (rst
= 0; rst
< C_NCC
; rst
++)
549 if (el
->el_tty
.t_c
[TS_IO
][rst
] !=
550 el
->el_tty
.t_vdisable
)
551 el
->el_tty
.t_c
[EX_IO
][rst
] =
552 el
->el_tty
.t_c
[TS_IO
][rst
];
554 tty__setchar(&el
->el_tty
.t_ex
, el
->el_tty
.t_c
[EX_IO
]);
555 if (tty_setty(el
, TCSADRAIN
, &el
->el_tty
.t_ex
) == -1) {
557 (void) fprintf(el
->el_errfile
,
558 "tty_setup: tty_setty: %s\n",
560 #endif /* DEBUG_TTY */
565 el
->el_tty
.t_ed
.c_iflag
&= ~el
->el_tty
.t_t
[ED_IO
][MD_INP
].t_clrmask
;
566 el
->el_tty
.t_ed
.c_iflag
|= el
->el_tty
.t_t
[ED_IO
][MD_INP
].t_setmask
;
568 el
->el_tty
.t_ed
.c_oflag
&= ~el
->el_tty
.t_t
[ED_IO
][MD_OUT
].t_clrmask
;
569 el
->el_tty
.t_ed
.c_oflag
|= el
->el_tty
.t_t
[ED_IO
][MD_OUT
].t_setmask
;
571 el
->el_tty
.t_ed
.c_cflag
&= ~el
->el_tty
.t_t
[ED_IO
][MD_CTL
].t_clrmask
;
572 el
->el_tty
.t_ed
.c_cflag
|= el
->el_tty
.t_t
[ED_IO
][MD_CTL
].t_setmask
;
574 el
->el_tty
.t_ed
.c_lflag
&= ~el
->el_tty
.t_t
[ED_IO
][MD_LIN
].t_clrmask
;
575 el
->el_tty
.t_ed
.c_lflag
|= el
->el_tty
.t_t
[ED_IO
][MD_LIN
].t_setmask
;
577 tty__setchar(&el
->el_tty
.t_ed
, el
->el_tty
.t_c
[ED_IO
]);
578 tty_bind_char(el
, 1);
583 tty_init(EditLine
*el
)
586 el
->el_tty
.t_mode
= EX_IO
;
587 el
->el_tty
.t_vdisable
= _POSIX_VDISABLE
;
588 (void) memcpy(el
->el_tty
.t_t
, ttyperm
, sizeof(ttyperm_t
));
589 (void) memcpy(el
->el_tty
.t_c
, ttychar
, sizeof(ttychar_t
));
590 return tty_setup(el
);
595 * Restore the tty to its original settings
599 tty_end(EditLine
*el
__attribute__((__unused__
)))
602 /* XXX: Maybe reset to an initial state? */
610 tty__getspeed(struct termios
*td
)
614 if ((spd
= cfgetispeed(td
)) == 0)
615 spd
= cfgetospeed(td
);
620 * Return the index of the asked char in the c_cc array
623 tty__getcharindex(int i
)
689 #endif /* VREPRINT */
693 #endif /* VDISCARD */
728 * Get the tty characters
731 tty__getchar(struct termios
*td
, unsigned char *s
)
735 s
[C_INTR
] = td
->c_cc
[VINTR
];
738 s
[C_QUIT
] = td
->c_cc
[VQUIT
];
741 s
[C_ERASE
] = td
->c_cc
[VERASE
];
744 s
[C_KILL
] = td
->c_cc
[VKILL
];
747 s
[C_EOF
] = td
->c_cc
[VEOF
];
750 s
[C_EOL
] = td
->c_cc
[VEOL
];
753 s
[C_EOL2
] = td
->c_cc
[VEOL2
];
756 s
[C_SWTCH
] = td
->c_cc
[VSWTCH
];
759 s
[C_DSWTCH
] = td
->c_cc
[VDSWTCH
];
762 s
[C_ERASE2
] = td
->c_cc
[VERASE2
];
765 s
[C_START
] = td
->c_cc
[VSTART
];
768 s
[C_STOP
] = td
->c_cc
[VSTOP
];
771 s
[C_WERASE
] = td
->c_cc
[VWERASE
];
774 s
[C_SUSP
] = td
->c_cc
[VSUSP
];
777 s
[C_DSUSP
] = td
->c_cc
[VDSUSP
];
780 s
[C_REPRINT
] = td
->c_cc
[VREPRINT
];
781 #endif /* VREPRINT */
783 s
[C_DISCARD
] = td
->c_cc
[VDISCARD
];
784 #endif /* VDISCARD */
786 s
[C_LNEXT
] = td
->c_cc
[VLNEXT
];
789 s
[C_STATUS
] = td
->c_cc
[VSTATUS
];
792 s
[C_PAGE
] = td
->c_cc
[VPAGE
];
795 s
[C_PGOFF
] = td
->c_cc
[VPGOFF
];
798 s
[C_KILL2
] = td
->c_cc
[VKILL2
];
801 s
[C_MIN
] = td
->c_cc
[VMIN
];
804 s
[C_TIME
] = td
->c_cc
[VTIME
];
810 * Set the tty characters
813 tty__setchar(struct termios
*td
, unsigned char *s
)
817 td
->c_cc
[VINTR
] = s
[C_INTR
];
820 td
->c_cc
[VQUIT
] = s
[C_QUIT
];
823 td
->c_cc
[VERASE
] = s
[C_ERASE
];
826 td
->c_cc
[VKILL
] = s
[C_KILL
];
829 td
->c_cc
[VEOF
] = s
[C_EOF
];
832 td
->c_cc
[VEOL
] = s
[C_EOL
];
835 td
->c_cc
[VEOL2
] = s
[C_EOL2
];
838 td
->c_cc
[VSWTCH
] = s
[C_SWTCH
];
841 td
->c_cc
[VDSWTCH
] = s
[C_DSWTCH
];
844 td
->c_cc
[VERASE2
] = s
[C_ERASE2
];
847 td
->c_cc
[VSTART
] = s
[C_START
];
850 td
->c_cc
[VSTOP
] = s
[C_STOP
];
853 td
->c_cc
[VWERASE
] = s
[C_WERASE
];
856 td
->c_cc
[VSUSP
] = s
[C_SUSP
];
859 td
->c_cc
[VDSUSP
] = s
[C_DSUSP
];
862 td
->c_cc
[VREPRINT
] = s
[C_REPRINT
];
863 #endif /* VREPRINT */
865 td
->c_cc
[VDISCARD
] = s
[C_DISCARD
];
866 #endif /* VDISCARD */
868 td
->c_cc
[VLNEXT
] = s
[C_LNEXT
];
871 td
->c_cc
[VSTATUS
] = s
[C_STATUS
];
874 td
->c_cc
[VPAGE
] = s
[C_PAGE
];
877 td
->c_cc
[VPGOFF
] = s
[C_PGOFF
];
880 td
->c_cc
[VKILL2
] = s
[C_KILL2
];
883 td
->c_cc
[VMIN
] = s
[C_MIN
];
886 td
->c_cc
[VTIME
] = s
[C_TIME
];
892 * Rebind the editline functions
895 tty_bind_char(EditLine
*el
, int force
)
898 unsigned char *t_n
= el
->el_tty
.t_c
[ED_IO
];
899 unsigned char *t_o
= el
->el_tty
.t_ed
.c_cc
;
902 el_action_t
*map
, *alt
;
903 const el_action_t
*dmap
, *dalt
;
904 new[1] = old
[1] = '\0';
906 map
= el
->el_map
.key
;
907 alt
= el
->el_map
.alt
;
908 if (el
->el_map
.type
== MAP_VI
) {
909 dmap
= el
->el_map
.vii
;
910 dalt
= el
->el_map
.vic
;
912 dmap
= el
->el_map
.emacs
;
916 for (tp
= tty_map
; tp
->nch
!= (Int
)-1; tp
++) {
917 new[0] = t_n
[tp
->nch
];
918 old
[0] = t_o
[tp
->och
];
919 if (new[0] == old
[0] && !force
)
921 /* Put the old default binding back, and set the new binding */
922 keymacro_clear(el
, map
, old
);
923 map
[UC(old
[0])] = dmap
[UC(old
[0])];
924 keymacro_clear(el
, map
, new);
925 /* MAP_VI == 1, MAP_EMACS == 0... */
926 map
[UC(new[0])] = tp
->bind
[el
->el_map
.type
];
928 keymacro_clear(el
, alt
, old
);
929 alt
[UC(old
[0])] = dalt
[UC(old
[0])];
930 keymacro_clear(el
, alt
, new);
931 alt
[UC(new[0])] = tp
->bind
[el
->el_map
.type
+ 1];
938 * Set terminal into 1 character at a time mode.
941 tty_rawmode(EditLine
*el
)
944 if (el
->el_tty
.t_mode
== ED_IO
|| el
->el_tty
.t_mode
== QU_IO
)
947 if (el
->el_flags
& EDIT_DISABLED
)
950 if (tty_getty(el
, &el
->el_tty
.t_ts
) == -1) {
952 (void) fprintf(el
->el_errfile
, "tty_rawmode: tty_getty: %s\n",
954 #endif /* DEBUG_TTY */
958 * We always keep up with the eight bit setting and the speed of the
959 * tty. But we only believe changes that are made to cooked mode!
961 el
->el_tty
.t_eight
= tty__geteightbit(&el
->el_tty
.t_ts
);
962 el
->el_tty
.t_speed
= tty__getspeed(&el
->el_tty
.t_ts
);
964 if (tty__getspeed(&el
->el_tty
.t_ex
) != el
->el_tty
.t_speed
||
965 tty__getspeed(&el
->el_tty
.t_ed
) != el
->el_tty
.t_speed
) {
966 (void) cfsetispeed(&el
->el_tty
.t_ex
, el
->el_tty
.t_speed
);
967 (void) cfsetospeed(&el
->el_tty
.t_ex
, el
->el_tty
.t_speed
);
968 (void) cfsetispeed(&el
->el_tty
.t_ed
, el
->el_tty
.t_speed
);
969 (void) cfsetospeed(&el
->el_tty
.t_ed
, el
->el_tty
.t_speed
);
971 if (tty__cooked_mode(&el
->el_tty
.t_ts
)) {
972 if (el
->el_tty
.t_ts
.c_cflag
!= el
->el_tty
.t_ex
.c_cflag
) {
973 el
->el_tty
.t_ex
.c_cflag
=
974 el
->el_tty
.t_ts
.c_cflag
;
975 el
->el_tty
.t_ex
.c_cflag
&=
976 ~el
->el_tty
.t_t
[EX_IO
][MD_CTL
].t_clrmask
;
977 el
->el_tty
.t_ex
.c_cflag
|=
978 el
->el_tty
.t_t
[EX_IO
][MD_CTL
].t_setmask
;
980 el
->el_tty
.t_ed
.c_cflag
=
981 el
->el_tty
.t_ts
.c_cflag
;
982 el
->el_tty
.t_ed
.c_cflag
&=
983 ~el
->el_tty
.t_t
[ED_IO
][MD_CTL
].t_clrmask
;
984 el
->el_tty
.t_ed
.c_cflag
|=
985 el
->el_tty
.t_t
[ED_IO
][MD_CTL
].t_setmask
;
987 if ((el
->el_tty
.t_ts
.c_lflag
!= el
->el_tty
.t_ex
.c_lflag
) &&
988 (el
->el_tty
.t_ts
.c_lflag
!= el
->el_tty
.t_ed
.c_lflag
)) {
989 el
->el_tty
.t_ex
.c_lflag
=
990 el
->el_tty
.t_ts
.c_lflag
;
991 el
->el_tty
.t_ex
.c_lflag
&=
992 ~el
->el_tty
.t_t
[EX_IO
][MD_LIN
].t_clrmask
;
993 el
->el_tty
.t_ex
.c_lflag
|=
994 el
->el_tty
.t_t
[EX_IO
][MD_LIN
].t_setmask
;
996 el
->el_tty
.t_ed
.c_lflag
=
997 el
->el_tty
.t_ts
.c_lflag
;
998 el
->el_tty
.t_ed
.c_lflag
&=
999 ~el
->el_tty
.t_t
[ED_IO
][MD_LIN
].t_clrmask
;
1000 el
->el_tty
.t_ed
.c_lflag
|=
1001 el
->el_tty
.t_t
[ED_IO
][MD_LIN
].t_setmask
;
1003 if ((el
->el_tty
.t_ts
.c_iflag
!= el
->el_tty
.t_ex
.c_iflag
) &&
1004 (el
->el_tty
.t_ts
.c_iflag
!= el
->el_tty
.t_ed
.c_iflag
)) {
1005 el
->el_tty
.t_ex
.c_iflag
=
1006 el
->el_tty
.t_ts
.c_iflag
;
1007 el
->el_tty
.t_ex
.c_iflag
&=
1008 ~el
->el_tty
.t_t
[EX_IO
][MD_INP
].t_clrmask
;
1009 el
->el_tty
.t_ex
.c_iflag
|=
1010 el
->el_tty
.t_t
[EX_IO
][MD_INP
].t_setmask
;
1012 el
->el_tty
.t_ed
.c_iflag
=
1013 el
->el_tty
.t_ts
.c_iflag
;
1014 el
->el_tty
.t_ed
.c_iflag
&=
1015 ~el
->el_tty
.t_t
[ED_IO
][MD_INP
].t_clrmask
;
1016 el
->el_tty
.t_ed
.c_iflag
|=
1017 el
->el_tty
.t_t
[ED_IO
][MD_INP
].t_setmask
;
1019 if ((el
->el_tty
.t_ts
.c_oflag
!= el
->el_tty
.t_ex
.c_oflag
) &&
1020 (el
->el_tty
.t_ts
.c_oflag
!= el
->el_tty
.t_ed
.c_oflag
)) {
1021 el
->el_tty
.t_ex
.c_oflag
=
1022 el
->el_tty
.t_ts
.c_oflag
;
1023 el
->el_tty
.t_ex
.c_oflag
&=
1024 ~el
->el_tty
.t_t
[EX_IO
][MD_OUT
].t_clrmask
;
1025 el
->el_tty
.t_ex
.c_oflag
|=
1026 el
->el_tty
.t_t
[EX_IO
][MD_OUT
].t_setmask
;
1028 el
->el_tty
.t_ed
.c_oflag
=
1029 el
->el_tty
.t_ts
.c_oflag
;
1030 el
->el_tty
.t_ed
.c_oflag
&=
1031 ~el
->el_tty
.t_t
[ED_IO
][MD_OUT
].t_clrmask
;
1032 el
->el_tty
.t_ed
.c_oflag
|=
1033 el
->el_tty
.t_t
[ED_IO
][MD_OUT
].t_setmask
;
1035 if (tty__gettabs(&el
->el_tty
.t_ex
) == 0)
1036 el
->el_tty
.t_tabs
= 0;
1038 el
->el_tty
.t_tabs
= EL_CAN_TAB
? 1 : 0;
1043 tty__getchar(&el
->el_tty
.t_ts
, el
->el_tty
.t_c
[TS_IO
]);
1045 * Check if the user made any changes.
1046 * If he did, then propagate the changes to the
1047 * edit and execute data structures.
1049 for (i
= 0; i
< C_NCC
; i
++)
1050 if (el
->el_tty
.t_c
[TS_IO
][i
] !=
1051 el
->el_tty
.t_c
[EX_IO
][i
])
1056 * Propagate changes only to the unprotected
1057 * chars that have been modified just now.
1059 for (i
= 0; i
< C_NCC
; i
++) {
1060 if (!((el
->el_tty
.t_t
[ED_IO
][MD_CHAR
].t_setmask
& C_SH(i
)))
1061 && (el
->el_tty
.t_c
[TS_IO
][i
] != el
->el_tty
.t_c
[EX_IO
][i
]))
1062 el
->el_tty
.t_c
[ED_IO
][i
] = el
->el_tty
.t_c
[TS_IO
][i
];
1063 if (el
->el_tty
.t_t
[ED_IO
][MD_CHAR
].t_clrmask
& C_SH(i
))
1064 el
->el_tty
.t_c
[ED_IO
][i
] = el
->el_tty
.t_vdisable
;
1066 tty_bind_char(el
, 0);
1067 tty__setchar(&el
->el_tty
.t_ed
, el
->el_tty
.t_c
[ED_IO
]);
1069 for (i
= 0; i
< C_NCC
; i
++) {
1070 if (!((el
->el_tty
.t_t
[EX_IO
][MD_CHAR
].t_setmask
& C_SH(i
)))
1071 && (el
->el_tty
.t_c
[TS_IO
][i
] != el
->el_tty
.t_c
[EX_IO
][i
]))
1072 el
->el_tty
.t_c
[EX_IO
][i
] = el
->el_tty
.t_c
[TS_IO
][i
];
1073 if (el
->el_tty
.t_t
[EX_IO
][MD_CHAR
].t_clrmask
& C_SH(i
))
1074 el
->el_tty
.t_c
[EX_IO
][i
] = el
->el_tty
.t_vdisable
;
1076 tty__setchar(&el
->el_tty
.t_ex
, el
->el_tty
.t_c
[EX_IO
]);
1080 if (tty_setty(el
, TCSADRAIN
, &el
->el_tty
.t_ed
) == -1) {
1082 (void) fprintf(el
->el_errfile
, "tty_rawmode: tty_setty: %s\n",
1084 #endif /* DEBUG_TTY */
1087 el
->el_tty
.t_mode
= ED_IO
;
1092 /* tty_cookedmode():
1093 * Set the tty back to normal mode
1096 tty_cookedmode(EditLine
*el
)
1097 { /* set tty in normal setup */
1099 if (el
->el_tty
.t_mode
== EX_IO
)
1102 if (el
->el_flags
& EDIT_DISABLED
)
1105 if (tty_setty(el
, TCSADRAIN
, &el
->el_tty
.t_ex
) == -1) {
1107 (void) fprintf(el
->el_errfile
,
1108 "tty_cookedmode: tty_setty: %s\n",
1110 #endif /* DEBUG_TTY */
1113 el
->el_tty
.t_mode
= EX_IO
;
1119 * Turn on quote mode
1122 tty_quotemode(EditLine
*el
)
1124 if (el
->el_tty
.t_mode
== QU_IO
)
1127 el
->el_tty
.t_qu
= el
->el_tty
.t_ed
;
1129 el
->el_tty
.t_qu
.c_iflag
&= ~el
->el_tty
.t_t
[QU_IO
][MD_INP
].t_clrmask
;
1130 el
->el_tty
.t_qu
.c_iflag
|= el
->el_tty
.t_t
[QU_IO
][MD_INP
].t_setmask
;
1132 el
->el_tty
.t_qu
.c_oflag
&= ~el
->el_tty
.t_t
[QU_IO
][MD_OUT
].t_clrmask
;
1133 el
->el_tty
.t_qu
.c_oflag
|= el
->el_tty
.t_t
[QU_IO
][MD_OUT
].t_setmask
;
1135 el
->el_tty
.t_qu
.c_cflag
&= ~el
->el_tty
.t_t
[QU_IO
][MD_CTL
].t_clrmask
;
1136 el
->el_tty
.t_qu
.c_cflag
|= el
->el_tty
.t_t
[QU_IO
][MD_CTL
].t_setmask
;
1138 el
->el_tty
.t_qu
.c_lflag
&= ~el
->el_tty
.t_t
[QU_IO
][MD_LIN
].t_clrmask
;
1139 el
->el_tty
.t_qu
.c_lflag
|= el
->el_tty
.t_t
[QU_IO
][MD_LIN
].t_setmask
;
1141 if (tty_setty(el
, TCSADRAIN
, &el
->el_tty
.t_qu
) == -1) {
1143 (void) fprintf(el
->el_errfile
, "QuoteModeOn: tty_setty: %s\n",
1145 #endif /* DEBUG_TTY */
1148 el
->el_tty
.t_mode
= QU_IO
;
1153 /* tty_noquotemode():
1154 * Turn off quote mode
1157 tty_noquotemode(EditLine
*el
)
1160 if (el
->el_tty
.t_mode
!= QU_IO
)
1162 if (tty_setty(el
, TCSADRAIN
, &el
->el_tty
.t_ed
) == -1) {
1164 (void) fprintf(el
->el_errfile
, "QuoteModeOff: tty_setty: %s\n",
1166 #endif /* DEBUG_TTY */
1169 el
->el_tty
.t_mode
= ED_IO
;
1179 tty_stty(EditLine
*el
, int argc
__attribute__((__unused__
)), const Char
**argv
)
1181 const ttymodes_t
*m
;
1185 char name
[EL_BUFSIZ
];
1186 struct termios
*tios
= &el
->el_tty
.t_ex
;
1191 strncpy(name
, ct_encode_string(*argv
++, &el
->el_scratch
), sizeof(name
));
1192 name
[sizeof(name
) - 1] = '\0';
1194 while (argv
&& *argv
&& argv
[0][0] == '-' && argv
[0][2] == '\0')
1195 switch (argv
[0][1]) {
1202 tios
= &el
->el_tty
.t_ed
;
1207 tios
= &el
->el_tty
.t_ex
;
1212 tios
= &el
->el_tty
.t_ts
;
1216 (void) fprintf(el
->el_errfile
,
1217 "%s: Unknown switch `%c'.\n",
1222 if (!argv
|| !*argv
) {
1224 size_t len
= 0, st
= 0, cu
;
1225 for (m
= ttymodes
; m
->m_name
; m
++) {
1226 if (m
->m_type
!= i
) {
1227 (void) fprintf(el
->el_outfile
, "%s%s",
1228 i
!= -1 ? "\n" : "",
1229 el
->el_tty
.t_t
[z
][m
->m_type
].t_name
);
1232 strlen(el
->el_tty
.t_t
[z
][m
->m_type
].t_name
);
1235 x
= (el
->el_tty
.t_t
[z
][i
].t_setmask
& m
->m_value
)
1238 if (el
->el_tty
.t_t
[z
][i
].t_clrmask
& m
->m_value
)
1244 if (x
!= '\0' || aflag
) {
1246 cu
= strlen(m
->m_name
) + (x
!= '\0') + 1;
1248 if (len
+ cu
>= (size_t)el
->el_terminal
.t_size
.h
) {
1249 (void) fprintf(el
->el_outfile
, "\n%*s",
1256 (void) fprintf(el
->el_outfile
, "%c%s ",
1259 (void) fprintf(el
->el_outfile
, "%s ",
1263 (void) fprintf(el
->el_outfile
, "\n");
1266 while (argv
&& (s
= *argv
++)) {
1279 for (m
= ttymodes
; m
->m_name
; m
++)
1280 if ((p
? strncmp(m
->m_name
, ct_encode_string(d
, &el
->el_scratch
), (size_t)(p
- d
)) :
1281 strcmp(m
->m_name
, ct_encode_string(d
, &el
->el_scratch
))) == 0 &&
1282 (p
== NULL
|| m
->m_type
== MD_CHAR
))
1286 (void) fprintf(el
->el_errfile
,
1287 "%s: Invalid argument `" FSTR
"'.\n", name
, d
);
1291 int c
= ffs((int)m
->m_value
);
1292 int v
= *++p
? parse__escape(&p
) :
1293 el
->el_tty
.t_vdisable
;
1296 c
= tty__getcharindex(c
);
1298 tios
->c_cc
[c
] = (cc_t
)v
;
1303 el
->el_tty
.t_t
[z
][m
->m_type
].t_setmask
|= m
->m_value
;
1304 el
->el_tty
.t_t
[z
][m
->m_type
].t_clrmask
&= ~m
->m_value
;
1307 el
->el_tty
.t_t
[z
][m
->m_type
].t_setmask
&= ~m
->m_value
;
1308 el
->el_tty
.t_t
[z
][m
->m_type
].t_clrmask
|= m
->m_value
;
1311 el
->el_tty
.t_t
[z
][m
->m_type
].t_setmask
&= ~m
->m_value
;
1312 el
->el_tty
.t_t
[z
][m
->m_type
].t_clrmask
&= ~m
->m_value
;
1317 if (el
->el_tty
.t_mode
== z
) {
1318 if (tty_setty(el
, TCSADRAIN
, tios
) == -1) {
1320 (void) fprintf(el
->el_errfile
,
1321 "tty_stty: tty_setty: %s\n", strerror(errno
));
1322 #endif /* DEBUG_TTY */
1333 * DEbugging routine to print the tty characters
1336 tty_printchar(EditLine
*el
, unsigned char *s
)
1341 for (i
= 0; i
< C_NCC
; i
++) {
1342 for (m
= el
->el_tty
.t_t
; m
->m_name
; m
++)
1343 if (m
->m_type
== MD_CHAR
&& C_SH(i
) == m
->m_value
)
1346 (void) fprintf(el
->el_errfile
, "%s ^%c ",
1347 m
->m_name
, s
[i
] + 'A' - 1);
1349 (void) fprintf(el
->el_errfile
, "\n");
1351 (void) fprintf(el
->el_errfile
, "\n");