[BACK]Return to tty.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libedit

Annotation of src/lib/libedit/tty.c, Revision 1.54

1.54    ! christos    1: /*     $NetBSD: tty.c,v 1.51 2016/02/14 14:49:34 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.54    ! christos   40: __RCSID("$NetBSD: tty.c,v 1.51 2016/02/14 14:49:34 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.34      christos   49: #include <unistd.h>    /* for isatty */
1.33      christos   50: #include <strings.h>   /* for ffs */
1.46      christos   51: #include <stdlib.h>    /* for abort */
1.52      christos   52:
1.32      christos   53: #include "el.h"
1.1       cgd        54:
                     55: typedef struct ttymodes_t {
1.14      jdolecek   56:        const char *m_name;
1.23      lukem      57:        unsigned int m_value;
1.13      lukem      58:        int m_type;
                     59: }          ttymodes_t;
1.1       cgd        60:
                     61: typedef struct ttymap_t {
1.51      christos   62:        wint_t nch, och;        /* Internal and termio rep of chars */
1.13      lukem      63:        el_action_t bind[3];    /* emacs, vi, and vi-cmd */
1.16      christos   64: } ttymap_t;
1.1       cgd        65:
                     66:
1.14      jdolecek   67: private const ttyperm_t ttyperm = {
1.13      lukem      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:        }
1.1       cgd        93: };
                     94:
1.14      jdolecek   95: private const ttychar_t ttychar = {
1.13      lukem      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:        }
1.1       cgd       123: };
                    124:
