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