1 /** $MirOS: src/lib/libedit/tty.c,v 1.2 2005/04/19 15:16:17 tg Exp $ */
2 /* $OpenBSD: tty.c,v 1.10 2003/11/25 20:12:38 otto Exp $ */
3 /* $NetBSD: tty.c,v 1.21 2004/08/13 12:10:39 mycroft Exp $ */
4
5 /*-
6 * Copyright (c) 1992, 1993
7 * The Regents of the University of California. All rights reserved.
8 *
9 * This code is derived from software contributed to Berkeley by
10 * Christos Zoulas of Cornell University.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37 #include "config.h"
38
39 /*
40 * tty.c: tty interface stuff
41 */
42 #include <assert.h>
43 #include "tty.h"
44 #include "el.h"
45
46 __SCCSID("@(#)tty.c 8.1 (Berkeley) 6/4/93");
47 __RCSID("$MirOS: src/lib/libedit/tty.c,v 1.2 2005/04/19 15:16:17 tg Exp $");
48
49 typedef struct ttymodes_t {
50 const char *m_name;
51 u_int m_value;
52 int m_type;
53 } ttymodes_t;
54
55 typedef struct ttymap_t {
56 int nch, och; /* Internal and termio rep of chars */
57 el_action_t bind[3]; /* emacs, vi, and vi-cmd */
58 } ttymap_t;
59
60
61 private const ttyperm_t ttyperm = {
62 {
63 {"iflag:", ICRNL, (INLCR | IGNCR)},
64 {"oflag:", (OPOST | ONLCR), ONLRET},
65 {"cflag:", 0, 0},
66 {"lflag:", (ISIG | ICANON | ECHO | ECHOE | ECHOCTL | IEXTEN),
67 (NOFLSH | ECHONL | EXTPROC | FLUSHO)},
68 {"chars:", 0, 0},
69 },
70 {
71 {"iflag:", (INLCR | ICRNL), IGNCR},
72 {"oflag:", (OPOST | ONLCR), ONLRET},
73 {"cflag:", 0, 0},
74 {"lflag:", ISIG,
75 (NOFLSH | ICANON | ECHO | ECHOK | ECHONL | EXTPROC | IEXTEN | FLUSHO)},
76 {"chars:", (C_SH(C_MIN) | C_SH(C_TIME) | C_SH(C_SWTCH) | C_SH(C_DSWTCH) |
77 C_SH(C_SUSP) | C_SH(C_DSUSP) | C_SH(C_EOL) | C_SH(C_DISCARD) |
78 C_SH(C_PGOFF) | C_SH(C_PAGE) | C_SH(C_STATUS)), 0}
79 },
80 {
81 {"iflag:", 0, IXON | IXOFF | INLCR | ICRNL},
82 {"oflag:", 0, 0},
83 {"cflag:", 0, 0},
84 {"lflag:", 0, ISIG | IEXTEN},
85 {"chars:", 0, 0},
86 }
87 };
88
89 private const ttychar_t ttychar = {
90 {
91 CINTR, CQUIT, CERASE, CKILL,
92 CEOF, CEOL, CEOL2, CSWTCH,
93 CDSWTCH, CERASE2, CSTART, CSTOP,
94 CWERASE, CSUSP, CDSUSP, CREPRINT,
95 CDISCARD, CLNEXT, CSTATUS, CPAGE,
96 CPGOFF, CKILL2, CBRK, CMIN,
97 CTIME
98 },
99 {
100 CINTR, CQUIT, CERASE, CKILL,
101 _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
102 _POSIX_VDISABLE, CERASE2, CSTART, CSTOP,
103 _POSIX_VDISABLE, CSUSP, _POSIX_VDISABLE, _POSIX_VDISABLE,
104 CDISCARD, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
105 _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 1,
106 0
107 },
108 {
109 0, 0, 0, 0,
110 0, 0, 0, 0,
111 0, 0, 0, 0,
112 0, 0, 0, 0,
113 0, 0, 0, 0,
114 0, 0, 0, 0,
115 0
116 }
117 };
118
119 private const ttymap_t tty_map[] = {
120 #ifdef VERASE
121 {C_ERASE, VERASE,
122 {ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
123 #endif /* VERASE */
124 #ifdef VERASE2
125 {C_ERASE2, VERASE2,
126 {ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
127 #endif /* VERASE2 */
128 #ifdef VKILL
129 {C_KILL, VKILL,
130 {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
131 #endif /* VKILL */
132 #ifdef VKILL2
133 {C_KILL2, VKILL2,
134 {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
135 #endif /* VKILL2 */
136 #ifdef VEOF
137 {C_EOF, VEOF,
138 {EM_DELETE_OR_LIST, VI_LIST_OR_EOF, ED_UNASSIGNED}},
139 #endif /* VEOF */
140 #ifdef VWERASE
141 {C_WERASE, VWERASE,
142 {ED_DELETE_PREV_WORD, ED_DELETE_PREV_WORD, ED_PREV_WORD}},
143 #endif /* VWERASE */
144 #ifdef VREPRINT
145 {C_REPRINT, VREPRINT,
146 {ED_REDISPLAY, ED_INSERT, ED_REDISPLAY}},
147 #endif /* VREPRINT */
148 #ifdef VLNEXT
149 {C_LNEXT, VLNEXT,
150 {ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED}},
151 #endif /* VLNEXT */
152 {-1, -1,
153 {ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED}}
154 };
155
156 private const ttymodes_t ttymodes[] = {
157 #ifdef IGNBRK
158 {"ignbrk", IGNBRK, MD_INP},
159 #endif /* IGNBRK */
160 #ifdef BRKINT
161 {"brkint", BRKINT, MD_INP},
162 #endif /* BRKINT */
163 #ifdef IGNPAR
164 {"ignpar", IGNPAR, MD_INP},
165 #endif /* IGNPAR */
166 #ifdef PARMRK
167 {"parmrk", PARMRK, MD_INP},
168 #endif /* PARMRK */
169 #ifdef INPCK
170 {"inpck", INPCK, MD_INP},
171 #endif /* INPCK */
172 #ifdef ISTRIP
173 {"istrip", ISTRIP, MD_INP},
174 #endif /* ISTRIP */
175 #ifdef INLCR
176 {"inlcr", INLCR, MD_INP},
177 #endif /* INLCR */
178 #ifdef IGNCR
179 {"igncr", IGNCR, MD_INP},
180 #endif /* IGNCR */
181 #ifdef ICRNL
182 {"icrnl", ICRNL, MD_INP},
183 #endif /* ICRNL */
184 #ifdef IUCLC
185 {"iuclc", IUCLC, MD_INP},
186 #endif /* IUCLC */
187 #ifdef IXON
188 {"ixon", IXON, MD_INP},
189 #endif /* IXON */
190 #ifdef IXANY
191 {"ixany", IXANY, MD_INP},
192 #endif /* IXANY */
193 #ifdef IXOFF
194 {"ixoff", IXOFF, MD_INP},
195 #endif /* IXOFF */
196 #ifdef IMAXBEL
197 {"imaxbel", IMAXBEL, MD_INP},
198 #endif /* IMAXBEL */
199
200 #ifdef OPOST
201 {"opost", OPOST, MD_OUT},
202 #endif /* OPOST */
203 #ifdef OLCUC
204 {"olcuc", OLCUC, MD_OUT},
205 #endif /* OLCUC */
206 #ifdef ONLCR
207 {"onlcr", ONLCR, MD_OUT},
208 #endif /* ONLCR */
209 #ifdef OCRNL
210 {"ocrnl", OCRNL, MD_OUT},
211 #endif /* OCRNL */
212 #ifdef ONOCR
213 {"onocr", ONOCR, MD_OUT},
214 #endif /* ONOCR */
215 #ifdef ONOEOT
216 {"onoeot", ONOEOT, MD_OUT},
217 #endif /* ONOEOT */
218 #ifdef ONLRET
219 {"onlret", ONLRET, MD_OUT},
220 #endif /* ONLRET */
221 #ifdef OFILL
222 {"ofill", OFILL, MD_OUT},
223 #endif /* OFILL */
224 #ifdef OFDEL
225 {"ofdel", OFDEL, MD_OUT},
226 #endif /* OFDEL */
227 #ifdef NLDLY
228 {"nldly", NLDLY, MD_OUT},
229 #endif /* NLDLY */
230 #ifdef CRDLY
231 {"crdly", CRDLY, MD_OUT},
232 #endif /* CRDLY */
233 #ifdef TABDLY
234 {"tabdly", TABDLY, MD_OUT},
235 #endif /* TABDLY */
236 #ifdef XTABS
237 {"xtabs", XTABS, MD_OUT},
238 #endif /* XTABS */
239 #ifdef BSDLY
240 {"bsdly", BSDLY, MD_OUT},
241 #endif /* BSDLY */
242 #ifdef VTDLY
243 {"vtdly", VTDLY, MD_OUT},
244 #endif /* VTDLY */
245 #ifdef FFDLY
246 {"ffdly", FFDLY, MD_OUT},
247 #endif /* FFDLY */
248 #ifdef PAGEOUT
249 {"pageout", PAGEOUT, MD_OUT},
250 #endif /* PAGEOUT */
251 #ifdef WRAP
252 {"wrap", WRAP, MD_OUT},
253 #endif /* WRAP */
254
255 #ifdef CIGNORE
256 {"cignore", CIGNORE, MD_CTL},
257 #endif /* CBAUD */
258 #ifdef CBAUD
259 {"cbaud", CBAUD, MD_CTL},
260 #endif /* CBAUD */
261 #ifdef CSTOPB
262 {"cstopb", CSTOPB, MD_CTL},
263 #endif /* CSTOPB */
264 #ifdef CREAD
265 {"cread", CREAD, MD_CTL},
266 #endif /* CREAD */
267 #ifdef PARENB
268 {"parenb", PARENB, MD_CTL},
269 #endif /* PARENB */
270 #ifdef PARODD
271 {"parodd", PARODD, MD_CTL},
272 #endif /* PARODD */
273 #ifdef HUPCL
274 {"hupcl", HUPCL, MD_CTL},
275 #endif /* HUPCL */
276 #ifdef CLOCAL
277 {"clocal", CLOCAL, MD_CTL},
278 #endif /* CLOCAL */
279 #ifdef LOBLK
280 {"loblk", LOBLK, MD_CTL},
281 #endif /* LOBLK */
282 #ifdef CIBAUD
283 {"cibaud", CIBAUD, MD_CTL},
284 #endif /* CIBAUD */
285 #ifdef CRTSCTS
286 #ifdef CCTS_OFLOW
287 {"ccts_oflow", CCTS_OFLOW, MD_CTL},
288 #else
289 {"crtscts", CRTSCTS, MD_CTL},
290 #endif /* CCTS_OFLOW */
291 #endif /* CRTSCTS */
292 #ifdef CRTS_IFLOW
293 {"crts_iflow", CRTS_IFLOW, MD_CTL},
294 #endif /* CRTS_IFLOW */
295 #ifdef CDTRCTS
296 {"cdtrcts", CDTRCTS, MD_CTL},
297 #endif /* CDTRCTS */
298 #ifdef MDMBUF
299 {"mdmbuf", MDMBUF, MD_CTL},
300 #endif /* MDMBUF */
301 #ifdef RCV1EN
302 {"rcv1en", RCV1EN, MD_CTL},
303 #endif /* RCV1EN */
304 #ifdef XMT1EN
305 {"xmt1en", XMT1EN, MD_CTL},
306 #endif /* XMT1EN */
307
308 #ifdef ISIG
309 {"isig", ISIG, MD_LIN},
310 #endif /* ISIG */
311 #ifdef ICANON
312 {"icanon", ICANON, MD_LIN},
313 #endif /* ICANON */
314 #ifdef XCASE
315 {"xcase", XCASE, MD_LIN},
316 #endif /* XCASE */
317 #ifdef ECHO
318 {"echo", ECHO, MD_LIN},
319 #endif /* ECHO */
320 #ifdef ECHOE
321 {"echoe", ECHOE, MD_LIN},
322 #endif /* ECHOE */
323 #ifdef ECHOK
324 {"echok", ECHOK, MD_LIN},
325 #endif /* ECHOK */
326 #ifdef ECHONL
327 {"echonl", ECHONL, MD_LIN},
328 #endif /* ECHONL */
329 #ifdef NOFLSH
330 {"noflsh", NOFLSH, MD_LIN},
331 #endif /* NOFLSH */
332 #ifdef TOSTOP
333 {"tostop", TOSTOP, MD_LIN},
334 #endif /* TOSTOP */
335 #ifdef ECHOCTL
336 {"echoctl", ECHOCTL, MD_LIN},
337 #endif /* ECHOCTL */
338 #ifdef ECHOPRT
339 {"echoprt", ECHOPRT, MD_LIN},
340 #endif /* ECHOPRT */
341 #ifdef ECHOKE
342 {"echoke", ECHOKE, MD_LIN},
343 #endif /* ECHOKE */
344 #ifdef DEFECHO
345 {"defecho", DEFECHO, MD_LIN},
346 #endif /* DEFECHO */
347 #ifdef FLUSHO
348 {"flusho", FLUSHO, MD_LIN},
349 #endif /* FLUSHO */
350 #ifdef PENDIN
351 {"pendin", PENDIN, MD_LIN},
352 #endif /* PENDIN */
353 #ifdef IEXTEN
354 {"iexten", IEXTEN, MD_LIN},
355 #endif /* IEXTEN */
356 #ifdef NOKERNINFO
357 {"nokerninfo", NOKERNINFO, MD_LIN},
358 #endif /* NOKERNINFO */
359 #ifdef ALTWERASE
360 {"altwerase", ALTWERASE, MD_LIN},
361 #endif /* ALTWERASE */
362 #ifdef EXTPROC
363 {"extproc", EXTPROC, MD_LIN},
364 #endif /* EXTPROC */
365
366 #if defined(VINTR)
367 {"intr", C_SH(C_INTR), MD_CHAR},
368 #endif /* VINTR */
369 #if defined(VQUIT)
370 {"quit", C_SH(C_QUIT), MD_CHAR},
371 #endif /* VQUIT */
372 #if defined(VERASE)
373 {"erase", C_SH(C_ERASE), MD_CHAR},
374 #endif /* VERASE */
375 #if defined(VKILL)
376 {"kill", C_SH(C_KILL), MD_CHAR},
377 #endif /* VKILL */
378 #if defined(VEOF)
379 {"eof", C_SH(C_EOF), MD_CHAR},
380 #endif /* VEOF */
381 #if defined(VEOL)
382 {"eol", C_SH(C_EOL), MD_CHAR},
383 #endif /* VEOL */
384 #if defined(VEOL2)
385 {"eol2", C_SH(C_EOL2), MD_CHAR},
386 #endif /* VEOL2 */
387 #if defined(VSWTCH)
388 {"swtch", C_SH(C_SWTCH), MD_CHAR},
389 #endif /* VSWTCH */
390 #if defined(VDSWTCH)
391 {"dswtch", C_SH(C_DSWTCH), MD_CHAR},
392 #endif /* VDSWTCH */
393 #if defined(VERASE2)
394 {"erase2", C_SH(C_ERASE2), MD_CHAR},
395 #endif /* VERASE2 */
396 #if defined(VSTART)
397 {"start", C_SH(C_START), MD_CHAR},
398 #endif /* VSTART */
399 #if defined(VSTOP)
400 {"stop", C_SH(C_STOP), MD_CHAR},
401 #endif /* VSTOP */
402 #if defined(VWERASE)
403 {"werase", C_SH(C_WERASE), MD_CHAR},
404 #endif /* VWERASE */
405 #if defined(VSUSP)
406 {"susp", C_SH(C_SUSP), MD_CHAR},
407 #endif /* VSUSP */
408 #if defined(VDSUSP)
409 {"dsusp", C_SH(C_DSUSP), MD_CHAR},
410 #endif /* VDSUSP */
411 #if defined(VREPRINT)
412 {"reprint", C_SH(C_REPRINT), MD_CHAR},
413 #endif /* VREPRINT */
414 #if defined(VDISCARD)
415 {"discard", C_SH(C_DISCARD), MD_CHAR},
416 #endif /* VDISCARD */
417 #if defined(VLNEXT)
418 {"lnext", C_SH(C_LNEXT), MD_CHAR},
419 #endif /* VLNEXT */
420 #if defined(VSTATUS)
421 {"status", C_SH(C_STATUS), MD_CHAR},
422 #endif /* VSTATUS */
423 #if defined(VPAGE)
424 {"page", C_SH(C_PAGE), MD_CHAR},
425 #endif /* VPAGE */
426 #if defined(VPGOFF)
427 {"pgoff", C_SH(C_PGOFF), MD_CHAR},
428 #endif /* VPGOFF */
429 #if defined(VKILL2)
430 {"kill2", C_SH(C_KILL2), MD_CHAR},
431 #endif /* VKILL2 */
432 #if defined(VBRK)
433 {"brk", C_SH(C_BRK), MD_CHAR},
434 #endif /* VBRK */
435 #if defined(VMIN)
436 {"min", C_SH(C_MIN), MD_CHAR},
437 #endif /* VMIN */
438 #if defined(VTIME)
439 {"time", C_SH(C_TIME), MD_CHAR},
440 #endif /* VTIME */
441 {NULL, 0, -1},
442 };
443
444
445
446 #define tty_getty(el, td) tcgetattr((el)->el_infd, (td))
447 #define tty_setty(el, td) tcsetattr((el)->el_infd, TCSADRAIN, (td))
448
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)
452
453 private int tty__getcharindex(int);
454 private void tty__getchar(struct termios *, unsigned char *);
455 private void tty__setchar(struct termios *, unsigned char *);
456 private speed_t tty__getspeed(struct termios *);
457 private int tty_setup(EditLine *);
458
459 #define t_qu t_ts
460
461
462 /* tty_setup():
463 * Get the tty parameters and initialize the editing state
464 */
465 private int
tty_setup(EditLine * el)466 tty_setup(EditLine *el)
467 {
468 int rst = 1;
469
470 if (el->el_flags & EDIT_DISABLED)
471 return (0);
472
473 if (tty_getty(el, &el->el_tty.t_ed) == -1) {
474 #ifdef DEBUG_TTY
475 (void) fprintf(el->el_errfile,
476 "tty_setup: tty_getty: %s\n", strerror(errno));
477 #endif /* DEBUG_TTY */
478 return (-1);
479 }
480 el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed;
481
482 el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex);
483 el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex);
484 el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex);
485
486 el->el_tty.t_ex.c_iflag &= ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask;
487 el->el_tty.t_ex.c_iflag |= el->el_tty.t_t[EX_IO][MD_INP].t_setmask;
488
489 el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask;
490 el->el_tty.t_ex.c_oflag |= el->el_tty.t_t[EX_IO][MD_OUT].t_setmask;
491
492 el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask;
493 el->el_tty.t_ex.c_cflag |= el->el_tty.t_t[EX_IO][MD_CTL].t_setmask;
494
495 el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask;
496 el->el_tty.t_ex.c_lflag |= el->el_tty.t_t[EX_IO][MD_LIN].t_setmask;
497
498 /*
499 * Reset the tty chars to reasonable defaults
500 * If they are disabled, then enable them.
501 */
502 if (rst) {
503 if (tty__cooked_mode(&el->el_tty.t_ts)) {
504 tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
505 /*
506 * Don't affect CMIN and CTIME for the editor mode
507 */
508 for (rst = 0; rst < C_NCC - 2; rst++)
509 if (el->el_tty.t_c[TS_IO][rst] !=
510 el->el_tty.t_vdisable
511 && el->el_tty.t_c[ED_IO][rst] !=
512 el->el_tty.t_vdisable)
513 el->el_tty.t_c[ED_IO][rst] =
514 el->el_tty.t_c[TS_IO][rst];
515 for (rst = 0; rst < C_NCC; rst++)
516 if (el->el_tty.t_c[TS_IO][rst] !=
517 el->el_tty.t_vdisable)
518 el->el_tty.t_c[EX_IO][rst] =
519 el->el_tty.t_c[TS_IO][rst];
520 }
521 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
522 if (tty_setty(el, &el->el_tty.t_ex) == -1) {
523 #ifdef DEBUG_TTY
524 (void) fprintf(el->el_errfile,
525 "tty_setup: tty_setty: %s\n",
526 strerror(errno));
527 #endif /* DEBUG_TTY */
528 return (-1);
529 }
530 } else
531 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
532
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;
535
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;
538
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;
541
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;
544
545 tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
546 tty_bind_char(el, 1);
547 return (0);
548 }
549
550 protected int
tty_init(EditLine * el)551 tty_init(EditLine *el)
552 {
553
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));
559 }
560
561
562 /* tty_end():
563 * Restore the tty to its original settings
564 */
565 protected void
566 /*ARGSUSED*/
tty_end(EditLine * el)567 tty_end(EditLine *el __attribute__((__unused__)))
568 {
569
570 /* XXX: Maybe reset to an initial state? */
571 }
572
573
574 /* tty__getspeed():
575 * Get the tty speed
576 */
577 private speed_t
tty__getspeed(struct termios * td)578 tty__getspeed(struct termios *td)
579 {
580 speed_t spd;
581
582 if ((spd = cfgetispeed(td)) == 0)
583 spd = cfgetospeed(td);
584 return (spd);
585 }
586
587 /* tty__getspeed():
588 * Return the index of the asked char in the c_cc array
589 */
590 private int
tty__getcharindex(int i)591 tty__getcharindex(int i)
592 {
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;
692 }
693 }
694
695 /* tty__getchar():
696 * Get the tty characters
697 */
698 private void
tty__getchar(struct termios * td,unsigned char * s)699 tty__getchar(struct termios *td, unsigned char *s)
700 {
701
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 */
775
776
777 /* tty__setchar():
778 * Set the tty characters
779 */
780 private void
tty__setchar(struct termios * td,unsigned char * s)781 tty__setchar(struct termios *td, unsigned char *s)
782 {
783
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 */
857
858
859 /* tty_bind_char():
860 * Rebind the editline functions
861 */
862 protected void
tty_bind_char(EditLine * el,int force)863 tty_bind_char(EditLine *el, int force)
864 {
865
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';
873
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;
882 }
883
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];
900 }
901 }
902 }
903
904
905 /* tty_rawmode():
906 * Set terminal into 1 character at a time mode.
907 */
908 protected int
tty_rawmode(EditLine * el)909 tty_rawmode(EditLine *el)
910 {
911
912 if (el->el_tty.t_mode == ED_IO || el->el_tty.t_mode == QU_IO)
913 return (0);
914
915 if (el->el_flags & EDIT_DISABLED)
916 return (0);
917
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);
924 }
925 /*
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!
928 */
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);
931
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);
938 }
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;
947
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;
954 }
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;
963
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;
970 }
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;
979
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;
986 }
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;
995
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;
1002 }
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;
1007
1008 {
1009 int i;
1010
1011 tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
1012 /*
1013 * Check if the user made any changes.
1014 * If he did, then propagate the changes to the
1015 * edit and execute data structures.
1016 */
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;
1021
1022 if (i != C_NCC) {
1023 /*
1024 * Propagate changes only to the unprotected
1025 * chars that have been modified just now.
1026 */
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;
1033 }
1034 tty_bind_char(el, 0);
1035 tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
1036
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;
1043 }
1044 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
1045 }
1046 }
1047 }
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);
1054 }
1055 el->el_tty.t_mode = ED_IO;
1056 return (0);
1057 }
1058
1059
1060 /* tty_cookedmode():
1061 * Set the tty back to normal mode
1062 */
1063 protected int
tty_cookedmode(EditLine * el)1064 tty_cookedmode(EditLine *el)
1065 { /* set tty in normal setup */
1066
1067 if (el->el_tty.t_mode == EX_IO)
1068 return (0);
1069
1070 if (el->el_flags & EDIT_DISABLED)
1071 return (0);
1072
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);
1080 }
1081 el->el_tty.t_mode = EX_IO;
1082 return (0);
1083 }
1084
1085
1086 /* tty_quotemode():
1087 * Turn on quote mode
1088 */
1089 protected int
tty_quotemode(EditLine * el)1090 tty_quotemode(EditLine *el)
1091 {
1092 if (el->el_tty.t_mode == QU_IO)
1093 return (0);
1094
1095 el->el_tty.t_qu = el->el_tty.t_ed;
1096
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;
1099
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;
1102
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;
1105
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;
1108
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);
1115 }
1116 el->el_tty.t_mode = QU_IO;
1117 return (0);
1118 }
1119
1120
1121 /* tty_noquotemode():
1122 * Turn off quote mode
1123 */
1124 protected int
tty_noquotemode(EditLine * el)1125 tty_noquotemode(EditLine *el)
1126 {
1127
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);
1136 }
1137 el->el_tty.t_mode = ED_IO;
1138 return (0);
1139 }
1140
1141
1142 /* tty_stty():
1143 * Stty builtin
1144 */
1145 protected int
1146 /*ARGSUSED*/
tty_stty(EditLine * el,int argc,const char ** argv)1147 tty_stty(EditLine *el, int argc __attribute__((__unused__)), const char **argv)
1148 {
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;
1156
1157 if (argv == NULL)
1158 return (-1);
1159 name = *argv++;
1160
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);
1187 }
1188
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);
1200 }
1201 x = (el->el_tty.t_t[z][i].t_setmask & m->m_value)
1202 ? '+' : '\0';
1203 x = (el->el_tty.t_t[z][i].t_clrmask & m->m_value)
1204 ? '-' : x;
1205
1206 if (x != '\0' || aflag) {
1207
1208 cu = strlen(m->m_name) + (x != '\0') + 1;
1209
1210 if (len + cu >= el->el_term.t_size.h) {
1211 (void) fprintf(el->el_outfile, "\n%*s",
1212 st, "");
1213 len = st + cu;
1214 } else
1215 len += cu;
1216
1217 if (x != '\0')
1218 (void) fprintf(el->el_outfile, "%c%s ",
1219 x, m->m_name);
1220 else
1221 (void) fprintf(el->el_outfile, "%s ",
1222 m->m_name);
1223 }
1224 }
1225 (void) fprintf(el->el_outfile, "\n");
1226 return (0);
1227 }
1228 while (argv && (s = *argv++)) {
1229 char *p;
1230 switch (*s) {
1231 case '+':
1232 case '-':
1233 x = *s++;
1234 break;
1235 default:
1236 x = '\0';
1237 break;
1238 }
1239 d = s;
1240 if ((p = strchr(s, '=')) != NULL)
1241 *p++ = '\0';
1242 for (m = ttymodes; m->m_name; m++)
1243 if (strcmp(m->m_name, d) == 0 &&
1244 (p == NULL || m->m_type == MD_CHAR))
1245 break;
1246
1247 if (!m->m_name) {
1248 (void) fprintf(el->el_errfile,
1249 "%s: Invalid argument `%s'.\n", name, d);
1250 return (-1);
1251 }
1252 if (p) {
1253 int c = ffs((int)m->m_value);
1254 int v = *p ? parse__escape((const char **const) &p) :
1255 el->el_tty.t_vdisable;
1256 assert(c-- != 0);
1257 c = tty__getcharindex(c);
1258 assert(c != -1);
1259 tios->c_cc[c] = v;
1260 continue;
1261 }
1262 switch (x) {
1263 case '+':
1264 el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value;
1265 el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
1266 break;
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 default:
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 }
1276 }
1277 return (0);
1278 }
1279
1280
1281 #ifdef notyet
1282 /* tty_printchar():
1283 * DEbugging routine to print the tty characters
1284 */
1285 private void
tty_printchar(EditLine * el,unsigned char * s)1286 tty_printchar(EditLine *el, unsigned char *s)
1287 {
1288 ttyperm_t *m;
1289 int i;
1290
1291 for (i = 0; i < C_NCC; i++) {
1292 for (m = el->el_tty.t_t; m->m_name; m++)
1293 if (m->m_type == MD_CHAR && C_SH(i) == m->m_value)
1294 break;
1295 if (m->m_name)
1296 (void) fprintf(el->el_errfile, "%s ^%c ",
1297 m->m_name, s[i] + 'A' - 1);
1298 if (i % 5 == 0)
1299 (void) fprintf(el->el_errfile, "\n");
1300 }
1301 (void) fprintf(el->el_errfile, "\n");
1302 }
1303 #endif /* notyet */
1304