1.14      jdolecek  125: private const ttymap_t tty_map[] = {
1.1       cgd       126: #ifdef VERASE
1.13      lukem     127:        {C_ERASE, VERASE,
1.21      mycroft   128:        {EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
1.1       cgd       129: #endif /* VERASE */
                    130: #ifdef VERASE2
1.13      lukem     131:        {C_ERASE2, VERASE2,
1.21      mycroft   132:        {EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
1.1       cgd       133: #endif /* VERASE2 */
                    134: #ifdef VKILL
1.13      lukem     135:        {C_KILL, VKILL,
                    136:        {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
1.1       cgd       137: #endif /* VKILL */
                    138: #ifdef VKILL2
1.13      lukem     139:        {C_KILL2, VKILL2,
                    140:        {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
1.1       cgd       141: #endif /* VKILL2 */
                    142: #ifdef VEOF
1.13      lukem     143:        {C_EOF, VEOF,
                    144:        {EM_DELETE_OR_LIST, VI_LIST_OR_EOF, ED_UNASSIGNED}},
1.1       cgd       145: #endif /* VEOF */
                    146: #ifdef VWERASE
1.13      lukem     147:        {C_WERASE, VWERASE,
                    148:        {ED_DELETE_PREV_WORD, ED_DELETE_PREV_WORD, ED_PREV_WORD}},
1.1       cgd       149: #endif /* VWERASE */
                    150: #ifdef VREPRINT
1.13      lukem     151:        {C_REPRINT, VREPRINT,
                    152:        {ED_REDISPLAY, ED_INSERT, ED_REDISPLAY}},
1.1       cgd       153: #endif /* VREPRINT */
                    154: #ifdef VLNEXT
1.13      lukem     155:        {C_LNEXT, VLNEXT,
                    156:        {ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED}},
1.1       cgd       157: #endif /* VLNEXT */
1.51      christos  158:        {(wint_t)-1, (wint_t)-1,
1.13      lukem     159:        {ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED}}
                    160: };
1.1       cgd       161:
1.14      jdolecek  162: private const ttymodes_t ttymodes[] = {
1.13      lukem     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},
1.1       cgd       448: };
                    449:
                    450:
                    451:
1.13      lukem     452: #define        tty__gettabs(td)        ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1)
                    453: #define        tty__geteightbit(td)    (((td)->c_cflag & CSIZE) == CS8)
                    454: #define        tty__cooked_mode(td)    ((td)->c_lflag & ICANON)
                    455:
1.26      christos  456: private int    tty_getty(EditLine *, struct termios *);
                    457: private int    tty_setty(EditLine *, int, const struct termios *);
1.19      christos  458: private int    tty__getcharindex(int);
1.13      lukem     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 *);
1.43      christos  463: private void   tty_setup_flags(EditLine *, struct termios *, int);
1.1       cgd       464:
1.13      lukem     465: #define        t_qu    t_ts
1.1       cgd       466:
1.26      christos  467: /* tty_getty():
                    468:  *     Wrapper for tcgetattr to handle EINTR
                    469:  */
                    470: private int
                    471: tty_getty(EditLine *el, struct termios *t)
                    472: {
                    473:        int rv;
                    474:        while ((rv = tcgetattr(el->el_infd, t)) == -1 && errno == EINTR)
                    475:                continue;
                    476:        return rv;
                    477: }
                    478:
                    479: /* tty_setty():
                    480:  *     Wrapper for tcsetattr to handle EINTR
                    481:  */
                    482: private int
                    483: tty_setty(EditLine *el, int action, const struct termios *t)
                    484: {
                    485:        int rv;
                    486:        while ((rv = tcsetattr(el->el_infd, action, t)) == -1 && errno == EINTR)
                    487:                continue;
                    488:        return rv;
                    489: }
1.1       cgd       490:
                    491: /* tty_setup():
                    492:  *     Get the tty parameters and initialize the editing state
                    493:  */
1.11      simonb    494: private int
1.13      lukem     495: tty_setup(EditLine *el)
1.1       cgd       496: {
1.13      lukem     497:        int rst = 1;
1.12      sommerfe  498:
1.13      lukem     499:        if (el->el_flags & EDIT_DISABLED)
1.38      christos  500:                return 0;
1.13      lukem     501:
1.34      christos  502:        if (!isatty(el->el_outfd)) {
                    503: #ifdef DEBUG_TTY
1.42      christos  504:                (void) fprintf(el->el_errfile, "%s: isatty: %s\n", __func__,
                    505:                    strerror(errno));
1.34      christos  506: #endif /* DEBUG_TTY */
1.38      christos  507:                return -1;
1.34      christos  508:        }
1.42      christos  509:        if (tty_getty(el, &el->el_tty.t_or) == -1) {
1.1       cgd       510: #ifdef DEBUG_TTY
1.42      christos  511:                (void) fprintf(el->el_errfile, "%s: tty_getty: %s\n", __func__,
                    512:                    strerror(errno));
1.1       cgd       513: #endif /* DEBUG_TTY */
1.38      christos  514:                return -1;
1.13      lukem     515:        }
1.42      christos  516:        el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed = el->el_tty.t_or;
1.13      lukem     517:
                    518:        el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex);
                    519:        el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex);
                    520:        el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex);
                    521:
1.43      christos  522:        tty_setup_flags(el, &el->el_tty.t_ex, EX_IO);
1.13      lukem     523:
                    524:        /*
                    525:          * Reset the tty chars to reasonable defaults
                    526:          * If they are disabled, then enable them.
                    527:          */
                    528:        if (rst) {
                    529:                if (tty__cooked_mode(&el->el_tty.t_ts)) {
                    530:                        tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
                    531:                        /*
                    532:                         * Don't affect CMIN and CTIME for the editor mode
                    533:                         */
                    534:                        for (rst = 0; rst < C_NCC - 2; rst++)
                    535:                                if (el->el_tty.t_c[TS_IO][rst] !=
                    536:                                      el->el_tty.t_vdisable
                    537:                                    && el->el_tty.t_c[ED_IO][rst] !=
                    538:                                      el->el_tty.t_vdisable)
                    539:                                        el->el_tty.t_c[ED_IO][rst] =
                    540:                                            el->el_tty.t_c[TS_IO][rst];
                    541:                        for (rst = 0; rst < C_NCC; rst++)
                    542:                                if (el->el_tty.t_c[TS_IO][rst] !=
                    543:                                    el->el_tty.t_vdisable)
                    544:                                        el->el_tty.t_c[EX_IO][rst] =
                    545:                                            el->el_tty.t_c[TS_IO][rst];
                    546:                }
                    547:                tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
1.26      christos  548:                if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) {
1.1       cgd       549: #ifdef DEBUG_TTY
1.42      christos  550:                        (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n",
                    551:                            __func__, strerror(errno));
1.1       cgd       552: #endif /* DEBUG_TTY */
1.38      christos  553:                        return -1;
1.13      lukem     554:                }
1.25      christos  555:        }
1.13      lukem     556:
1.43      christos  557:        tty_setup_flags(el, &el->el_tty.t_ed, ED_IO);
1.13      lukem     558:
                    559:        tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
                    560:        tty_bind_char(el, 1);
1.38      christos  561:        return 0;
1.1       cgd       562: }
                    563:
                    564: protected int
1.13      lukem     565: tty_init(EditLine *el)
1.1       cgd       566: {
1.13      lukem     567:
                    568:        el->el_tty.t_mode = EX_IO;
                    569:        el->el_tty.t_vdisable = _POSIX_VDISABLE;
                    570:        (void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t));
                    571:        (void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t));
1.38      christos  572:        return tty_setup(el);
1.13      lukem     573: }
1.1       cgd       574:
                    575:
                    576: /* tty_end():
                    577:  *     Restore the tty to its original settings
                    578:  */
                    579: protected void
                    580: /*ARGSUSED*/
1.42      christos  581: tty_end(EditLine *el)
1.1       cgd       582: {
1.48      christos  583:        if (el->el_flags & EDIT_DISABLED)
1.49      gson      584:                return;
1.48      christos  585:
1.42      christos  586:        if (tty_setty(el, TCSAFLUSH, &el->el_tty.t_or) == -1) {
                    587: #ifdef DEBUG_TTY
                    588:                (void) fprintf(el->el_errfile,
                    589:                    "%s: tty_setty: %s\n", __func__, strerror(errno));
                    590: #endif /* DEBUG_TTY */
                    591:        }
1.1       cgd       592: }
                    593:
                    594:
                    595: /* tty__getspeed():
                    596:  *     Get the tty speed
                    597:  */
                    598: private speed_t
