1 /* $NetBSD: tty.c,v 1.16 2002/03/18 16:01:01 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.16 2002/03/18 16:01:01 christos Exp $");
46 #endif /* not lint && not SCCSID */
49 * tty.c: tty interface stuff
54 typedef struct ttymodes_t
{
60 typedef struct ttymap_t
{
61 int nch
, och
; /* Internal and termio rep of chars */
62 el_action_t bind
[3]; /* emacs, vi, and vi-cmd */
66 private const ttyperm_t ttyperm
= {
68 {"iflag:", ICRNL
, (INLCR
| IGNCR
)},
69 {"oflag:", (OPOST
| ONLCR
), ONLRET
},
71 {"lflag:", (ISIG
| ICANON
| ECHO
| ECHOE
| ECHOCTL
| IEXTEN
),
72 (NOFLSH
| ECHONL
| EXTPROC
| FLUSHO
)},
76 {"iflag:", (INLCR
| ICRNL
), IGNCR
},
77 {"oflag:", (OPOST
| ONLCR
), ONLRET
},
80 (NOFLSH
| ICANON
| ECHO
| ECHOK
| ECHONL
| EXTPROC
| IEXTEN
| FLUSHO
)},
81 {"chars:", (C_SH(C_MIN
) | C_SH(C_TIME
) | C_SH(C_SWTCH
) | C_SH(C_DSWTCH
) |
82 C_SH(C_SUSP
) | C_SH(C_DSUSP
) | C_SH(C_EOL
) | C_SH(C_DISCARD
) |
83 C_SH(C_PGOFF
) | C_SH(C_PAGE
) | C_SH(C_STATUS
)), 0}
86 {"iflag:", 0, IXON
| IXOFF
| INLCR
| ICRNL
},
89 {"lflag:", 0, ISIG
| IEXTEN
},
94 private const ttychar_t ttychar
= {
96 CINTR
, CQUIT
, CERASE
, CKILL
,
97 CEOF
, CEOL
, CEOL2
, CSWTCH
,
98 CDSWTCH
, CERASE2
, CSTART
, CSTOP
,
99 CWERASE
, CSUSP
, CDSUSP
, CREPRINT
,
100 CDISCARD
, CLNEXT
, CSTATUS
, CPAGE
,
101 CPGOFF
, CKILL2
, CBRK
, CMIN
,
105 CINTR
, CQUIT
, CERASE
, CKILL
,
106 _POSIX_VDISABLE
, _POSIX_VDISABLE
, _POSIX_VDISABLE
, _POSIX_VDISABLE
,
107 _POSIX_VDISABLE
, CERASE2
, CSTART
, CSTOP
,
108 _POSIX_VDISABLE
, CSUSP
, _POSIX_VDISABLE
, _POSIX_VDISABLE
,
109 CDISCARD
, _POSIX_VDISABLE
, _POSIX_VDISABLE
, _POSIX_VDISABLE
,
110 _POSIX_VDISABLE
, _POSIX_VDISABLE
, _POSIX_VDISABLE
, 1,
124 private const ttymap_t tty_map
[] = {
127 {ED_DELETE_PREV_CHAR
, VI_DELETE_PREV_CHAR
, ED_PREV_CHAR
}},
131 {ED_DELETE_PREV_CHAR
, VI_DELETE_PREV_CHAR
, ED_PREV_CHAR
}},
135 {EM_KILL_LINE
, VI_KILL_LINE_PREV
, ED_UNASSIGNED
}},
139 {EM_KILL_LINE
, VI_KILL_LINE_PREV
, ED_UNASSIGNED
}},
143 {EM_DELETE_OR_LIST
, VI_LIST_OR_EOF
, ED_UNASSIGNED
}},
147 {ED_DELETE_PREV_WORD
, ED_DELETE_PREV_WORD
, ED_PREV_WORD
}},
150 {C_REPRINT
, VREPRINT
,
151 {ED_REDISPLAY
, ED_INSERT
, ED_REDISPLAY
}},
152 #endif /* VREPRINT */
155 {ED_QUOTED_INSERT
, ED_QUOTED_INSERT
, ED_UNASSIGNED
}},
158 {ED_UNASSIGNED
, ED_UNASSIGNED
, ED_UNASSIGNED
}}
161 private const ttymodes_t ttymodes
[] = {
163 {"ignbrk", IGNBRK
, MD_INP
},
166 {"brkint", BRKINT
, MD_INP
},
169 {"ignpar", IGNPAR
, MD_INP
},
172 {"parmrk", PARMRK
, MD_INP
},
175 {"inpck", INPCK
, MD_INP
},
178 {"istrip", ISTRIP
, MD_INP
},
181 {"inlcr", INLCR
, MD_INP
},
184 {"igncr", IGNCR
, MD_INP
},
187 {"icrnl", ICRNL
, MD_INP
},
190 {"iuclc", IUCLC
, MD_INP
},
193 {"ixon", IXON
, MD_INP
},
196 {"ixany", IXANY
, MD_INP
},
199 {"ixoff", IXOFF
, MD_INP
},
202 {"imaxbel", IMAXBEL
, MD_INP
},
206 {"opost", OPOST
, MD_OUT
},
209 {"olcuc", OLCUC
, MD_OUT
},
212 {"onlcr", ONLCR
, MD_OUT
},
215 {"ocrnl", OCRNL
, MD_OUT
},
218 {"onocr", ONOCR
, MD_OUT
},
221 {"onoeot", ONOEOT
, MD_OUT
},
224 {"onlret", ONLRET
, MD_OUT
},
227 {"ofill", OFILL
, MD_OUT
},
230 {"ofdel", OFDEL
, MD_OUT
},
233 {"nldly", NLDLY
, MD_OUT
},
236 {"crdly", CRDLY
, MD_OUT
},
239 {"tabdly", TABDLY
, MD_OUT
},
242 {"xtabs", XTABS
, MD_OUT
},
245 {"bsdly", BSDLY
, MD_OUT
},
248 {"vtdly", VTDLY
, MD_OUT
},
251 {"ffdly", FFDLY
, MD_OUT
},
254 {"pageout", PAGEOUT
, MD_OUT
},
257 {"wrap", WRAP
, MD_OUT
},
261 {"cignore", CIGNORE
, MD_CTL
},
264 {"cbaud", CBAUD
, MD_CTL
},
267 {"cstopb", CSTOPB
, MD_CTL
},
270 {"cread", CREAD
, MD_CTL
},
273 {"parenb", PARENB
, MD_CTL
},
276 {"parodd", PARODD
, MD_CTL
},
279 {"hupcl", HUPCL
, MD_CTL
},
282 {"clocal", CLOCAL
, MD_CTL
},
285 {"loblk", LOBLK
, MD_CTL
},
288 {"cibaud", CIBAUD
, MD_CTL
},
292 {"ccts_oflow", CCTS_OFLOW
, MD_CTL
},
294 {"crtscts", CRTSCTS
, MD_CTL
},
295 #endif /* CCTS_OFLOW */
298 {"crts_iflow", CRTS_IFLOW
, MD_CTL
},
299 #endif /* CRTS_IFLOW */
301 {"cdtrcts", CDTRCTS
, MD_CTL
},
304 {"mdmbuf", MDMBUF
, MD_CTL
},
307 {"rcv1en", RCV1EN
, MD_CTL
},
310 {"xmt1en", XMT1EN
, MD_CTL
},
314 {"isig", ISIG
, MD_LIN
},
317 {"icanon", ICANON
, MD_LIN
},
320 {"xcase", XCASE
, MD_LIN
},
323 {"echo", ECHO
, MD_LIN
},
326 {"echoe", ECHOE
, MD_LIN
},
329 {"echok", ECHOK
, MD_LIN
},
332 {"echonl", ECHONL
, MD_LIN
},
335 {"noflsh", NOFLSH
, MD_LIN
},
338 {"tostop", TOSTOP
, MD_LIN
},
341 {"echoctl", ECHOCTL
, MD_LIN
},
344 {"echoprt", ECHOPRT
, MD_LIN
},
347 {"echoke", ECHOKE
, MD_LIN
},
350 {"defecho", DEFECHO
, MD_LIN
},
353 {"flusho", FLUSHO
, MD_LIN
},
356 {"pendin", PENDIN
, MD_LIN
},
359 {"iexten", IEXTEN
, MD_LIN
},
362 {"nokerninfo", NOKERNINFO
, MD_LIN
},
363 #endif /* NOKERNINFO */
365 {"altwerase", ALTWERASE
, MD_LIN
},
366 #endif /* ALTWERASE */
368 {"extproc", EXTPROC
, MD_LIN
},
372 {"intr", C_SH(C_INTR
), MD_CHAR
},
375 {"quit", C_SH(C_QUIT
), MD_CHAR
},
378 {"erase", C_SH(C_ERASE
), MD_CHAR
},
381 {"kill", C_SH(C_KILL
), MD_CHAR
},
384 {"eof", C_SH(C_EOF
), MD_CHAR
},
387 {"eol", C_SH(C_EOL
), MD_CHAR
},
390 {"eol2", C_SH(C_EOL2
), MD_CHAR
},
393 {"swtch", C_SH(C_SWTCH
), MD_CHAR
},
396 {"dswtch", C_SH(C_DSWTCH
), MD_CHAR
},
399 {"erase2", C_SH(C_ERASE2
), MD_CHAR
},
402 {"start", C_SH(C_START
), MD_CHAR
},
405 {"stop", C_SH(C_STOP
), MD_CHAR
},
408 {"werase", C_SH(C_WERASE
), MD_CHAR
},
411 {"susp", C_SH(C_SUSP
), MD_CHAR
},
414 {"dsusp", C_SH(C_DSUSP
), MD_CHAR
},
416 #if defined(VREPRINT)
417 {"reprint", C_SH(C_REPRINT
), MD_CHAR
},
418 #endif /* VREPRINT */
419 #if defined(VDISCARD)
420 {"discard", C_SH(C_DISCARD
), MD_CHAR
},
421 #endif /* VDISCARD */
423 {"lnext", C_SH(C_LNEXT
), MD_CHAR
},
426 {"status", C_SH(C_STATUS
), MD_CHAR
},
429 {"page", C_SH(C_PAGE
), MD_CHAR
},
432 {"pgoff", C_SH(C_PGOFF
), MD_CHAR
},
435 {"kill2", C_SH(C_KILL2
), MD_CHAR
},
438 {"brk", C_SH(C_BRK
), MD_CHAR
},
441 {"min", C_SH(C_MIN
), MD_CHAR
},
444 {"time", C_SH(C_TIME
), MD_CHAR
},
451 #define tty_getty(el, td) tcgetattr((el)->el_infd, (td))
452 #define tty_setty(el, td) tcsetattr((el)->el_infd, TCSADRAIN, (td))
454 #define tty__gettabs(td) ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1)
455 #define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8)
456 #define tty__cooked_mode(td) ((td)->c_lflag & ICANON)
458 private void tty__getchar(struct termios
*, unsigned char *);
459 private void tty__setchar(struct termios
*, unsigned char *);
460 private speed_t
tty__getspeed(struct termios
*);
461 private int tty_setup(EditLine
*);
467 * Get the tty parameters and initialize the editing state
470 tty_setup(EditLine
*el
)
474 if (el
->el_flags
& EDIT_DISABLED
)
477 if (tty_getty(el
, &el
->el_tty
.t_ed
) == -1) {
479 (void) fprintf(el
->el_errfile
,
480 "tty_setup: tty_getty: %s\n", strerror(errno
));
481 #endif /* DEBUG_TTY */
484 el
->el_tty
.t_ts
= el
->el_tty
.t_ex
= el
->el_tty
.t_ed
;
486 el
->el_tty
.t_speed
= tty__getspeed(&el
->el_tty
.t_ex
);
487 el
->el_tty
.t_tabs
= tty__gettabs(&el
->el_tty
.t_ex
);
488 el
->el_tty
.t_eight
= tty__geteightbit(&el
->el_tty
.t_ex
);
490 el
->el_tty
.t_ex
.c_iflag
&= ~el
->el_tty
.t_t
[EX_IO
][MD_INP
].t_clrmask
;
491 el
->el_tty
.t_ex
.c_iflag
|= el
->el_tty
.t_t
[EX_IO
][MD_INP
].t_setmask
;
493 el
->el_tty
.t_ex
.c_oflag
&= ~el
->el_tty
.t_t
[EX_IO
][MD_OUT
].t_clrmask
;
494 el
->el_tty
.t_ex
.c_oflag
|= el
->el_tty
.t_t
[EX_IO
][MD_OUT
].t_setmask
;
496 el
->el_tty
.t_ex
.c_cflag
&= ~el
->el_tty
.t_t
[EX_IO
][MD_CTL
].t_clrmask
;
497 el
->el_tty
.t_ex
.c_cflag
|= el
->el_tty
.t_t
[EX_IO
][MD_CTL
].t_setmask
;
499 el
->el_tty
.t_ex
.c_lflag
&= ~el
->el_tty
.t_t
[EX_IO
][MD_LIN
].t_clrmask
;
500 el
->el_tty
.t_ex
.c_lflag
|= el
->el_tty
.t_t
[EX_IO
][MD_LIN
].t_setmask
;
503 * Reset the tty chars to reasonable defaults
504 * If they are disabled, then enable them.
507 if (tty__cooked_mode(&el
->el_tty
.t_ts
)) {
508 tty__getchar(&el
->el_tty
.t_ts
, el
->el_tty
.t_c
[TS_IO
]);
510 * Don't affect CMIN and CTIME for the editor mode
512 for (rst
= 0; rst
< C_NCC
- 2; rst
++)
513 if (el
->el_tty
.t_c
[TS_IO
][rst
] !=
514 el
->el_tty
.t_vdisable
515 && el
->el_tty
.t_c
[ED_IO
][rst
] !=
516 el
->el_tty
.t_vdisable
)
517 el
->el_tty
.t_c
[ED_IO
][rst
] =
518 el
->el_tty
.t_c
[TS_IO
][rst
];
519 for (rst
= 0; rst
< C_NCC
; rst
++)
520 if (el
->el_tty
.t_c
[TS_IO
][rst
] !=
521 el
->el_tty
.t_vdisable
)
522 el
->el_tty
.t_c
[EX_IO
][rst
] =
523 el
->el_tty
.t_c
[TS_IO
][rst
];
525 tty__setchar(&el
->el_tty
.t_ex
, el
->el_tty
.t_c
[EX_IO
]);
526 if (tty_setty(el
, &el
->el_tty
.t_ex
) == -1) {
528 (void) fprintf(el
->el_errfile
,
529 "tty_setup: tty_setty: %s\n",
531 #endif /* DEBUG_TTY */
535 tty__setchar(&el
->el_tty
.t_ex
, el
->el_tty
.t_c
[EX_IO
]);
537 el
->el_tty
.t_ed
.c_iflag
&= ~el
->el_tty
.t_t
[ED_IO
][MD_INP
].t_clrmask
;
538 el
->el_tty
.t_ed
.c_iflag
|= el
->el_tty
.t_t
[ED_IO
][MD_INP
].t_setmask
;
540 el
->el_tty
.t_ed
.c_oflag
&= ~el
->el_tty
.t_t
[ED_IO
][MD_OUT
].t_clrmask
;
541 el
->el_tty
.t_ed
.c_oflag
|= el
->el_tty
.t_t
[ED_IO
][MD_OUT
].t_setmask
;
543 el
->el_tty
.t_ed
.c_cflag
&= ~el
->el_tty
.t_t
[ED_IO
][MD_CTL
].t_clrmask
;
544 el
->el_tty
.t_ed
.c_cflag
|= el
->el_tty
.t_t
[ED_IO
][MD_CTL
].t_setmask
;
546 el
->el_tty
.t_ed
.c_lflag
&= ~el
->el_tty
.t_t
[ED_IO
][MD_LIN
].t_clrmask
;
547 el
->el_tty
.t_ed
.c_lflag
|= el
->el_tty
.t_t
[ED_IO
][MD_LIN
].t_setmask
;
549 tty__setchar(&el
->el_tty
.t_ed
, el
->el_tty
.t_c
[ED_IO
]);
550 tty_bind_char(el
, 1);
555 tty_init(EditLine
*el
)
558 el
->el_tty
.t_mode
= EX_IO
;
559 el
->el_tty
.t_vdisable
= _POSIX_VDISABLE
;
560 (void) memcpy(el
->el_tty
.t_t
, ttyperm
, sizeof(ttyperm_t
));
561 (void) memcpy(el
->el_tty
.t_c
, ttychar
, sizeof(ttychar_t
));
562 return (tty_setup(el
));
567 * Restore the tty to its original settings
571 tty_end(EditLine
*el
)
574 /* XXX: Maybe reset to an initial state? */
582 tty__getspeed(struct termios
*td
)
586 if ((spd
= cfgetispeed(td
)) == 0)
587 spd
= cfgetospeed(td
);
593 * Get the tty characters
596 tty__getchar(struct termios
*td
, unsigned char *s
)
600 s
[C_INTR
] = td
->c_cc
[VINTR
];
603 s
[C_QUIT
] = td
->c_cc
[VQUIT
];
606 s
[C_ERASE
] = td
->c_cc
[VERASE
];
609 s
[C_KILL
] = td
->c_cc
[VKILL
];
612 s
[C_EOF
] = td
->c_cc
[VEOF
];
615 s
[C_EOL
] = td
->c_cc
[VEOL
];
618 s
[C_EOL2
] = td
->c_cc
[VEOL2
];
621 s
[C_SWTCH
] = td
->c_cc
[VSWTCH
];
624 s
[C_DSWTCH
] = td
->c_cc
[VDSWTCH
];
627 s
[C_ERASE2
] = td
->c_cc
[VERASE2
];
630 s
[C_START
] = td
->c_cc
[VSTART
];
633 s
[C_STOP
] = td
->c_cc
[VSTOP
];
636 s
[C_WERASE
] = td
->c_cc
[VWERASE
];
639 s
[C_SUSP
] = td
->c_cc
[VSUSP
];
642 s
[C_DSUSP
] = td
->c_cc
[VDSUSP
];
645 s
[C_REPRINT
] = td
->c_cc
[VREPRINT
];
646 #endif /* VREPRINT */
648 s
[C_DISCARD
] = td
->c_cc
[VDISCARD
];
649 #endif /* VDISCARD */
651 s
[C_LNEXT
] = td
->c_cc
[VLNEXT
];
654 s
[C_STATUS
] = td
->c_cc
[VSTATUS
];
657 s
[C_PAGE
] = td
->c_cc
[VPAGE
];
660 s
[C_PGOFF
] = td
->c_cc
[VPGOFF
];
663 s
[C_KILL2
] = td
->c_cc
[VKILL2
];
666 s
[C_MIN
] = td
->c_cc
[VMIN
];
669 s
[C_TIME
] = td
->c_cc
[VTIME
];
675 * Set the tty characters
678 tty__setchar(struct termios
*td
, unsigned char *s
)
682 td
->c_cc
[VINTR
] = s
[C_INTR
];
685 td
->c_cc
[VQUIT
] = s
[C_QUIT
];
688 td
->c_cc
[VERASE
] = s
[C_ERASE
];
691 td
->c_cc
[VKILL
] = s
[C_KILL
];
694 td
->c_cc
[VEOF
] = s
[C_EOF
];
697 td
->c_cc
[VEOL
] = s
[C_EOL
];
700 td
->c_cc
[VEOL2
] = s
[C_EOL2
];
703 td
->c_cc
[VSWTCH
] = s
[C_SWTCH
];
706 td
->c_cc
[VDSWTCH
] = s
[C_DSWTCH
];
709 td
->c_cc
[VERASE2
] = s
[C_ERASE2
];
712 td
->c_cc
[VSTART
] = s
[C_START
];
715 td
->c_cc
[VSTOP
] = s
[C_STOP
];
718 td
->c_cc
[VWERASE
] = s
[C_WERASE
];
721 td
->c_cc
[VSUSP
] = s
[C_SUSP
];
724 td
->c_cc
[VDSUSP
] = s
[C_DSUSP
];
727 td
->c_cc
[VREPRINT
] = s
[C_REPRINT
];
728 #endif /* VREPRINT */
730 td
->c_cc
[VDISCARD
] = s
[C_DISCARD
];
731 #endif /* VDISCARD */
733 td
->c_cc
[VLNEXT
] = s
[C_LNEXT
];
736 td
->c_cc
[VSTATUS
] = s
[C_STATUS
];
739 td
->c_cc
[VPAGE
] = s
[C_PAGE
];
742 td
->c_cc
[VPGOFF
] = s
[C_PGOFF
];
745 td
->c_cc
[VKILL2
] = s
[C_KILL2
];
748 td
->c_cc
[VMIN
] = s
[C_MIN
];
751 td
->c_cc
[VTIME
] = s
[C_TIME
];
757 * Rebind the editline functions
760 tty_bind_char(EditLine
*el
, int force
)
763 unsigned char *t_n
= el
->el_tty
.t_c
[ED_IO
];
764 unsigned char *t_o
= el
->el_tty
.t_ed
.c_cc
;
765 unsigned char new[2], old
[2];
767 el_action_t
*map
, *alt
;
768 const el_action_t
*dmap
, *dalt
;
769 new[1] = old
[1] = '\0';
771 map
= el
->el_map
.key
;
772 alt
= el
->el_map
.alt
;
773 if (el
->el_map
.type
== MAP_VI
) {
774 dmap
= el
->el_map
.vii
;
775 dalt
= el
->el_map
.vic
;
777 dmap
= el
->el_map
.emacs
;
781 for (tp
= tty_map
; tp
->nch
!= -1; tp
++) {
782 new[0] = t_n
[tp
->nch
];
783 old
[0] = t_o
[tp
->och
];
784 if (new[0] == old
[0] && !force
)
786 /* Put the old default binding back, and set the new binding */
787 key_clear(el
, map
, (char *)old
);
788 map
[old
[0]] = dmap
[old
[0]];
789 key_clear(el
, map
, (char *)new);
790 /* MAP_VI == 1, MAP_EMACS == 0... */
791 map
[new[0]] = tp
->bind
[el
->el_map
.type
];
793 key_clear(el
, alt
, (char *)old
);
794 alt
[old
[0]] = dalt
[old
[0]];
795 key_clear(el
, alt
, (char *)new);
796 alt
[new[0]] = tp
->bind
[el
->el_map
.type
+ 1];
803 * Set terminal into 1 character at a time mode.
806 tty_rawmode(EditLine
*el
)
809 if (el
->el_tty
.t_mode
== ED_IO
|| el
->el_tty
.t_mode
== QU_IO
)
812 if (el
->el_flags
& EDIT_DISABLED
)
815 if (tty_getty(el
, &el
->el_tty
.t_ts
) == -1) {
817 (void) fprintf(el
->el_errfile
, "tty_rawmode: tty_getty: %s\n",
819 #endif /* DEBUG_TTY */
823 * We always keep up with the eight bit setting and the speed of the
824 * tty. But only we only believe changes that are made to cooked mode!
826 el
->el_tty
.t_eight
= tty__geteightbit(&el
->el_tty
.t_ts
);
827 el
->el_tty
.t_speed
= tty__getspeed(&el
->el_tty
.t_ts
);
829 if (tty__getspeed(&el
->el_tty
.t_ex
) != el
->el_tty
.t_speed
||
830 tty__getspeed(&el
->el_tty
.t_ed
) != el
->el_tty
.t_speed
) {
831 (void) cfsetispeed(&el
->el_tty
.t_ex
, el
->el_tty
.t_speed
);
832 (void) cfsetospeed(&el
->el_tty
.t_ex
, el
->el_tty
.t_speed
);
833 (void) cfsetispeed(&el
->el_tty
.t_ed
, el
->el_tty
.t_speed
);
834 (void) cfsetospeed(&el
->el_tty
.t_ed
, el
->el_tty
.t_speed
);
836 if (tty__cooked_mode(&el
->el_tty
.t_ts
)) {
837 if (el
->el_tty
.t_ts
.c_cflag
!= el
->el_tty
.t_ex
.c_cflag
) {
838 el
->el_tty
.t_ex
.c_cflag
=
839 el
->el_tty
.t_ts
.c_cflag
;
840 el
->el_tty
.t_ex
.c_cflag
&=
841 ~el
->el_tty
.t_t
[EX_IO
][MD_CTL
].t_clrmask
;
842 el
->el_tty
.t_ex
.c_cflag
|=
843 el
->el_tty
.t_t
[EX_IO
][MD_CTL
].t_setmask
;
845 el
->el_tty
.t_ed
.c_cflag
=
846 el
->el_tty
.t_ts
.c_cflag
;
847 el
->el_tty
.t_ed
.c_cflag
&=
848 ~el
->el_tty
.t_t
[ED_IO
][MD_CTL
].t_clrmask
;
849 el
->el_tty
.t_ed
.c_cflag
|=
850 el
->el_tty
.t_t
[ED_IO
][MD_CTL
].t_setmask
;
852 if ((el
->el_tty
.t_ts
.c_lflag
!= el
->el_tty
.t_ex
.c_lflag
) &&
853 (el
->el_tty
.t_ts
.c_lflag
!= el
->el_tty
.t_ed
.c_lflag
)) {
854 el
->el_tty
.t_ex
.c_lflag
=
855 el
->el_tty
.t_ts
.c_lflag
;
856 el
->el_tty
.t_ex
.c_lflag
&=
857 ~el
->el_tty
.t_t
[EX_IO
][MD_LIN
].t_clrmask
;
858 el
->el_tty
.t_ex
.c_lflag
|=
859 el
->el_tty
.t_t
[EX_IO
][MD_LIN
].t_setmask
;
861 el
->el_tty
.t_ed
.c_lflag
=
862 el
->el_tty
.t_ts
.c_lflag
;
863 el
->el_tty
.t_ed
.c_lflag
&=
864 ~el
->el_tty
.t_t
[ED_IO
][MD_LIN
].t_clrmask
;
865 el
->el_tty
.t_ed
.c_lflag
|=
866 el
->el_tty
.t_t
[ED_IO
][MD_LIN
].t_setmask
;
868 if ((el
->el_tty
.t_ts
.c_iflag
!= el
->el_tty
.t_ex
.c_iflag
) &&
869 (el
->el_tty
.t_ts
.c_iflag
!= el
->el_tty
.t_ed
.c_iflag
)) {
870 el
->el_tty
.t_ex
.c_iflag
=
871 el
->el_tty
.t_ts
.c_iflag
;
872 el
->el_tty
.t_ex
.c_iflag
&=
873 ~el
->el_tty
.t_t
[EX_IO
][MD_INP
].t_clrmask
;
874 el
->el_tty
.t_ex
.c_iflag
|=
875 el
->el_tty
.t_t
[EX_IO
][MD_INP
].t_setmask
;
877 el
->el_tty
.t_ed
.c_iflag
=
878 el
->el_tty
.t_ts
.c_iflag
;
879 el
->el_tty
.t_ed
.c_iflag
&=
880 ~el
->el_tty
.t_t
[ED_IO
][MD_INP
].t_clrmask
;
881 el
->el_tty
.t_ed
.c_iflag
|=
882 el
->el_tty
.t_t
[ED_IO
][MD_INP
].t_setmask
;
884 if ((el
->el_tty
.t_ts
.c_oflag
!= el
->el_tty
.t_ex
.c_oflag
) &&
885 (el
->el_tty
.t_ts
.c_oflag
!= el
->el_tty
.t_ed
.c_oflag
)) {
886 el
->el_tty
.t_ex
.c_oflag
=
887 el
->el_tty
.t_ts
.c_oflag
;
888 el
->el_tty
.t_ex
.c_oflag
&=
889 ~el
->el_tty
.t_t
[EX_IO
][MD_OUT
].t_clrmask
;
890 el
->el_tty
.t_ex
.c_oflag
|=
891 el
->el_tty
.t_t
[EX_IO
][MD_OUT
].t_setmask
;
893 el
->el_tty
.t_ed
.c_oflag
=
894 el
->el_tty
.t_ts
.c_oflag
;
895 el
->el_tty
.t_ed
.c_oflag
&=
896 ~el
->el_tty
.t_t
[ED_IO
][MD_OUT
].t_clrmask
;
897 el
->el_tty
.t_ed
.c_oflag
|=
898 el
->el_tty
.t_t
[ED_IO
][MD_OUT
].t_setmask
;
900 if (tty__gettabs(&el
->el_tty
.t_ex
) == 0)
901 el
->el_tty
.t_tabs
= 0;
903 el
->el_tty
.t_tabs
= EL_CAN_TAB
? 1 : 0;
908 tty__getchar(&el
->el_tty
.t_ts
, el
->el_tty
.t_c
[TS_IO
]);
910 * Check if the user made any changes.
911 * If he did, then propagate the changes to the
912 * edit and execute data structures.
914 for (i
= 0; i
< C_NCC
; i
++)
915 if (el
->el_tty
.t_c
[TS_IO
][i
] !=
916 el
->el_tty
.t_c
[EX_IO
][i
])
921 * Propagate changes only to the unprotected
922 * chars that have been modified just now.
924 for (i
= 0; i
< C_NCC
; i
++) {
925 if (!((el
->el_tty
.t_t
[ED_IO
][MD_CHAR
].t_setmask
& C_SH(i
)))
926 && (el
->el_tty
.t_c
[TS_IO
][i
] != el
->el_tty
.t_c
[EX_IO
][i
]))
927 el
->el_tty
.t_c
[ED_IO
][i
] = el
->el_tty
.t_c
[TS_IO
][i
];
928 if (el
->el_tty
.t_t
[ED_IO
][MD_CHAR
].t_clrmask
& C_SH(i
))
929 el
->el_tty
.t_c
[ED_IO
][i
] = el
->el_tty
.t_vdisable
;
931 tty_bind_char(el
, 0);
932 tty__setchar(&el
->el_tty
.t_ed
, el
->el_tty
.t_c
[ED_IO
]);
934 for (i
= 0; i
< C_NCC
; i
++) {
935 if (!((el
->el_tty
.t_t
[EX_IO
][MD_CHAR
].t_setmask
& C_SH(i
)))
936 && (el
->el_tty
.t_c
[TS_IO
][i
] != el
->el_tty
.t_c
[EX_IO
][i
]))
937 el
->el_tty
.t_c
[EX_IO
][i
] = el
->el_tty
.t_c
[TS_IO
][i
];
938 if (el
->el_tty
.t_t
[EX_IO
][MD_CHAR
].t_clrmask
& C_SH(i
))
939 el
->el_tty
.t_c
[EX_IO
][i
] = el
->el_tty
.t_vdisable
;
941 tty__setchar(&el
->el_tty
.t_ex
, el
->el_tty
.t_c
[EX_IO
]);
945 if (tty_setty(el
, &el
->el_tty
.t_ed
) == -1) {
947 (void) fprintf(el
->el_errfile
, "tty_rawmode: tty_setty: %s\n",
949 #endif /* DEBUG_TTY */
952 el
->el_tty
.t_mode
= ED_IO
;
958 * Set the tty back to normal mode
961 tty_cookedmode(EditLine
*el
)
962 { /* set tty in normal setup */
964 if (el
->el_tty
.t_mode
== EX_IO
)
967 if (el
->el_flags
& EDIT_DISABLED
)
970 if (tty_setty(el
, &el
->el_tty
.t_ex
) == -1) {
972 (void) fprintf(el
->el_errfile
,
973 "tty_cookedmode: tty_setty: %s\n",
975 #endif /* DEBUG_TTY */
978 el
->el_tty
.t_mode
= EX_IO
;
987 tty_quotemode(EditLine
*el
)
989 if (el
->el_tty
.t_mode
== QU_IO
)
992 el
->el_tty
.t_qu
= el
->el_tty
.t_ed
;
994 el
->el_tty
.t_qu
.c_iflag
&= ~el
->el_tty
.t_t
[QU_IO
][MD_INP
].t_clrmask
;
995 el
->el_tty
.t_qu
.c_iflag
|= el
->el_tty
.t_t
[QU_IO
][MD_INP
].t_setmask
;
997 el
->el_tty
.t_qu
.c_oflag
&= ~el
->el_tty
.t_t
[QU_IO
][MD_OUT
].t_clrmask
;
998 el
->el_tty
.t_qu
.c_oflag
|= el
->el_tty
.t_t
[QU_IO
][MD_OUT
].t_setmask
;
1000 el
->el_tty
.t_qu
.c_cflag
&= ~el
->el_tty
.t_t
[QU_IO
][MD_CTL
].t_clrmask
;
1001 el
->el_tty
.t_qu
.c_cflag
|= el
->el_tty
.t_t
[QU_IO
][MD_CTL
].t_setmask
;
1003 el
->el_tty
.t_qu
.c_lflag
&= ~el
->el_tty
.t_t
[QU_IO
][MD_LIN
].t_clrmask
;
1004 el
->el_tty
.t_qu
.c_lflag
|= el
->el_tty
.t_t
[QU_IO
][MD_LIN
].t_setmask
;
1006 if (tty_setty(el
, &el
->el_tty
.t_qu
) == -1) {
1008 (void) fprintf(el
->el_errfile
, "QuoteModeOn: tty_setty: %s\n",
1010 #endif /* DEBUG_TTY */
1013 el
->el_tty
.t_mode
= QU_IO
;
1018 /* tty_noquotemode():
1019 * Turn off quote mode
1022 tty_noquotemode(EditLine
*el
)
1025 if (el
->el_tty
.t_mode
!= QU_IO
)
1027 if (tty_setty(el
, &el
->el_tty
.t_ed
) == -1) {
1029 (void) fprintf(el
->el_errfile
, "QuoteModeOff: tty_setty: %s\n",
1031 #endif /* DEBUG_TTY */
1034 el
->el_tty
.t_mode
= ED_IO
;
1044 tty_stty(EditLine
*el
, int argc
, const char **argv
)
1046 const ttymodes_t
*m
;
1057 while (argv
&& *argv
&& argv
[0][0] == '-' && argv
[0][2] == '\0')
1058 switch (argv
[0][1]) {
1076 (void) fprintf(el
->el_errfile
,
1077 "%s: Unknown switch `%c'.\n",
1082 if (!argv
|| !*argv
) {
1084 int len
= 0, st
= 0, cu
;
1085 for (m
= ttymodes
; m
->m_name
; m
++) {
1086 if (m
->m_type
!= i
) {
1087 (void) fprintf(el
->el_outfile
, "%s%s",
1088 i
!= -1 ? "\n" : "",
1089 el
->el_tty
.t_t
[z
][m
->m_type
].t_name
);
1092 strlen(el
->el_tty
.t_t
[z
][m
->m_type
].t_name
);
1094 x
= (el
->el_tty
.t_t
[z
][i
].t_setmask
& m
->m_value
)
1096 x
= (el
->el_tty
.t_t
[z
][i
].t_clrmask
& m
->m_value
)
1099 if (x
!= '\0' || aflag
) {
1101 cu
= strlen(m
->m_name
) + (x
!= '\0') + 1;
1103 if (len
+ cu
>= el
->el_term
.t_size
.h
) {
1104 (void) fprintf(el
->el_outfile
, "\n%*s",
1111 (void) fprintf(el
->el_outfile
, "%c%s ",
1114 (void) fprintf(el
->el_outfile
, "%s ",
1118 (void) fprintf(el
->el_outfile
, "\n");
1121 while (argv
&& (s
= *argv
++)) {
1132 for (m
= ttymodes
; m
->m_name
; m
++)
1133 if (strcmp(m
->m_name
, d
) == 0)
1137 (void) fprintf(el
->el_errfile
,
1138 "%s: Invalid argument `%s'.\n", name
, d
);
1143 el
->el_tty
.t_t
[z
][m
->m_type
].t_setmask
|= m
->m_value
;
1144 el
->el_tty
.t_t
[z
][m
->m_type
].t_clrmask
&= ~m
->m_value
;
1147 el
->el_tty
.t_t
[z
][m
->m_type
].t_setmask
&= ~m
->m_value
;
1148 el
->el_tty
.t_t
[z
][m
->m_type
].t_clrmask
|= m
->m_value
;
1151 el
->el_tty
.t_t
[z
][m
->m_type
].t_setmask
&= ~m
->m_value
;
1152 el
->el_tty
.t_t
[z
][m
->m_type
].t_clrmask
&= ~m
->m_value
;
1162 * DEbugging routine to print the tty characters
1165 tty_printchar(EditLine
*el
, unsigned char *s
)
1170 for (i
= 0; i
< C_NCC
; i
++) {
1171 for (m
= el
->el_tty
.t_t
; m
->m_name
; m
++)
1172 if (m
->m_type
== MD_CHAR
&& C_SH(i
) == m
->m_value
)
1175 (void) fprintf(el
->el_errfile
, "%s ^%c ",
1176 m
->m_name
, s
[i
] + 'A' - 1);
1178 (void) fprintf(el
->el_errfile
, "\n");
1180 (void) fprintf(el
->el_errfile
, "\n");