|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.