|
|
1.1 ! root 1: /********************************************************************* ! 2: * COPYRIGHT NOTICE * ! 3: ********************************************************************** ! 4: * This software is copyright (C) 1982 by Pavel Curtis * ! 5: * * ! 6: * Permission is granted to reproduce and distribute * ! 7: * this file by any means so long as no fee is charged * ! 8: * above a nominal handling fee and so long as this * ! 9: * notice is always included in the copies. * ! 10: * * ! 11: * Other rights are reserved except as explicitly granted * ! 12: * by written permission of the author. * ! 13: * Pavel Curtis * ! 14: * Computer Science Dept. * ! 15: * 405 Upson Hall * ! 16: * Cornell University * ! 17: * Ithaca, NY 14853 * ! 18: * * ! 19: * Ph- (607) 256-4934 * ! 20: * * ! 21: * Pavel.Cornell@Udel-Relay (ARPAnet) * ! 22: * decvax!cornell!pavel (UUCPnet) * ! 23: *********************************************************************/ ! 24: ! 25: /* ! 26: ** lib_getch.c ! 27: ** ! 28: ** The routine getch(). ! 29: ** ! 30: ** $Log: lib_getch.c,v $ ! 31: * Revision 1.9 93/04/12 14:13:39 bin ! 32: * Udo: third color update ! 33: * ! 34: * Revision 2.3 92/11/21 14:47:37 munk ! 35: * Improved alarm signal handling ! 36: * ! 37: * Revision 1.3 92/06/10 14:17:06 bin ! 38: * changed ref to sys/fcntl.h ! 39: * ! 40: * Revision 1.2 92/04/13 14:37:30 bin ! 41: * update by vlad ! 42: * ! 43: * Revision 2.2 91/02/09 13:37:40 munk ! 44: * Conditional code added for systems that don't support ioctl with ! 45: * the command FIONREAD (use fcntl O_NDELAY). ! 46: * Bug fixed in kgetch(), do not put EOF in buffer. ! 47: * Save the old alarm-timer and restart it, after use by kgetch(). ! 48: * ! 49: * Revision 2.1 82/10/25 14:47:29 pavel ! 50: * Added Copyright Notice ! 51: * ! 52: * Revision 2.0 82/10/25 13:45:19 pavel ! 53: * Beta-one Test Release ! 54: * ! 55: ** ! 56: */ ! 57: ! 58: #ifdef RCSHDR ! 59: static char RCSid[] = ! 60: "$Header: /src386/usr/lib/ncurses/RCS/lib_getch.c,v 1.9 93/04/12 14:13:39 bin Exp Locker: bin $"; ! 61: #endif ! 62: ! 63: #include <signal.h> ! 64: #ifdef COHERENT ! 65: #include <fcntl.h> ! 66: #else ! 67: #include <fcntl.h> ! 68: #endif ! 69: #include "curses.h" ! 70: #include "curses.priv.h" ! 71: ! 72: #define nextc() (SP->_backcnt > 0 ? SP->_backbuf[--SP->_backcnt] \ ! 73: : getc(SP->_ifp)) ! 74: ! 75: #define putback(ch) SP->_backbuf[SP->_backcnt++] = ch ! 76: ! 77: ! 78: wgetch(win) ! 79: register WINDOW *win; ! 80: { ! 81: bool setHere = FALSE; /* cbreak mode was set here */ ! 82: register int ch; /* 'int' because of keypad codes */ ! 83: ! 84: #ifdef TRACE ! 85: if (_tracing) ! 86: _tracef("wgetch(%o) called flags = 0%o", win, win->_flags); ! 87: #endif ! 88: ! 89: if (! win->_scroll && (win->_flags & _FULLWIN) ! 90: && win->_curx == win->_maxx ! 91: && win->_cury == win->_maxy) ! 92: return(ERR); ! 93: ! 94: #ifdef FIONREAD ! 95: if (win->_nodelay) ! 96: { ! 97: long count; ! 98: ! 99: ioctl(fileno(SP->_ifp), FIONREAD, &count); ! 100: ! 101: if (! count) ! 102: return(-1); ! 103: } ! 104: #else ! 105: if (win->_nodelay) ! 106: { ! 107: int flags; ! 108: ! 109: flags = fcntl(fileno(SP->_ifp), F_GETFL, 0); ! 110: fcntl(fileno(SP->_ifp), F_SETFL, flags | O_NDELAY); ! 111: ch = fgetc(SP->_ifp); ! 112: fcntl(fileno(SP->_ifp), F_SETFL, flags); ! 113: if (ch == -1) ! 114: return(-1); ! 115: ungetc(ch, SP->_ifp); ! 116: } ! 117: #endif ! 118: ! 119: if (SP->_echo && ! (SP->_raw || SP->_cbreak)) ! 120: { ! 121: cbreak(); ! 122: setHere = TRUE; ! 123: } ! 124: ! 125: if (win->_use_keypad) ! 126: ch = kgetch(); ! 127: else { ! 128: while ((ch = nextc()) == EOF) /* ignore interrupted */ ! 129: ; /* system call */ ! 130: } ! 131: ! 132: if (SP->_echo && ch < 0400 && ch >= 0)/* ch < 0400 => not a keypad key */ ! 133: { ! 134: mvwaddch(curscr, win->_begy + win->_cury, ! 135: win->_begx + win->_curx, ch | win->_attrs); ! 136: waddch(win, ch | win->_attrs); ! 137: } ! 138: ! 139: if (setHere) { ! 140: nocbreak(); ! 141: } ! 142: ! 143: return(ch); ! 144: } ! 145: ! 146: ! 147: /* ! 148: ** kgetch() ! 149: ** ! 150: ** Get an input character, but take care of keypad sequences, returning ! 151: ** an appropriate code when one matches the input. After each character ! 152: ** is received, set a one-second alarm call. If no more of the sequence ! 153: ** is received by the time the alarm goes off, pass through the sequence ! 154: ** gotten so far. ! 155: ** ! 156: */ ! 157: ! 158: static bool alarmed; ! 159: ! 160: static ! 161: int ! 162: kgetch() ! 163: { ! 164: struct try *ptr; ! 165: register int ch; ! 166: char buffer[10]; /* Assume no sequences longer than 10 */ ! 167: register char *bufp = buffer; ! 168: int (*oldsig)(); ! 169: int oldalarm; ! 170: int sigalrm(); ! 171: ! 172: ptr = SP->_keytry; ! 173: ! 174: oldalarm = alarm(0); ! 175: oldsig = signal(SIGALRM, sigalrm); ! 176: signal(SIGALRM, oldsig); ! 177: alarm(oldalarm); ! 178: alarmed = FALSE; ! 179: ! 180: do ! 181: { ! 182: readagain: ! 183: ch = nextc(); ! 184: if (ch != EOF) /* do not put EOF in buffer */ ! 185: *(bufp++) = ch; ! 186: else if (alarmed) /* handle interrupted system */ ! 187: break; /* call properly */ ! 188: else ! 189: goto readagain; ! 190: ! 191: while (ptr != NULL && ptr->ch != ch) ! 192: ptr = ptr->sibling; ! 193: ! 194: if (ptr != NULL) ! 195: { ! 196: if (ptr->value != 0) ! 197: { ! 198: signal(SIGALRM, oldsig); ! 199: alarm(oldalarm); ! 200: return(ptr->value); ! 201: } ! 202: else ! 203: { ! 204: ptr = ptr->child; ! 205: signal(SIGALRM, sigalrm); ! 206: alarm(1); ! 207: } ! 208: } ! 209: ! 210: } while (ptr != NULL); ! 211: ! 212: signal(SIGALRM, oldsig); ! 213: alarm(oldalarm); ! 214: ! 215: while (--bufp > buffer) ! 216: putback(*bufp); ! 217: ! 218: return(*bufp); ! 219: } ! 220: ! 221: ! 222: static ! 223: sigalrm() ! 224: { ! 225: alarmed = TRUE; ! 226: signal(SIGALRM, sigalrm); ! 227: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.