1.13      lukem     599: tty__getspeed(struct termios *td)
1.1       cgd       600: {
1.13      lukem     601:        speed_t spd;
1.1       cgd       602:
1.13      lukem     603:        if ((spd = cfgetispeed(td)) == 0)
                    604:                spd = cfgetospeed(td);
1.38      christos  605:        return spd;
1.13      lukem     606: }
1.1       cgd       607:
1.19      christos  608: /* tty__getspeed():
                    609:  *     Return the index of the asked char in the c_cc array
                    610:  */
                    611: private int
                    612: tty__getcharindex(int i)
                    613: {
                    614:        switch (i) {
                    615: #ifdef VINTR
                    616:        case C_INTR:
                    617:                return VINTR;
                    618: #endif /* VINTR */
                    619: #ifdef VQUIT
                    620:        case C_QUIT:
                    621:                return VQUIT;
                    622: #endif /* VQUIT */
                    623: #ifdef VERASE
                    624:        case C_ERASE:
                    625:                return VERASE;
                    626: #endif /* VERASE */
                    627: #ifdef VKILL
                    628:        case C_KILL:
                    629:                return VKILL;
                    630: #endif /* VKILL */
                    631: #ifdef VEOF
                    632:        case C_EOF:
                    633:                return VEOF;
                    634: #endif /* VEOF */
                    635: #ifdef VEOL
                    636:        case C_EOL:
                    637:                return VEOL;
                    638: #endif /* VEOL */
                    639: #ifdef VEOL2
                    640:        case C_EOL2:
                    641:                return VEOL2;
                    642: #endif /* VEOL2 */
                    643: #ifdef VSWTCH
                    644:        case C_SWTCH:
                    645:                return VSWTCH;
                    646: #endif /* VSWTCH */
                    647: #ifdef VDSWTCH
                    648:        case C_DSWTCH:
                    649:                return VDSWTCH;
                    650: #endif /* VDSWTCH */
                    651: #ifdef VERASE2
                    652:        case C_ERASE2:
                    653:                return VERASE2;
                    654: #endif /* VERASE2 */
                    655: #ifdef VSTART
                    656:        case C_START:
                    657:                return VSTART;
                    658: #endif /* VSTART */
                    659: #ifdef VSTOP
                    660:        case C_STOP:
                    661:                return VSTOP;
                    662: #endif /* VSTOP */
                    663: #ifdef VWERASE
                    664:        case C_WERASE:
                    665:                return VWERASE;
                    666: #endif /* VWERASE */
                    667: #ifdef VSUSP
                    668:        case C_SUSP:
                    669:                return VSUSP;
                    670: #endif /* VSUSP */
                    671: #ifdef VDSUSP
                    672:        case C_DSUSP:
                    673:                return VDSUSP;
                    674: #endif /* VDSUSP */
                    675: #ifdef VREPRINT
                    676:        case C_REPRINT:
                    677:                return VREPRINT;
                    678: #endif /* VREPRINT */
                    679: #ifdef VDISCARD
                    680:        case C_DISCARD:
                    681:                return VDISCARD;
                    682: #endif /* VDISCARD */
                    683: #ifdef VLNEXT
                    684:        case C_LNEXT:
                    685:                return VLNEXT;
                    686: #endif /* VLNEXT */
                    687: #ifdef VSTATUS
                    688:        case C_STATUS:
                    689:                return VSTATUS;
                    690: #endif /* VSTATUS */
                    691: #ifdef VPAGE
                    692:        case C_PAGE:
                    693:                return VPAGE;
                    694: #endif /* VPAGE */
                    695: #ifdef VPGOFF
                    696:        case C_PGOFF:
                    697:                return VPGOFF;
                    698: #endif /* VPGOFF */
                    699: #ifdef VKILL2
                    700:        case C_KILL2:
                    701:                return VKILL2;
                    702: #endif /* KILL2 */
                    703: #ifdef VMIN
                    704:        case C_MIN:
                    705:                return VMIN;
                    706: #endif /* VMIN */
                    707: #ifdef VTIME
                    708:        case C_TIME:
                    709:                return VTIME;
                    710: #endif /* VTIME */
                    711:        default:
                    712:                return -1;
                    713:        }
                    714: }
1.1       cgd       715:
                    716: /* tty__getchar():
                    717:  *     Get the tty characters
                    718:  */
                    719: private void
