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