- Recollect TX descs, if et(4) is going to enter OACTIVE state.
[dragonfly.git] / lib / libedit / tty.c
blob6cbbddb2fadf6c4d138ebd4f390063a85bc3ec51
1 /*-
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Christos Zoulas of Cornell University.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
32 * @(#)tty.c 8.1 (Berkeley) 6/4/93
33 * $NetBSD: tty.c,v 1.25 2006/03/18 09:09:41 christos Exp $
34 * $DragonFly: src/lib/libedit/tty.c,v 1.5 2007/05/05 00:27:40 pavalos Exp $
37 #include "config.h"
40 * tty.c: tty interface stuff
42 #include <assert.h>
43 #include "tty.h"
44 #include "el.h"
46 typedef struct ttymodes_t {
47 const char *m_name;
48 unsigned int m_value;
49 int m_type;
50 } ttymodes_t;
52 typedef struct ttymap_t {
53 int nch, och; /* Internal and termio rep of chars */
54 el_action_t bind[3]; /* emacs, vi, and vi-cmd */
55 } ttymap_t;
58 private const ttyperm_t ttyperm = {
60 {"iflag:", ICRNL, (INLCR | IGNCR)},
61 {"oflag:", (OPOST | ONLCR), ONLRET},
62 {"cflag:", 0, 0},
63 {"lflag:", (ISIG | ICANON | ECHO | ECHOE | ECHOCTL | IEXTEN),
64 (NOFLSH | ECHONL | EXTPROC | FLUSHO)},
65 {"chars:", 0, 0},
68 {"iflag:", (INLCR | ICRNL), IGNCR},
69 {"oflag:", (OPOST | ONLCR), ONLRET},
70 {"cflag:", 0, 0},
71 {"lflag:", ISIG,
72 (NOFLSH | ICANON | ECHO | ECHOK | ECHONL | EXTPROC | IEXTEN | FLUSHO)},
73 {"chars:", (C_SH(C_MIN) | C_SH(C_TIME) | C_SH(C_SWTCH) | C_SH(C_DSWTCH) |
74 C_SH(C_SUSP) | C_SH(C_DSUSP) | C_SH(C_EOL) | C_SH(C_DISCARD) |
75 C_SH(C_PGOFF) | C_SH(C_PAGE) | C_SH(C_STATUS)), 0}
78 {"iflag:", 0, IXON | IXOFF | INLCR | ICRNL},
79 {"oflag:", 0, 0},
80 {"cflag:", 0, 0},
81 {"lflag:", 0, ISIG | IEXTEN},
82 {"chars:", 0, 0},
86 private const ttychar_t ttychar = {
88 CINTR, CQUIT, CERASE, CKILL,
89 CEOF, CEOL, CEOL2, CSWTCH,
90 CDSWTCH, CERASE2, CSTART, CSTOP,
91 CWERASE, CSUSP, CDSUSP, CREPRINT,
92 CDISCARD, CLNEXT, CSTATUS, CPAGE,
93 CPGOFF, CKILL2, CBRK, CMIN,
94 CTIME
97 CINTR, CQUIT, CERASE, CKILL,
98 _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
99 _POSIX_VDISABLE, CERASE2, CSTART, CSTOP,
100 _POSIX_VDISABLE, CSUSP, _POSIX_VDISABLE, _POSIX_VDISABLE,
101 CDISCARD, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
102 _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 1,
106 0, 0, 0, 0,
107 0, 0, 0, 0,
108 0, 0, 0, 0,
109 0, 0, 0, 0,
110 0, 0, 0, 0,
111 0, 0, 0, 0,
116 private const ttymap_t tty_map[] = {
117 #ifdef VERASE
118 {C_ERASE, VERASE,
119 {EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
120 #endif /* VERASE */
121 #ifdef VERASE2
122 {C_ERASE2, VERASE2,
123 {EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
124 #endif /* VERASE2 */
125 #ifdef VKILL
126 {C_KILL, VKILL,
127 {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
128 #endif /* VKILL */
129 #ifdef VKILL2
130 {C_KILL2, VKILL2,
131 {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
132 #endif /* VKILL2 */
133 #ifdef VEOF
134 {C_EOF, VEOF,
135 {EM_DELETE_OR_LIST, VI_LIST_OR_EOF, ED_UNASSIGNED}},
136 #endif /* VEOF */
137 #ifdef VWERASE
138 {C_WERASE, VWERASE,
139 {ED_DELETE_PREV_WORD, ED_DELETE_PREV_WORD, ED_PREV_WORD}},
140 #endif /* VWERASE */
141 #ifdef VREPRINT
142 {C_REPRINT, VREPRINT,
143 {ED_REDISPLAY, ED_INSERT, ED_REDISPLAY}},
144 #endif /* VREPRINT */
145 #ifdef VLNEXT
146 {C_LNEXT, VLNEXT,
147 {ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED}},
148 #endif /* VLNEXT */
149 {-1, -1,
150 {ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED}}
153 private const ttymodes_t ttymodes[] = {
154 #ifdef IGNBRK
155 {"ignbrk", IGNBRK, MD_INP},
156 #endif /* IGNBRK */
157 #ifdef BRKINT
158 {"brkint", BRKINT, MD_INP},
159 #endif /* BRKINT */
160 #ifdef IGNPAR
161 {"ignpar", IGNPAR, MD_INP},
162 #endif /* IGNPAR */
163 #ifdef PARMRK
164 {"parmrk", PARMRK, MD_INP},
165 #endif /* PARMRK */
166 #ifdef INPCK
167 {"inpck", INPCK, MD_INP},
168 #endif /* INPCK */
169 #ifdef ISTRIP
170 {"istrip", ISTRIP, MD_INP},
171 #endif /* ISTRIP */
172 #ifdef INLCR
173 {"inlcr", INLCR, MD_INP},
174 #endif /* INLCR */
175 #ifdef IGNCR
176 {"igncr", IGNCR, MD_INP},
177 #endif /* IGNCR */
178 #ifdef ICRNL
179 {"icrnl", ICRNL, MD_INP},
180 #endif /* ICRNL */
181 #ifdef IUCLC
182 {"iuclc", IUCLC, MD_INP},
183 #endif /* IUCLC */
184 #ifdef IXON
185 {"ixon", IXON, MD_INP},
186 #endif /* IXON */
187 #ifdef IXANY
188 {"ixany", IXANY, MD_INP},
189 #endif /* IXANY */
190 #ifdef IXOFF
191 {"ixoff", IXOFF, MD_INP},
192 #endif /* IXOFF */
193 #ifdef IMAXBEL
194 {"imaxbel", IMAXBEL, MD_INP},
195 #endif /* IMAXBEL */
197 #ifdef OPOST
198 {"opost", OPOST, MD_OUT},
199 #endif /* OPOST */
200 #ifdef OLCUC
201 {"olcuc", OLCUC, MD_OUT},
202 #endif /* OLCUC */
203 #ifdef ONLCR
204 {"onlcr", ONLCR, MD_OUT},
205 #endif /* ONLCR */
206 #ifdef OCRNL
207 {"ocrnl", OCRNL, MD_OUT},
208 #endif /* OCRNL */
209 #ifdef ONOCR
210 {"onocr", ONOCR, MD_OUT},
211 #endif /* ONOCR */
212 #ifdef ONOEOT
213 {"onoeot", ONOEOT, MD_OUT},
214 #endif /* ONOEOT */
215 #ifdef ONLRET
216 {"onlret", ONLRET, MD_OUT},
217 #endif /* ONLRET */
218 #ifdef OFILL
219 {"ofill", OFILL, MD_OUT},
220 #endif /* OFILL */
221 #ifdef OFDEL
222 {"ofdel", OFDEL, MD_OUT},
223 #endif /* OFDEL */
224 #ifdef NLDLY
225 {"nldly", NLDLY, MD_OUT},
226 #endif /* NLDLY */
227 #ifdef CRDLY
228 {"crdly", CRDLY, MD_OUT},
229 #endif /* CRDLY */
230 #ifdef TABDLY
231 {"tabdly", TABDLY, MD_OUT},
232 #endif /* TABDLY */
233 #ifdef XTABS
234 {"xtabs", XTABS, MD_OUT},
235 #endif /* XTABS */
236 #ifdef BSDLY
237 {"bsdly", BSDLY, MD_OUT},
238 #endif /* BSDLY */
239 #ifdef VTDLY
240 {"vtdly", VTDLY, MD_OUT},
241 #endif /* VTDLY */
242 #ifdef FFDLY
243 {"ffdly", FFDLY, MD_OUT},
244 #endif /* FFDLY */
245 #ifdef PAGEOUT
246 {"pageout", PAGEOUT, MD_OUT},
247 #endif /* PAGEOUT */
248 #ifdef WRAP
249 {"wrap", WRAP, MD_OUT},
250 #endif /* WRAP */
252 #ifdef CIGNORE
253 {"cignore", CIGNORE, MD_CTL},
254 #endif /* CBAUD */
255 #ifdef CBAUD
256 {"cbaud", CBAUD, MD_CTL},
257 #endif /* CBAUD */
258 #ifdef CSTOPB
259 {"cstopb", CSTOPB, MD_CTL},
260 #endif /* CSTOPB */
261 #ifdef CREAD
262 {"cread", CREAD, MD_CTL},
263 #endif /* CREAD */
264 #ifdef PARENB
265 {"parenb", PARENB, MD_CTL},
266 #endif /* PARENB */
267 #ifdef PARODD
268 {"parodd", PARODD, MD_CTL},
269 #endif /* PARODD */
270 #ifdef HUPCL
271 {"hupcl", HUPCL, MD_CTL},
272 #endif /* HUPCL */
273 #ifdef CLOCAL
274 {"clocal", CLOCAL, MD_CTL},
275 #endif /* CLOCAL */
276 #ifdef LOBLK
277 {"loblk", LOBLK, MD_CTL},
278 #endif /* LOBLK */
279 #ifdef CIBAUD
280 {"cibaud", CIBAUD, MD_CTL},
281 #endif /* CIBAUD */
282 #ifdef CRTSCTS
283 #ifdef CCTS_OFLOW
284 {"ccts_oflow", CCTS_OFLOW, MD_CTL},
285 #else
286 {"crtscts", CRTSCTS, MD_CTL},
287 #endif /* CCTS_OFLOW */
288 #endif /* CRTSCTS */
289 #ifdef CRTS_IFLOW
290 {"crts_iflow", CRTS_IFLOW, MD_CTL},
291 #endif /* CRTS_IFLOW */
292 #ifdef CDTRCTS
293 {"cdtrcts", CDTRCTS, MD_CTL},
294 #endif /* CDTRCTS */
295 #ifdef MDMBUF
296 {"mdmbuf", MDMBUF, MD_CTL},
297 #endif /* MDMBUF */
298 #ifdef RCV1EN
299 {"rcv1en", RCV1EN, MD_CTL},
300 #endif /* RCV1EN */
301 #ifdef XMT1EN
302 {"xmt1en", XMT1EN, MD_CTL},
303 #endif /* XMT1EN */
305 #ifdef ISIG
306 {"isig", ISIG, MD_LIN},
307 #endif /* ISIG */
308 #ifdef ICANON
309 {"icanon", ICANON, MD_LIN},
310 #endif /* ICANON */
311 #ifdef XCASE
312 {"xcase", XCASE, MD_LIN},
313 #endif /* XCASE */
314 #ifdef ECHO
315 {"echo", ECHO, MD_LIN},
316 #endif /* ECHO */
317 #ifdef ECHOE
318 {"echoe", ECHOE, MD_LIN},
319 #endif /* ECHOE */
320 #ifdef ECHOK
321 {"echok", ECHOK, MD_LIN},
322 #endif /* ECHOK */
323 #ifdef ECHONL
324 {"echonl", ECHONL, MD_LIN},
325 #endif /* ECHONL */
326 #ifdef NOFLSH
327 {"noflsh", NOFLSH, MD_LIN},
328 #endif /* NOFLSH */
329 #ifdef TOSTOP
330 {"tostop", TOSTOP, MD_LIN},
331 #endif /* TOSTOP */
332 #ifdef ECHOCTL
333 {"echoctl", ECHOCTL, MD_LIN},
334 #endif /* ECHOCTL */
335 #ifdef ECHOPRT
336 {"echoprt", ECHOPRT, MD_LIN},
337 #endif /* ECHOPRT */
338 #ifdef ECHOKE
339 {"echoke", ECHOKE, MD_LIN},
340 #endif /* ECHOKE */
341 #ifdef DEFECHO
342 {"defecho", DEFECHO, MD_LIN},
343 #endif /* DEFECHO */
344 #ifdef FLUSHO
345 {"flusho", FLUSHO, MD_LIN},
346 #endif /* FLUSHO */
347 #ifdef PENDIN
348 {"pendin", PENDIN, MD_LIN},
349 #endif /* PENDIN */
350 #ifdef IEXTEN
351 {"iexten", IEXTEN, MD_LIN},
352 #endif /* IEXTEN */
353 #ifdef NOKERNINFO
354 {"nokerninfo", NOKERNINFO, MD_LIN},
355 #endif /* NOKERNINFO */
356 #ifdef ALTWERASE
357 {"altwerase", ALTWERASE, MD_LIN},
358 #endif /* ALTWERASE */
359 #ifdef EXTPROC
360 {"extproc", EXTPROC, MD_LIN},
361 #endif /* EXTPROC */
363 #if defined(VINTR)
364 {"intr", C_SH(C_INTR), MD_CHAR},
365 #endif /* VINTR */
366 #if defined(VQUIT)
367 {"quit", C_SH(C_QUIT), MD_CHAR},
368 #endif /* VQUIT */
369 #if defined(VERASE)
370 {"erase", C_SH(C_ERASE), MD_CHAR},
371 #endif /* VERASE */
372 #if defined(VKILL)
373 {"kill", C_SH(C_KILL), MD_CHAR},
374 #endif /* VKILL */
375 #if defined(VEOF)
376 {"eof", C_SH(C_EOF), MD_CHAR},
377 #endif /* VEOF */
378 #if defined(VEOL)
379 {"eol", C_SH(C_EOL), MD_CHAR},
380 #endif /* VEOL */
381 #if defined(VEOL2)
382 {"eol2", C_SH(C_EOL2), MD_CHAR},
383 #endif /* VEOL2 */
384 #if defined(VSWTCH)
385 {"swtch", C_SH(C_SWTCH), MD_CHAR},
386 #endif /* VSWTCH */
387 #if defined(VDSWTCH)
388 {"dswtch", C_SH(C_DSWTCH), MD_CHAR},
389 #endif /* VDSWTCH */
390 #if defined(VERASE2)
391 {"erase2", C_SH(C_ERASE2), MD_CHAR},
392 #endif /* VERASE2 */
393 #if defined(VSTART)
394 {"start", C_SH(C_START), MD_CHAR},
395 #endif /* VSTART */
396 #if defined(VSTOP)
397 {"stop", C_SH(C_STOP), MD_CHAR},
398 #endif /* VSTOP */
399 #if defined(VWERASE)
400 {"werase", C_SH(C_WERASE), MD_CHAR},
401 #endif /* VWERASE */
402 #if defined(VSUSP)
403 {"susp", C_SH(C_SUSP), MD_CHAR},
404 #endif /* VSUSP */
405 #if defined(VDSUSP)
406 {"dsusp", C_SH(C_DSUSP), MD_CHAR},
407 #endif /* VDSUSP */
408 #if defined(VREPRINT)
409 {"reprint", C_SH(C_REPRINT), MD_CHAR},
410 #endif /* VREPRINT */
411 #if defined(VDISCARD)
412 {"discard", C_SH(C_DISCARD), MD_CHAR},
413 #endif /* VDISCARD */
414 #if defined(VLNEXT)
415 {"lnext", C_SH(C_LNEXT), MD_CHAR},
416 #endif /* VLNEXT */
417 #if defined(VSTATUS)
418 {"status", C_SH(C_STATUS), MD_CHAR},
419 #endif /* VSTATUS */
420 #if defined(VPAGE)
421 {"page", C_SH(C_PAGE), MD_CHAR},
422 #endif /* VPAGE */
423 #if defined(VPGOFF)
424 {"pgoff", C_SH(C_PGOFF), MD_CHAR},
425 #endif /* VPGOFF */
426 #if defined(VKILL2)
427 {"kill2", C_SH(C_KILL2), MD_CHAR},
428 #endif /* VKILL2 */
429 #if defined(VBRK)
430 {"brk", C_SH(C_BRK), MD_CHAR},
431 #endif /* VBRK */
432 #if defined(VMIN)
433 {"min", C_SH(C_MIN), MD_CHAR},
434 #endif /* VMIN */
435 #if defined(VTIME)
436 {"time", C_SH(C_TIME), MD_CHAR},
437 #endif /* VTIME */
438 {NULL, 0, -1},
443 #define tty_getty(el, td) tcgetattr((el)->el_infd, (td))
444 #define tty_setty(el, td) tcsetattr((el)->el_infd, TCSADRAIN, (td))
446 #define tty__gettabs(td) ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1)
447 #define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8)
448 #define tty__cooked_mode(td) ((td)->c_lflag & ICANON)
450 private int tty__getcharindex(int);
451 private void tty__getchar(struct termios *, unsigned char *);
452 private void tty__setchar(struct termios *, unsigned char *);
453 private speed_t tty__getspeed(struct termios *);
454 private int tty_setup(EditLine *);
456 #define t_qu t_ts
459 /* tty_setup():
460 * Get the tty parameters and initialize the editing state
462 private int
463 tty_setup(EditLine *el)
465 int rst = 1;
467 if (el->el_flags & EDIT_DISABLED)
468 return (0);
470 if (tty_getty(el, &el->el_tty.t_ed) == -1) {
471 #ifdef DEBUG_TTY
472 (void) fprintf(el->el_errfile,
473 "tty_setup: tty_getty: %s\n", strerror(errno));
474 #endif /* DEBUG_TTY */
475 return (-1);
477 el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed;
479 el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex);
480 el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex);
481 el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex);
483 el->el_tty.t_ex.c_iflag &= ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask;
484 el->el_tty.t_ex.c_iflag |= el->el_tty.t_t[EX_IO][MD_INP].t_setmask;
486 el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask;
487 el->el_tty.t_ex.c_oflag |= el->el_tty.t_t[EX_IO][MD_OUT].t_setmask;
489 el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask;
490 el->el_tty.t_ex.c_cflag |= el->el_tty.t_t[EX_IO][MD_CTL].t_setmask;
492 el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask;
493 el->el_tty.t_ex.c_lflag |= el->el_tty.t_t[EX_IO][MD_LIN].t_setmask;
496 * Reset the tty chars to reasonable defaults
497 * If they are disabled, then enable them.
499 if (rst) {
500 if (tty__cooked_mode(&el->el_tty.t_ts)) {
501 tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
503 * Don't affect CMIN and CTIME for the editor mode
505 for (rst = 0; rst < C_NCC - 2; rst++)
506 if (el->el_tty.t_c[TS_IO][rst] !=
507 el->el_tty.t_vdisable
508 && el->el_tty.t_c[ED_IO][rst] !=
509 el->el_tty.t_vdisable)
510 el->el_tty.t_c[ED_IO][rst] =
511 el->el_tty.t_c[TS_IO][rst];
512 for (rst = 0; rst < C_NCC; rst++)
513 if (el->el_tty.t_c[TS_IO][rst] !=
514 el->el_tty.t_vdisable)
515 el->el_tty.t_c[EX_IO][rst] =
516 el->el_tty.t_c[TS_IO][rst];
518 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
519 if (tty_setty(el, &el->el_tty.t_ex) == -1) {
520 #ifdef DEBUG_TTY
521 (void) fprintf(el->el_errfile,
522 "tty_setup: tty_setty: %s\n",
523 strerror(errno));
524 #endif /* DEBUG_TTY */
525 return (-1);
528 #ifdef notdef
529 else
530 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
531 #endif
533 el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask;
534 el->el_tty.t_ed.c_iflag |= el->el_tty.t_t[ED_IO][MD_INP].t_setmask;
536 el->el_tty.t_ed.c_oflag &= ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask;
537 el->el_tty.t_ed.c_oflag |= el->el_tty.t_t[ED_IO][MD_OUT].t_setmask;
539 el->el_tty.t_ed.c_cflag &= ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask;
540 el->el_tty.t_ed.c_cflag |= el->el_tty.t_t[ED_IO][MD_CTL].t_setmask;
542 el->el_tty.t_ed.c_lflag &= ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask;
543 el->el_tty.t_ed.c_lflag |= el->el_tty.t_t[ED_IO][MD_LIN].t_setmask;
545 tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
546 tty_bind_char(el, 1);
547 return (0);
550 protected int
551 tty_init(EditLine *el)
554 el->el_tty.t_mode = EX_IO;
555 el->el_tty.t_vdisable = _POSIX_VDISABLE;
556 (void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t));
557 (void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t));
558 return (tty_setup(el));
562 /* tty_end():
563 * Restore the tty to its original settings
565 protected void
566 /*ARGSUSED*/
567 tty_end(EditLine *el __attribute__((__unused__)))
570 /* XXX: Maybe reset to an initial state? */
574 /* tty__getspeed():
575 * Get the tty speed
577 private speed_t
578 tty__getspeed(struct termios *td)
580 speed_t spd;
582 if ((spd = cfgetispeed(td)) == 0)
583 spd = cfgetospeed(td);
584 return (spd);
587 /* tty__getspeed():
588 * Return the index of the asked char in the c_cc array
590 private int
591 tty__getcharindex(int i)
593 switch (i) {
594 #ifdef VINTR
595 case C_INTR:
596 return VINTR;
597 #endif /* VINTR */
598 #ifdef VQUIT
599 case C_QUIT:
600 return VQUIT;
601 #endif /* VQUIT */
602 #ifdef VERASE
603 case C_ERASE:
604 return VERASE;
605 #endif /* VERASE */
606 #ifdef VKILL
607 case C_KILL:
608 return VKILL;
609 #endif /* VKILL */
610 #ifdef VEOF
611 case C_EOF:
612 return VEOF;
613 #endif /* VEOF */
614 #ifdef VEOL
615 case C_EOL:
616 return VEOL;
617 #endif /* VEOL */
618 #ifdef VEOL2
619 case C_EOL2:
620 return VEOL2;
621 #endif /* VEOL2 */
622 #ifdef VSWTCH
623 case C_SWTCH:
624 return VSWTCH;
625 #endif /* VSWTCH */
626 #ifdef VDSWTCH
627 case C_DSWTCH:
628 return VDSWTCH;
629 #endif /* VDSWTCH */
630 #ifdef VERASE2
631 case C_ERASE2:
632 return VERASE2;
633 #endif /* VERASE2 */
634 #ifdef VSTART
635 case C_START:
636 return VSTART;
637 #endif /* VSTART */
638 #ifdef VSTOP
639 case C_STOP:
640 return VSTOP;
641 #endif /* VSTOP */
642 #ifdef VWERASE
643 case C_WERASE:
644 return VWERASE;
645 #endif /* VWERASE */
646 #ifdef VSUSP
647 case C_SUSP:
648 return VSUSP;
649 #endif /* VSUSP */
650 #ifdef VDSUSP
651 case C_DSUSP:
652 return VDSUSP;
653 #endif /* VDSUSP */
654 #ifdef VREPRINT
655 case C_REPRINT:
656 return VREPRINT;
657 #endif /* VREPRINT */
658 #ifdef VDISCARD
659 case C_DISCARD:
660 return VDISCARD;
661 #endif /* VDISCARD */
662 #ifdef VLNEXT
663 case C_LNEXT:
664 return VLNEXT;
665 #endif /* VLNEXT */
666 #ifdef VSTATUS
667 case C_STATUS:
668 return VSTATUS;
669 #endif /* VSTATUS */
670 #ifdef VPAGE
671 case C_PAGE:
672 return VPAGE;
673 #endif /* VPAGE */
674 #ifdef VPGOFF
675 case C_PGOFF:
676 return VPGOFF;
677 #endif /* VPGOFF */
678 #ifdef VKILL2
679 case C_KILL2:
680 return VKILL2;
681 #endif /* KILL2 */
682 #ifdef VMIN
683 case C_MIN:
684 return VMIN;
685 #endif /* VMIN */
686 #ifdef VTIME
687 case C_TIME:
688 return VTIME;
689 #endif /* VTIME */
690 default:
691 return -1;
695 /* tty__getchar():
696 * Get the tty characters
698 private void
699 tty__getchar(struct termios *td, unsigned char *s)
702 #ifdef VINTR
703 s[C_INTR] = td->c_cc[VINTR];
704 #endif /* VINTR */
705 #ifdef VQUIT
706 s[C_QUIT] = td->c_cc[VQUIT];
707 #endif /* VQUIT */
708 #ifdef VERASE
709 s[C_ERASE] = td->c_cc[VERASE];
710 #endif /* VERASE */
711 #ifdef VKILL
712 s[C_KILL] = td->c_cc[VKILL];
713 #endif /* VKILL */
714 #ifdef VEOF
715 s[C_EOF] = td->c_cc[VEOF];
716 #endif /* VEOF */
717 #ifdef VEOL
718 s[C_EOL] = td->c_cc[VEOL];
719 #endif /* VEOL */
720 #ifdef VEOL2
721 s[C_EOL2] = td->c_cc[VEOL2];
722 #endif /* VEOL2 */
723 #ifdef VSWTCH
724 s[C_SWTCH] = td->c_cc[VSWTCH];
725 #endif /* VSWTCH */
726 #ifdef VDSWTCH
727 s[C_DSWTCH] = td->c_cc[VDSWTCH];
728 #endif /* VDSWTCH */
729 #ifdef VERASE2
730 s[C_ERASE2] = td->c_cc[VERASE2];
731 #endif /* VERASE2 */
732 #ifdef VSTART
733 s[C_START] = td->c_cc[VSTART];
734 #endif /* VSTART */
735 #ifdef VSTOP
736 s[C_STOP] = td->c_cc[VSTOP];
737 #endif /* VSTOP */
738 #ifdef VWERASE
739 s[C_WERASE] = td->c_cc[VWERASE];
740 #endif /* VWERASE */
741 #ifdef VSUSP
742 s[C_SUSP] = td->c_cc[VSUSP];
743 #endif /* VSUSP */
744 #ifdef VDSUSP
745 s[C_DSUSP] = td->c_cc[VDSUSP];
746 #endif /* VDSUSP */
747 #ifdef VREPRINT
748 s[C_REPRINT] = td->c_cc[VREPRINT];
749 #endif /* VREPRINT */
750 #ifdef VDISCARD
751 s[C_DISCARD] = td->c_cc[VDISCARD];
752 #endif /* VDISCARD */
753 #ifdef VLNEXT
754 s[C_LNEXT] = td->c_cc[VLNEXT];
755 #endif /* VLNEXT */
756 #ifdef VSTATUS
757 s[C_STATUS] = td->c_cc[VSTATUS];
758 #endif /* VSTATUS */
759 #ifdef VPAGE
760 s[C_PAGE] = td->c_cc[VPAGE];
761 #endif /* VPAGE */
762 #ifdef VPGOFF
763 s[C_PGOFF] = td->c_cc[VPGOFF];
764 #endif /* VPGOFF */
765 #ifdef VKILL2
766 s[C_KILL2] = td->c_cc[VKILL2];
767 #endif /* KILL2 */
768 #ifdef VMIN
769 s[C_MIN] = td->c_cc[VMIN];
770 #endif /* VMIN */
771 #ifdef VTIME
772 s[C_TIME] = td->c_cc[VTIME];
773 #endif /* VTIME */
774 } /* tty__getchar */
777 /* tty__setchar():
778 * Set the tty characters
780 private void
781 tty__setchar(struct termios *td, unsigned char *s)
784 #ifdef VINTR
785 td->c_cc[VINTR] = s[C_INTR];
786 #endif /* VINTR */
787 #ifdef VQUIT
788 td->c_cc[VQUIT] = s[C_QUIT];
789 #endif /* VQUIT */
790 #ifdef VERASE
791 td->c_cc[VERASE] = s[C_ERASE];
792 #endif /* VERASE */
793 #ifdef VKILL
794 td->c_cc[VKILL] = s[C_KILL];
795 #endif /* VKILL */
796 #ifdef VEOF
797 td->c_cc[VEOF] = s[C_EOF];
798 #endif /* VEOF */
799 #ifdef VEOL
800 td->c_cc[VEOL] = s[C_EOL];
801 #endif /* VEOL */
802 #ifdef VEOL2
803 td->c_cc[VEOL2] = s[C_EOL2];
804 #endif /* VEOL2 */
805 #ifdef VSWTCH
806 td->c_cc[VSWTCH] = s[C_SWTCH];
807 #endif /* VSWTCH */
808 #ifdef VDSWTCH
809 td->c_cc[VDSWTCH] = s[C_DSWTCH];
810 #endif /* VDSWTCH */
811 #ifdef VERASE2
812 td->c_cc[VERASE2] = s[C_ERASE2];
813 #endif /* VERASE2 */
814 #ifdef VSTART
815 td->c_cc[VSTART] = s[C_START];
816 #endif /* VSTART */
817 #ifdef VSTOP
818 td->c_cc[VSTOP] = s[C_STOP];
819 #endif /* VSTOP */
820 #ifdef VWERASE
821 td->c_cc[VWERASE] = s[C_WERASE];
822 #endif /* VWERASE */
823 #ifdef VSUSP
824 td->c_cc[VSUSP] = s[C_SUSP];
825 #endif /* VSUSP */
826 #ifdef VDSUSP
827 td->c_cc[VDSUSP] = s[C_DSUSP];
828 #endif /* VDSUSP */
829 #ifdef VREPRINT
830 td->c_cc[VREPRINT] = s[C_REPRINT];
831 #endif /* VREPRINT */
832 #ifdef VDISCARD
833 td->c_cc[VDISCARD] = s[C_DISCARD];
834 #endif /* VDISCARD */
835 #ifdef VLNEXT
836 td->c_cc[VLNEXT] = s[C_LNEXT];
837 #endif /* VLNEXT */
838 #ifdef VSTATUS
839 td->c_cc[VSTATUS] = s[C_STATUS];
840 #endif /* VSTATUS */
841 #ifdef VPAGE
842 td->c_cc[VPAGE] = s[C_PAGE];
843 #endif /* VPAGE */
844 #ifdef VPGOFF
845 td->c_cc[VPGOFF] = s[C_PGOFF];
846 #endif /* VPGOFF */
847 #ifdef VKILL2
848 td->c_cc[VKILL2] = s[C_KILL2];
849 #endif /* VKILL2 */
850 #ifdef VMIN
851 td->c_cc[VMIN] = s[C_MIN];
852 #endif /* VMIN */
853 #ifdef VTIME
854 td->c_cc[VTIME] = s[C_TIME];
855 #endif /* VTIME */
856 } /* tty__setchar */
859 /* tty_bind_char():
860 * Rebind the editline functions
862 protected void
863 tty_bind_char(EditLine *el, int force)
866 unsigned char *t_n = el->el_tty.t_c[ED_IO];
867 unsigned char *t_o = el->el_tty.t_ed.c_cc;
868 unsigned char new[2], old[2];
869 const ttymap_t *tp;
870 el_action_t *map, *alt;
871 const el_action_t *dmap, *dalt;
872 new[1] = old[1] = '\0';
874 map = el->el_map.key;
875 alt = el->el_map.alt;
876 if (el->el_map.type == MAP_VI) {
877 dmap = el->el_map.vii;
878 dalt = el->el_map.vic;
879 } else {
880 dmap = el->el_map.emacs;
881 dalt = NULL;
884 for (tp = tty_map; tp->nch != -1; tp++) {
885 new[0] = t_n[tp->nch];
886 old[0] = t_o[tp->och];
887 if (new[0] == old[0] && !force)
888 continue;
889 /* Put the old default binding back, and set the new binding */
890 key_clear(el, map, (char *)old);
891 map[old[0]] = dmap[old[0]];
892 key_clear(el, map, (char *)new);
893 /* MAP_VI == 1, MAP_EMACS == 0... */
894 map[new[0]] = tp->bind[el->el_map.type];
895 if (dalt) {
896 key_clear(el, alt, (char *)old);
897 alt[old[0]] = dalt[old[0]];
898 key_clear(el, alt, (char *)new);
899 alt[new[0]] = tp->bind[el->el_map.type + 1];
905 /* tty_rawmode():
906 * Set terminal into 1 character at a time mode.
908 protected int
909 tty_rawmode(EditLine *el)
912 if (el->el_tty.t_mode == ED_IO || el->el_tty.t_mode == QU_IO)
913 return (0);
915 if (el->el_flags & EDIT_DISABLED)
916 return (0);
918 if (tty_getty(el, &el->el_tty.t_ts) == -1) {
919 #ifdef DEBUG_TTY
920 (void) fprintf(el->el_errfile, "tty_rawmode: tty_getty: %s\n",
921 strerror(errno));
922 #endif /* DEBUG_TTY */
923 return (-1);
926 * We always keep up with the eight bit setting and the speed of the
927 * tty. But only we only believe changes that are made to cooked mode!
929 el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts);
930 el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts);
932 if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed ||
933 tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) {
934 (void) cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed);
935 (void) cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed);
936 (void) cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed);
937 (void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed);
939 if (tty__cooked_mode(&el->el_tty.t_ts)) {
940 if (el->el_tty.t_ts.c_cflag != el->el_tty.t_ex.c_cflag) {
941 el->el_tty.t_ex.c_cflag =
942 el->el_tty.t_ts.c_cflag;
943 el->el_tty.t_ex.c_cflag &=
944 ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask;
945 el->el_tty.t_ex.c_cflag |=
946 el->el_tty.t_t[EX_IO][MD_CTL].t_setmask;
948 el->el_tty.t_ed.c_cflag =
949 el->el_tty.t_ts.c_cflag;
950 el->el_tty.t_ed.c_cflag &=
951 ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask;
952 el->el_tty.t_ed.c_cflag |=
953 el->el_tty.t_t[ED_IO][MD_CTL].t_setmask;
955 if ((el->el_tty.t_ts.c_lflag != el->el_tty.t_ex.c_lflag) &&
956 (el->el_tty.t_ts.c_lflag != el->el_tty.t_ed.c_lflag)) {
957 el->el_tty.t_ex.c_lflag =
958 el->el_tty.t_ts.c_lflag;
959 el->el_tty.t_ex.c_lflag &=
960 ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask;
961 el->el_tty.t_ex.c_lflag |=
962 el->el_tty.t_t[EX_IO][MD_LIN].t_setmask;
964 el->el_tty.t_ed.c_lflag =
965 el->el_tty.t_ts.c_lflag;
966 el->el_tty.t_ed.c_lflag &=
967 ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask;
968 el->el_tty.t_ed.c_lflag |=
969 el->el_tty.t_t[ED_IO][MD_LIN].t_setmask;
971 if ((el->el_tty.t_ts.c_iflag != el->el_tty.t_ex.c_iflag) &&
972 (el->el_tty.t_ts.c_iflag != el->el_tty.t_ed.c_iflag)) {
973 el->el_tty.t_ex.c_iflag =
974 el->el_tty.t_ts.c_iflag;
975 el->el_tty.t_ex.c_iflag &=
976 ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask;
977 el->el_tty.t_ex.c_iflag |=
978 el->el_tty.t_t[EX_IO][MD_INP].t_setmask;
980 el->el_tty.t_ed.c_iflag =
981 el->el_tty.t_ts.c_iflag;
982 el->el_tty.t_ed.c_iflag &=
983 ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask;
984 el->el_tty.t_ed.c_iflag |=
985 el->el_tty.t_t[ED_IO][MD_INP].t_setmask;
987 if ((el->el_tty.t_ts.c_oflag != el->el_tty.t_ex.c_oflag) &&
988 (el->el_tty.t_ts.c_oflag != el->el_tty.t_ed.c_oflag)) {
989 el->el_tty.t_ex.c_oflag =
990 el->el_tty.t_ts.c_oflag;
991 el->el_tty.t_ex.c_oflag &=
992 ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask;
993 el->el_tty.t_ex.c_oflag |=
994 el->el_tty.t_t[EX_IO][MD_OUT].t_setmask;
996 el->el_tty.t_ed.c_oflag =
997 el->el_tty.t_ts.c_oflag;
998 el->el_tty.t_ed.c_oflag &=
999 ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask;
1000 el->el_tty.t_ed.c_oflag |=
1001 el->el_tty.t_t[ED_IO][MD_OUT].t_setmask;
1003 if (tty__gettabs(&el->el_tty.t_ex) == 0)
1004 el->el_tty.t_tabs = 0;
1005 else
1006 el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0;
1009 int i;
1011 tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
1013 * Check if the user made any changes.
1014 * If he did, then propagate the changes to the
1015 * edit and execute data structures.
1017 for (i = 0; i < C_NCC; i++)
1018 if (el->el_tty.t_c[TS_IO][i] !=
1019 el->el_tty.t_c[EX_IO][i])
1020 break;
1022 if (i != C_NCC) {
1024 * Propagate changes only to the unprotected
1025 * chars that have been modified just now.
1027 for (i = 0; i < C_NCC; i++) {
1028 if (!((el->el_tty.t_t[ED_IO][MD_CHAR].t_setmask & C_SH(i)))
1029 && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
1030 el->el_tty.t_c[ED_IO][i] = el->el_tty.t_c[TS_IO][i];
1031 if (el->el_tty.t_t[ED_IO][MD_CHAR].t_clrmask & C_SH(i))
1032 el->el_tty.t_c[ED_IO][i] = el->el_tty.t_vdisable;
1034 tty_bind_char(el, 0);
1035 tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
1037 for (i = 0; i < C_NCC; i++) {
1038 if (!((el->el_tty.t_t[EX_IO][MD_CHAR].t_setmask & C_SH(i)))
1039 && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
1040 el->el_tty.t_c[EX_IO][i] = el->el_tty.t_c[TS_IO][i];
1041 if (el->el_tty.t_t[EX_IO][MD_CHAR].t_clrmask & C_SH(i))
1042 el->el_tty.t_c[EX_IO][i] = el->el_tty.t_vdisable;
1044 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
1048 if (tty_setty(el, &el->el_tty.t_ed) == -1) {
1049 #ifdef DEBUG_TTY
1050 (void) fprintf(el->el_errfile, "tty_rawmode: tty_setty: %s\n",
1051 strerror(errno));
1052 #endif /* DEBUG_TTY */
1053 return (-1);
1055 el->el_tty.t_mode = ED_IO;
1056 return (0);
1060 /* tty_cookedmode():
1061 * Set the tty back to normal mode
1063 protected int
1064 tty_cookedmode(EditLine *el)
1065 { /* set tty in normal setup */
1067 if (el->el_tty.t_mode == EX_IO)
1068 return (0);
1070 if (el->el_flags & EDIT_DISABLED)
1071 return (0);
1073 if (tty_setty(el, &el->el_tty.t_ex) == -1) {
1074 #ifdef DEBUG_TTY
1075 (void) fprintf(el->el_errfile,
1076 "tty_cookedmode: tty_setty: %s\n",
1077 strerror(errno));
1078 #endif /* DEBUG_TTY */
1079 return (-1);
1081 el->el_tty.t_mode = EX_IO;
1082 return (0);
1086 /* tty_quotemode():
1087 * Turn on quote mode
1089 protected int
1090 tty_quotemode(EditLine *el)
1092 if (el->el_tty.t_mode == QU_IO)
1093 return (0);
1095 el->el_tty.t_qu = el->el_tty.t_ed;
1097 el->el_tty.t_qu.c_iflag &= ~el->el_tty.t_t[QU_IO][MD_INP].t_clrmask;
1098 el->el_tty.t_qu.c_iflag |= el->el_tty.t_t[QU_IO][MD_INP].t_setmask;
1100 el->el_tty.t_qu.c_oflag &= ~el->el_tty.t_t[QU_IO][MD_OUT].t_clrmask;
1101 el->el_tty.t_qu.c_oflag |= el->el_tty.t_t[QU_IO][MD_OUT].t_setmask;
1103 el->el_tty.t_qu.c_cflag &= ~el->el_tty.t_t[QU_IO][MD_CTL].t_clrmask;
1104 el->el_tty.t_qu.c_cflag |= el->el_tty.t_t[QU_IO][MD_CTL].t_setmask;
1106 el->el_tty.t_qu.c_lflag &= ~el->el_tty.t_t[QU_IO][MD_LIN].t_clrmask;
1107 el->el_tty.t_qu.c_lflag |= el->el_tty.t_t[QU_IO][MD_LIN].t_setmask;
1109 if (tty_setty(el, &el->el_tty.t_qu) == -1) {
1110 #ifdef DEBUG_TTY
1111 (void) fprintf(el->el_errfile, "QuoteModeOn: tty_setty: %s\n",
1112 strerror(errno));
1113 #endif /* DEBUG_TTY */
1114 return (-1);
1116 el->el_tty.t_mode = QU_IO;
1117 return (0);
1121 /* tty_noquotemode():
1122 * Turn off quote mode
1124 protected int
1125 tty_noquotemode(EditLine *el)
1128 if (el->el_tty.t_mode != QU_IO)
1129 return (0);
1130 if (tty_setty(el, &el->el_tty.t_ed) == -1) {
1131 #ifdef DEBUG_TTY
1132 (void) fprintf(el->el_errfile, "QuoteModeOff: tty_setty: %s\n",
1133 strerror(errno));
1134 #endif /* DEBUG_TTY */
1135 return (-1);
1137 el->el_tty.t_mode = ED_IO;
1138 return (0);
1142 /* tty_stty():
1143 * Stty builtin
1145 protected int
1146 /*ARGSUSED*/
1147 tty_stty(EditLine *el, int argc __attribute__((__unused__)), const char **argv)
1149 const ttymodes_t *m;
1150 char x;
1151 int aflag = 0;
1152 const char *s, *d;
1153 const char *name;
1154 struct termios *tios = &el->el_tty.t_ex;
1155 int z = EX_IO;
1157 if (argv == NULL)
1158 return (-1);
1159 name = *argv++;
1161 while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0')
1162 switch (argv[0][1]) {
1163 case 'a':
1164 aflag++;
1165 argv++;
1166 break;
1167 case 'd':
1168 argv++;
1169 tios = &el->el_tty.t_ed;
1170 z = ED_IO;
1171 break;
1172 case 'x':
1173 argv++;
1174 tios = &el->el_tty.t_ex;
1175 z = EX_IO;
1176 break;
1177 case 'q':
1178 argv++;
1179 tios = &el->el_tty.t_ts;
1180 z = QU_IO;
1181 break;
1182 default:
1183 (void) fprintf(el->el_errfile,
1184 "%s: Unknown switch `%c'.\n",
1185 name, argv[0][1]);
1186 return (-1);
1189 if (!argv || !*argv) {
1190 int i = -1;
1191 int len = 0, st = 0, cu;
1192 for (m = ttymodes; m->m_name; m++) {
1193 if (m->m_type != i) {
1194 (void) fprintf(el->el_outfile, "%s%s",
1195 i != -1 ? "\n" : "",
1196 el->el_tty.t_t[z][m->m_type].t_name);
1197 i = m->m_type;
1198 st = len =
1199 strlen(el->el_tty.t_t[z][m->m_type].t_name);
1201 if (i != -1) {
1202 x = (el->el_tty.t_t[z][i].t_setmask & m->m_value)
1203 ? '+' : '\0';
1204 x = (el->el_tty.t_t[z][i].t_clrmask & m->m_value)
1205 ? '-' : x;
1206 } else {
1207 x = '\0';
1210 if (x != '\0' || aflag) {
1212 cu = strlen(m->m_name) + (x != '\0') + 1;
1214 if (len + cu >= el->el_term.t_size.h) {
1215 (void) fprintf(el->el_outfile, "\n%*s",
1216 st, "");
1217 len = st + cu;
1218 } else
1219 len += cu;
1221 if (x != '\0')
1222 (void) fprintf(el->el_outfile, "%c%s ",
1223 x, m->m_name);
1224 else
1225 (void) fprintf(el->el_outfile, "%s ",
1226 m->m_name);
1229 (void) fprintf(el->el_outfile, "\n");
1230 return (0);
1232 while (argv && (s = *argv++)) {
1233 const char *p;
1234 switch (*s) {
1235 case '+':
1236 case '-':
1237 x = *s++;
1238 break;
1239 default:
1240 x = '\0';
1241 break;
1243 d = s;
1244 p = strchr(s, '=');
1245 for (m = ttymodes; m->m_name; m++)
1246 if ((p ? strncmp(m->m_name, d, (size_t)(p - d)) :
1247 strcmp(m->m_name, d)) == 0 &&
1248 (p == NULL || m->m_type == MD_CHAR))
1249 break;
1251 if (!m->m_name) {
1252 (void) fprintf(el->el_errfile,
1253 "%s: Invalid argument `%s'.\n", name, d);
1254 return (-1);
1256 if (p) {
1257 int c = ffs((int)m->m_value);
1258 int v = *++p ? parse__escape((const char **) &p) :
1259 el->el_tty.t_vdisable;
1260 assert(c-- != 0);
1261 c = tty__getcharindex(c);
1262 assert(c != -1);
1263 tios->c_cc[c] = v;
1264 continue;
1266 switch (x) {
1267 case '+':
1268 el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value;
1269 el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
1270 break;
1271 case '-':
1272 el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
1273 el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value;
1274 break;
1275 default:
1276 el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
1277 el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
1278 break;
1281 return (0);
1285 #ifdef notyet
1286 /* tty_printchar():
1287 * DEbugging routine to print the tty characters
1289 private void
1290 tty_printchar(EditLine *el, unsigned char *s)
1292 ttyperm_t *m;
1293 int i;
1295 for (i = 0; i < C_NCC; i++) {
1296 for (m = el->el_tty.t_t; m->m_name; m++)
1297 if (m->m_type == MD_CHAR && C_SH(i) == m->m_value)
1298 break;
1299 if (m->m_name)
1300 (void) fprintf(el->el_errfile, "%s ^%c ",
1301 m->m_name, s[i] + 'A' - 1);
1302 if (i % 5 == 0)
1303 (void) fprintf(el->el_errfile, "\n");
1305 (void) fprintf(el->el_errfile, "\n");
1307 #endif /* notyet */