1.13      lukem     720: tty__getchar(struct termios *td, unsigned char *s)
1.11      simonb    721: {
1.13      lukem     722:
                    723: #ifdef VINTR
                    724:        s[C_INTR] = td->c_cc[VINTR];
                    725: #endif /* VINTR */
                    726: #ifdef VQUIT
                    727:        s[C_QUIT] = td->c_cc[VQUIT];
                    728: #endif /* VQUIT */
                    729: #ifdef VERASE
                    730:        s[C_ERASE] = td->c_cc[VERASE];
                    731: #endif /* VERASE */
                    732: #ifdef VKILL
                    733:        s[C_KILL] = td->c_cc[VKILL];
                    734: #endif /* VKILL */
                    735: #ifdef VEOF
                    736:        s[C_EOF] = td->c_cc[VEOF];
                    737: #endif /* VEOF */
                    738: #ifdef VEOL
                    739:        s[C_EOL] = td->c_cc[VEOL];
                    740: #endif /* VEOL */
                    741: #ifdef VEOL2
                    742:        s[C_EOL2] = td->c_cc[VEOL2];
                    743: #endif /* VEOL2 */
                    744: #ifdef VSWTCH
                    745:        s[C_SWTCH] = td->c_cc[VSWTCH];
                    746: #endif /* VSWTCH */
                    747: #ifdef VDSWTCH
                    748:        s[C_DSWTCH] = td->c_cc[VDSWTCH];
                    749: #endif /* VDSWTCH */
                    750: #ifdef VERASE2
                    751:        s[C_ERASE2] = td->c_cc[VERASE2];
                    752: #endif /* VERASE2 */
                    753: #ifdef VSTART
                    754:        s[C_START] = td->c_cc[VSTART];
                    755: #endif /* VSTART */
                    756: #ifdef VSTOP
                    757:        s[C_STOP] = td->c_cc[VSTOP];
                    758: #endif /* VSTOP */
                    759: #ifdef VWERASE
                    760:        s[C_WERASE] = td->c_cc[VWERASE];
                    761: #endif /* VWERASE */
                    762: #ifdef VSUSP
                    763:        s[C_SUSP] = td->c_cc[VSUSP];
                    764: #endif /* VSUSP */
                    765: #ifdef VDSUSP
                    766:        s[C_DSUSP] = td->c_cc[VDSUSP];
                    767: #endif /* VDSUSP */
                    768: #ifdef VREPRINT
                    769:        s[C_REPRINT] = td->c_cc[VREPRINT];
                    770: #endif /* VREPRINT */
                    771: #ifdef VDISCARD
                    772:        s[C_DISCARD] = td->c_cc[VDISCARD];
                    773: #endif /* VDISCARD */
                    774: #ifdef VLNEXT
                    775:        s[C_LNEXT] = td->c_cc[VLNEXT];
                    776: #endif /* VLNEXT */
                    777: #ifdef VSTATUS
                    778:        s[C_STATUS] = td->c_cc[VSTATUS];
                    779: #endif /* VSTATUS */
                    780: #ifdef VPAGE
                    781:        s[C_PAGE] = td->c_cc[VPAGE];
                    782: #endif /* VPAGE */
                    783: #ifdef VPGOFF
                    784:        s[C_PGOFF] = td->c_cc[VPGOFF];
                    785: #endif /* VPGOFF */
                    786: #ifdef VKILL2
                    787:        s[C_KILL2] = td->c_cc[VKILL2];
                    788: #endif /* KILL2 */
                    789: #ifdef VMIN
                    790:        s[C_MIN] = td->c_cc[VMIN];
                    791: #endif /* VMIN */
                    792: #ifdef VTIME
                    793:        s[C_TIME] = td->c_cc[VTIME];
                    794: #endif /* VTIME */
                    795: }                              /* tty__getchar */
1.1       cgd       796:
                    797:
                    798: /* tty__setchar():
                    799:  *     Set the tty characters
                    800:  */
                    801: private void
1.13      lukem     802: tty__setchar(struct termios *td, unsigned char *s)
1.11      simonb    803: {
1.13      lukem     804:
                    805: #ifdef VINTR
                    806:        td->c_cc[VINTR] = s[C_INTR];
                    807: #endif /* VINTR */
                    808: #ifdef VQUIT
                    809:        td->c_cc[VQUIT] = s[C_QUIT];
                    810: #endif /* VQUIT */
                    811: #ifdef VERASE
                    812:        td->c_cc[VERASE] = s[C_ERASE];
                    813: #endif /* VERASE */
                    814: #ifdef VKILL
                    815:        td->c_cc[VKILL] = s[C_KILL];
                    816: #endif /* VKILL */
                    817: #ifdef VEOF
                    818:        td->c_cc[VEOF] = s[C_EOF];
                    819: #endif /* VEOF */
                    820: #ifdef VEOL
                    821:        td->c_cc[VEOL] = s[C_EOL];
                    822: #endif /* VEOL */
                    823: #ifdef VEOL2
                    824:        td->c_cc[VEOL2] = s[C_EOL2];
                    825: #endif /* VEOL2 */
                    826: #ifdef VSWTCH
                    827:        td->c_cc[VSWTCH] = s[C_SWTCH];
                    828: #endif /* VSWTCH */
                    829: #ifdef VDSWTCH
                    830:        td->c_cc[VDSWTCH] = s[C_DSWTCH];
                    831: #endif /* VDSWTCH */
                    832: #ifdef VERASE2
                    833:        td->c_cc[VERASE2] = s[C_ERASE2];
                    834: #endif /* VERASE2 */
                    835: #ifdef VSTART
                    836:        td->c_cc[VSTART] = s[C_START];
                    837: #endif /* VSTART */
                    838: #ifdef VSTOP
                    839:        td->c_cc[VSTOP] = s[C_STOP];
                    840: #endif /* VSTOP */
                    841: #ifdef VWERASE
                    842:        td->c_cc[VWERASE] = s[C_WERASE];
                    843: #endif /* VWERASE */
                    844: #ifdef VSUSP
                    845:        td->c_cc[VSUSP] = s[C_SUSP];
                    846: #endif /* VSUSP */
                    847: #ifdef VDSUSP
                    848:        td->c_cc[VDSUSP] = s[C_DSUSP];
                    849: #endif /* VDSUSP */
                    850: #ifdef VREPRINT
                    851:        td->c_cc[VREPRINT] = s[C_REPRINT];
                    852: #endif /* VREPRINT */
                    853: #ifdef VDISCARD
                    854:        td->c_cc[VDISCARD] = s[C_DISCARD];
                    855: #endif /* VDISCARD */
                    856: #ifdef VLNEXT
                    857:        td->c_cc[VLNEXT] = s[C_LNEXT];
                    858: #endif /* VLNEXT */
                    859: #ifdef VSTATUS
                    860:        td->c_cc[VSTATUS] = s[C_STATUS];
                    861: #endif /* VSTATUS */
                    862: #ifdef VPAGE
                    863:        td->c_cc[VPAGE] = s[C_PAGE];
                    864: #endif /* VPAGE */
                    865: #ifdef VPGOFF
                    866:        td->c_cc[VPGOFF] = s[C_PGOFF];
                    867: #endif /* VPGOFF */
                    868: #ifdef VKILL2
                    869:        td->c_cc[VKILL2] = s[C_KILL2];
                    870: #endif /* VKILL2 */
                    871: #ifdef VMIN
                    872:        td->c_cc[VMIN] = s[C_MIN];
                    873: #endif /* VMIN */
                    874: #ifdef VTIME
                    875:        td->c_cc[VTIME] = s[C_TIME];
                    876: #endif /* VTIME */
                    877: }                              /* tty__setchar */
