[BACK]Return to ttyio.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mg

Annotation of src/usr.bin/mg/ttyio.c, Revision 1.2

1.1       deraadt     1: /*
                      2:  * Name:       MicroEMACS
                      3:  *             System V terminal I/O.
                      4:  * Version:    0
                      5:  * Last edit:  Tue Aug 26 23:57:57 PDT 1986
                      6:  * By:         gonzo!daveb
                      7:  *             {sun, amdahl, mtxinu}!rtech!gonzo!daveb
                      8:  *
                      9:  * The functions in this file
                     10:  * negotiate with the operating system for
                     11:  * keyboard characters, and write characters to
                     12:  * the display in a barely buffered fashion.
                     13:  *
                     14:  * This version goes along with tty/termcap/tty.c.
                     15:  * Terminal size is determined there, rather than here, and
                     16:  * this does not open the termcap file
                     17:  */
                     18: #include       "def.h"
                     19:
                     20: #include       <sys/types.h>
                     21: #include       <fcntl.h>
1.2     ! deraadt    22: #include       <termios.h>
1.1       deraadt    23:
                     24: #define        NOBUF   512                     /* Output buffer size.          */
                     25:
                     26: char   obuf[NOBUF];                    /* Output buffer.               */
                     27: int    nobuf;                          /* buffer count                 */
                     28:
1.2     ! deraadt    29: static struct termios  ot;             /* entry state of the terminal  */
        !            30: static struct termios  nt;             /* editor's terminal state      */
