87677bae2ef265c673653d96f4d22527a2046a3c
[coreboot.git] / payloads / libpayload / curses / PDCurses-3.4 / pdcurses / getch.c
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