Annotation of researchv10no/ncurses/screen/getch.c, revision 1.1.1.1

1.1       root        1: # include      "curses.ext"
                      2: # include      <signal.h>
                      3: # include      <errno.h>
                      4: 
                      5: /*     @(#) getch.c: 1.1 10/15/83      (1.16   3/16/83)        */
                      6: 
                      7: static int sig_caught;
                      8: 
                      9: /*
                     10:  *     This routine reads in a character from the window.
                     11:  *
                     12:  *     wgetch MUST return an int, not a char, because it can return
                     13:  *     things like ERR, meta characters, and function keys > 256.
                     14:  */
                     15: int
                     16: wgetch(win)
                     17: register WINDOW        *win;
                     18: {
                     19: 
                     20:        register int inp;
                     21:        register int i, j;
                     22:        char c;
                     23:        int arg;
                     24:        bool    weset = FALSE;
                     25:        FILE *inf;
                     26: 
                     27:        if (SP->fl_echoit && !win->_scroll && (win->_flags&_FULLWIN)
                     28:            && win->_curx == win->_maxx && win->_cury == win->_maxy)
                     29:                return ERR;
                     30: # ifdef DEBUG
                     31:        if(outf) fprintf(outf, "WGETCH: SP->fl_echoit = %c, SP->fl_rawmode = %c\n", SP->fl_echoit ? 'T' : 'F', SP->fl_rawmode ? 'T' : 'F');
                     32:        if (outf) fprintf(outf, "_use_keypad %d, kp_state %d\n", win->_use_keypad, SP->kp_state);
                     33: # endif
                     34:        if (SP->fl_echoit && !SP->fl_rawmode) {
                     35:                cbreak();
                     36:                weset++;
                     37:        }
                     38: 
                     39: #ifdef KEYPAD
                     40:        /* Make sure keypad on is in proper state */
                     41:        if (win->_use_keypad != SP->kp_state) {
                     42:                _kpmode(win->_use_keypad);
                     43:                fflush(stdout);
                     44:        }
                     45: #endif
                     46: 
                     47:        /* Make sure we are in proper nodelay state */
                     48:        if (win->_nodelay != SP->fl_nodelay)
                     49:                _fixdelay(SP->fl_nodelay, win->_nodelay);
                     50: 
                     51:        /* Check for pushed typeahead.  We make the assumption that
                     52:         * if a function key is being typed, there is no pushed
                     53:         * typeahead from the previous key waiting.
                     54:         */
                     55:        if (SP->input_queue[0] >= 0) {
                     56:                inp = SP->input_queue[0];
                     57:                for (i=0; i<16; i++) {
                     58:                        SP->input_queue[i] = SP->input_queue[i+1];
                     59:                        if (SP->input_queue[i] < 0)
                     60:                                break;
                     61:                }
                     62:                goto gotit;
                     63:        }
                     64: 
                     65:        inf = SP->input_file;
                     66:        if (inf == stdout)      /* so output can be teed somewhere */
                     67:                inf = stdin;
                     68: #ifdef FIONREAD
                     69:        if (win->_nodelay) {
                     70:                ioctl(fileno(inf), FIONREAD, &arg);
                     71: #ifdef DEBUG
                     72:                if (outf) fprintf(outf, "FIONREAD returns %d\n", arg);
                     73: #endif
                     74:                if (arg < 1)
                     75:                        return -1;
                     76:        }
                     77: #endif
                     78:        for (i = -1; i<0; ) {
                     79:                extern int errno;
                     80:                sig_caught = 0;
                     81:                i = read(fileno(inf), &c, 1);
                     82:                /*
                     83:                 * I hope the system won't retern infinite EINTRS - maybe
                     84:                 * there should be a hop count here.
                     85:                 */
                     86:                if (i < 0 && errno != EINTR && !sig_caught) {
                     87:                        inp = ERR;
                     88:                        goto gotit;
                     89:                }
                     90:        }
                     91:        if (i > 0) {
                     92:                inp = c;
                     93:                if (!win->_use_meta)
                     94:                        inp &= 0177;
                     95:                else
                     96:                        inp &= 0377;
                     97:        } else {
                     98:                inp = ERR;
                     99:                goto gotit;
                    100:        }
                    101: # ifdef DEBUG
                    102:        if(outf) fprintf(outf,"WGETCH got '%s'\n",unctrl(inp));
                    103: # endif
                    104: 
                    105: #ifdef KEYPAD
                    106:        /* Check for arrow and function keys */
                    107:        if (win->_use_keypad) {
                    108:                SP->input_queue[0] = inp;
                    109:                SP->input_queue[1] = -1;
                    110:                for (i=0; SP->kp[i].keynum >= 0; i++) {
                    111:                        if (SP->kp[i].sends[0] == inp) {
                    112:                                for (j=0; ; j++) {
                    113:                                        if (SP->kp[i].sends[j] <= 0)
                    114:                                                break;  /* found */
                    115:                                        if (SP->input_queue[j] == -1) {
                    116:                                                SP->input_queue[j] = _fpk(inf);
                    117:                                                SP->input_queue[j+1] = -1;
                    118:                                        }
                    119:                                        if (SP->kp[i].sends[j] != SP->input_queue[j])
                    120:                                                goto contouter; /* not this one */
                    121:                                }
                    122:                                /* It matched the function key. */
                    123:                                inp = SP->kp[i].keynum;
                    124:                                SP->input_queue[0] = -1;
                    125:                                goto gotit;
                    126:                        }
                    127:                contouter:;
                    128:                }
                    129:                /* Didn't match any function keys. */
                    130:                inp = SP->input_queue[0];
                    131:                for (i=0; i<16; i++) {
                    132:                        SP->input_queue[i] = SP->input_queue[i+1];
                    133:                        if (SP->input_queue[i] < 0)
                    134:                                break;
                    135:                }
                    136:                goto gotit;
                    137:        }
                    138: #endif
                    139: 
                    140:        if (SP->fl_echoit) {
                    141:                waddch(win, (chtype) inp);
                    142:                wrefresh(win);
                    143:        }
                    144: gotit:
                    145:        if (weset)
                    146:                nocbreak();
                    147: #ifdef DEBUG
                    148:        if(outf) fprintf(outf, "getch returns %o, pushed %o %o %o\n",
                    149:                inp, SP->input_queue[0], SP->input_queue[1], SP->input_queue[2]);
                    150: #endif
                    151:        return inp;
                    152: }
                    153: _catch_alarm()
                    154: {
                    155:        sig_caught = 1;
                    156: }
                    157: 
                    158: /*
                    159:  * Fast peek key.  Like getchar but if the right flags are set, times out
                    160:  * quickly if there is nothing waiting, returning -1.
                    161:  * f is an output stdio descriptor, we read from the fileno.  win is the
                    162:  * window this is supposed to have something to do with.
                    163:  */
                    164: #ifndef FIONREAD
                    165: /*
                    166:  * Traditional implementation.  The best resolution we have is 1 second,
                    167:  * so we set a 1 second alarm and try to read.  If we fail for 1 second,
                    168:  * we assume there is no key waiting.  Problem here is that 1 second is
                    169:  * too long, people can type faster than this.
                    170:  */
                    171: static
                    172: _fpk(f)
                    173: FILE *f;
                    174: {
                    175:        char c;
                    176:        int rc;
                    177:        int (*oldsig)();
                    178:        int oldalarm;
                    179: 
                    180:        oldsig = signal(SIGALRM, _catch_alarm);
                    181:        oldalarm = alarm(1);
                    182:        sig_caught = 0;
                    183:        rc = read(fileno(f), &c, 1);
                    184:        if (sig_caught) {
                    185:                sig_caught = 0;
                    186:                alarm(oldalarm);
                    187:                return -2;
                    188:        }
                    189:        signal(SIGALRM, oldsig);
                    190:        alarm(oldalarm);
                    191:        return rc == 1 ? c : -1;
                    192: }
                    193: #else FIONREAD
                    194: /*
                    195:  * If we have the select system call, we can do much better.
                    196:  * We wait for long enough for a terminal to send another character
                    197:  * (at 15cps repeat rate, this is 67 ms, I'm using 100ms to allow
                    198:  * a bit of a fudge factor) and time out more quickly.  Even if we
                    199:  * don't have the real 4.2BSD select, we can emulate it with napms
                    200:  * and FIONREAD.  napms might be done with only 1 second resolution,
                    201:  * but this is no worse than what we have above.
                    202:  */
                    203: static
                    204: _fpk(f)
                    205: FILE *f;
                    206: {
                    207:        int infd, rc;
                    208:        int *outfd, *exfd;
                    209:        char c;
                    210: 
                    211:        infd = 1 << fileno(f);
                    212:        outfd = exfd = (int *) NULL;
                    213:        rc = select(20, &infd, outfd, exfd, 100);
                    214:        if (rc < 0)
                    215:                return -2;
                    216:        rc = read(fileno(f), &c, 1);
                    217:        return rc == 1 ? c : -1;
                    218: }
                    219: #endif FIONREAD

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.