[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.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>