1.1       cgd       878:
                    879:
                    880: /* tty_bind_char():
                    881:  *     Rebind the editline functions
                    882:  */
                    883: protected void
1.13      lukem     884: tty_bind_char(EditLine *el, int force)
1.1       cgd       885: {
1.13      lukem     886:
                    887:        unsigned char *t_n = el->el_tty.t_c[ED_IO];
                    888:        unsigned char *t_o = el->el_tty.t_ed.c_cc;
1.32      christos  889:        Char new[2], old[2];
1.14      jdolecek  890:        const ttymap_t *tp;
                    891:        el_action_t *map, *alt;
                    892:        const el_action_t *dmap, *dalt;
1.13      lukem     893:        new[1] = old[1] = '\0';
                    894:
                    895:        map = el->el_map.key;
                    896:        alt = el->el_map.alt;
                    897:        if (el->el_map.type == MAP_VI) {
                    898:                dmap = el->el_map.vii;
                    899:                dalt = el->el_map.vic;
                    900:        } else {
                    901:                dmap = el->el_map.emacs;
                    902:                dalt = NULL;
                    903:        }
                    904:
1.51      christos  905:        for (tp = tty_map; tp->nch != (wint_t)-1; tp++) {
1.50      christos  906:                new[0] = (Char)t_n[tp->nch];
                    907:                old[0] = (Char)t_o[tp->och];
1.13      lukem     908:                if (new[0] == old[0] && !force)
                    909:                        continue;
                    910:                /* Put the old default binding back, and set the new binding */
1.37      christos  911:                keymacro_clear(el, map, old);
1.32      christos  912:                map[UC(old[0])] = dmap[UC(old[0])];
1.37      christos  913:                keymacro_clear(el, map, new);
1.13      lukem     914:                /* MAP_VI == 1, MAP_EMACS == 0... */
1.32      christos  915:                map[UC(new[0])] = tp->bind[el->el_map.type];
1.13      lukem     916:                if (dalt) {
1.37      christos  917:                        keymacro_clear(el, alt, old);
1.32      christos  918:                        alt[UC(old[0])] = dalt[UC(old[0])];
1.37      christos  919:                        keymacro_clear(el, alt, new);
1.32      christos  920:                        alt[UC(new[0])] = tp->bind[el->el_map.type + 1];
1.13      lukem     921:                }
1.1       cgd       922:        }
                    923: }
                    924:
1.13      lukem     925:
1.44      christos  926: private tcflag_t *
                    927: tty__get_flag(struct termios *t, int kind) {
                    928:        switch (kind) {
                    929:        case MD_INP:
                    930:                return &t->c_iflag;
                    931:        case MD_OUT:
                    932:                return &t->c_oflag;
                    933:        case MD_CTL:
                    934:                return &t->c_cflag;
                    935:        case MD_LIN:
                    936:                return &t->c_lflag;
                    937:        default:
                    938:                abort();
                    939:                /*NOTREACHED*/
                    940:        }
                    941: }
                    942:
                    943:
                    944: private tcflag_t
                    945: tty_update_flag(EditLine *el, tcflag_t f, int mode, int kind)
                    946: {
                    947:        f &= ~el->el_tty.t_t[mode][kind].t_clrmask;
                    948:        f |= el->el_tty.t_t[mode][kind].t_setmask;
                    949:        return f;
                    950: }
                    951:
                    952:
                    953: private void
                    954: tty_update_flags(EditLine *el, int kind)
                    955: {
                    956:        tcflag_t *tt, *ed, *ex;
                    957:        tt = tty__get_flag(&el->el_tty.t_ts, kind);
                    958:        ed = tty__get_flag(&el->el_tty.t_ed, kind);
                    959:        ex = tty__get_flag(&el->el_tty.t_ex, kind);
                    960:
                    961:        if (*tt != *ex && (kind != MD_CTL || *tt != *ed)) {
                    962:                *ed = tty_update_flag(el, *tt, ED_IO, kind);
                    963:                *ex = tty_update_flag(el, *tt, EX_IO, kind);
                    964:        }
                    965: }
                    966:
                    967:
                    968: private void
                    969: tty_update_char(EditLine *el, int mode, int c) {
                    970:        if (!((el->el_tty.t_t[mode][MD_CHAR].t_setmask & C_SH(c)))
                    971:            && (el->el_tty.t_c[TS_IO][c] != el->el_tty.t_c[EX_IO][c]))
                    972:                el->el_tty.t_c[mode][c] = el->el_tty.t_c[TS_IO][c];
                    973:        if (el->el_tty.t_t[mode][MD_CHAR].t_clrmask & C_SH(c))
                    974:                el->el_tty.t_c[mode][c] = el->el_tty.t_vdisable;
                    975: }
                    976:
                    977:
