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

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