root/src/noitedit/tty.c

Revision 11d2dcb8820fdb77c35384ce926e2b7014559bb0, 28.9 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 6 years ago)

replace FILEs with file descriptors

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