1.1       cgd       978: /* tty_rawmode():
                    979:  *     Set terminal into 1 character at a time mode.
                    980:  */
                    981: protected int
1.13      lukem     982: tty_rawmode(EditLine *el)
1.1       cgd       983: {
                    984:
1.13      lukem     985:        if (el->el_tty.t_mode == ED_IO || el->el_tty.t_mode == QU_IO)
1.38      christos  986:                return 0;
1.13      lukem     987:
                    988:        if (el->el_flags & EDIT_DISABLED)
1.38      christos  989:                return 0;
1.12      sommerfe  990:
1.13      lukem     991:        if (tty_getty(el, &el->el_tty.t_ts) == -1) {
1.1       cgd       992: #ifdef DEBUG_TTY
1.42      christos  993:                (void) fprintf(el->el_errfile, "%s: tty_getty: %s\n", __func__,
1.13      lukem     994:                    strerror(errno));
1.1       cgd       995: #endif /* DEBUG_TTY */
1.38      christos  996:                return -1;
1.1       cgd       997:        }
1.13      lukem     998:        /*
                    999:          * We always keep up with the eight bit setting and the speed of the
1.32      christos 1000:          * tty. But we only believe changes that are made to cooked mode!
1.13      lukem    1001:          */
                   1002:        el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts);
                   1003:        el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts);
                   1004:
                   1005:        if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed ||
                   1006:            tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) {
                   1007:                (void) cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed);
                   1008:                (void) cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed);
                   1009:                (void) cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed);
                   1010:                (void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed);
1.1       cgd      1011:        }
1.13      lukem    1012:        if (tty__cooked_mode(&el->el_tty.t_ts)) {
1.44      christos 1013:                int i;
                   1014:
                   1015:                for (i = MD_INP; i <= MD_LIN; i++)
                   1016:                        tty_update_flags(el, i);
                   1017:
1.13      lukem    1018:                if (tty__gettabs(&el->el_tty.t_ex) == 0)
                   1019:                        el->el_tty.t_tabs = 0;
                   1020:                else
                   1021:                        el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0;
1.1       cgd      1022:
1.44      christos 1023:                tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
                   1024:                /*
                   1025:                 * Check if the user made any changes.
                   1026:                 * If he did, then propagate the changes to the
                   1027:                 * edit and execute data structures.
                   1028:                 */
                   1029:                for (i = 0; i < C_NCC; i++)
                   1030:                        if (el->el_tty.t_c[TS_IO][i] !=
                   1031:                            el->el_tty.t_c[EX_IO][i])
                   1032:                                break;
1.1       cgd      1033:
1.44      christos 1034:                if (i != C_NCC) {
1.13      lukem    1035:                        /*
1.44      christos 1036:                         * Propagate changes only to the unprotected
                   1037:                         * chars that have been modified just now.
                   1038:                         */
                   1039:                        for (i = 0; i < C_NCC; i++)
                   1040:                                tty_update_char(el, ED_IO, i);
                   1041:
                   1042:                        tty_bind_char(el, 0);
                   1043:                        tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
                   1044:
1.13      lukem    1045:                        for (i = 0; i < C_NCC; i++)
1.44      christos 1046:                                tty_update_char(el, EX_IO, i);
                   1047:
                   1048:                        tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
1.1       cgd      1049:                }
                   1050:        }
1.26      christos 1051:        if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) {
1.1       cgd      1052: #ifdef DEBUG_TTY
1.42      christos 1053:                (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1.13      lukem    1054:                    strerror(errno));
1.1       cgd      1055: #endif /* DEBUG_TTY */
1.38      christos 1056:                return -1;
1.13      lukem    1057:        }
                   1058:        el->el_tty.t_mode = ED_IO;
1.38      christos 1059:        return 0;
1.13      lukem    1060: }
1.1       cgd      1061:
                   1062:
                   1063: /* tty_cookedmode():
                   1064:  *     Set the tty back to normal mode
                   1065:  */
                   1066: protected int
1.13      lukem    1067: tty_cookedmode(EditLine *el)
1.1       cgd      1068: {                              /* set tty in normal setup */
                   1069:
1.13      lukem    1070:        if (el->el_tty.t_mode == EX_IO)
1.38      christos 1071:                return 0;
1.13      lukem    1072:
                   1073:        if (el->el_flags & EDIT_DISABLED)
1.38      christos 1074:                return 0;
1.13      lukem    1075:
1.26      christos 1076:        if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) {
1.1       cgd      1077: #ifdef DEBUG_TTY
1.42      christos 1078:                (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1.13      lukem    1079:                    strerror(errno));
1.1       cgd      1080: #endif /* DEBUG_TTY */
1.38      christos 1081:                return -1;
1.13      lukem    1082:        }
                   1083:        el->el_tty.t_mode = EX_IO;
1.38      christos 1084:        return 0;
1.13      lukem    1085: }
1.1       cgd      1086:
                   1087:
                   1088: /* tty_quotemode():
                   1089:  *     Turn on quote mode
                   1090:  */
                   1091: protected int
