pdcurses/getch.c

branch
protocol5
changeset 106
7b156b764d11
parent 97
2d43f05b284c
equal deleted inserted replaced
104:a76af67a3a4b 106:7b156b764d11
1 /* Public Domain Curses */
2
3 #include <curspriv.h>
4
5 RCSID("$Id: getch.c,v 1.72 2008/07/13 16:08:18 wmcbrine Exp $")
6
7 /*man-start**************************************************************
8
9 Name: getch
10
11 Synopsis:
12 int getch(void);
13 int wgetch(WINDOW *win);
14 int mvgetch(int y, int x);
15 int mvwgetch(WINDOW *win, int y, int x);
16 int ungetch(int ch);
17 int flushinp(void);
18
19 int get_wch(wint_t *wch);
20 int wget_wch(WINDOW *win, wint_t *wch);
21 int mvget_wch(int y, int x, wint_t *wch);
22 int mvwget_wch(WINDOW *win, int y, int x, wint_t *wch);
23 int unget_wch(const wchar_t wch);
24
25 unsigned long PDC_get_key_modifiers(void);
26 int PDC_save_key_modifiers(bool flag);
27 int PDC_return_key_modifiers(bool flag);
28
29 Description:
30 With the getch(), wgetch(), mvgetch(), and mvwgetch() functions,
31 a character is read from the terminal associated with the window.
32 In nodelay mode, if there is no input waiting, the value ERR is
33 returned. In delay mode, the program will hang until the system
34 passes text through to the program. Depending on the setting of
35 cbreak(), this will be after one character or after the first
36 newline. Unless noecho() has been set, the character will also
37 be echoed into the designated window.
38
39 If keypad() is TRUE, and a function key is pressed, the token for
40 that function key will be returned instead of the raw characters.
41 Possible function keys are defined in <curses.h> with integers
42 beginning with 0401, whose names begin with KEY_.
43
44 If nodelay(win, TRUE) has been called on the window and no input
45 is waiting, the value ERR is returned.
46
47 ungetch() places ch back onto the input queue to be returned by
48 the next call to wgetch().
49
50 flushinp() throws away any type-ahead that has been typed by the
51 user and has not yet been read by the program.
52
53 PDC_get_key_modifiers() returns the keyboard modifiers (shift,
54 control, alt, numlock) effective at the time of the last getch()
55 call, if PDC_save_key_modifiers(TRUE) has been called before the
56 getch(). Use the macros PDC_KEY_MODIFIER_* to determine which
57 modifier(s) were set. PDC_return_key_modifiers() tells getch()
58 to return modifier keys pressed alone as keystrokes (KEY_ALT_L,
59 etc.). These may not work on all platforms.
60
61 NOTE: getch() and ungetch() are implemented as macros, to avoid
62 conflict with many DOS compiler's runtime libraries.
63
64 Return Value:
65 These functions return ERR or the value of the character, meta
66 character or function key token.
67
68 Portability X/Open BSD SYS V
69 getch Y Y Y
70 wgetch Y Y Y
71 mvgetch Y Y Y
72 mvwgetch Y Y Y
73 ungetch Y Y Y
74 flushinp Y Y Y
75 get_wch Y
76 wget_wch Y
77 mvget_wch Y
78 mvwget_wch Y
79 unget_wch Y
80 PDC_get_key_modifiers - - -
81
82 **man-end****************************************************************/
83
84 #define _INBUFSIZ 512 /* size of terminal input buffer */
85 #define NUNGETCH 256 /* max # chars to ungetch() */
86
87 static int c_pindex = 0; /* putter index */
88 static int c_gindex = 1; /* getter index */
89 static int c_ungind = 0; /* ungetch() push index */
90 static int c_ungch[NUNGETCH]; /* array of ungotten chars */
91
92 static int _mouse_key(WINDOW *win)
93 {
94 int i, key = KEY_MOUSE;
95 unsigned long mbe = SP->_trap_mbe;
96
97 /* Filter unwanted mouse events */
98
99 for (i = 0; i < 3; i++)
100 {
101 if (pdc_mouse_status.changes & (1 << i))
102 {
103 int shf = i * 5;
104 short button = pdc_mouse_status.button[i] & BUTTON_ACTION_MASK;
105
106 if ( (!(mbe & (BUTTON1_PRESSED << shf)) &&
107 (button == BUTTON_PRESSED))
108
109 || (!(mbe & (BUTTON1_CLICKED << shf)) &&
110 (button == BUTTON_CLICKED))
111
112 || (!(mbe & (BUTTON1_DOUBLE_CLICKED << shf)) &&
113 (button == BUTTON_DOUBLE_CLICKED))
114
115 || (!(mbe & (BUTTON1_MOVED << shf)) &&
116 (button == BUTTON_MOVED))
117
118 || (!(mbe & (BUTTON1_RELEASED << shf)) &&
119 (button == BUTTON_RELEASED))
120 )
121 pdc_mouse_status.changes ^= (1 << i);
122 }
123 }
124
125 if (pdc_mouse_status.changes & PDC_MOUSE_MOVED)
126 {
127 if (!(mbe & (BUTTON1_MOVED|BUTTON2_MOVED|BUTTON3_MOVED)))
128 pdc_mouse_status.changes ^= PDC_MOUSE_MOVED;
129 }
130
131 if (pdc_mouse_status.changes &
132 (PDC_MOUSE_WHEEL_UP|PDC_MOUSE_WHEEL_DOWN))
133 {
134 if (!(mbe & MOUSE_WHEEL_SCROLL))
135 pdc_mouse_status.changes &=
136 ~(PDC_MOUSE_WHEEL_UP|PDC_MOUSE_WHEEL_DOWN);
137 }
138
139 if (!pdc_mouse_status.changes)
140 return -1;
141
142 /* Check for click in slk area */
143
144 i = PDC_mouse_in_slk(pdc_mouse_status.y, pdc_mouse_status.x);
145
146 if (i)
147 {
148 if (pdc_mouse_status.button[0] & (BUTTON_PRESSED|BUTTON_CLICKED))
149 key = KEY_F(i);
150 else
151 key = -1;
152 }
153
154 return key;
155 }
156
157 int wgetch(WINDOW *win)
158 {
159 static int buffer[_INBUFSIZ]; /* character buffer */
160 int key, waitcount;
161
162 PDC_LOG(("wgetch() - called\n"));
163
164 if (!win)
165 return ERR;
166
167 waitcount = 0;
168
169 /* set the number of 1/20th second napms() calls */
170
171 if (SP->delaytenths)
172 waitcount = 2 * SP->delaytenths;
173 else
174 if (win->_delayms)
175 {
176 /* Can't really do millisecond intervals, so delay in
177 1/20ths of a second (50ms) */
178
179 waitcount = win->_delayms / 50;
180 if (!waitcount)
181 waitcount = 1;
182 }
183
184 /* refresh window when wgetch is called if there have been changes
185 to it and it is not a pad */
186
187 if (!(win->_flags & _PAD) && ((!win->_leaveit &&
188 (win->_begx + win->_curx != SP->curscol ||
189 win->_begy + win->_cury != SP->cursrow)) || is_wintouched(win)))
190 wrefresh(win);
191
192 /* if ungotten char exists, remove and return it */
193
194 if (c_ungind)
195 return c_ungch[--c_ungind];
196
197 /* if normal and data in buffer */
198
199 if ((!SP->raw_inp && !SP->cbreak) && (c_gindex < c_pindex))
200 return buffer[c_gindex++];
201
202 /* prepare to buffer data */
203
204 c_pindex = 0;
205 c_gindex = 0;
206
207 /* to get here, no keys are buffered. go and get one. */
208
209 for (;;) /* loop for any buffering */
210 {
211 /* is there a keystroke ready? */
212
213 if (!PDC_check_key())
214 {
215 /* if not, handle timeout() and halfdelay() */
216
217 if (SP->delaytenths || win->_delayms)
218 {
219 if (!waitcount)
220 return ERR;
221
222 waitcount--;
223 }
224 else
225 if (win->_nodelay)
226 return ERR;
227
228 napms(50); /* sleep for 1/20th second */
229 continue; /* then check again */
230 }
231
232 /* if there is, fetch it */
233
234 key = PDC_get_key();
235
236 if (SP->key_code)
237 {
238 /* filter special keys if not in keypad mode */
239
240 if (!win->_use_keypad)
241 key = -1;
242
243 /* filter mouse events; translate mouse clicks in the slk
244 area to function keys */
245
246 else if (key == KEY_MOUSE)
247 key = _mouse_key(win);
248 }
249
250 /* unwanted key? loop back */
251
252 if (key == -1)
253 continue;
254
255 /* translate CR */
256
257 if (key == '\r' && SP->autocr && !SP->raw_inp)
258 key = '\n';
259
260 /* if echo is enabled */
261
262 if (SP->echo && !SP->key_code)
263 {
264 waddch(win, key);
265 wrefresh(win);
266 }
267
268 /* if no buffering */
269
270 if (SP->raw_inp || SP->cbreak)
271 return key;
272
273 /* if no overflow, put data in buffer */
274
275 if (key == '\b')
276 {
277 if (c_pindex > c_gindex)
278 c_pindex--;
279 }
280 else
281 if (c_pindex < _INBUFSIZ - 2)
282 buffer[c_pindex++] = key;
283
284 /* if we got a line */
285
286 if (key == '\n' || key == '\r')
287 return buffer[c_gindex++];
288 }
289 }
290
291 int mvgetch(int y, int x)
292 {
293 PDC_LOG(("mvgetch() - called\n"));
294
295 if (move(y, x) == ERR)
296 return ERR;
297
298 return wgetch(stdscr);
299 }
300
301 int mvwgetch(WINDOW *win, int y, int x)
302 {
303 PDC_LOG(("mvwgetch() - called\n"));
304
305 if (wmove(win, y, x) == ERR)
306 return ERR;
307
308 return wgetch(win);
309 }
310
311 int PDC_ungetch(int ch)
312 {
313 PDC_LOG(("ungetch() - called\n"));
314
315 if (c_ungind >= NUNGETCH) /* pushback stack full */
316 return ERR;
317
318 c_ungch[c_ungind++] = ch;
319
320 return OK;
321 }
322
323 int flushinp(void)
324 {
325 PDC_LOG(("flushinp() - called\n"));
326
327 PDC_flushinp();
328
329 c_gindex = 1; /* set indices to kill buffer */
330 c_pindex = 0;
331 c_ungind = 0; /* clear c_ungch array */
332
333 return OK;
334 }
335
336 unsigned long PDC_get_key_modifiers(void)
337 {
338 PDC_LOG(("PDC_get_key_modifiers() - called\n"));
339
340 return pdc_key_modifiers;
341 }
342
343 int PDC_save_key_modifiers(bool flag)
344 {
345 PDC_LOG(("PDC_save_key_modifiers() - called\n"));
346
347 SP->save_key_modifiers = flag;
348 return OK;
349 }
350
351 int PDC_return_key_modifiers(bool flag)
352 {
353 PDC_LOG(("PDC_return_key_modifiers() - called\n"));
354
355 SP->return_key_modifiers = flag;
356 return PDC_modifiers_set();
357 }
358
359 #ifdef PDC_WIDE
360 int wget_wch(WINDOW *win, wint_t *wch)
361 {
362 int key;
363
364 PDC_LOG(("wget_wch() - called\n"));
365
366 if (!wch)
367 return ERR;
368
369 key = wgetch(win);
370
371 if (key == ERR)
372 return ERR;
373
374 *wch = key;
375
376 return SP->key_code ? KEY_CODE_YES : OK;
377 }
378
379 int get_wch(wint_t *wch)
380 {
381 PDC_LOG(("get_wch() - called\n"));
382
383 return wget_wch(stdscr, wch);
384 }
385
386 int mvget_wch(int y, int x, wint_t *wch)
387 {
388 PDC_LOG(("mvget_wch() - called\n"));
389
390 if (move(y, x) == ERR)
391 return ERR;
392
393 return wget_wch(stdscr, wch);
394 }
395
396 int mvwget_wch(WINDOW *win, int y, int x, wint_t *wch)
397 {
398 PDC_LOG(("mvwget_wch() - called\n"));
399
400 if (wmove(win, y, x) == ERR)
401 return ERR;
402
403 return wget_wch(win, wch);
404 }
405
406 int unget_wch(const wchar_t wch)
407 {
408 return PDC_ungetch(wch);
409 }
410 #endif

mercurial