libpayload: Add PDCurses and ncurses' libform/libmenu
[coreboot.git] / payloads / libpayload / curses / PDCurses-3.4 / os2 / pdckbd.c
1 /* Public Domain Curses */
2
3 #if defined(__EMX__) || defined(__WATCOMC__) || defined(__IBMC__) || \
4 defined(__TURBOC__)
5 # define HAVE_SIGNAL
6 # include <signal.h>
7 #endif
8
9 #include "pdcos2.h"
10
11 RCSID("$Id: pdckbd.c,v 1.89 2008/07/14 04:24:51 wmcbrine Exp $")
12
13 /*man-start**************************************************************
14
15   Name:                                                         pdckbd
16
17   Synopsis:
18         unsigned long PDC_get_input_fd(void);
19
20   Description:
21         PDC_get_input_fd() returns the file descriptor that PDCurses 
22         reads its input from. It can be used for select().
23
24   Portability                                X/Open    BSD    SYS V
25         PDC_get_input_fd                        -       -       -
26
27 **man-end****************************************************************/
28
29 #ifdef EMXVIDEO
30 # include <termios.h>
31 static int tahead = -1;
32 #else
33 static KBDINFO kbdinfo;     /* default keyboard mode */
34 static HMOU mouse_handle = 0;
35 static MOUSE_STATUS old_mouse_status;
36 static USHORT old_shift = 0;
37 static bool key_pressed = FALSE;
38 static int mouse_events = 0;
39 #endif
40
41 /************************************************************************
42  *    Table for key code translation of function keys in keypad mode    *
43  *    These values are for strict IBM keyboard compatibles only         *
44  ************************************************************************/
45
46 static short key_table[] =
47 {
48     -1,             ALT_ESC,        -1,             0,
49     -1,             -1,             -1,             -1,
50     -1,             -1,             -1,             -1,
51     -1,             -1,             ALT_BKSP,       KEY_BTAB,
52     ALT_Q,          ALT_W,          ALT_E,          ALT_R,
53     ALT_T,          ALT_Y,          ALT_U,          ALT_I,
54     ALT_O,          ALT_P,          ALT_LBRACKET,   ALT_RBRACKET,
55     ALT_ENTER,      -1,             ALT_A,          ALT_S,
56     ALT_D,          ALT_F,          ALT_G,          ALT_H,
57     ALT_J,          ALT_K,          ALT_L,          ALT_SEMICOLON,
58     ALT_FQUOTE,     ALT_BQUOTE,     -1,             ALT_BSLASH,
59     ALT_Z,          ALT_X,          ALT_C,          ALT_V,
60     ALT_B,          ALT_N,          ALT_M,          ALT_COMMA,
61     ALT_STOP,       ALT_FSLASH,     -1,             ALT_PADSTAR,
62     -1,             -1,             -1,             KEY_F(1),
63     KEY_F(2),       KEY_F(3),       KEY_F(4),       KEY_F(5),
64     KEY_F(6),       KEY_F(7),       KEY_F(8),       KEY_F(9),
65     KEY_F(10),      -1,             -1,             KEY_HOME,
66     KEY_UP,         KEY_PPAGE,      ALT_PADMINUS,   KEY_LEFT,
67     KEY_B2,         KEY_RIGHT,      ALT_PADPLUS,    KEY_END,
68     KEY_DOWN,       KEY_NPAGE,      KEY_IC,         KEY_DC,
69     KEY_F(13),      KEY_F(14),      KEY_F(15),      KEY_F(16),
70     KEY_F(17),      KEY_F(18),      KEY_F(19),      KEY_F(20),
71     KEY_F(21),      KEY_F(22),      KEY_F(25),      KEY_F(26),
72     KEY_F(27),      KEY_F(28),      KEY_F(29),      KEY_F(30),
73     KEY_F(31),      KEY_F(32),      KEY_F(33),      KEY_F(34),
74     KEY_F(37),      KEY_F(38),      KEY_F(39),      KEY_F(40),
75     KEY_F(41),      KEY_F(42),      KEY_F(43),      KEY_F(44),
76     KEY_F(45),      KEY_F(46),      -1,             CTL_LEFT,
77     CTL_RIGHT,      CTL_END,        CTL_PGDN,       CTL_HOME,
78     ALT_1,          ALT_2,          ALT_3,          ALT_4,
79     ALT_5,          ALT_6,          ALT_7,          ALT_8,
80     ALT_9,          ALT_0,          ALT_MINUS,      ALT_EQUAL,
81     CTL_PGUP,       KEY_F(11),      KEY_F(12),      KEY_F(23),
82     KEY_F(24),      KEY_F(35),      KEY_F(36),      KEY_F(47),
83     KEY_F(48),      CTL_UP,         CTL_PADMINUS,   CTL_PADCENTER,
84     CTL_PADPLUS,    CTL_DOWN,       CTL_INS,        CTL_DEL,
85     CTL_TAB,        CTL_PADSLASH,   CTL_PADSTAR,    ALT_HOME,
86     ALT_UP,         ALT_PGUP,       -1,             ALT_LEFT,
87     -1,             ALT_RIGHT,      -1,             ALT_END,
88     ALT_DOWN,       ALT_PGDN,       ALT_INS,        ALT_DEL,
89     ALT_PADSLASH,   ALT_TAB,        ALT_PADENTER,   -1
90 };
91
92 unsigned long pdc_key_modifiers = 0L;
93
94 unsigned long PDC_get_input_fd(void)
95 {
96     PDC_LOG(("PDC_get_input_fd() - called\n"));
97
98     return (unsigned long)fileno(stdin);
99 }
100
101 #ifndef EMXVIDEO
102
103 void PDC_get_keyboard_info(void)
104 {
105     kbdinfo.cb = sizeof(kbdinfo);
106     KbdGetStatus(&kbdinfo, 0);
107 }
108
109 void PDC_set_keyboard_default(void)
110 {
111     KbdSetStatus(&kbdinfo, 0);
112 }
113
114 #endif /* ifndef EMXVIDEO */
115
116 void PDC_set_keyboard_binary(bool on)
117 {
118     PDC_LOG(("PDC_set_keyboard_binary() - called\n"));
119
120 #ifndef EMXVIDEO
121     if (on)
122     {
123         kbdinfo.fsMask &= ~(KEYBOARD_ASCII_MODE);
124         kbdinfo.fsMask |= KEYBOARD_BINARY_MODE;
125     }
126     else
127     {
128         kbdinfo.fsMask &= ~(KEYBOARD_BINARY_MODE);
129         kbdinfo.fsMask |= KEYBOARD_ASCII_MODE;
130     }
131
132     KbdSetStatus(&kbdinfo, 0);
133 #endif
134
135 #ifdef HAVE_SIGNAL
136     signal(SIGBREAK, on ? SIG_IGN : SIG_DFL);
137 #endif
138 }
139
140 /* check if a key or mouse event is waiting */
141
142 bool PDC_check_key(void)
143 {
144 #if !defined(_MSC_VER) && !defined(EMXVIDEO)
145     KBDKEYINFO keyInfo = {0};
146 #endif
147
148 #ifdef EMXVIDEO
149     if (tahead == -1)       /* Nothing typed yet */
150     {                    
151         tahead = _read_kbd(0, 0, 0);
152
153         /* Read additional */
154
155         if (tahead == 0)    
156             tahead = _read_kbd(0, 1, 0) << 8;
157     }
158
159     return (tahead != -1);
160 #else
161 # ifndef _MSC_VER
162
163     KbdGetStatus(&kbdinfo, 0);
164
165     if (mouse_handle)
166     {
167         MOUQUEINFO queue;
168
169         MouGetNumQueEl(&queue, mouse_handle);
170         mouse_events = queue.cEvents;
171
172         if (mouse_events)
173             return TRUE;
174     }
175
176     if (old_shift && !kbdinfo.fsState)  /* modifier released */
177     {
178         if (!key_pressed && SP->return_key_modifiers)
179             return TRUE;
180     }
181     else if (!old_shift && kbdinfo.fsState) /* modifier pressed */
182         key_pressed = FALSE;
183
184     old_shift = kbdinfo.fsState;
185
186     KbdPeek(&keyInfo, 0);   /* peek at keyboard  */
187     return (keyInfo.fbStatus != 0);
188 # else
189     return kbhit();
190 # endif
191 #endif
192 }         
193
194 #ifndef EMXVIDEO
195
196 static int _process_mouse_events(void)
197 {
198     MOUEVENTINFO event;
199     static const USHORT button_mask[] = {6, 96, 24},
200                         move_mask[] = {2, 32, 8},
201                         press_mask[] = {4, 64, 16};
202     USHORT count = 1;
203     short shift_flags = 0;
204     int i;
205
206     MouReadEventQue(&event, &count, mouse_handle);
207     mouse_events--;
208
209     for (i = 0; i < 3; i++)
210     {
211         pdc_mouse_status.button[i] =
212             ((event.fs & move_mask[i]) ? BUTTON_MOVED : 0) |
213             ((event.fs & press_mask[i]) ? BUTTON_PRESSED : 0);
214
215         /* PRESS events are sometimes mistakenly reported as MOVE 
216            events. A MOVE should always follow a PRESS, so treat a MOVE 
217            immediately after a RELEASE as a PRESS. */
218
219         if ((pdc_mouse_status.button[i] == BUTTON_MOVED) &&
220             (old_mouse_status.button[i] == BUTTON_RELEASED))
221         {
222             pdc_mouse_status.button[i] = BUTTON_PRESSED;
223         }
224
225         if (pdc_mouse_status.button[i] == BUTTON_PRESSED && SP->mouse_wait)
226         {
227             /* Check for a click -- a PRESS followed immediately by a 
228                release */
229
230             if (!mouse_events)
231             {
232                 MOUQUEINFO queue;
233
234                 napms(SP->mouse_wait);
235
236                 MouGetNumQueEl(&queue, mouse_handle);
237                 mouse_events = queue.cEvents;
238             }
239
240             if (mouse_events)
241             {
242                 MouReadEventQue(&event, &count, mouse_handle);
243
244                 if (!(event.fs & button_mask[i]))
245                     pdc_mouse_status.button[i] = BUTTON_CLICKED;
246             }
247         }
248     }
249
250     pdc_mouse_status.x = event.col;
251     pdc_mouse_status.y = event.row;
252
253     pdc_mouse_status.changes = 0;
254
255     for (i = 0; i < 3; i++)
256     {
257         if (old_mouse_status.button[i] != pdc_mouse_status.button[i])
258             pdc_mouse_status.changes |= (1 << i);
259
260         if (pdc_mouse_status.button[i] == BUTTON_MOVED)
261         {
262             /* Discard non-moved "moves" */
263
264             if (pdc_mouse_status.x == old_mouse_status.x &&
265                 pdc_mouse_status.y == old_mouse_status.y)
266                 return -1;
267
268             /* Motion events always flag the button as changed */
269
270             pdc_mouse_status.changes |= (1 << i);
271             pdc_mouse_status.changes |= PDC_MOUSE_MOVED;
272             break;
273         }
274     }
275
276     old_mouse_status = pdc_mouse_status;
277
278     /* Treat click events as release events for comparison purposes */
279
280     for (i = 0; i < 3; i++)
281     {
282         if (old_mouse_status.button[i] == BUTTON_CLICKED)
283             old_mouse_status.button[i] = BUTTON_RELEASED;
284     }
285
286     /* Check for SHIFT/CONTROL/ALT */
287
288     if (kbdinfo.fsState & KBDSTF_ALT)
289         shift_flags |= BUTTON_ALT;
290
291     if (kbdinfo.fsState & KBDSTF_CONTROL)
292         shift_flags |= BUTTON_CONTROL;
293
294     if (kbdinfo.fsState & (KBDSTF_LEFTSHIFT|KBDSTF_RIGHTSHIFT))
295         shift_flags |= BUTTON_SHIFT;
296
297     if (shift_flags)
298     {
299         for (i = 0; i < 3; i++)
300         {
301             if (pdc_mouse_status.changes & (1 << i))
302                 pdc_mouse_status.button[i] |= shift_flags;
303         }
304     }
305
306     old_shift = kbdinfo.fsState;
307     key_pressed = TRUE;
308
309     SP->key_code = TRUE;
310     return KEY_MOUSE;
311 }
312
313 #endif
314
315 /* return the next available key or mouse event */
316
317 int PDC_get_key(void)
318 {
319     int key, scan;
320 #ifndef EMXVIDEO
321     KBDKEYINFO keyInfo = {0};
322 #endif
323
324 #ifdef EMXVIDEO
325     if (tahead == -1)
326     {
327         tahead = _read_kbd(0, 1, 0);
328
329         /* Read additional */
330
331         if (tahead == 0)
332             tahead = _read_kbd(0, 1, 0) << 8;
333     }
334
335     key = tahead & 0xff;
336     scan = tahead >> 8;
337     pdc_key_modifiers = 0L;
338
339     tahead = -1;
340 #else
341     pdc_key_modifiers = 0L;
342
343     if (mouse_handle && mouse_events)
344         return _process_mouse_events();
345
346     if (old_shift && !kbdinfo.fsState)
347     {
348         key = -1;
349
350         if (old_shift & KBDSTF_LEFTALT)
351         {
352             key = KEY_ALT_L;
353         }
354         else if (old_shift & KBDSTF_RIGHTALT)
355         {
356             key = KEY_ALT_R;
357         }
358         else if (old_shift & KBDSTF_LEFTCONTROL)
359         {
360             key = KEY_CONTROL_L;
361         }
362         else if (old_shift & KBDSTF_RIGHTCONTROL)
363         {
364             key = KEY_CONTROL_R;
365         }
366         else if (old_shift & KBDSTF_LEFTSHIFT)
367         {
368             key = KEY_SHIFT_L;
369         }
370         else if (old_shift & KBDSTF_RIGHTSHIFT)
371         {
372             key = KEY_SHIFT_R;
373         }
374
375         key_pressed = FALSE;
376         old_shift = kbdinfo.fsState;
377
378         SP->key_code = TRUE;
379         return key;
380     }
381
382     KbdCharIn(&keyInfo, IO_WAIT, 0);    /* get a character */
383
384     key = keyInfo.chChar;
385     scan = keyInfo.chScan;
386
387     if (SP->save_key_modifiers)
388     {
389         if (keyInfo.fsState & KBDSTF_ALT)
390             pdc_key_modifiers |= PDC_KEY_MODIFIER_ALT;
391
392         if (keyInfo.fsState & KBDSTF_CONTROL)
393             pdc_key_modifiers |= PDC_KEY_MODIFIER_CONTROL;
394
395         if (keyInfo.fsState & KBDSTF_NUMLOCK_ON)
396             pdc_key_modifiers |= PDC_KEY_MODIFIER_NUMLOCK;
397
398         if (keyInfo.fsState & (KBDSTF_LEFTSHIFT|KBDSTF_RIGHTSHIFT))
399             pdc_key_modifiers |= PDC_KEY_MODIFIER_SHIFT;
400     }
401 #endif
402     if (scan == 0x1c && key == 0x0a)    /* ^Enter */
403         key = CTL_ENTER;
404     else if (scan == 0xe0 && key == 0x0d)   /* PadEnter */
405         key = PADENTER;
406     else if (scan == 0xe0 && key == 0x0a)   /* ^PadEnter */
407         key = CTL_PADENTER;
408     else if (scan == 0x37 && key == 0x2a)   /* Star */
409         key = PADSTAR;
410     else if (scan == 0x4a && key == 0x2d)   /* Minus */
411         key = PADMINUS;
412     else if (scan == 0x4e && key == 0x2b)   /* Plus */
413         key = PADPLUS;
414     else if (scan == 0xe0 && key == 0x2f)   /* Slash */
415         key = PADSLASH;
416     else if (key == 0x00 || (key == 0xe0 && scan > 53 && scan != 86))
417         key = (scan > 0xa7) ? -1 : key_table[scan];
418
419     if (keyInfo.fsState & (KBDSTF_LEFTSHIFT|KBDSTF_RIGHTSHIFT))
420     {
421         switch (key)
422         {
423         case KEY_HOME:  /* Shift Home */
424             key = KEY_SHOME;
425             break;
426         case KEY_UP:    /* Shift Up */
427             key = KEY_SUP;
428             break;
429         case KEY_PPAGE: /* Shift PgUp */
430             key = KEY_SPREVIOUS;
431             break;
432         case KEY_LEFT:  /* Shift Left */
433             key = KEY_SLEFT;
434             break;
435         case KEY_RIGHT: /* Shift Right */
436             key = KEY_SRIGHT;
437             break;
438         case KEY_END:   /* Shift End */
439             key = KEY_SEND;
440             break;
441         case KEY_DOWN:  /* Shift Down */
442             key = KEY_SDOWN;
443             break;
444         case KEY_NPAGE: /* Shift PgDn */
445             key = KEY_SNEXT;
446             break;
447         case KEY_IC:    /* Shift Ins */
448             key = KEY_SIC;
449             break;
450         case KEY_DC:    /* Shift Del */
451             key = KEY_SDC;
452         }
453     }
454
455     key_pressed = TRUE;
456     SP->key_code = ((unsigned)key >= 256);
457
458     return key;
459 }
460
461 /* discard any pending keyboard or mouse input -- this is the core
462    routine for flushinp() */
463
464 void PDC_flushinp(void)
465 {
466     PDC_LOG(("PDC_flushinp() - called\n"));
467
468 #ifdef EMXVIDEO
469     tcflush(0, TCIFLUSH);
470 #else
471     if (mouse_handle)
472         MouFlushQue(mouse_handle);
473
474     KbdFlushBuffer(0);
475 #endif
476 }
477
478 int PDC_mouse_set(void)
479 {
480 #ifndef EMXVIDEO
481
482     unsigned long mbe = SP->_trap_mbe;
483
484     if (mbe && !mouse_handle)
485     {
486         memset(&old_mouse_status, 0, sizeof(MOUSE_STATUS));
487         MouOpen(NULL, &mouse_handle);
488         if (mouse_handle)
489             MouDrawPtr(mouse_handle);
490     }
491     else if (!mbe && mouse_handle)
492     {
493         MouClose(mouse_handle);
494         mouse_handle = 0;
495     }
496
497     if (mbe && mouse_handle)
498     {
499         USHORT mask = ((mbe & (BUTTON1_PRESSED | BUTTON1_CLICKED |
500                                BUTTON1_MOVED)) ? 6 : 0) |
501
502                       ((mbe & (BUTTON3_PRESSED | BUTTON3_CLICKED | 
503                                BUTTON3_MOVED)) ? 24 : 0) |
504
505                       ((mbe & (BUTTON2_PRESSED | BUTTON2_CLICKED | 
506                                BUTTON2_MOVED)) ? 96 : 0);
507
508         MouSetEventMask(&mask, mouse_handle);
509     }
510 #endif
511     return OK;
512 }
513
514 int PDC_modifiers_set(void)
515 {
516     key_pressed = FALSE;
517
518     return OK;
519 }