1.13      lukem    1092: tty_quotemode(EditLine *el)
1.1       cgd      1093: {
1.13      lukem    1094:        if (el->el_tty.t_mode == QU_IO)
1.38      christos 1095:                return 0;
1.1       cgd      1096:
1.13      lukem    1097:        el->el_tty.t_qu = el->el_tty.t_ed;
1.1       cgd      1098:
1.43      christos 1099:        tty_setup_flags(el, &el->el_tty.t_qu, QU_IO);
1.1       cgd      1100:
1.26      christos 1101:        if (tty_setty(el, TCSADRAIN, &el->el_tty.t_qu) == -1) {
1.1       cgd      1102: #ifdef DEBUG_TTY
1.42      christos 1103:                (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1.13      lukem    1104:                    strerror(errno));
1.1       cgd      1105: #endif /* DEBUG_TTY */
1.38      christos 1106:                return -1;
1.13      lukem    1107:        }
                   1108:        el->el_tty.t_mode = QU_IO;
1.38      christos 1109:        return 0;
1.13      lukem    1110: }
1.1       cgd      1111:
                   1112:
                   1113: /* tty_noquotemode():
                   1114:  *     Turn off quote mode
                   1115:  */
                   1116: protected int
1.13      lukem    1117: tty_noquotemode(EditLine *el)
1.1       cgd      1118: {
1.13      lukem    1119:
                   1120:        if (el->el_tty.t_mode != QU_IO)
1.38      christos 1121:                return 0;
1.26      christos 1122:        if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) {
1.1       cgd      1123: #ifdef DEBUG_TTY
1.42      christos 1124:                (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1.13      lukem    1125:                    strerror(errno));
1.1       cgd      1126: #endif /* DEBUG_TTY */
1.38      christos 1127:                return -1;
1.13      lukem    1128:        }
                   1129:        el->el_tty.t_mode = ED_IO;
1.38      christos 1130:        return 0;
1.1       cgd      1131: }
                   1132:
1.13      lukem    1133:
1.1       cgd      1134: /* tty_stty():
                   1135:  *     Stty builtin
                   1136:  */
                   1137: protected int
                   1138: /*ARGSUSED*/
