fix various other problems found by gcc 4.3
[asterisk-bristuff.git] / main / editline / tty.c
blob256cf780bfaf32ffe7eb6db747c5d7bcee200f76
1 /* $NetBSD: tty.c,v 1.16 2002/03/18 16:01:01 christos Exp $ */
3 /*-
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
12 * are met:
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
36 * SUCH DAMAGE.
39 #include "config.h"
40 #if !defined(lint) && !defined(SCCSID)
41 #if 0
42 static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) 6/4/93";
43 #else
44 __RCSID("$NetBSD: tty.c,v 1.16 2002/03/18 16:01:01 christos Exp $");
45 #endif
46 #endif /* not lint && not SCCSID */
49 * tty.c: tty interface stuff
51 #include "tty.h"
52 #include "el.h"
54 typedef struct ttymodes_t {
55 const char *m_name;
56 u_int m_value;
57 int m_type;
58 } 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 */
63 } ttymap_t;
66 private const ttyperm_t ttyperm = {
68 {"iflag:", ICRNL, (INLCR | IGNCR)},
69 {"oflag:", (OPOST | ONLCR), ONLRET},
70 {"cflag:", 0, 0},
71 {"lflag:", (ISIG | ICANON | ECHO | ECHOE | ECHOCTL | IEXTEN),
72 (NOFLSH | ECHONL | EXTPROC | FLUSHO)},
73 {"chars:", 0, 0},
76 {"iflag:", (INLCR | ICRNL), IGNCR},
77 {"oflag:", (OPOST | ONLCR), ONLRET},
78 {"cflag:", 0, 0},
79 {"lflag:", ISIG,
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},
87 {"oflag:", 0, 0},
88 {"cflag:", 0, 0},
89 {"lflag:", 0, ISIG | IEXTEN},
90 {"chars:", 0, 0},
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,
102 CTIME
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,
114 0, 0, 0, 0,
115 0, 0, 0, 0,
116 0, 0, 0, 0,
117 0, 0, 0, 0,
118 0, 0, 0, 0,
119 0, 0, 0, 0,
124 private const ttymap_t tty_map[] = {
125 #ifdef VERASE
126 {C_ERASE, VERASE,
127 {ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
128 #endif /* VERASE */
129 #ifdef VERASE2
130 {C_ERASE2, VERASE2,
131 {ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
132 #endif /* VERASE2 */
133 #ifdef VKILL
134 {C_KILL, VKILL,
135 {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
136 #endif /* VKILL */
137 #ifdef VKILL2
138 {C_KILL2, VKILL2,
139 {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
140 #endif /* VKILL2 */
141 #ifdef VEOF
142 {C_EOF, VEOF,
143 {EM_DELETE_OR_LIST, VI_LIST_OR_EOF, ED_UNASSIGNED}},
144 #endif /* VEOF */
145 #ifdef VWERASE
146 {C_WERASE, VWERASE,
147 {ED_DELETE_PREV_WORD, ED_DELETE_PREV_WORD, ED_PREV_WORD}},
148 #endif /* VWERASE */
149 #ifdef VREPRINT
150 {C_REPRINT, VREPRINT,
151 {ED_REDISPLAY, ED_INSERT, ED_REDISPLAY}},
152 #endif /* VREPRINT */
153 #ifdef VLNEXT
154 {C_LNEXT, VLNEXT,
155 {ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED}},
156 #endif /* VLNEXT */
157 {-1, -1,
158 {ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED}}
161 private const ttymodes_t ttymodes[] = {
162 #ifdef IGNBRK
163 {"ignbrk", IGNBRK, MD_INP},
164 #endif /* IGNBRK */
165 #ifdef BRKINT
166 {"brkint", BRKINT, MD_INP},
167 #endif /* BRKINT */
168 #ifdef IGNPAR
169 {"ignpar", IGNPAR, MD_INP},
170 #endif /* IGNPAR */
171 #ifdef PARMRK
172 {"parmrk", PARMRK, MD_INP},
173 #endif /* PARMRK */
174 #ifdef INPCK
175 {"inpck", INPCK, MD_INP},
176 #endif /* INPCK */
177 #ifdef ISTRIP
178 {"istrip", ISTRIP, MD_INP},
179 #endif /* ISTRIP */
180 #ifdef INLCR
181 {"inlcr", INLCR, MD_INP},
182 #endif /* INLCR */
183 #ifdef IGNCR
184 {"igncr", IGNCR, MD_INP},
185 #endif /* IGNCR */
186 #ifdef ICRNL
187 {"icrnl", ICRNL, MD_INP},
188 #endif /* ICRNL */
189 #ifdef IUCLC
190 {"iuclc", IUCLC, MD_INP},
191 #endif /* IUCLC */
192 #ifdef IXON
193 {"ixon", IXON, MD_INP},
194 #endif /* IXON */
195 #ifdef IXANY
196 {"ixany", IXANY, MD_INP},
197 #endif /* IXANY */
198 #ifdef IXOFF
199 {"ixoff", IXOFF, MD_INP},
200 #endif /* IXOFF */
201 #ifdef IMAXBEL
202 {"imaxbel", IMAXBEL, MD_INP},
203 #endif /* IMAXBEL */
205 #ifdef OPOST
206 {"opost", OPOST, MD_OUT},
207 #endif /* OPOST */
208 #ifdef OLCUC
209 {"olcuc", OLCUC, MD_OUT},
210 #endif /* OLCUC */
211 #ifdef ONLCR
212 {"onlcr", ONLCR, MD_OUT},
213 #endif /* ONLCR */
214 #ifdef OCRNL
215 {"ocrnl", OCRNL, MD_OUT},
216 #endif /* OCRNL */
217 #ifdef ONOCR
218 {"onocr", ONOCR, MD_OUT},
219 #endif /* ONOCR */
220 #ifdef ONOEOT
221 {"onoeot", ONOEOT, MD_OUT},
222 #endif /* ONOEOT */
223 #ifdef ONLRET
224 {"onlret", ONLRET, MD_OUT},
225 #endif /* ONLRET */
226 #ifdef OFILL
227 {"ofill", OFILL, MD_OUT},
228 #endif /* OFILL */
229 #ifdef OFDEL
230 {"ofdel", OFDEL, MD_OUT},
231 #endif /* OFDEL */
232 #ifdef NLDLY
233 {"nldly", NLDLY, MD_OUT},
234 #endif /* NLDLY */
235 #ifdef CRDLY
236 {"crdly", CRDLY, MD_OUT},
237 #endif /* CRDLY */
238 #ifdef TABDLY
239 {"tabdly", TABDLY, MD_OUT},
240 #endif /* TABDLY */
241 #ifdef XTABS
242 {"xtabs", XTABS, MD_OUT},
243 #endif /* XTABS */
244 #ifdef BSDLY
245 {"bsdly", BSDLY, MD_OUT},
246 #endif /* BSDLY */
247 #ifdef VTDLY
248 {"vtdly", VTDLY, MD_OUT},
249 #endif /* VTDLY */
250 #ifdef FFDLY
251 {"ffdly", FFDLY, MD_OUT},
252 #endif /* FFDLY */
253 #ifdef PAGEOUT
254 {"pageout", PAGEOUT, MD_OUT},
255 #endif /* PAGEOUT */
256 #ifdef WRAP
257 {"wrap", WRAP, MD_OUT},
258 #endif /* WRAP */
260 #ifdef CIGNORE
261 {"cignore", CIGNORE, MD_CTL},
262 #endif /* CBAUD */
263 #ifdef CBAUD
264 {"cbaud", CBAUD, MD_CTL},
265 #endif /* CBAUD */
266 #ifdef CSTOPB
267 {"cstopb", CSTOPB, MD_CTL},
268 #endif /* CSTOPB */
269 #ifdef CREAD
270 {"cread", CREAD, MD_CTL},
271 #endif /* CREAD */
272 #ifdef PARENB
273 {"parenb", PARENB, MD_CTL},
274 #endif /* PARENB */
275 #ifdef PARODD
276 {"parodd", PARODD, MD_CTL},
277 #endif /* PARODD */
278 #ifdef HUPCL
279 {"hupcl", HUPCL, MD_CTL},
280 #endif /* HUPCL */
281 #ifdef CLOCAL
282 {"clocal", CLOCAL, MD_CTL},
283 #endif /* CLOCAL */
284 #ifdef LOBLK
285 {"loblk", LOBLK, MD_CTL},
286 #endif /* LOBLK */
287 #ifdef CIBAUD
288 {"cibaud", CIBAUD, MD_CTL},
289 #endif /* CIBAUD */
290 #ifdef CRTSCTS
291 #ifdef CCTS_OFLOW
292 {"ccts_oflow", CCTS_OFLOW, MD_CTL},
293 #else
294 {"crtscts", CRTSCTS, MD_CTL},
295 #endif /* CCTS_OFLOW */
296 #endif /* CRTSCTS */
297 #ifdef CRTS_IFLOW
298 {"crts_iflow", CRTS_IFLOW, MD_CTL},
299 #endif /* CRTS_IFLOW */
300 #ifdef CDTRCTS
301 {"cdtrcts", CDTRCTS, MD_CTL},
302 #endif /* CDTRCTS */
303 #ifdef MDMBUF
304 {"mdmbuf", MDMBUF, MD_CTL},
305 #endif /* MDMBUF */
306 #ifdef RCV1EN
307 {"rcv1en", RCV1EN, MD_CTL},
308 #endif /* RCV1EN */
309 #ifdef XMT1EN
310 {"xmt1en", XMT1EN, MD_CTL},
311 #endif /* XMT1EN */
313 #ifdef ISIG
314 {"isig", ISIG, MD_LIN},
315 #endif /* ISIG */
316 #ifdef ICANON
317 {"icanon", ICANON, MD_LIN},
318 #endif /* ICANON */
319 #ifdef XCASE
320 {"xcase", XCASE, MD_LIN},
321 #endif /* XCASE */
322 #ifdef ECHO
323 {"echo", ECHO, MD_LIN},
324 #endif /* ECHO */
325 #ifdef ECHOE
326 {"echoe", ECHOE, MD_LIN},
327 #endif /* ECHOE */
328 #ifdef ECHOK
329 {"echok", ECHOK, MD_LIN},
330 #endif /* ECHOK */
331 #ifdef ECHONL
332 {"echonl", ECHONL, MD_LIN},
333 #endif /* ECHONL */
334 #ifdef NOFLSH
335 {"noflsh", NOFLSH, MD_LIN},
336 #endif /* NOFLSH */
337 #ifdef TOSTOP
338 {"tostop", TOSTOP, MD_LIN},
339 #endif /* TOSTOP */
340 #ifdef ECHOCTL
341 {"echoctl", ECHOCTL, MD_LIN},
342 #endif /* ECHOCTL */
343 #ifdef ECHOPRT
344 {"echoprt", ECHOPRT, MD_LIN},
345 #endif /* ECHOPRT */
346 #ifdef ECHOKE
347 {"echoke", ECHOKE, MD_LIN},
348 #endif /* ECHOKE */
349 #ifdef DEFECHO
350 {"defecho", DEFECHO, MD_LIN},
351 #endif /* DEFECHO */
352 #ifdef FLUSHO
353 {"flusho", FLUSHO, MD_LIN},
354 #endif /* FLUSHO */
355 #ifdef PENDIN
356 {"pendin", PENDIN, MD_LIN},
357 #endif /* PENDIN */
358 #ifdef IEXTEN
359 {"iexten", IEXTEN, MD_LIN},
360 #endif /* IEXTEN */
361 #ifdef NOKERNINFO
362 {"nokerninfo", NOKERNINFO, MD_LIN},
363 #endif /* NOKERNINFO */
364 #ifdef ALTWERASE
365 {"altwerase", ALTWERASE, MD_LIN},
366 #endif /* ALTWERASE */
367 #ifdef EXTPROC
368 {"extproc", EXTPROC, MD_LIN},
369 #endif /* EXTPROC */
371 #if defined(VINTR)
372 {"intr", C_SH(C_INTR), MD_CHAR},
373 #endif /* VINTR */
374 #if defined(VQUIT)
375 {"quit", C_SH(C_QUIT), MD_CHAR},
376 #endif /* VQUIT */
377 #if defined(VERASE)
378 {"erase", C_SH(C_ERASE), MD_CHAR},
379 #endif /* VERASE */
380 #if defined(VKILL)
381 {"kill", C_SH(C_KILL), MD_CHAR},
382 #endif /* VKILL */
383 #if defined(VEOF)
384 {"eof", C_SH(C_EOF), MD_CHAR},
385 #endif /* VEOF */
386 #if defined(VEOL)
387 {"eol", C_SH(C_EOL), MD_CHAR},
388 #endif /* VEOL */
389 #if defined(VEOL2)
390 {"eol2", C_SH(C_EOL2), MD_CHAR},
391 #endif /* VEOL2 */
392 #if defined(VSWTCH)
393 {"swtch", C_SH(C_SWTCH), MD_CHAR},
394 #endif /* VSWTCH */
395 #if defined(VDSWTCH)
396 {"dswtch", C_SH(C_DSWTCH), MD_CHAR},
397 #endif /* VDSWTCH */
398 #if defined(VERASE2)
399 {"erase2", C_SH(C_ERASE2), MD_CHAR},
400 #endif /* VERASE2 */
401 #if defined(VSTART)
402 {"start", C_SH(C_START), MD_CHAR},
403 #endif /* VSTART */
404 #if defined(VSTOP)
405 {"stop", C_SH(C_STOP), MD_CHAR},
406 #endif /* VSTOP */
407 #if defined(VWERASE)
408 {"werase", C_SH(C_WERASE), MD_CHAR},
409 #endif /* VWERASE */
410 #if defined(VSUSP)
411 {"susp", C_SH(C_SUSP), MD_CHAR},
412 #endif /* VSUSP */
413 #if defined(VDSUSP)
414 {"dsusp", C_SH(C_DSUSP), MD_CHAR},
415 #endif /* VDSUSP */
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 */
422 #if defined(VLNEXT)
423 {"lnext", C_SH(C_LNEXT), MD_CHAR},
424 #endif /* VLNEXT */
425 #if defined(VSTATUS)
426 {"status", C_SH(C_STATUS), MD_CHAR},
427 #endif /* VSTATUS */
428 #if defined(VPAGE)
429 {"page", C_SH(C_PAGE), MD_CHAR},
430 #endif /* VPAGE */
431 #if defined(VPGOFF)
432 {"pgoff", C_SH(C_PGOFF), MD_CHAR},
433 #endif /* VPGOFF */
434 #if defined(VKILL2)
435 {"kill2", C_SH(C_KILL2), MD_CHAR},
436 #endif /* VKILL2 */
437 #if defined(VBRK)
438 {"brk", C_SH(C_BRK), MD_CHAR},
439 #endif /* VBRK */
440 #if defined(VMIN)
441 {"min", C_SH(C_MIN), MD_CHAR},
442 #endif /* VMIN */
443 #if defined(VTIME)
444 {"time", C_SH(C_TIME), MD_CHAR},
445 #endif /* VTIME */
446 {NULL, 0, -1},
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 *);
463 #define t_qu t_ts
466 /* tty_setup():
467 * Get the tty parameters and initialize the editing state
469 private int
470 tty_setup(EditLine *el)
472 int rst = 1;
474 if (el->el_flags & EDIT_DISABLED)
475 return (0);
477 if (tty_getty(el, &el->el_tty.t_ed) == -1) {
478 #ifdef DEBUG_TTY
479 (void) fprintf(el->el_errfile,
480 "tty_setup: tty_getty: %s\n", strerror(errno));
481 #endif /* DEBUG_TTY */
482 return (-1);
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.
506 if (rst) {
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) {
527 #ifdef DEBUG_TTY
528 (void) fprintf(el->el_errfile,
529 "tty_setup: tty_setty: %s\n",
530 strerror(errno));
531 #endif /* DEBUG_TTY */
532 return (-1);
534 } else
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);
551 return (0);
554 protected int
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));
566 /* tty_end():
567 * Restore the tty to its original settings
569 protected void
570 /*ARGSUSED*/
571 tty_end(EditLine *el)
574 /* XXX: Maybe reset to an initial state? */
578 /* tty__getspeed():
579 * Get the tty speed
581 private speed_t
582 tty__getspeed(struct termios *td)
584 speed_t spd;
586 if ((spd = cfgetispeed(td)) == 0)
587 spd = cfgetospeed(td);
588 return (spd);
592 /* tty__getchar():
593 * Get the tty characters
595 private void
596 tty__getchar(struct termios *td, unsigned char *s)
599 #ifdef VINTR
600 s[C_INTR] = td->c_cc[VINTR];
601 #endif /* VINTR */
602 #ifdef VQUIT
603 s[C_QUIT] = td->c_cc[VQUIT];
604 #endif /* VQUIT */
605 #ifdef VERASE
606 s[C_ERASE] = td->c_cc[VERASE];
607 #endif /* VERASE */
608 #ifdef VKILL
609 s[C_KILL] = td->c_cc[VKILL];
610 #endif /* VKILL */
611 #ifdef VEOF
612 s[C_EOF] = td->c_cc[VEOF];
613 #endif /* VEOF */
614 #ifdef VEOL
615 s[C_EOL] = td->c_cc[VEOL];
616 #endif /* VEOL */
617 #ifdef VEOL2
618 s[C_EOL2] = td->c_cc[VEOL2];
619 #endif /* VEOL2 */
620 #ifdef VSWTCH
621 s[C_SWTCH] = td->c_cc[VSWTCH];
622 #endif /* VSWTCH */
623 #ifdef VDSWTCH
624 s[C_DSWTCH] = td->c_cc[VDSWTCH];
625 #endif /* VDSWTCH */
626 #ifdef VERASE2
627 s[C_ERASE2] = td->c_cc[VERASE2];
628 #endif /* VERASE2 */
629 #ifdef VSTART
630 s[C_START] = td->c_cc[VSTART];
631 #endif /* VSTART */
632 #ifdef VSTOP
633 s[C_STOP] = td->c_cc[VSTOP];
634 #endif /* VSTOP */
635 #ifdef VWERASE
636 s[C_WERASE] = td->c_cc[VWERASE];
637 #endif /* VWERASE */
638 #ifdef VSUSP
639 s[C_SUSP] = td->c_cc[VSUSP];
640 #endif /* VSUSP */
641 #ifdef VDSUSP
642 s[C_DSUSP] = td->c_cc[VDSUSP];
643 #endif /* VDSUSP */
644 #ifdef VREPRINT
645 s[C_REPRINT] = td->c_cc[VREPRINT];
646 #endif /* VREPRINT */
647 #ifdef VDISCARD
648 s[C_DISCARD] = td->c_cc[VDISCARD];
649 #endif /* VDISCARD */
650 #ifdef VLNEXT
651 s[C_LNEXT] = td->c_cc[VLNEXT];
652 #endif /* VLNEXT */
653 #ifdef VSTATUS
654 s[C_STATUS] = td->c_cc[VSTATUS];
655 #endif /* VSTATUS */
656 #ifdef VPAGE
657 s[C_PAGE] = td->c_cc[VPAGE];
658 #endif /* VPAGE */
659 #ifdef VPGOFF
660 s[C_PGOFF] = td->c_cc[VPGOFF];
661 #endif /* VPGOFF */
662 #ifdef VKILL2
663 s[C_KILL2] = td->c_cc[VKILL2];
664 #endif /* KILL2 */
665 #ifdef VMIN
666 s[C_MIN] = td->c_cc[VMIN];
667 #endif /* VMIN */
668 #ifdef VTIME
669 s[C_TIME] = td->c_cc[VTIME];
670 #endif /* VTIME */
671 } /* tty__getchar */
674 /* tty__setchar():
675 * Set the tty characters
677 private void
678 tty__setchar(struct termios *td, unsigned char *s)
681 #ifdef VINTR
682 td->c_cc[VINTR] = s[C_INTR];
683 #endif /* VINTR */
684 #ifdef VQUIT
685 td->c_cc[VQUIT] = s[C_QUIT];
686 #endif /* VQUIT */
687 #ifdef VERASE
688 td->c_cc[VERASE] = s[C_ERASE];
689 #endif /* VERASE */
690 #ifdef VKILL
691 td->c_cc[VKILL] = s[C_KILL];
692 #endif /* VKILL */
693 #ifdef VEOF
694 td->c_cc[VEOF] = s[C_EOF];
695 #endif /* VEOF */
696 #ifdef VEOL
697 td->c_cc[VEOL] = s[C_EOL];
698 #endif /* VEOL */
699 #ifdef VEOL2
700 td->c_cc[VEOL2] = s[C_EOL2];
701 #endif /* VEOL2 */
702 #ifdef VSWTCH
703 td->c_cc[VSWTCH] = s[C_SWTCH];
704 #endif /* VSWTCH */
705 #ifdef VDSWTCH
706 td->c_cc[VDSWTCH] = s[C_DSWTCH];
707 #endif /* VDSWTCH */
708 #ifdef VERASE2
709 td->c_cc[VERASE2] = s[C_ERASE2];
710 #endif /* VERASE2 */
711 #ifdef VSTART
712 td->c_cc[VSTART] = s[C_START];
713 #endif /* VSTART */
714 #ifdef VSTOP
715 td->c_cc[VSTOP] = s[C_STOP];
716 #endif /* VSTOP */
717 #ifdef VWERASE
718 td->c_cc[VWERASE] = s[C_WERASE];
719 #endif /* VWERASE */
720 #ifdef VSUSP
721 td->c_cc[VSUSP] = s[C_SUSP];
722 #endif /* VSUSP */
723 #ifdef VDSUSP
724 td->c_cc[VDSUSP] = s[C_DSUSP];
725 #endif /* VDSUSP */
726 #ifdef VREPRINT
727 td->c_cc[VREPRINT] = s[C_REPRINT];
728 #endif /* VREPRINT */
729 #ifdef VDISCARD
730 td->c_cc[VDISCARD] = s[C_DISCARD];
731 #endif /* VDISCARD */
732 #ifdef VLNEXT
733 td->c_cc[VLNEXT] = s[C_LNEXT];
734 #endif /* VLNEXT */
735 #ifdef VSTATUS
736 td->c_cc[VSTATUS] = s[C_STATUS];
737 #endif /* VSTATUS */
738 #ifdef VPAGE
739 td->c_cc[VPAGE] = s[C_PAGE];
740 #endif /* VPAGE */
741 #ifdef VPGOFF
742 td->c_cc[VPGOFF] = s[C_PGOFF];
743 #endif /* VPGOFF */
744 #ifdef VKILL2
745 td->c_cc[VKILL2] = s[C_KILL2];
746 #endif /* VKILL2 */
747 #ifdef VMIN
748 td->c_cc[VMIN] = s[C_MIN];
749 #endif /* VMIN */
750 #ifdef VTIME
751 td->c_cc[VTIME] = s[C_TIME];
752 #endif /* VTIME */
753 } /* tty__setchar */
756 /* tty_bind_char():
757 * Rebind the editline functions
759 protected void
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];
766 const ttymap_t *tp;
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;
776 } else {
777 dmap = el->el_map.emacs;
778 dalt = NULL;
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)
785 continue;
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];
792 if (dalt) {
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];
802 /* tty_rawmode():
803 * Set terminal into 1 character at a time mode.
805 protected int
806 tty_rawmode(EditLine *el)
809 if (el->el_tty.t_mode == ED_IO || el->el_tty.t_mode == QU_IO)
810 return (0);
812 if (el->el_flags & EDIT_DISABLED)
813 return (0);
815 if (tty_getty(el, &el->el_tty.t_ts) == -1) {
816 #ifdef DEBUG_TTY
817 (void) fprintf(el->el_errfile, "tty_rawmode: tty_getty: %s\n",
818 strerror(errno));
819 #endif /* DEBUG_TTY */
820 return (-1);
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;
902 else
903 el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0;
906 int i;
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])
917 break;
919 if (i != C_NCC) {
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) {
946 #ifdef DEBUG_TTY
947 (void) fprintf(el->el_errfile, "tty_rawmode: tty_setty: %s\n",
948 strerror(errno));
949 #endif /* DEBUG_TTY */
950 return (-1);
952 el->el_tty.t_mode = ED_IO;
953 return (0);
957 /* tty_cookedmode():
958 * Set the tty back to normal mode
960 protected int
961 tty_cookedmode(EditLine *el)
962 { /* set tty in normal setup */
964 if (el->el_tty.t_mode == EX_IO)
965 return (0);
967 if (el->el_flags & EDIT_DISABLED)
968 return (0);
970 if (tty_setty(el, &el->el_tty.t_ex) == -1) {
971 #ifdef DEBUG_TTY
972 (void) fprintf(el->el_errfile,
973 "tty_cookedmode: tty_setty: %s\n",
974 strerror(errno));
975 #endif /* DEBUG_TTY */
976 return (-1);
978 el->el_tty.t_mode = EX_IO;
979 return (0);
983 /* tty_quotemode():
984 * Turn on quote mode
986 protected int
987 tty_quotemode(EditLine *el)
989 if (el->el_tty.t_mode == QU_IO)
990 return (0);
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) {
1007 #ifdef DEBUG_TTY
1008 (void) fprintf(el->el_errfile, "QuoteModeOn: tty_setty: %s\n",
1009 strerror(errno));
1010 #endif /* DEBUG_TTY */
1011 return (-1);
1013 el->el_tty.t_mode = QU_IO;
1014 return (0);
1018 /* tty_noquotemode():
1019 * Turn off quote mode
1021 protected int
1022 tty_noquotemode(EditLine *el)
1025 if (el->el_tty.t_mode != QU_IO)
1026 return (0);
1027 if (tty_setty(el, &el->el_tty.t_ed) == -1) {
1028 #ifdef DEBUG_TTY
1029 (void) fprintf(el->el_errfile, "QuoteModeOff: tty_setty: %s\n",
1030 strerror(errno));
1031 #endif /* DEBUG_TTY */
1032 return (-1);
1034 el->el_tty.t_mode = ED_IO;
1035 return (0);
1039 /* tty_stty():
1040 * Stty builtin
1042 protected int
1043 /*ARGSUSED*/
1044 tty_stty(EditLine *el, int argc, const char **argv)
1046 const ttymodes_t *m;
1047 char x;
1048 int aflag = 0;
1049 const char *s, *d;
1050 const char *name;
1051 int z = EX_IO;
1053 if (argv == NULL)
1054 return (-1);
1055 name = *argv++;
1057 while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0')
1058 switch (argv[0][1]) {
1059 case 'a':
1060 aflag++;
1061 argv++;
1062 break;
1063 case 'd':
1064 argv++;
1065 z = ED_IO;
1066 break;
1067 case 'x':
1068 argv++;
1069 z = EX_IO;
1070 break;
1071 case 'q':
1072 argv++;
1073 z = QU_IO;
1074 break;
1075 default:
1076 (void) fprintf(el->el_errfile,
1077 "%s: Unknown switch `%c'.\n",
1078 name, argv[0][1]);
1079 return (-1);
1082 if (!argv || !*argv) {
1083 int i = -1;
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);
1090 i = m->m_type;
1091 st = len =
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)
1095 ? '+' : '\0';
1096 x = (el->el_tty.t_t[z][i].t_clrmask & m->m_value)
1097 ? '-' : x;
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",
1105 st, "");
1106 len = st + cu;
1107 } else
1108 len += cu;
1110 if (x != '\0')
1111 (void) fprintf(el->el_outfile, "%c%s ",
1112 x, m->m_name);
1113 else
1114 (void) fprintf(el->el_outfile, "%s ",
1115 m->m_name);
1118 (void) fprintf(el->el_outfile, "\n");
1119 return (0);
1121 while (argv && (s = *argv++)) {
1122 switch (*s) {
1123 case '+':
1124 case '-':
1125 x = *s++;
1126 break;
1127 default:
1128 x = '\0';
1129 break;
1131 d = s;
1132 for (m = ttymodes; m->m_name; m++)
1133 if (strcmp(m->m_name, d) == 0)
1134 break;
1136 if (!m->m_name) {
1137 (void) fprintf(el->el_errfile,
1138 "%s: Invalid argument `%s'.\n", name, d);
1139 return (-1);
1141 switch (x) {
1142 case '+':
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;
1145 break;
1146 case '-':
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;
1149 break;
1150 default:
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;
1153 break;
1156 return (0);
1160 #ifdef notyet
1161 /* tty_printchar():
1162 * DEbugging routine to print the tty characters
1164 private void
1165 tty_printchar(EditLine *el, unsigned char *s)
1167 ttyperm_t *m;
1168 int i;
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)
1173 break;
1174 if (m->m_name)
1175 (void) fprintf(el->el_errfile, "%s ^%c ",
1176 m->m_name, s[i] + 'A' - 1);
1177 if (i % 5 == 0)
1178 (void) fprintf(el->el_errfile, "\n");
1180 (void) fprintf(el->el_errfile, "\n");
1182 #endif /* notyet */