Fix mdoc(7)/man(7) mix up.
[netbsd-mini2440.git] / lib / libedit / tty.c
blobe59e8cffeb1f6d26d49bf416868d9855d838d293
1 /* $NetBSD: tty.c,v 1.31 2009/07/22 15:58:09 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. 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
32 * SUCH DAMAGE.
35 #include "config.h"
36 #if !defined(lint) && !defined(SCCSID)
37 #if 0
38 static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) 6/4/93";
39 #else
40 __RCSID("$NetBSD: tty.c,v 1.31 2009/07/22 15:58:09 christos Exp $");
41 #endif
42 #endif /* not lint && not SCCSID */
45 * tty.c: tty interface stuff
47 #include <assert.h>
48 #include <errno.h>
49 #include "el.h"
50 #include "tty.h"
52 typedef struct ttymodes_t {
53 const char *m_name;
54 unsigned int m_value;
55 int m_type;
56 } ttymodes_t;
58 typedef struct ttymap_t {
59 Int nch, och; /* Internal and termio rep of chars */
60 el_action_t bind[3]; /* emacs, vi, and vi-cmd */
61 } ttymap_t;
64 private const ttyperm_t ttyperm = {
66 {"iflag:", ICRNL, (INLCR | IGNCR)},
67 {"oflag:", (OPOST | ONLCR), ONLRET},
68 {"cflag:", 0, 0},
69 {"lflag:", (ISIG | ICANON | ECHO | ECHOE | ECHOCTL | IEXTEN),
70 (NOFLSH | ECHONL | EXTPROC | FLUSHO)},
71 {"chars:", 0, 0},
74 {"iflag:", (INLCR | ICRNL), IGNCR},
75 {"oflag:", (OPOST | ONLCR), ONLRET},
76 {"cflag:", 0, 0},
77 {"lflag:", ISIG,
78 (NOFLSH | ICANON | ECHO | ECHOK | ECHONL | EXTPROC | IEXTEN | FLUSHO)},
79 {"chars:", (C_SH(C_MIN) | C_SH(C_TIME) | C_SH(C_SWTCH) | C_SH(C_DSWTCH) |
80 C_SH(C_SUSP) | C_SH(C_DSUSP) | C_SH(C_EOL) | C_SH(C_DISCARD) |
81 C_SH(C_PGOFF) | C_SH(C_PAGE) | C_SH(C_STATUS)), 0}
84 {"iflag:", 0, IXON | IXOFF | INLCR | ICRNL},
85 {"oflag:", 0, 0},
86 {"cflag:", 0, 0},
87 {"lflag:", 0, ISIG | IEXTEN},
88 {"chars:", 0, 0},
92 private const ttychar_t ttychar = {
94 CINTR, CQUIT, CERASE, CKILL,
95 CEOF, CEOL, CEOL2, CSWTCH,
96 CDSWTCH, CERASE2, CSTART, CSTOP,
97 CWERASE, CSUSP, CDSUSP, CREPRINT,
98 CDISCARD, CLNEXT, CSTATUS, CPAGE,
99 CPGOFF, CKILL2, CBRK, CMIN,
100 CTIME
103 CINTR, CQUIT, CERASE, CKILL,
104 _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
105 _POSIX_VDISABLE, CERASE2, CSTART, CSTOP,
106 _POSIX_VDISABLE, CSUSP, _POSIX_VDISABLE, _POSIX_VDISABLE,
107 CDISCARD, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
108 _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 1,
112 0, 0, 0, 0,
113 0, 0, 0, 0,
114 0, 0, 0, 0,
115 0, 0, 0, 0,
116 0, 0, 0, 0,
117 0, 0, 0, 0,
122 private const ttymap_t tty_map[] = {
123 #ifdef VERASE
124 {C_ERASE, VERASE,
125 {EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
126 #endif /* VERASE */
127 #ifdef VERASE2
128 {C_ERASE2, VERASE2,
129 {EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
130 #endif /* VERASE2 */
131 #ifdef VKILL
132 {C_KILL, VKILL,
133 {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
134 #endif /* VKILL */
135 #ifdef VKILL2
136 {C_KILL2, VKILL2,
137 {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
138 #endif /* VKILL2 */
139 #ifdef VEOF
140 {C_EOF, VEOF,
141 {EM_DELETE_OR_LIST, VI_LIST_OR_EOF, ED_UNASSIGNED}},
142 #endif /* VEOF */
143 #ifdef VWERASE
144 {C_WERASE, VWERASE,
145 {ED_DELETE_PREV_WORD, ED_DELETE_PREV_WORD, ED_PREV_WORD}},
146 #endif /* VWERASE */
147 #ifdef VREPRINT
148 {C_REPRINT, VREPRINT,
149 {ED_REDISPLAY, ED_INSERT, ED_REDISPLAY}},
150 #endif /* VREPRINT */
151 #ifdef VLNEXT
152 {C_LNEXT, VLNEXT,
153 {ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED}},
154 #endif /* VLNEXT */
155 {-1, -1,
156 {ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED}}
159 private const ttymodes_t ttymodes[] = {
160 #ifdef IGNBRK
161 {"ignbrk", IGNBRK, MD_INP},
162 #endif /* IGNBRK */
163 #ifdef BRKINT
164 {"brkint", BRKINT, MD_INP},
165 #endif /* BRKINT */
166 #ifdef IGNPAR
167 {"ignpar", IGNPAR, MD_INP},
168 #endif /* IGNPAR */
169 #ifdef PARMRK
170 {"parmrk", PARMRK, MD_INP},
171 #endif /* PARMRK */
172 #ifdef INPCK
173 {"inpck", INPCK, MD_INP},
174 #endif /* INPCK */
175 #ifdef ISTRIP
176 {"istrip", ISTRIP, MD_INP},
177 #endif /* ISTRIP */
178 #ifdef INLCR
179 {"inlcr", INLCR, MD_INP},
180 #endif /* INLCR */
181 #ifdef IGNCR
182 {"igncr", IGNCR, MD_INP},
183 #endif /* IGNCR */
184 #ifdef ICRNL
185 {"icrnl", ICRNL, MD_INP},
186 #endif /* ICRNL */
187 #ifdef IUCLC
188 {"iuclc", IUCLC, MD_INP},
189 #endif /* IUCLC */
190 #ifdef IXON
191 {"ixon", IXON, MD_INP},
192 #endif /* IXON */
193 #ifdef IXANY
194 {"ixany", IXANY, MD_INP},
195 #endif /* IXANY */
196 #ifdef IXOFF
197 {"ixoff", IXOFF, MD_INP},
198 #endif /* IXOFF */
199 #ifdef IMAXBEL
200 {"imaxbel", IMAXBEL, MD_INP},
201 #endif /* IMAXBEL */
203 #ifdef OPOST
204 {"opost", OPOST, MD_OUT},
205 #endif /* OPOST */
206 #ifdef OLCUC
207 {"olcuc", OLCUC, MD_OUT},
208 #endif /* OLCUC */
209 #ifdef ONLCR
210 {"onlcr", ONLCR, MD_OUT},
211 #endif /* ONLCR */
212 #ifdef OCRNL
213 {"ocrnl", OCRNL, MD_OUT},
214 #endif /* OCRNL */
215 #ifdef ONOCR
216 {"onocr", ONOCR, MD_OUT},
217 #endif /* ONOCR */
218 #ifdef ONOEOT
219 {"onoeot", ONOEOT, MD_OUT},
220 #endif /* ONOEOT */
221 #ifdef ONLRET
222 {"onlret", ONLRET, MD_OUT},
223 #endif /* ONLRET */
224 #ifdef OFILL
225 {"ofill", OFILL, MD_OUT},
226 #endif /* OFILL */
227 #ifdef OFDEL
228 {"ofdel", OFDEL, MD_OUT},
229 #endif /* OFDEL */
230 #ifdef NLDLY
231 {"nldly", NLDLY, MD_OUT},
232 #endif /* NLDLY */
233 #ifdef CRDLY
234 {"crdly", CRDLY, MD_OUT},
235 #endif /* CRDLY */
236 #ifdef TABDLY
237 {"tabdly", TABDLY, MD_OUT},
238 #endif /* TABDLY */
239 #ifdef XTABS
240 {"xtabs", XTABS, MD_OUT},
241 #endif /* XTABS */
242 #ifdef BSDLY
243 {"bsdly", BSDLY, MD_OUT},
244 #endif /* BSDLY */
245 #ifdef VTDLY
246 {"vtdly", VTDLY, MD_OUT},
247 #endif /* VTDLY */
248 #ifdef FFDLY
249 {"ffdly", FFDLY, MD_OUT},
250 #endif /* FFDLY */
251 #ifdef PAGEOUT
252 {"pageout", PAGEOUT, MD_OUT},
253 #endif /* PAGEOUT */
254 #ifdef WRAP
255 {"wrap", WRAP, MD_OUT},
256 #endif /* WRAP */
258 #ifdef CIGNORE
259 {"cignore", CIGNORE, MD_CTL},
260 #endif /* CBAUD */
261 #ifdef CBAUD
262 {"cbaud", CBAUD, MD_CTL},
263 #endif /* CBAUD */
264 #ifdef CSTOPB
265 {"cstopb", CSTOPB, MD_CTL},
266 #endif /* CSTOPB */
267 #ifdef CREAD
268 {"cread", CREAD, MD_CTL},
269 #endif /* CREAD */
270 #ifdef PARENB
271 {"parenb", PARENB, MD_CTL},
272 #endif /* PARENB */
273 #ifdef PARODD
274 {"parodd", PARODD, MD_CTL},
275 #endif /* PARODD */
276 #ifdef HUPCL
277 {"hupcl", HUPCL, MD_CTL},
278 #endif /* HUPCL */
279 #ifdef CLOCAL
280 {"clocal", CLOCAL, MD_CTL},
281 #endif /* CLOCAL */
282 #ifdef LOBLK
283 {"loblk", LOBLK, MD_CTL},
284 #endif /* LOBLK */
285 #ifdef CIBAUD
286 {"cibaud", CIBAUD, MD_CTL},
287 #endif /* CIBAUD */
288 #ifdef CRTSCTS
289 #ifdef CCTS_OFLOW
290 {"ccts_oflow", CCTS_OFLOW, MD_CTL},
291 #else
292 {"crtscts", CRTSCTS, MD_CTL},
293 #endif /* CCTS_OFLOW */
294 #endif /* CRTSCTS */
295 #ifdef CRTS_IFLOW
296 {"crts_iflow", CRTS_IFLOW, MD_CTL},
297 #endif /* CRTS_IFLOW */
298 #ifdef CDTRCTS
299 {"cdtrcts", CDTRCTS, MD_CTL},
300 #endif /* CDTRCTS */
301 #ifdef MDMBUF
302 {"mdmbuf", MDMBUF, MD_CTL},
303 #endif /* MDMBUF */
304 #ifdef RCV1EN
305 {"rcv1en", RCV1EN, MD_CTL},
306 #endif /* RCV1EN */
307 #ifdef XMT1EN
308 {"xmt1en", XMT1EN, MD_CTL},
309 #endif /* XMT1EN */
311 #ifdef ISIG
312 {"isig", ISIG, MD_LIN},
313 #endif /* ISIG */
314 #ifdef ICANON
315 {"icanon", ICANON, MD_LIN},
316 #endif /* ICANON */
317 #ifdef XCASE
318 {"xcase", XCASE, MD_LIN},
319 #endif /* XCASE */
320 #ifdef ECHO
321 {"echo", ECHO, MD_LIN},
322 #endif /* ECHO */
323 #ifdef ECHOE
324 {"echoe", ECHOE, MD_LIN},
325 #endif /* ECHOE */
326 #ifdef ECHOK
327 {"echok", ECHOK, MD_LIN},
328 #endif /* ECHOK */
329 #ifdef ECHONL
330 {"echonl", ECHONL, MD_LIN},
331 #endif /* ECHONL */
332 #ifdef NOFLSH
333 {"noflsh", NOFLSH, MD_LIN},
334 #endif /* NOFLSH */
335 #ifdef TOSTOP
336 {"tostop", TOSTOP, MD_LIN},
337 #endif /* TOSTOP */
338 #ifdef ECHOCTL
339 {"echoctl", ECHOCTL, MD_LIN},
340 #endif /* ECHOCTL */
341 #ifdef ECHOPRT
342 {"echoprt", ECHOPRT, MD_LIN},
343 #endif /* ECHOPRT */
344 #ifdef ECHOKE
345 {"echoke", ECHOKE, MD_LIN},
346 #endif /* ECHOKE */
347 #ifdef DEFECHO
348 {"defecho", DEFECHO, MD_LIN},
349 #endif /* DEFECHO */
350 #ifdef FLUSHO
351 {"flusho", FLUSHO, MD_LIN},
352 #endif /* FLUSHO */
353 #ifdef PENDIN
354 {"pendin", PENDIN, MD_LIN},
355 #endif /* PENDIN */
356 #ifdef IEXTEN
357 {"iexten", IEXTEN, MD_LIN},
358 #endif /* IEXTEN */
359 #ifdef NOKERNINFO
360 {"nokerninfo", NOKERNINFO, MD_LIN},
361 #endif /* NOKERNINFO */
362 #ifdef ALTWERASE
363 {"altwerase", ALTWERASE, MD_LIN},
364 #endif /* ALTWERASE */
365 #ifdef EXTPROC
366 {"extproc", EXTPROC, MD_LIN},
367 #endif /* EXTPROC */
369 #if defined(VINTR)
370 {"intr", C_SH(C_INTR), MD_CHAR},
371 #endif /* VINTR */
372 #if defined(VQUIT)
373 {"quit", C_SH(C_QUIT), MD_CHAR},
374 #endif /* VQUIT */
375 #if defined(VERASE)
376 {"erase", C_SH(C_ERASE), MD_CHAR},
377 #endif /* VERASE */
378 #if defined(VKILL)
379 {"kill", C_SH(C_KILL), MD_CHAR},
380 #endif /* VKILL */
381 #if defined(VEOF)
382 {"eof", C_SH(C_EOF), MD_CHAR},
383 #endif /* VEOF */
384 #if defined(VEOL)
385 {"eol", C_SH(C_EOL), MD_CHAR},
386 #endif /* VEOL */
387 #if defined(VEOL2)
388 {"eol2", C_SH(C_EOL2), MD_CHAR},
389 #endif /* VEOL2 */
390 #if defined(VSWTCH)
391 {"swtch", C_SH(C_SWTCH), MD_CHAR},
392 #endif /* VSWTCH */
393 #if defined(VDSWTCH)
394 {"dswtch", C_SH(C_DSWTCH), MD_CHAR},
395 #endif /* VDSWTCH */
396 #if defined(VERASE2)
397 {"erase2", C_SH(C_ERASE2), MD_CHAR},
398 #endif /* VERASE2 */
399 #if defined(VSTART)
400 {"start", C_SH(C_START), MD_CHAR},
401 #endif /* VSTART */
402 #if defined(VSTOP)
403 {"stop", C_SH(C_STOP), MD_CHAR},
404 #endif /* VSTOP */
405 #if defined(VWERASE)
406 {"werase", C_SH(C_WERASE), MD_CHAR},
407 #endif /* VWERASE */
408 #if defined(VSUSP)
409 {"susp", C_SH(C_SUSP), MD_CHAR},
410 #endif /* VSUSP */
411 #if defined(VDSUSP)
412 {"dsusp", C_SH(C_DSUSP), MD_CHAR},
413 #endif /* VDSUSP */
414 #if defined(VREPRINT)
415 {"reprint", C_SH(C_REPRINT), MD_CHAR},
416 #endif /* VREPRINT */
417 #if defined(VDISCARD)
418 {"discard", C_SH(C_DISCARD), MD_CHAR},
419 #endif /* VDISCARD */
420 #if defined(VLNEXT)
421 {"lnext", C_SH(C_LNEXT), MD_CHAR},
422 #endif /* VLNEXT */
423 #if defined(VSTATUS)
424 {"status", C_SH(C_STATUS), MD_CHAR},
425 #endif /* VSTATUS */
426 #if defined(VPAGE)
427 {"page", C_SH(C_PAGE), MD_CHAR},
428 #endif /* VPAGE */
429 #if defined(VPGOFF)
430 {"pgoff", C_SH(C_PGOFF), MD_CHAR},
431 #endif /* VPGOFF */
432 #if defined(VKILL2)
433 {"kill2", C_SH(C_KILL2), MD_CHAR},
434 #endif /* VKILL2 */
435 #if defined(VBRK)
436 {"brk", C_SH(C_BRK), MD_CHAR},
437 #endif /* VBRK */
438 #if defined(VMIN)
439 {"min", C_SH(C_MIN), MD_CHAR},
440 #endif /* VMIN */
441 #if defined(VTIME)
442 {"time", C_SH(C_TIME), MD_CHAR},
443 #endif /* VTIME */
444 {NULL, 0, -1},
449 #define tty__gettabs(td) ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1)
450 #define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8)
451 #define tty__cooked_mode(td) ((td)->c_lflag & ICANON)
453 private int tty_getty(EditLine *, struct termios *);
454 private int tty_setty(EditLine *, int, const struct termios *);
455 private int tty__getcharindex(int);
456 private void tty__getchar(struct termios *, unsigned char *);
457 private void tty__setchar(struct termios *, unsigned char *);
458 private speed_t tty__getspeed(struct termios *);
459 private int tty_setup(EditLine *);
461 #define t_qu t_ts
463 /* tty_getty():
464 * Wrapper for tcgetattr to handle EINTR
466 private int
467 tty_getty(EditLine *el, struct termios *t)
469 int rv;
470 while ((rv = tcgetattr(el->el_infd, t)) == -1 && errno == EINTR)
471 continue;
472 return rv;
475 /* tty_setty():
476 * Wrapper for tcsetattr to handle EINTR
478 private int
479 tty_setty(EditLine *el, int action, const struct termios *t)
481 int rv;
482 while ((rv = tcsetattr(el->el_infd, action, t)) == -1 && errno == EINTR)
483 continue;
484 return rv;
487 /* tty_setup():
488 * Get the tty parameters and initialize the editing state
490 private int
491 tty_setup(EditLine *el)
493 int rst = 1;
495 if (el->el_flags & EDIT_DISABLED)
496 return (0);
498 if (tty_getty(el, &el->el_tty.t_ed) == -1) {
499 #ifdef DEBUG_TTY
500 (void) fprintf(el->el_errfile,
501 "tty_setup: tty_getty: %s\n", strerror(errno));
502 #endif /* DEBUG_TTY */
503 return (-1);
505 el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed;
507 el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex);
508 el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex);
509 el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex);
511 el->el_tty.t_ex.c_iflag &= ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask;
512 el->el_tty.t_ex.c_iflag |= el->el_tty.t_t[EX_IO][MD_INP].t_setmask;
514 el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask;
515 el->el_tty.t_ex.c_oflag |= el->el_tty.t_t[EX_IO][MD_OUT].t_setmask;
517 el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask;
518 el->el_tty.t_ex.c_cflag |= el->el_tty.t_t[EX_IO][MD_CTL].t_setmask;
520 el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask;
521 el->el_tty.t_ex.c_lflag |= el->el_tty.t_t[EX_IO][MD_LIN].t_setmask;
524 * Reset the tty chars to reasonable defaults
525 * If they are disabled, then enable them.
527 if (rst) {
528 if (tty__cooked_mode(&el->el_tty.t_ts)) {
529 tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
531 * Don't affect CMIN and CTIME for the editor mode
533 for (rst = 0; rst < C_NCC - 2; rst++)
534 if (el->el_tty.t_c[TS_IO][rst] !=
535 el->el_tty.t_vdisable
536 && el->el_tty.t_c[ED_IO][rst] !=
537 el->el_tty.t_vdisable)
538 el->el_tty.t_c[ED_IO][rst] =
539 el->el_tty.t_c[TS_IO][rst];
540 for (rst = 0; rst < C_NCC; rst++)
541 if (el->el_tty.t_c[TS_IO][rst] !=
542 el->el_tty.t_vdisable)
543 el->el_tty.t_c[EX_IO][rst] =
544 el->el_tty.t_c[TS_IO][rst];
546 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
547 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) {
548 #ifdef DEBUG_TTY
549 (void) fprintf(el->el_errfile,
550 "tty_setup: tty_setty: %s\n",
551 strerror(errno));
552 #endif /* DEBUG_TTY */
553 return (-1);
556 #ifdef notdef
557 else
558 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
559 #endif
561 el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask;
562 el->el_tty.t_ed.c_iflag |= el->el_tty.t_t[ED_IO][MD_INP].t_setmask;
564 el->el_tty.t_ed.c_oflag &= ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask;
565 el->el_tty.t_ed.c_oflag |= el->el_tty.t_t[ED_IO][MD_OUT].t_setmask;
567 el->el_tty.t_ed.c_cflag &= ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask;
568 el->el_tty.t_ed.c_cflag |= el->el_tty.t_t[ED_IO][MD_CTL].t_setmask;
570 el->el_tty.t_ed.c_lflag &= ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask;
571 el->el_tty.t_ed.c_lflag |= el->el_tty.t_t[ED_IO][MD_LIN].t_setmask;
573 tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
574 tty_bind_char(el, 1);
575 return (0);
578 protected int
579 tty_init(EditLine *el)
582 el->el_tty.t_mode = EX_IO;
583 el->el_tty.t_vdisable = _POSIX_VDISABLE;
584 (void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t));
585 (void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t));
586 return (tty_setup(el));
590 /* tty_end():
591 * Restore the tty to its original settings
593 protected void
594 /*ARGSUSED*/
595 tty_end(EditLine *el __attribute__((__unused__)))
598 /* XXX: Maybe reset to an initial state? */
602 /* tty__getspeed():
603 * Get the tty speed
605 private speed_t
606 tty__getspeed(struct termios *td)
608 speed_t spd;
610 if ((spd = cfgetispeed(td)) == 0)
611 spd = cfgetospeed(td);
612 return (spd);
615 /* tty__getspeed():
616 * Return the index of the asked char in the c_cc array
618 private int
619 tty__getcharindex(int i)
621 switch (i) {
622 #ifdef VINTR
623 case C_INTR:
624 return VINTR;
625 #endif /* VINTR */
626 #ifdef VQUIT
627 case C_QUIT:
628 return VQUIT;
629 #endif /* VQUIT */
630 #ifdef VERASE
631 case C_ERASE:
632 return VERASE;
633 #endif /* VERASE */
634 #ifdef VKILL
635 case C_KILL:
636 return VKILL;
637 #endif /* VKILL */
638 #ifdef VEOF
639 case C_EOF:
640 return VEOF;
641 #endif /* VEOF */
642 #ifdef VEOL
643 case C_EOL:
644 return VEOL;
645 #endif /* VEOL */
646 #ifdef VEOL2
647 case C_EOL2:
648 return VEOL2;
649 #endif /* VEOL2 */
650 #ifdef VSWTCH
651 case C_SWTCH:
652 return VSWTCH;
653 #endif /* VSWTCH */
654 #ifdef VDSWTCH
655 case C_DSWTCH:
656 return VDSWTCH;
657 #endif /* VDSWTCH */
658 #ifdef VERASE2
659 case C_ERASE2:
660 return VERASE2;
661 #endif /* VERASE2 */
662 #ifdef VSTART
663 case C_START:
664 return VSTART;
665 #endif /* VSTART */
666 #ifdef VSTOP
667 case C_STOP:
668 return VSTOP;
669 #endif /* VSTOP */
670 #ifdef VWERASE
671 case C_WERASE:
672 return VWERASE;
673 #endif /* VWERASE */
674 #ifdef VSUSP
675 case C_SUSP:
676 return VSUSP;
677 #endif /* VSUSP */
678 #ifdef VDSUSP
679 case C_DSUSP:
680 return VDSUSP;
681 #endif /* VDSUSP */
682 #ifdef VREPRINT
683 case C_REPRINT:
684 return VREPRINT;
685 #endif /* VREPRINT */
686 #ifdef VDISCARD
687 case C_DISCARD:
688 return VDISCARD;
689 #endif /* VDISCARD */
690 #ifdef VLNEXT
691 case C_LNEXT:
692 return VLNEXT;
693 #endif /* VLNEXT */
694 #ifdef VSTATUS
695 case C_STATUS:
696 return VSTATUS;
697 #endif /* VSTATUS */
698 #ifdef VPAGE
699 case C_PAGE:
700 return VPAGE;
701 #endif /* VPAGE */
702 #ifdef VPGOFF
703 case C_PGOFF:
704 return VPGOFF;
705 #endif /* VPGOFF */
706 #ifdef VKILL2
707 case C_KILL2:
708 return VKILL2;
709 #endif /* KILL2 */
710 #ifdef VMIN
711 case C_MIN:
712 return VMIN;
713 #endif /* VMIN */
714 #ifdef VTIME
715 case C_TIME:
716 return VTIME;
717 #endif /* VTIME */
718 default:
719 return -1;
723 /* tty__getchar():
724 * Get the tty characters
726 private void
727 tty__getchar(struct termios *td, unsigned char *s)
730 #ifdef VINTR
731 s[C_INTR] = td->c_cc[VINTR];
732 #endif /* VINTR */
733 #ifdef VQUIT
734 s[C_QUIT] = td->c_cc[VQUIT];
735 #endif /* VQUIT */
736 #ifdef VERASE
737 s[C_ERASE] = td->c_cc[VERASE];
738 #endif /* VERASE */
739 #ifdef VKILL
740 s[C_KILL] = td->c_cc[VKILL];
741 #endif /* VKILL */
742 #ifdef VEOF
743 s[C_EOF] = td->c_cc[VEOF];
744 #endif /* VEOF */
745 #ifdef VEOL
746 s[C_EOL] = td->c_cc[VEOL];
747 #endif /* VEOL */
748 #ifdef VEOL2
749 s[C_EOL2] = td->c_cc[VEOL2];
750 #endif /* VEOL2 */
751 #ifdef VSWTCH
752 s[C_SWTCH] = td->c_cc[VSWTCH];
753 #endif /* VSWTCH */
754 #ifdef VDSWTCH
755 s[C_DSWTCH] = td->c_cc[VDSWTCH];
756 #endif /* VDSWTCH */
757 #ifdef VERASE2
758 s[C_ERASE2] = td->c_cc[VERASE2];
759 #endif /* VERASE2 */
760 #ifdef VSTART
761 s[C_START] = td->c_cc[VSTART];
762 #endif /* VSTART */
763 #ifdef VSTOP
764 s[C_STOP] = td->c_cc[VSTOP];
765 #endif /* VSTOP */
766 #ifdef VWERASE
767 s[C_WERASE] = td->c_cc[VWERASE];
768 #endif /* VWERASE */
769 #ifdef VSUSP
770 s[C_SUSP] = td->c_cc[VSUSP];
771 #endif /* VSUSP */
772 #ifdef VDSUSP
773 s[C_DSUSP] = td->c_cc[VDSUSP];
774 #endif /* VDSUSP */
775 #ifdef VREPRINT
776 s[C_REPRINT] = td->c_cc[VREPRINT];
777 #endif /* VREPRINT */
778 #ifdef VDISCARD
779 s[C_DISCARD] = td->c_cc[VDISCARD];
780 #endif /* VDISCARD */
781 #ifdef VLNEXT
782 s[C_LNEXT] = td->c_cc[VLNEXT];
783 #endif /* VLNEXT */
784 #ifdef VSTATUS
785 s[C_STATUS] = td->c_cc[VSTATUS];
786 #endif /* VSTATUS */
787 #ifdef VPAGE
788 s[C_PAGE] = td->c_cc[VPAGE];
789 #endif /* VPAGE */
790 #ifdef VPGOFF
791 s[C_PGOFF] = td->c_cc[VPGOFF];
792 #endif /* VPGOFF */
793 #ifdef VKILL2
794 s[C_KILL2] = td->c_cc[VKILL2];
795 #endif /* KILL2 */
796 #ifdef VMIN
797 s[C_MIN] = td->c_cc[VMIN];
798 #endif /* VMIN */
799 #ifdef VTIME
800 s[C_TIME] = td->c_cc[VTIME];
801 #endif /* VTIME */
802 } /* tty__getchar */
805 /* tty__setchar():
806 * Set the tty characters
808 private void
809 tty__setchar(struct termios *td, unsigned char *s)
812 #ifdef VINTR
813 td->c_cc[VINTR] = s[C_INTR];
814 #endif /* VINTR */
815 #ifdef VQUIT
816 td->c_cc[VQUIT] = s[C_QUIT];
817 #endif /* VQUIT */
818 #ifdef VERASE
819 td->c_cc[VERASE] = s[C_ERASE];
820 #endif /* VERASE */
821 #ifdef VKILL
822 td->c_cc[VKILL] = s[C_KILL];
823 #endif /* VKILL */
824 #ifdef VEOF
825 td->c_cc[VEOF] = s[C_EOF];
826 #endif /* VEOF */
827 #ifdef VEOL
828 td->c_cc[VEOL] = s[C_EOL];
829 #endif /* VEOL */
830 #ifdef VEOL2
831 td->c_cc[VEOL2] = s[C_EOL2];
832 #endif /* VEOL2 */
833 #ifdef VSWTCH
834 td->c_cc[VSWTCH] = s[C_SWTCH];
835 #endif /* VSWTCH */
836 #ifdef VDSWTCH
837 td->c_cc[VDSWTCH] = s[C_DSWTCH];
838 #endif /* VDSWTCH */
839 #ifdef VERASE2
840 td->c_cc[VERASE2] = s[C_ERASE2];
841 #endif /* VERASE2 */
842 #ifdef VSTART
843 td->c_cc[VSTART] = s[C_START];
844 #endif /* VSTART */
845 #ifdef VSTOP
846 td->c_cc[VSTOP] = s[C_STOP];
847 #endif /* VSTOP */
848 #ifdef VWERASE
849 td->c_cc[VWERASE] = s[C_WERASE];
850 #endif /* VWERASE */
851 #ifdef VSUSP
852 td->c_cc[VSUSP] = s[C_SUSP];
853 #endif /* VSUSP */
854 #ifdef VDSUSP
855 td->c_cc[VDSUSP] = s[C_DSUSP];
856 #endif /* VDSUSP */
857 #ifdef VREPRINT
858 td->c_cc[VREPRINT] = s[C_REPRINT];
859 #endif /* VREPRINT */
860 #ifdef VDISCARD
861 td->c_cc[VDISCARD] = s[C_DISCARD];
862 #endif /* VDISCARD */
863 #ifdef VLNEXT
864 td->c_cc[VLNEXT] = s[C_LNEXT];
865 #endif /* VLNEXT */
866 #ifdef VSTATUS
867 td->c_cc[VSTATUS] = s[C_STATUS];
868 #endif /* VSTATUS */
869 #ifdef VPAGE
870 td->c_cc[VPAGE] = s[C_PAGE];
871 #endif /* VPAGE */
872 #ifdef VPGOFF
873 td->c_cc[VPGOFF] = s[C_PGOFF];
874 #endif /* VPGOFF */
875 #ifdef VKILL2
876 td->c_cc[VKILL2] = s[C_KILL2];
877 #endif /* VKILL2 */
878 #ifdef VMIN
879 td->c_cc[VMIN] = s[C_MIN];
880 #endif /* VMIN */
881 #ifdef VTIME
882 td->c_cc[VTIME] = s[C_TIME];
883 #endif /* VTIME */
884 } /* tty__setchar */
887 /* tty_bind_char():
888 * Rebind the editline functions
890 protected void
891 tty_bind_char(EditLine *el, int force)
894 unsigned char *t_n = el->el_tty.t_c[ED_IO];
895 unsigned char *t_o = el->el_tty.t_ed.c_cc;
896 Char new[2], old[2];
897 const ttymap_t *tp;
898 el_action_t *map, *alt;
899 const el_action_t *dmap, *dalt;
900 new[1] = old[1] = '\0';
902 map = el->el_map.key;
903 alt = el->el_map.alt;
904 if (el->el_map.type == MAP_VI) {
905 dmap = el->el_map.vii;
906 dalt = el->el_map.vic;
907 } else {
908 dmap = el->el_map.emacs;
909 dalt = NULL;
912 for (tp = tty_map; tp->nch != -1; tp++) {
913 new[0] = t_n[tp->nch];
914 old[0] = t_o[tp->och];
915 if (new[0] == old[0] && !force)
916 continue;
917 /* Put the old default binding back, and set the new binding */
918 key_clear(el, map, old);
919 map[UC(old[0])] = dmap[UC(old[0])];
920 key_clear(el, map, new);
921 /* MAP_VI == 1, MAP_EMACS == 0... */
922 map[UC(new[0])] = tp->bind[el->el_map.type];
923 if (dalt) {
924 key_clear(el, alt, old);
925 alt[UC(old[0])] = dalt[UC(old[0])];
926 key_clear(el, alt, new);
927 alt[UC(new[0])] = tp->bind[el->el_map.type + 1];
933 /* tty_rawmode():
934 * Set terminal into 1 character at a time mode.
936 protected int
937 tty_rawmode(EditLine *el)
940 if (el->el_tty.t_mode == ED_IO || el->el_tty.t_mode == QU_IO)
941 return (0);
943 if (el->el_flags & EDIT_DISABLED)
944 return (0);
946 if (tty_getty(el, &el->el_tty.t_ts) == -1) {
947 #ifdef DEBUG_TTY
948 (void) fprintf(el->el_errfile, "tty_rawmode: tty_getty: %s\n",
949 strerror(errno));
950 #endif /* DEBUG_TTY */
951 return (-1);
954 * We always keep up with the eight bit setting and the speed of the
955 * tty. But we only believe changes that are made to cooked mode!
957 el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts);
958 el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts);
960 if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed ||
961 tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) {
962 (void) cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed);
963 (void) cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed);
964 (void) cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed);
965 (void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed);
967 if (tty__cooked_mode(&el->el_tty.t_ts)) {
968 if (el->el_tty.t_ts.c_cflag != el->el_tty.t_ex.c_cflag) {
969 el->el_tty.t_ex.c_cflag =
970 el->el_tty.t_ts.c_cflag;
971 el->el_tty.t_ex.c_cflag &=
972 ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask;
973 el->el_tty.t_ex.c_cflag |=
974 el->el_tty.t_t[EX_IO][MD_CTL].t_setmask;
976 el->el_tty.t_ed.c_cflag =
977 el->el_tty.t_ts.c_cflag;
978 el->el_tty.t_ed.c_cflag &=
979 ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask;
980 el->el_tty.t_ed.c_cflag |=
981 el->el_tty.t_t[ED_IO][MD_CTL].t_setmask;
983 if ((el->el_tty.t_ts.c_lflag != el->el_tty.t_ex.c_lflag) &&
984 (el->el_tty.t_ts.c_lflag != el->el_tty.t_ed.c_lflag)) {
985 el->el_tty.t_ex.c_lflag =
986 el->el_tty.t_ts.c_lflag;
987 el->el_tty.t_ex.c_lflag &=
988 ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask;
989 el->el_tty.t_ex.c_lflag |=
990 el->el_tty.t_t[EX_IO][MD_LIN].t_setmask;
992 el->el_tty.t_ed.c_lflag =
993 el->el_tty.t_ts.c_lflag;
994 el->el_tty.t_ed.c_lflag &=
995 ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask;
996 el->el_tty.t_ed.c_lflag |=
997 el->el_tty.t_t[ED_IO][MD_LIN].t_setmask;
999 if ((el->el_tty.t_ts.c_iflag != el->el_tty.t_ex.c_iflag) &&
1000 (el->el_tty.t_ts.c_iflag != el->el_tty.t_ed.c_iflag)) {
1001 el->el_tty.t_ex.c_iflag =
1002 el->el_tty.t_ts.c_iflag;
1003 el->el_tty.t_ex.c_iflag &=
1004 ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask;
1005 el->el_tty.t_ex.c_iflag |=
1006 el->el_tty.t_t[EX_IO][MD_INP].t_setmask;
1008 el->el_tty.t_ed.c_iflag =
1009 el->el_tty.t_ts.c_iflag;
1010 el->el_tty.t_ed.c_iflag &=
1011 ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask;
1012 el->el_tty.t_ed.c_iflag |=
1013 el->el_tty.t_t[ED_IO][MD_INP].t_setmask;
1015 if ((el->el_tty.t_ts.c_oflag != el->el_tty.t_ex.c_oflag) &&
1016 (el->el_tty.t_ts.c_oflag != el->el_tty.t_ed.c_oflag)) {
1017 el->el_tty.t_ex.c_oflag =
1018 el->el_tty.t_ts.c_oflag;
1019 el->el_tty.t_ex.c_oflag &=
1020 ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask;
1021 el->el_tty.t_ex.c_oflag |=
1022 el->el_tty.t_t[EX_IO][MD_OUT].t_setmask;
1024 el->el_tty.t_ed.c_oflag =
1025 el->el_tty.t_ts.c_oflag;
1026 el->el_tty.t_ed.c_oflag &=
1027 ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask;
1028 el->el_tty.t_ed.c_oflag |=
1029 el->el_tty.t_t[ED_IO][MD_OUT].t_setmask;
1031 if (tty__gettabs(&el->el_tty.t_ex) == 0)
1032 el->el_tty.t_tabs = 0;
1033 else
1034 el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0;
1037 int i;
1039 tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
1041 * Check if the user made any changes.
1042 * If he did, then propagate the changes to the
1043 * edit and execute data structures.
1045 for (i = 0; i < C_NCC; i++)
1046 if (el->el_tty.t_c[TS_IO][i] !=
1047 el->el_tty.t_c[EX_IO][i])
1048 break;
1050 if (i != C_NCC) {
1052 * Propagate changes only to the unprotected
1053 * chars that have been modified just now.
1055 for (i = 0; i < C_NCC; i++) {
1056 if (!((el->el_tty.t_t[ED_IO][MD_CHAR].t_setmask & C_SH(i)))
1057 && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
1058 el->el_tty.t_c[ED_IO][i] = el->el_tty.t_c[TS_IO][i];
1059 if (el->el_tty.t_t[ED_IO][MD_CHAR].t_clrmask & C_SH(i))
1060 el->el_tty.t_c[ED_IO][i] = el->el_tty.t_vdisable;
1062 tty_bind_char(el, 0);
1063 tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
1065 for (i = 0; i < C_NCC; i++) {
1066 if (!((el->el_tty.t_t[EX_IO][MD_CHAR].t_setmask & C_SH(i)))
1067 && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
1068 el->el_tty.t_c[EX_IO][i] = el->el_tty.t_c[TS_IO][i];
1069 if (el->el_tty.t_t[EX_IO][MD_CHAR].t_clrmask & C_SH(i))
1070 el->el_tty.t_c[EX_IO][i] = el->el_tty.t_vdisable;
1072 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
1076 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) {
1077 #ifdef DEBUG_TTY
1078 (void) fprintf(el->el_errfile, "tty_rawmode: tty_setty: %s\n",
1079 strerror(errno));
1080 #endif /* DEBUG_TTY */
1081 return (-1);
1083 el->el_tty.t_mode = ED_IO;
1084 return (0);
1088 /* tty_cookedmode():
1089 * Set the tty back to normal mode
1091 protected int
1092 tty_cookedmode(EditLine *el)
1093 { /* set tty in normal setup */
1095 if (el->el_tty.t_mode == EX_IO)
1096 return (0);
1098 if (el->el_flags & EDIT_DISABLED)
1099 return (0);
1101 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) {
1102 #ifdef DEBUG_TTY
1103 (void) fprintf(el->el_errfile,
1104 "tty_cookedmode: tty_setty: %s\n",
1105 strerror(errno));
1106 #endif /* DEBUG_TTY */
1107 return (-1);
1109 el->el_tty.t_mode = EX_IO;
1110 return (0);
1114 /* tty_quotemode():
1115 * Turn on quote mode
1117 protected int
1118 tty_quotemode(EditLine *el)
1120 if (el->el_tty.t_mode == QU_IO)
1121 return (0);
1123 el->el_tty.t_qu = el->el_tty.t_ed;
1125 el->el_tty.t_qu.c_iflag &= ~el->el_tty.t_t[QU_IO][MD_INP].t_clrmask;
1126 el->el_tty.t_qu.c_iflag |= el->el_tty.t_t[QU_IO][MD_INP].t_setmask;
1128 el->el_tty.t_qu.c_oflag &= ~el->el_tty.t_t[QU_IO][MD_OUT].t_clrmask;
1129 el->el_tty.t_qu.c_oflag |= el->el_tty.t_t[QU_IO][MD_OUT].t_setmask;
1131 el->el_tty.t_qu.c_cflag &= ~el->el_tty.t_t[QU_IO][MD_CTL].t_clrmask;
1132 el->el_tty.t_qu.c_cflag |= el->el_tty.t_t[QU_IO][MD_CTL].t_setmask;
1134 el->el_tty.t_qu.c_lflag &= ~el->el_tty.t_t[QU_IO][MD_LIN].t_clrmask;
1135 el->el_tty.t_qu.c_lflag |= el->el_tty.t_t[QU_IO][MD_LIN].t_setmask;
1137 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_qu) == -1) {
1138 #ifdef DEBUG_TTY
1139 (void) fprintf(el->el_errfile, "QuoteModeOn: tty_setty: %s\n",
1140 strerror(errno));
1141 #endif /* DEBUG_TTY */
1142 return (-1);
1144 el->el_tty.t_mode = QU_IO;
1145 return (0);
1149 /* tty_noquotemode():
1150 * Turn off quote mode
1152 protected int
1153 tty_noquotemode(EditLine *el)
1156 if (el->el_tty.t_mode != QU_IO)
1157 return (0);
1158 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) {
1159 #ifdef DEBUG_TTY
1160 (void) fprintf(el->el_errfile, "QuoteModeOff: tty_setty: %s\n",
1161 strerror(errno));
1162 #endif /* DEBUG_TTY */
1163 return (-1);
1165 el->el_tty.t_mode = ED_IO;
1166 return (0);
1170 /* tty_stty():
1171 * Stty builtin
1173 protected int
1174 /*ARGSUSED*/
1175 tty_stty(EditLine *el, int argc __attribute__((__unused__)), const Char **argv)
1177 const ttymodes_t *m;
1178 char x;
1179 int aflag = 0;
1180 const Char *s, *d;
1181 char name[EL_BUFSIZ];
1182 struct termios *tios = &el->el_tty.t_ex;
1183 int z = EX_IO;
1185 if (argv == NULL)
1186 return (-1);
1187 strncpy(name, ct_encode_string(*argv++, &el->el_scratch), sizeof(name));
1188 name[sizeof(name) - 1] = '\0';
1190 while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0')
1191 switch (argv[0][1]) {
1192 case 'a':
1193 aflag++;
1194 argv++;
1195 break;
1196 case 'd':
1197 argv++;
1198 tios = &el->el_tty.t_ed;
1199 z = ED_IO;
1200 break;
1201 case 'x':
1202 argv++;
1203 tios = &el->el_tty.t_ex;
1204 z = EX_IO;
1205 break;
1206 case 'q':
1207 argv++;
1208 tios = &el->el_tty.t_ts;
1209 z = QU_IO;
1210 break;
1211 default:
1212 (void) fprintf(el->el_errfile,
1213 "%s: Unknown switch `%c'.\n",
1214 name, argv[0][1]);
1215 return (-1);
1218 if (!argv || !*argv) {
1219 int i = -1;
1220 size_t len = 0, st = 0, cu;
1221 for (m = ttymodes; m->m_name; m++) {
1222 if (m->m_type != i) {
1223 (void) fprintf(el->el_outfile, "%s%s",
1224 i != -1 ? "\n" : "",
1225 el->el_tty.t_t[z][m->m_type].t_name);
1226 i = m->m_type;
1227 st = len =
1228 strlen(el->el_tty.t_t[z][m->m_type].t_name);
1230 if (i != -1) {
1231 x = (el->el_tty.t_t[z][i].t_setmask & m->m_value)
1232 ? '+' : '\0';
1233 x = (el->el_tty.t_t[z][i].t_clrmask & m->m_value)
1234 ? '-' : x;
1235 } else {
1236 x = '\0';
1239 if (x != '\0' || aflag) {
1241 cu = strlen(m->m_name) + (x != '\0') + 1;
1243 if (len + cu >= (size_t)el->el_term.t_size.h) {
1244 (void) fprintf(el->el_outfile, "\n%*s",
1245 (int)st, "");
1246 len = st + cu;
1247 } else
1248 len += cu;
1250 if (x != '\0')
1251 (void) fprintf(el->el_outfile, "%c%s ",
1252 x, m->m_name);
1253 else
1254 (void) fprintf(el->el_outfile, "%s ",
1255 m->m_name);
1258 (void) fprintf(el->el_outfile, "\n");
1259 return (0);
1261 while (argv && (s = *argv++)) {
1262 const Char *p;
1263 switch (*s) {
1264 case '+':
1265 case '-':
1266 x = *s++;
1267 break;
1268 default:
1269 x = '\0';
1270 break;
1272 d = s;
1273 p = Strchr(s, '=');
1274 for (m = ttymodes; m->m_name; m++)
1275 if ((p ? strncmp(m->m_name, ct_encode_string(d, &el->el_scratch), (size_t)(p - d)) :
1276 strcmp(m->m_name, ct_encode_string(d, &el->el_scratch))) == 0 &&
1277 (p == NULL || m->m_type == MD_CHAR))
1278 break;
1280 if (!m->m_name) {
1281 (void) fprintf(el->el_errfile,
1282 "%s: Invalid argument `" FSTR "'.\n", name, d);
1283 return (-1);
1285 if (p) {
1286 int c = ffs((int)m->m_value);
1287 int v = *++p ? parse__escape(&p) :
1288 el->el_tty.t_vdisable;
1289 assert(c != 0);
1290 c--;
1291 c = tty__getcharindex(c);
1292 assert(c != -1);
1293 tios->c_cc[c] = v;
1294 continue;
1296 switch (x) {
1297 case '+':
1298 el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value;
1299 el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
1300 break;
1301 case '-':
1302 el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
1303 el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value;
1304 break;
1305 default:
1306 el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
1307 el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
1308 break;
1312 if (el->el_tty.t_mode == z) {
1313 if (tty_setty(el, TCSADRAIN, tios) == -1) {
1314 #ifdef DEBUG_TTY
1315 (void) fprintf(el->el_errfile,
1316 "tty_stty: tty_setty: %s\n", strerror(errno));
1317 #endif /* DEBUG_TTY */
1318 return (-1);
1322 return (0);
1326 #ifdef notyet
1327 /* tty_printchar():
1328 * DEbugging routine to print the tty characters
1330 private void
1331 tty_printchar(EditLine *el, unsigned char *s)
1333 ttyperm_t *m;
1334 int i;
1336 for (i = 0; i < C_NCC; i++) {
1337 for (m = el->el_tty.t_t; m->m_name; m++)
1338 if (m->m_type == MD_CHAR && C_SH(i) == m->m_value)
1339 break;
1340 if (m->m_name)
1341 (void) fprintf(el->el_errfile, "%s ^%c ",
1342 m->m_name, s[i] + 'A' - 1);
1343 if (i % 5 == 0)
1344 (void) fprintf(el->el_errfile, "\n");
1346 (void) fprintf(el->el_errfile, "\n");
1348 #endif /* notyet */