1.32      christos 1139: tty_stty(EditLine *el, int argc __attribute__((__unused__)), const Char **argv)
1.1       cgd      1140: {
1.14      jdolecek 1141:        const ttymodes_t *m;
1.16      christos 1142:        char x;
1.13      lukem    1143:        int aflag = 0;
1.32      christos 1144:        const Char *s, *d;
                   1145:         char name[EL_BUFSIZ];
1.19      christos 1146:        struct termios *tios = &el->el_tty.t_ex;
1.13      lukem    1147:        int z = EX_IO;
                   1148:
                   1149:        if (argv == NULL)
1.38      christos 1150:                return -1;
1.32      christos 1151:        strncpy(name, ct_encode_string(*argv++, &el->el_scratch), sizeof(name));
                   1152:         name[sizeof(name) - 1] = '\0';
1.13      lukem    1153:
                   1154:        while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0')
                   1155:                switch (argv[0][1]) {
                   1156:                case 'a':
                   1157:                        aflag++;
                   1158:                        argv++;
                   1159:                        break;
                   1160:                case 'd':
                   1161:                        argv++;
1.19      christos 1162:                        tios = &el->el_tty.t_ed;
1.13      lukem    1163:                        z = ED_IO;
                   1164:                        break;
                   1165:                case 'x':
                   1166:                        argv++;
1.19      christos 1167:                        tios = &el->el_tty.t_ex;
1.13      lukem    1168:                        z = EX_IO;
                   1169:                        break;
                   1170:                case 'q':
                   1171:                        argv++;
1.19      christos 1172:                        tios = &el->el_tty.t_ts;
1.13      lukem    1173:                        z = QU_IO;
                   1174:                        break;
                   1175:                default:
                   1176:                        (void) fprintf(el->el_errfile,
1.51      christos 1177:                            "%s: Unknown switch `%lc'.\n",
                   1178:                            name, (wint_t)argv[0][1]);
1.38      christos 1179:                        return -1;
1.13      lukem    1180:                }
1.1       cgd      1181:
1.13      lukem    1182:        if (!argv || !*argv) {
                   1183:                int i = -1;
1.29      christos 1184:                size_t len = 0, st = 0, cu;
1.13      lukem    1185:                for (m = ttymodes; m->m_name; m++) {
                   1186:                        if (m->m_type != i) {
                   1187:                                (void) fprintf(el->el_outfile, "%s%s",
                   1188:                                    i != -1 ? "\n" : "",
                   1189:                                    el->el_tty.t_t[z][m->m_type].t_name);
                   1190:                                i = m->m_type;
                   1191:                                st = len =
                   1192:                                    strlen(el->el_tty.t_t[z][m->m_type].t_name);
                   1193:                        }
1.24      christos 1194:                        if (i != -1) {
                   1195:                            x = (el->el_tty.t_t[z][i].t_setmask & m->m_value)
                   1196:                                ?  '+' : '\0';
1.40      christos 1197:
                   1198:                            if (el->el_tty.t_t[z][i].t_clrmask & m->m_value)
                   1199:                                x = '-';
1.24      christos 1200:                        } else {
                   1201:                            x = '\0';
                   1202:                        }
1.13      lukem    1203:
                   1204:                        if (x != '\0' || aflag) {
                   1205:
                   1206:                                cu = strlen(m->m_name) + (x != '\0') + 1;
                   1207:
1.42      christos 1208:                                if (len + cu >=
                   1209:                                    (size_t)el->el_terminal.t_size.h) {
1.13      lukem    1210:                                        (void) fprintf(el->el_outfile, "\n%*s",
1.29      christos 1211:                                            (int)st, "");
1.13      lukem    1212:                                        len = st + cu;
                   1213:                                } else
                   1214:                                        len += cu;
                   1215:
                   1216:                                if (x != '\0')
                   1217:                                        (void) fprintf(el->el_outfile, "%c%s ",
                   1218:                                            x, m->m_name);
                   1219:                                else
                   1220:                                        (void) fprintf(el->el_outfile, "%s ",
                   1221:                                            m->m_name);
                   1222:                        }
1.1       cgd      1223:                }
1.13      lukem    1224:                (void) fprintf(el->el_outfile, "\n");
1.38      christos 1225:                return 0;
1.1       cgd      1226:        }
1.13      lukem    1227:        while (argv && (s = *argv++)) {
1.32      christos 1228:                const Char *p;
1.13      lukem    1229:                switch (*s) {
                   1230:                case '+':
                   1231:                case '-':
1.40      christos 1232:                        x = (char)*s++;
1.13      lukem    1233:                        break;
                   1234:                default:
                   1235:                        x = '\0';
                   1236:                        break;
                   1237:                }
                   1238:                d = s;
1.32      christos 1239:                p = Strchr(s, '=');
1.13      lukem    1240:                for (m = ttymodes; m->m_name; m++)
1.42      christos 1241:                        if ((p ? strncmp(m->m_name, ct_encode_string(d,
                   1242:                            &el->el_scratch), (size_t)(p - d)) :
                   1243:                            strcmp(m->m_name, ct_encode_string(d,
                   1244:                            &el->el_scratch))) == 0 &&
1.19      christos 1245:                            (p == NULL || m->m_type == MD_CHAR))
1.13      lukem    1246:                                break;
                   1247:
                   1248:                if (!m->m_name) {
                   1249:                        (void) fprintf(el->el_errfile,
1.32      christos 1250:                            "%s: Invalid argument `" FSTR "'.\n", name, d);
1.38      christos 1251:                        return -1;
1.19      christos 1252:                }
                   1253:                if (p) {
                   1254:                        int c = ffs((int)m->m_value);
1.32      christos 1255:                        int v = *++p ? parse__escape(&p) :
1.19      christos 1256:                            el->el_tty.t_vdisable;
1.31      christos 1257:                        assert(c != 0);
                   1258:                        c--;
1.19      christos 1259:                        c = tty__getcharindex(c);
                   1260:                        assert(c != -1);
1.40      christos 1261:                        tios->c_cc[c] = (cc_t)v;
1.19      christos 1262:                        continue;
1.13      lukem    1263:                }
                   1264:                switch (x) {
                   1265:                case '+':
                   1266:                        el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value;
                   1267:                        el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
                   1268:                        break;
                   1269:                case '-':
                   1270:                        el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
                   1271:                        el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value;
                   1272:                        break;
                   1273:                default:
                   1274:                        el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
                   1275:                        el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
                   1276:                        break;
                   1277:                }
1.1       cgd      1278:        }
1.27      christos 1279:
1.45      christos 1280:        tty_setup_flags(el, tios, z);
1.27      christos 1281:        if (el->el_tty.t_mode == z) {
                   1282:                if (tty_setty(el, TCSADRAIN, tios) == -1) {
                   1283: #ifdef DEBUG_TTY
1.42      christos 1284:                        (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n",
                   1285:                            __func__, strerror(errno));
1.27      christos 1286: #endif /* DEBUG_TTY */
1.38      christos 1287:                        return -1;
1.27      christos 1288:                }
                   1289:        }
                   1290:
1.38      christos 1291:        return 0;
1.13      lukem    1292: }
1.1       cgd      1293:
                   1294:
                   1295: #ifdef notyet
                   1296: /* tty_printchar():
                   1297:  *     DEbugging routine to print the tty characters
                   1298:  */
                   1299: private void
1.13      lukem    1300: tty_printchar(EditLine *el, unsigned char *s)
1.1       cgd      1301: {
1.13      lukem    1302:        ttyperm_t *m;
                   1303:        int i;
1.1       cgd      1304:
1.13      lukem    1305:        for (i = 0; i < C_NCC; i++) {
                   1306:                for (m = el->el_tty.t_t; m->m_name; m++)
                   1307:                        if (m->m_type == MD_CHAR && C_SH(i) == m->m_value)
                   1308:                                break;
                   1309:                if (m->m_name)
                   1310:                        (void) fprintf(el->el_errfile, "%s ^%c ",
                   1311:                            m->m_name, s[i] + 'A' - 1);
                   1312:                if (i % 5 == 0)
                   1313:                        (void) fprintf(el->el_errfile, "\n");
                   1314:        }
                   1315:        (void) fprintf(el->el_errfile, "\n");
1.1       cgd      1316: }
                   1317: #endif /* notyet */
1.43      christos 1318:
                   1319:
                   1320: private void
                   1321: tty_setup_flags(EditLine *el, struct termios *tios, int mode)
                   1322: {
1.44      christos 1323:        int kind;
                   1324:        for (kind = MD_INP; kind <= MD_LIN; kind++) {
                   1325:                tcflag_t *f = tty__get_flag(tios, kind);
                   1326:                *f = tty_update_flag(el, *f, mode, kind);
                   1327:        }
1.43      christos 1328: }

CVSweb <webmaster@jp.NetBSD.org>