Annotation of researchv10no/ncurses/screen/getch.c, revision 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.