1.1       deraadt    31:
                     32: static int ttyactivep = FALSE;         /* terminal in editor mode?     */
                     33: static int ttysavedp = FALSE;          /* terminal state saved?        */
                     34:
                     35: int    nrow;                           /* Terminal size, rows.         */
                     36: int    ncol;                           /* Terminal size, columns.      */
                     37:
                     38: /* These are used to implement typeahead on System V */
                     39:
                     40: int kbdflgs;                   /* saved keyboard fd flags      */
                     41: int kbdpoll;                   /* in O_NDELAY mode                     */
                     42: int kbdqp;                     /* there is a char in kbdq      */
                     43: char kbdq;                     /* char we've already read      */
                     44:
                     45: /*
                     46:  * This function gets called once, to set up
                     47:  * the terminal channel.  This version turns off flow
                     48:  * control.  This may be wrong for your system, but no
                     49:  * good solution has really been found (daveb).
                     50:  */
                     51: ttopen()
                     52: {
                     53:        register char   *cp;
                     54:        extern char     *getenv();
                     55:
                     56:        if (ttyactivep)
                     57:                return;
                     58:
                     59:        if( !ttysavedp )
                     60:        {
1.2     ! deraadt    61:                if (tcgetattr(0, &ot) < 0)
1.1       deraadt    62:                        abort();
                     63:                nt = ot;                /* save entry state             */
                     64:                nt.c_cc[VMIN] = 1;      /* one character read is OK     */
                     65:                nt.c_cc[VTIME] = 0;     /* Never time out.              */
                     66:                nt.c_iflag |= IGNBRK;
                     67:                nt.c_iflag &= ~( ICRNL | INLCR | ISTRIP | IXON | IXOFF );
                     68:                nt.c_oflag &= ~OPOST;
                     69:                nt.c_cflag |= CS8;      /* allow 8th bit on input       */
                     70:                nt.c_cflag &= ~PARENB;  /* Don't check parity           */
                     71:                nt.c_lflag &= ~( ECHO | ICANON | ISIG );
                     72:
                     73:                kbdpoll = (((kbdflgs = fcntl(0, F_GETFL, 0)) & O_NDELAY) != 0);
                     74:
                     75:                ttysavedp = TRUE;
                     76:        }
                     77:
1.2     ! deraadt    78:        if (tcsetattr(0, TCSAFLUSH, &nt) < 0)
1.1       deraadt    79:                abort();
                     80:
                     81:        /* This really belongs in tty/termcap... */
                     82:
                     83:        if ((cp=getenv("TERMCAP")) == NULL
                     84:        || (nrow=getvalue(cp, "li")) <= 0
                     85:        || (ncol=getvalue(cp, "co")) <= 0) {
                     86:                nrow = 24;
                     87:                ncol = 80;
                     88:        }
                     89:        if (nrow > NROW)                        /* Don't crash if the   */
                     90:                nrow = NROW;                    /* termcap entry is     */
                     91:        if (ncol > NCOL)                        /* too big.             */
                     92:                ncol = NCOL;
                     93:
                     94:        ttyactivep = TRUE;
                     95: }
                     96:
                     97: /*
                     98:  * This routine scans a string, which is
                     99:  * actually the return value of a getenv call for the TERMCAP
                    100:  * variable, looking for numeric parameter "name". Return the value
                    101:  * if found. Return -1 if not there. Assume that "name" is 2
                    102:  * characters long. This limited use of the TERMCAP lets us find
                    103:  * out the size of a window on the X display.
                    104:  */
                    105: getvalue(cp, name)
                    106: register char  *cp;
                    107: register char  *name;
                    108: {
                    109:        for (;;) {
                    110:                while (*cp!=0 && *cp!=':')
                    111:                        ++cp;
                    112:                if (*cp++ == 0)                 /* Not found.           */
                    113:                        return (-1);
                    114:                if (cp[0]==name[0] && cp[1]==name[1] && cp[2]=='#')
                    115:                        return (atoi(cp+3));    /* Stops on ":".        */
                    116:        }
                    117: }
                    118:
                    119: /*
                    120:  * This function gets called just
                    121:  * before we go back home to the shell. Put all of
                    122:  * the terminal parameters back.
                    123:  */
                    124: ttclose()
                    125: {
                    126:        if(!ttysavedp || !ttyactivep)
                    127:                return;
                    128:        ttflush();
1.2     ! deraadt   129:        if (tcsetattr(0, TCSAFLUSH, &ot) < 0 ||
        !           130:            fcntl( 0, F_SETFL, kbdflgs ) < 0)
1.1       deraadt   131:                abort();
                    132:        ttyactivep = FALSE;
                    133: }
                    134:
                    135: /*
                    136:  * Write character to the display.
                    137:  * Characters are buffered up, to make things
                    138:  * a little bit more efficient.
                    139:  */
                    140: ttputc(c)
                    141: {
                    142:        if (nobuf >= NOBUF)
                    143:                ttflush();
                    144:        obuf[nobuf++] = c;
                    145: }
                    146:
                    147: /*
                    148:  * Flush output.
                    149:  */
                    150: ttflush()
                    151: {
                    152:        if (nobuf != 0) {
                    153:                write(1, obuf, nobuf);
                    154:                nobuf = 0;
                    155:        }
                    156: }
                    157:
                    158: /*
                    159:  * Read character from terminal.
                    160:  * All 8 bits are returned, so that you can use
                    161:  * a multi-national terminal.
                    162:  *
                    163:  * If keyboard 'queue' already has typeahead from a typeahead() call,
                    164:  * just return it.  Otherwise, make sure we are in blocking i/o mode
                    165:  * and read a character.
                    166:  */
                    167: ttgetc()
                    168: {
                    169:        if( kbdqp )
                    170:                kbdqp = FALSE;
                    171:        else
                    172:        {
                    173:                if( kbdpoll && fcntl( 0, F_SETFL, kbdflgs ) < 0 )
                    174:                        abort();
                    175:                kbdpoll = FALSE;
                    176:                while (read(0, &kbdq, 1) != 1)
                    177:                        ;
                    178:        }
                    179:        return ( kbdq & 0xff );
                    180: }
                    181:
                    182: /*
                    183:  * Return non-FALSE if typeahead is pending.
                    184:  *
                    185:  * If already got unread typeahead, do nothing.
                    186:  * Otherwise, set keyboard to O_NDELAY if not already, and try
                    187:  * a one character read.
                    188:  */
                    189: typeahead()
                    190: {
                    191:        if( !kbdqp )
                    192:        {
                    193:                if( !kbdpoll && fcntl( 0, F_SETFL, kbdflgs | O_NDELAY ) < 0 )
                    194:                        abort();
                    195:                kbdpoll = TRUE;
                    196:                kbdqp = (1 == read( 0, &kbdq, 1 ));
                    197:        }
                    198:        return ( kbdqp );
                    199: }
                    200:
                    201:
                    202: /*
                    203:  * panic:  print error and die, leaving core file.
                    204:  * Don't know why this is needed (daveb).
                    205:  */
                    206: panic(s)
                    207: char *s;
                    208: {
                    209:        fprintf(stderr, "%s\r\n", s);
                    210:        abort();
                    211: }
                    212:
                    213:
                    214: /*
                    215: ** This should check the size of the window, and reset if needed.
                    216: */
                    217:
                    218: setttysize()
                    219: {
                    220: #ifdef TIOCGWINSZ
                    221:         struct winsize winsize;
                    222:        if (ioctl(0, TIOCGWINSZ, (char *) &winsize) == 0) {
                    223:                nrow = winsize . ws_row;
                    224:                ncol = winsize . ws_col;
                    225:        } else
                    226: #endif
                    227:        if ((nrow=tgetnum ("li")) <= 0
                    228:        || (ncol=tgetnum ("co")) <= 0) {
                    229:                nrow = 24;
                    230:                ncol = 80;
                    231:        }
                    232:        if (nrow > NROW)                        /* Don't crash if the   */
                    233:                nrow = NROW;                    /* termcap entry is     */
                    234:        if (ncol > NCOL)                        /* too big.             */
                    235:                ncol = NCOL;
                    236: }
                    237:
                    238: #ifndef NO_DPROMPT
                    239: #include <signal.h>
                    240: #include <setjmp.h>
                    241:
                    242: static jmp_buf tohere;
                    243:
                    244: static void alrm()
                    245: {
                    246:        longjmp(tohere, -1);
                    247: }
                    248:
                    249: /*
                    250:  * Return TRUE if we wait without doing anything, else return FALSE.
                    251:  */
                    252:
                    253: ttwait()
                    254: {
                    255:        if (kbdqp)
                    256:                return FALSE;           /* already pending input        */
                    257:        if (setjmp(tohere))
                    258:                return TRUE;            /* timeout on read if here      */
                    259:        signal(SIGALRM, alrm); alarm(2);
                    260:        kbdqp = (1 == read(0, &kbdq, 1));
                    261:        alarm(0);
                    262:        return FALSE;                   /* successful read if here      */
                    263: }
                    264: #endif NO_DPROMPT