ldivmod, uldivmod: fix qdivrem calls
[minix.git] / lib / libedit / tty.c
blob57c8ee8916c8824876b8b76422a1fff6d49e25b1
1 /* $NetBSD: tty.c,v 1.42 2012/05/15 15:59: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. 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.42 2012/05/15 15:59:01 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 <unistd.h> /* for isatty */
50 #include <strings.h> /* for ffs */
51 #include "el.h"
52 #include "tty.h"
54 typedef struct ttymodes_t {
55 const char *m_name;
56 unsigned 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 {EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
128 #endif /* VERASE */
129 #ifdef VERASE2
130 {C_ERASE2, VERASE2,
131 {EM_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 {(Int)-1, (Int)-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__gettabs(td) ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1)
452 #define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8)
453 #define tty__cooked_mode(td) ((td)->c_lflag & ICANON)
455 private int tty_getty(EditLine *, struct termios *);
456 private int tty_setty(EditLine *, int, const struct termios *);
457 private int tty__getcharindex(int);
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
465 /* tty_getty():
466 * Wrapper for tcgetattr to handle EINTR
468 private int
469 tty_getty(EditLine *el, struct termios *t)
471 int rv;
472 while ((rv = tcgetattr(el->el_infd, t)) == -1 && errno == EINTR)
473 continue;
474 return rv;
477 /* tty_setty():
478 * Wrapper for tcsetattr to handle EINTR
480 private int
481 tty_setty(EditLine *el, int action, const struct termios *t)
483 int rv;
484 while ((rv = tcsetattr(el->el_infd, action, t)) == -1 && errno == EINTR)
485 continue;
486 return rv;
489 /* tty_setup():
490 * Get the tty parameters and initialize the editing state
492 private int
493 tty_setup(EditLine *el)
495 int rst = 1;
497 if (el->el_flags & EDIT_DISABLED)
498 return 0;
500 if (!isatty(el->el_outfd)) {
501 #ifdef DEBUG_TTY
502 (void) fprintf(el->el_errfile, "%s: isatty: %s\n", __func__,
503 strerror(errno));
504 #endif /* DEBUG_TTY */
505 return -1;
507 if (tty_getty(el, &el->el_tty.t_or) == -1) {
508 #ifdef DEBUG_TTY
509 (void) fprintf(el->el_errfile, "%s: tty_getty: %s\n", __func__,
510 strerror(errno));
511 #endif /* DEBUG_TTY */
512 return -1;
514 el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed = el->el_tty.t_or;
516 el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex);
517 el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex);
518 el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex);
520 el->el_tty.t_ex.c_iflag &= ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask;
521 el->el_tty.t_ex.c_iflag |= el->el_tty.t_t[EX_IO][MD_INP].t_setmask;
523 el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask;
524 el->el_tty.t_ex.c_oflag |= el->el_tty.t_t[EX_IO][MD_OUT].t_setmask;
526 el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask;
527 el->el_tty.t_ex.c_cflag |= el->el_tty.t_t[EX_IO][MD_CTL].t_setmask;
529 el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask;
530 el->el_tty.t_ex.c_lflag |= el->el_tty.t_t[EX_IO][MD_LIN].t_setmask;
533 * Reset the tty chars to reasonable defaults
534 * If they are disabled, then enable them.
536 if (rst) {
537 if (tty__cooked_mode(&el->el_tty.t_ts)) {
538 tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
540 * Don't affect CMIN and CTIME for the editor mode
542 for (rst = 0; rst < C_NCC - 2; rst++)
543 if (el->el_tty.t_c[TS_IO][rst] !=
544 el->el_tty.t_vdisable
545 && el->el_tty.t_c[ED_IO][rst] !=
546 el->el_tty.t_vdisable)
547 el->el_tty.t_c[ED_IO][rst] =
548 el->el_tty.t_c[TS_IO][rst];
549 for (rst = 0; rst < C_NCC; rst++)
550 if (el->el_tty.t_c[TS_IO][rst] !=
551 el->el_tty.t_vdisable)
552 el->el_tty.t_c[EX_IO][rst] =
553 el->el_tty.t_c[TS_IO][rst];
555 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
556 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) {
557 #ifdef DEBUG_TTY
558 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n",
559 __func__, strerror(errno));
560 #endif /* DEBUG_TTY */
561 return -1;
565 el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask;
566 el->el_tty.t_ed.c_iflag |= el->el_tty.t_t[ED_IO][MD_INP].t_setmask;
568 el->el_tty.t_ed.c_oflag &= ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask;
569 el->el_tty.t_ed.c_oflag |= el->el_tty.t_t[ED_IO][MD_OUT].t_setmask;
571 el->el_tty.t_ed.c_cflag &= ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask;
572 el->el_tty.t_ed.c_cflag |= el->el_tty.t_t[ED_IO][MD_CTL].t_setmask;
574 el->el_tty.t_ed.c_lflag &= ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask;
575 el->el_tty.t_ed.c_lflag |= el->el_tty.t_t[ED_IO][MD_LIN].t_setmask;
577 tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
578 tty_bind_char(el, 1);
579 return 0;
582 protected int
583 tty_init(EditLine *el)
586 el->el_tty.t_mode = EX_IO;
587 el->el_tty.t_vdisable = _POSIX_VDISABLE;
588 (void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t));
589 (void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t));
590 return tty_setup(el);
594 /* tty_end():
595 * Restore the tty to its original settings
597 protected void
598 /*ARGSUSED*/
599 tty_end(EditLine *el)
601 if (tty_setty(el, TCSAFLUSH, &el->el_tty.t_or) == -1) {
602 #ifdef DEBUG_TTY
603 (void) fprintf(el->el_errfile,
604 "%s: tty_setty: %s\n", __func__, strerror(errno));
605 #endif /* DEBUG_TTY */
610 /* tty__getspeed():
611 * Get the tty speed
613 private speed_t
614 tty__getspeed(struct termios *td)
616 speed_t spd;
618 if ((spd = cfgetispeed(td)) == 0)
619 spd = cfgetospeed(td);
620 return spd;
623 /* tty__getspeed():
624 * Return the index of the asked char in the c_cc array
626 private int
627 tty__getcharindex(int i)
629 switch (i) {
630 #ifdef VINTR
631 case C_INTR:
632 return VINTR;
633 #endif /* VINTR */
634 #ifdef VQUIT
635 case C_QUIT:
636 return VQUIT;
637 #endif /* VQUIT */
638 #ifdef VERASE
639 case C_ERASE:
640 return VERASE;
641 #endif /* VERASE */
642 #ifdef VKILL
643 case C_KILL:
644 return VKILL;
645 #endif /* VKILL */
646 #ifdef VEOF
647 case C_EOF:
648 return VEOF;
649 #endif /* VEOF */
650 #ifdef VEOL
651 case C_EOL:
652 return VEOL;
653 #endif /* VEOL */
654 #ifdef VEOL2
655 case C_EOL2:
656 return VEOL2;
657 #endif /* VEOL2 */
658 #ifdef VSWTCH
659 case C_SWTCH:
660 return VSWTCH;
661 #endif /* VSWTCH */
662 #ifdef VDSWTCH
663 case C_DSWTCH:
664 return VDSWTCH;
665 #endif /* VDSWTCH */
666 #ifdef VERASE2
667 case C_ERASE2:
668 return VERASE2;
669 #endif /* VERASE2 */
670 #ifdef VSTART
671 case C_START:
672 return VSTART;
673 #endif /* VSTART */
674 #ifdef VSTOP
675 case C_STOP:
676 return VSTOP;
677 #endif /* VSTOP */
678 #ifdef VWERASE
679 case C_WERASE:
680 return VWERASE;
681 #endif /* VWERASE */
682 #ifdef VSUSP
683 case C_SUSP:
684 return VSUSP;
685 #endif /* VSUSP */
686 #ifdef VDSUSP
687 case C_DSUSP:
688 return VDSUSP;
689 #endif /* VDSUSP */
690 #ifdef VREPRINT
691 case C_REPRINT:
692 return VREPRINT;
693 #endif /* VREPRINT */
694 #ifdef VDISCARD
695 case C_DISCARD:
696 return VDISCARD;
697 #endif /* VDISCARD */
698 #ifdef VLNEXT
699 case C_LNEXT:
700 return VLNEXT;
701 #endif /* VLNEXT */
702 #ifdef VSTATUS
703 case C_STATUS:
704 return VSTATUS;
705 #endif /* VSTATUS */
706 #ifdef VPAGE
707 case C_PAGE:
708 return VPAGE;
709 #endif /* VPAGE */
710 #ifdef VPGOFF
711 case C_PGOFF:
712 return VPGOFF;
713 #endif /* VPGOFF */
714 #ifdef VKILL2
715 case C_KILL2:
716 return VKILL2;
717 #endif /* KILL2 */
718 #ifdef VMIN
719 case C_MIN:
720 return VMIN;
721 #endif /* VMIN */
722 #ifdef VTIME
723 case C_TIME:
724 return VTIME;
725 #endif /* VTIME */
726 default:
727 return -1;
731 /* tty__getchar():
732 * Get the tty characters
734 private void
735 tty__getchar(struct termios *td, unsigned char *s)
738 #ifdef VINTR
739 s[C_INTR] = td->c_cc[VINTR];
740 #endif /* VINTR */
741 #ifdef VQUIT
742 s[C_QUIT] = td->c_cc[VQUIT];
743 #endif /* VQUIT */
744 #ifdef VERASE
745 s[C_ERASE] = td->c_cc[VERASE];
746 #endif /* VERASE */
747 #ifdef VKILL
748 s[C_KILL] = td->c_cc[VKILL];
749 #endif /* VKILL */
750 #ifdef VEOF
751 s[C_EOF] = td->c_cc[VEOF];
752 #endif /* VEOF */
753 #ifdef VEOL
754 s[C_EOL] = td->c_cc[VEOL];
755 #endif /* VEOL */
756 #ifdef VEOL2
757 s[C_EOL2] = td->c_cc[VEOL2];
758 #endif /* VEOL2 */
759 #ifdef VSWTCH
760 s[C_SWTCH] = td->c_cc[VSWTCH];
761 #endif /* VSWTCH */
762 #ifdef VDSWTCH
763 s[C_DSWTCH] = td->c_cc[VDSWTCH];
764 #endif /* VDSWTCH */
765 #ifdef VERASE2
766 s[C_ERASE2] = td->c_cc[VERASE2];
767 #endif /* VERASE2 */
768 #ifdef VSTART
769 s[C_START] = td->c_cc[VSTART];
770 #endif /* VSTART */
771 #ifdef VSTOP
772 s[C_STOP] = td->c_cc[VSTOP];
773 #endif /* VSTOP */
774 #ifdef VWERASE
775 s[C_WERASE] = td->c_cc[VWERASE];
776 #endif /* VWERASE */
777 #ifdef VSUSP
778 s[C_SUSP] = td->c_cc[VSUSP];
779 #endif /* VSUSP */
780 #ifdef VDSUSP
781 s[C_DSUSP] = td->c_cc[VDSUSP];
782 #endif /* VDSUSP */
783 #ifdef VREPRINT
784 s[C_REPRINT] = td->c_cc[VREPRINT];
785 #endif /* VREPRINT */
786 #ifdef VDISCARD
787 s[C_DISCARD] = td->c_cc[VDISCARD];
788 #endif /* VDISCARD */
789 #ifdef VLNEXT
790 s[C_LNEXT] = td->c_cc[VLNEXT];
791 #endif /* VLNEXT */
792 #ifdef VSTATUS
793 s[C_STATUS] = td->c_cc[VSTATUS];
794 #endif /* VSTATUS */
795 #ifdef VPAGE
796 s[C_PAGE] = td->c_cc[VPAGE];
797 #endif /* VPAGE */
798 #ifdef VPGOFF
799 s[C_PGOFF] = td->c_cc[VPGOFF];
800 #endif /* VPGOFF */
801 #ifdef VKILL2
802 s[C_KILL2] = td->c_cc[VKILL2];
803 #endif /* KILL2 */
804 #ifdef VMIN
805 s[C_MIN] = td->c_cc[VMIN];
806 #endif /* VMIN */
807 #ifdef VTIME
808 s[C_TIME] = td->c_cc[VTIME];
809 #endif /* VTIME */
810 } /* tty__getchar */
813 /* tty__setchar():
814 * Set the tty characters
816 private void
817 tty__setchar(struct termios *td, unsigned char *s)
820 #ifdef VINTR
821 td->c_cc[VINTR] = s[C_INTR];
822 #endif /* VINTR */
823 #ifdef VQUIT
824 td->c_cc[VQUIT] = s[C_QUIT];
825 #endif /* VQUIT */
826 #ifdef VERASE
827 td->c_cc[VERASE] = s[C_ERASE];
828 #endif /* VERASE */
829 #ifdef VKILL
830 td->c_cc[VKILL] = s[C_KILL];
831 #endif /* VKILL */
832 #ifdef VEOF
833 td->c_cc[VEOF] = s[C_EOF];
834 #endif /* VEOF */
835 #ifdef VEOL
836 td->c_cc[VEOL] = s[C_EOL];
837 #endif /* VEOL */
838 #ifdef VEOL2
839 td->c_cc[VEOL2] = s[C_EOL2];
840 #endif /* VEOL2 */
841 #ifdef VSWTCH
842 td->c_cc[VSWTCH] = s[C_SWTCH];
843 #endif /* VSWTCH */
844 #ifdef VDSWTCH
845 td->c_cc[VDSWTCH] = s[C_DSWTCH];
846 #endif /* VDSWTCH */
847 #ifdef VERASE2
848 td->c_cc[VERASE2] = s[C_ERASE2];
849 #endif /* VERASE2 */
850 #ifdef VSTART
851 td->c_cc[VSTART] = s[C_START];
852 #endif /* VSTART */
853 #ifdef VSTOP
854 td->c_cc[VSTOP] = s[C_STOP];
855 #endif /* VSTOP */
856 #ifdef VWERASE
857 td->c_cc[VWERASE] = s[C_WERASE];
858 #endif /* VWERASE */
859 #ifdef VSUSP
860 td->c_cc[VSUSP] = s[C_SUSP];
861 #endif /* VSUSP */
862 #ifdef VDSUSP
863 td->c_cc[VDSUSP] = s[C_DSUSP];
864 #endif /* VDSUSP */
865 #ifdef VREPRINT
866 td->c_cc[VREPRINT] = s[C_REPRINT];
867 #endif /* VREPRINT */
868 #ifdef VDISCARD
869 td->c_cc[VDISCARD] = s[C_DISCARD];
870 #endif /* VDISCARD */
871 #ifdef VLNEXT
872 td->c_cc[VLNEXT] = s[C_LNEXT];
873 #endif /* VLNEXT */
874 #ifdef VSTATUS
875 td->c_cc[VSTATUS] = s[C_STATUS];
876 #endif /* VSTATUS */
877 #ifdef VPAGE
878 td->c_cc[VPAGE] = s[C_PAGE];
879 #endif /* VPAGE */
880 #ifdef VPGOFF
881 td->c_cc[VPGOFF] = s[C_PGOFF];
882 #endif /* VPGOFF */
883 #ifdef VKILL2
884 td->c_cc[VKILL2] = s[C_KILL2];
885 #endif /* VKILL2 */
886 #ifdef VMIN
887 td->c_cc[VMIN] = s[C_MIN];
888 #endif /* VMIN */
889 #ifdef VTIME
890 td->c_cc[VTIME] = s[C_TIME];
891 #endif /* VTIME */
892 } /* tty__setchar */
895 /* tty_bind_char():
896 * Rebind the editline functions
898 protected void
899 tty_bind_char(EditLine *el, int force)
902 unsigned char *t_n = el->el_tty.t_c[ED_IO];
903 unsigned char *t_o = el->el_tty.t_ed.c_cc;
904 Char new[2], old[2];
905 const ttymap_t *tp;
906 el_action_t *map, *alt;
907 const el_action_t *dmap, *dalt;
908 new[1] = old[1] = '\0';
910 map = el->el_map.key;
911 alt = el->el_map.alt;
912 if (el->el_map.type == MAP_VI) {
913 dmap = el->el_map.vii;
914 dalt = el->el_map.vic;
915 } else {
916 dmap = el->el_map.emacs;
917 dalt = NULL;
920 for (tp = tty_map; tp->nch != (Int)-1; tp++) {
921 new[0] = t_n[tp->nch];
922 old[0] = t_o[tp->och];
923 if (new[0] == old[0] && !force)
924 continue;
925 /* Put the old default binding back, and set the new binding */
926 keymacro_clear(el, map, old);
927 map[UC(old[0])] = dmap[UC(old[0])];
928 keymacro_clear(el, map, new);
929 /* MAP_VI == 1, MAP_EMACS == 0... */
930 map[UC(new[0])] = tp->bind[el->el_map.type];
931 if (dalt) {
932 keymacro_clear(el, alt, old);
933 alt[UC(old[0])] = dalt[UC(old[0])];
934 keymacro_clear(el, alt, new);
935 alt[UC(new[0])] = tp->bind[el->el_map.type + 1];
941 /* tty_rawmode():
942 * Set terminal into 1 character at a time mode.
944 protected int
945 tty_rawmode(EditLine *el)
948 if (el->el_tty.t_mode == ED_IO || el->el_tty.t_mode == QU_IO)
949 return 0;
951 if (el->el_flags & EDIT_DISABLED)
952 return 0;
954 if (tty_getty(el, &el->el_tty.t_ts) == -1) {
955 #ifdef DEBUG_TTY
956 (void) fprintf(el->el_errfile, "%s: tty_getty: %s\n", __func__,
957 strerror(errno));
958 #endif /* DEBUG_TTY */
959 return -1;
962 * We always keep up with the eight bit setting and the speed of the
963 * tty. But we only believe changes that are made to cooked mode!
965 el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts);
966 el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts);
968 if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed ||
969 tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) {
970 (void) cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed);
971 (void) cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed);
972 (void) cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed);
973 (void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed);
975 if (tty__cooked_mode(&el->el_tty.t_ts)) {
976 if (el->el_tty.t_ts.c_cflag != el->el_tty.t_ex.c_cflag) {
977 el->el_tty.t_ex.c_cflag =
978 el->el_tty.t_ts.c_cflag;
979 el->el_tty.t_ex.c_cflag &=
980 ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask;
981 el->el_tty.t_ex.c_cflag |=
982 el->el_tty.t_t[EX_IO][MD_CTL].t_setmask;
984 el->el_tty.t_ed.c_cflag =
985 el->el_tty.t_ts.c_cflag;
986 el->el_tty.t_ed.c_cflag &=
987 ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask;
988 el->el_tty.t_ed.c_cflag |=
989 el->el_tty.t_t[ED_IO][MD_CTL].t_setmask;
991 if ((el->el_tty.t_ts.c_lflag != el->el_tty.t_ex.c_lflag) &&
992 (el->el_tty.t_ts.c_lflag != el->el_tty.t_ed.c_lflag)) {
993 el->el_tty.t_ex.c_lflag =
994 el->el_tty.t_ts.c_lflag;
995 el->el_tty.t_ex.c_lflag &=
996 ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask;
997 el->el_tty.t_ex.c_lflag |=
998 el->el_tty.t_t[EX_IO][MD_LIN].t_setmask;
1000 el->el_tty.t_ed.c_lflag =
1001 el->el_tty.t_ts.c_lflag;
1002 el->el_tty.t_ed.c_lflag &=
1003 ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask;
1004 el->el_tty.t_ed.c_lflag |=
1005 el->el_tty.t_t[ED_IO][MD_LIN].t_setmask;
1007 if ((el->el_tty.t_ts.c_iflag != el->el_tty.t_ex.c_iflag) &&
1008 (el->el_tty.t_ts.c_iflag != el->el_tty.t_ed.c_iflag)) {
1009 el->el_tty.t_ex.c_iflag =
1010 el->el_tty.t_ts.c_iflag;
1011 el->el_tty.t_ex.c_iflag &=
1012 ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask;
1013 el->el_tty.t_ex.c_iflag |=
1014 el->el_tty.t_t[EX_IO][MD_INP].t_setmask;
1016 el->el_tty.t_ed.c_iflag =
1017 el->el_tty.t_ts.c_iflag;
1018 el->el_tty.t_ed.c_iflag &=
1019 ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask;
1020 el->el_tty.t_ed.c_iflag |=
1021 el->el_tty.t_t[ED_IO][MD_INP].t_setmask;
1023 if ((el->el_tty.t_ts.c_oflag != el->el_tty.t_ex.c_oflag) &&
1024 (el->el_tty.t_ts.c_oflag != el->el_tty.t_ed.c_oflag)) {
1025 el->el_tty.t_ex.c_oflag =
1026 el->el_tty.t_ts.c_oflag;
1027 el->el_tty.t_ex.c_oflag &=
1028 ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask;
1029 el->el_tty.t_ex.c_oflag |=
1030 el->el_tty.t_t[EX_IO][MD_OUT].t_setmask;
1032 el->el_tty.t_ed.c_oflag =
1033 el->el_tty.t_ts.c_oflag;
1034 el->el_tty.t_ed.c_oflag &=
1035 ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask;
1036 el->el_tty.t_ed.c_oflag |=
1037 el->el_tty.t_t[ED_IO][MD_OUT].t_setmask;
1039 if (tty__gettabs(&el->el_tty.t_ex) == 0)
1040 el->el_tty.t_tabs = 0;
1041 else
1042 el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0;
1045 int i;
1047 tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
1049 * Check if the user made any changes.
1050 * If he did, then propagate the changes to the
1051 * edit and execute data structures.
1053 for (i = 0; i < C_NCC; i++)
1054 if (el->el_tty.t_c[TS_IO][i] !=
1055 el->el_tty.t_c[EX_IO][i])
1056 break;
1058 if (i != C_NCC) {
1060 * Propagate changes only to the unprotected
1061 * chars that have been modified just now.
1063 for (i = 0; i < C_NCC; i++) {
1064 if (!((el->el_tty.t_t[ED_IO][MD_CHAR].t_setmask & C_SH(i)))
1065 && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
1066 el->el_tty.t_c[ED_IO][i] = el->el_tty.t_c[TS_IO][i];
1067 if (el->el_tty.t_t[ED_IO][MD_CHAR].t_clrmask & C_SH(i))
1068 el->el_tty.t_c[ED_IO][i] = el->el_tty.t_vdisable;
1070 tty_bind_char(el, 0);
1071 tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
1073 for (i = 0; i < C_NCC; i++) {
1074 if (!((el->el_tty.t_t[EX_IO][MD_CHAR].t_setmask & C_SH(i)))
1075 && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
1076 el->el_tty.t_c[EX_IO][i] = el->el_tty.t_c[TS_IO][i];
1077 if (el->el_tty.t_t[EX_IO][MD_CHAR].t_clrmask & C_SH(i))
1078 el->el_tty.t_c[EX_IO][i] = el->el_tty.t_vdisable;
1080 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
1084 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) {
1085 #ifdef DEBUG_TTY
1086 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1087 strerror(errno));
1088 #endif /* DEBUG_TTY */
1089 return -1;
1091 el->el_tty.t_mode = ED_IO;
1092 return 0;
1096 /* tty_cookedmode():
1097 * Set the tty back to normal mode
1099 protected int
1100 tty_cookedmode(EditLine *el)
1101 { /* set tty in normal setup */
1103 if (el->el_tty.t_mode == EX_IO)
1104 return 0;
1106 if (el->el_flags & EDIT_DISABLED)
1107 return 0;
1109 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) {
1110 #ifdef DEBUG_TTY
1111 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1112 strerror(errno));
1113 #endif /* DEBUG_TTY */
1114 return -1;
1116 el->el_tty.t_mode = EX_IO;
1117 return 0;
1121 /* tty_quotemode():
1122 * Turn on quote mode
1124 protected int
1125 tty_quotemode(EditLine *el)
1127 if (el->el_tty.t_mode == QU_IO)
1128 return 0;
1130 el->el_tty.t_qu = el->el_tty.t_ed;
1132 el->el_tty.t_qu.c_iflag &= ~el->el_tty.t_t[QU_IO][MD_INP].t_clrmask;
1133 el->el_tty.t_qu.c_iflag |= el->el_tty.t_t[QU_IO][MD_INP].t_setmask;
1135 el->el_tty.t_qu.c_oflag &= ~el->el_tty.t_t[QU_IO][MD_OUT].t_clrmask;
1136 el->el_tty.t_qu.c_oflag |= el->el_tty.t_t[QU_IO][MD_OUT].t_setmask;
1138 el->el_tty.t_qu.c_cflag &= ~el->el_tty.t_t[QU_IO][MD_CTL].t_clrmask;
1139 el->el_tty.t_qu.c_cflag |= el->el_tty.t_t[QU_IO][MD_CTL].t_setmask;
1141 el->el_tty.t_qu.c_lflag &= ~el->el_tty.t_t[QU_IO][MD_LIN].t_clrmask;
1142 el->el_tty.t_qu.c_lflag |= el->el_tty.t_t[QU_IO][MD_LIN].t_setmask;
1144 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_qu) == -1) {
1145 #ifdef DEBUG_TTY
1146 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1147 strerror(errno));
1148 #endif /* DEBUG_TTY */
1149 return -1;
1151 el->el_tty.t_mode = QU_IO;
1152 return 0;
1156 /* tty_noquotemode():
1157 * Turn off quote mode
1159 protected int
1160 tty_noquotemode(EditLine *el)
1163 if (el->el_tty.t_mode != QU_IO)
1164 return 0;
1165 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) {
1166 #ifdef DEBUG_TTY
1167 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1168 strerror(errno));
1169 #endif /* DEBUG_TTY */
1170 return -1;
1172 el->el_tty.t_mode = ED_IO;
1173 return 0;
1177 /* tty_stty():
1178 * Stty builtin
1180 protected int
1181 /*ARGSUSED*/
1182 tty_stty(EditLine *el, int argc __attribute__((__unused__)), const Char **argv)
1184 const ttymodes_t *m;
1185 char x;
1186 int aflag = 0;
1187 const Char *s, *d;
1188 char name[EL_BUFSIZ];
1189 struct termios *tios = &el->el_tty.t_ex;
1190 int z = EX_IO;
1192 if (argv == NULL)
1193 return -1;
1194 strncpy(name, ct_encode_string(*argv++, &el->el_scratch), sizeof(name));
1195 name[sizeof(name) - 1] = '\0';
1197 while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0')
1198 switch (argv[0][1]) {
1199 case 'a':
1200 aflag++;
1201 argv++;
1202 break;
1203 case 'd':
1204 argv++;
1205 tios = &el->el_tty.t_ed;
1206 z = ED_IO;
1207 break;
1208 case 'x':
1209 argv++;
1210 tios = &el->el_tty.t_ex;
1211 z = EX_IO;
1212 break;
1213 case 'q':
1214 argv++;
1215 tios = &el->el_tty.t_ts;
1216 z = QU_IO;
1217 break;
1218 default:
1219 (void) fprintf(el->el_errfile,
1220 "%s: Unknown switch `%c'.\n",
1221 name, argv[0][1]);
1222 return -1;
1225 if (!argv || !*argv) {
1226 int i = -1;
1227 size_t len = 0, st = 0, cu;
1228 for (m = ttymodes; m->m_name; m++) {
1229 if (m->m_type != i) {
1230 (void) fprintf(el->el_outfile, "%s%s",
1231 i != -1 ? "\n" : "",
1232 el->el_tty.t_t[z][m->m_type].t_name);
1233 i = m->m_type;
1234 st = len =
1235 strlen(el->el_tty.t_t[z][m->m_type].t_name);
1237 if (i != -1) {
1238 x = (el->el_tty.t_t[z][i].t_setmask & m->m_value)
1239 ? '+' : '\0';
1241 if (el->el_tty.t_t[z][i].t_clrmask & m->m_value)
1242 x = '-';
1243 } else {
1244 x = '\0';
1247 if (x != '\0' || aflag) {
1249 cu = strlen(m->m_name) + (x != '\0') + 1;
1251 if (len + cu >=
1252 (size_t)el->el_terminal.t_size.h) {
1253 (void) fprintf(el->el_outfile, "\n%*s",
1254 (int)st, "");
1255 len = st + cu;
1256 } else
1257 len += cu;
1259 if (x != '\0')
1260 (void) fprintf(el->el_outfile, "%c%s ",
1261 x, m->m_name);
1262 else
1263 (void) fprintf(el->el_outfile, "%s ",
1264 m->m_name);
1267 (void) fprintf(el->el_outfile, "\n");
1268 return 0;
1270 while (argv && (s = *argv++)) {
1271 const Char *p;
1272 switch (*s) {
1273 case '+':
1274 case '-':
1275 x = (char)*s++;
1276 break;
1277 default:
1278 x = '\0';
1279 break;
1281 d = s;
1282 p = Strchr(s, '=');
1283 for (m = ttymodes; m->m_name; m++)
1284 if ((p ? strncmp(m->m_name, ct_encode_string(d,
1285 &el->el_scratch), (size_t)(p - d)) :
1286 strcmp(m->m_name, ct_encode_string(d,
1287 &el->el_scratch))) == 0 &&
1288 (p == NULL || m->m_type == MD_CHAR))
1289 break;
1291 if (!m->m_name) {
1292 (void) fprintf(el->el_errfile,
1293 "%s: Invalid argument `" FSTR "'.\n", name, d);
1294 return -1;
1296 if (p) {
1297 int c = ffs((int)m->m_value);
1298 int v = *++p ? parse__escape(&p) :
1299 el->el_tty.t_vdisable;
1300 assert(c != 0);
1301 c--;
1302 c = tty__getcharindex(c);
1303 assert(c != -1);
1304 tios->c_cc[c] = (cc_t)v;
1305 continue;
1307 switch (x) {
1308 case '+':
1309 el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value;
1310 el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
1311 break;
1312 case '-':
1313 el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
1314 el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value;
1315 break;
1316 default:
1317 el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
1318 el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
1319 break;
1323 if (el->el_tty.t_mode == z) {
1324 if (tty_setty(el, TCSADRAIN, tios) == -1) {
1325 #ifdef DEBUG_TTY
1326 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n",
1327 __func__, strerror(errno));
1328 #endif /* DEBUG_TTY */
1329 return -1;
1333 return 0;
1337 #ifdef notyet
1338 /* tty_printchar():
1339 * DEbugging routine to print the tty characters
1341 private void
1342 tty_printchar(EditLine *el, unsigned char *s)
1344 ttyperm_t *m;
1345 int i;
1347 for (i = 0; i < C_NCC; i++) {
1348 for (m = el->el_tty.t_t; m->m_name; m++)
1349 if (m->m_type == MD_CHAR && C_SH(i) == m->m_value)
1350 break;
1351 if (m->m_name)
1352 (void) fprintf(el->el_errfile, "%s ^%c ",
1353 m->m_name, s[i] + 'A' - 1);
1354 if (i % 5 == 0)
1355 (void) fprintf(el->el_errfile, "\n");
1357 (void) fprintf(el->el_errfile, "\n");
1359 #endif /* notyet */