libpayload: Add PDCurses and ncurses' libform/libmenu
[coreboot.git] / payloads / libpayload / curses / PDCurses-3.4 / sdl1 / pdckbd.c
1 /* Public Domain Curses */
2
3 #include "pdcsdl.h"
4
5 RCSID("$Id: pdckbd.c,v 1.20 2008/07/14 04:24:52 wmcbrine Exp $")
6
7 /*man-start**************************************************************
8
9   Name:                                                         pdckbd
10
11   Synopsis:
12         unsigned long PDC_get_input_fd(void);
13
14   Description:
15         PDC_get_input_fd() returns the file descriptor that PDCurses 
16         reads its input from. It can be used for select().
17
18   Portability                                X/Open    BSD    SYS V
19         PDC_get_input_fd                        -       -       -
20
21 **man-end****************************************************************/
22
23 #include <string.h>
24
25 unsigned long pdc_key_modifiers = 0L;
26
27 static SDL_Event event;
28 static SDLKey oldkey;
29 static MOUSE_STATUS old_mouse_status;
30
31 static struct
32 {
33     SDLKey keycode;
34     bool numkeypad;
35     unsigned short normal;
36     unsigned short shifted;
37     unsigned short control;
38     unsigned short alt;
39 } key_table[] =
40 {
41 /* keycode      keypad  normal       shifted       control      alt*/
42  {SDLK_LEFT,    FALSE,  KEY_LEFT,    KEY_SLEFT,    CTL_LEFT,    ALT_LEFT},
43  {SDLK_RIGHT,   FALSE,  KEY_RIGHT,   KEY_SRIGHT,   CTL_RIGHT,   ALT_RIGHT},
44  {SDLK_UP,      FALSE,  KEY_UP,      KEY_SUP,      CTL_UP,      ALT_UP},
45  {SDLK_DOWN,    FALSE,  KEY_DOWN,    KEY_SDOWN,    CTL_DOWN,    ALT_DOWN},
46  {SDLK_HOME,    FALSE,  KEY_HOME,    KEY_SHOME,    CTL_HOME,    ALT_HOME},
47  {SDLK_END,     FALSE,  KEY_END,     KEY_SEND,     CTL_END,     ALT_END},
48  {SDLK_PAGEUP,  FALSE,  KEY_PPAGE,   KEY_SPREVIOUS,CTL_PGUP,    ALT_PGUP},
49  {SDLK_PAGEDOWN,FALSE,  KEY_NPAGE,   KEY_SNEXT,    CTL_PGDN,    ALT_PGDN},
50  {SDLK_INSERT,  FALSE,  KEY_IC,      KEY_SIC,      CTL_INS,     ALT_INS},
51  {SDLK_DELETE,  FALSE,  KEY_DC,      KEY_SDC,      CTL_DEL,     ALT_DEL},
52  {SDLK_F1,      FALSE,  KEY_F(1),    KEY_F(13),    KEY_F(25),   KEY_F(37)},
53  {SDLK_F2,      FALSE,  KEY_F(2),    KEY_F(14),    KEY_F(26),   KEY_F(38)},
54  {SDLK_F3,      FALSE,  KEY_F(3),    KEY_F(15),    KEY_F(27),   KEY_F(39)},
55  {SDLK_F4,      FALSE,  KEY_F(4),    KEY_F(16),    KEY_F(28),   KEY_F(40)},
56  {SDLK_F5,      FALSE,  KEY_F(5),    KEY_F(17),    KEY_F(29),   KEY_F(41)},
57  {SDLK_F6,      FALSE,  KEY_F(6),    KEY_F(18),    KEY_F(30),   KEY_F(42)},
58  {SDLK_F7,      FALSE,  KEY_F(7),    KEY_F(19),    KEY_F(31),   KEY_F(43)},
59  {SDLK_F8,      FALSE,  KEY_F(8),    KEY_F(20),    KEY_F(32),   KEY_F(44)},
60  {SDLK_F9,      FALSE,  KEY_F(9),    KEY_F(21),    KEY_F(33),   KEY_F(45)},
61  {SDLK_F10,     FALSE,  KEY_F(10),   KEY_F(22),    KEY_F(34),   KEY_F(46)},
62  {SDLK_F11,     FALSE,  KEY_F(11),   KEY_F(23),    KEY_F(35),   KEY_F(47)},
63  {SDLK_F12,     FALSE,  KEY_F(12),   KEY_F(24),    KEY_F(36),   KEY_F(48)},
64  {SDLK_F13,     FALSE,  KEY_F(13),   KEY_F(25),    KEY_F(37),   KEY_F(49)},
65  {SDLK_F14,     FALSE,  KEY_F(14),   KEY_F(26),    KEY_F(38),   KEY_F(50)},
66  {SDLK_F15,     FALSE,  KEY_F(15),   KEY_F(27),    KEY_F(39),   KEY_F(51)},
67  {SDLK_BACKSPACE,FALSE, 0x08,        0x08,         CTL_BKSP,    ALT_BKSP},
68  {SDLK_TAB,     FALSE,  0x09,        KEY_BTAB,     CTL_TAB,     ALT_TAB},
69  {SDLK_PRINT,   FALSE,  KEY_PRINT,   KEY_SPRINT,   KEY_PRINT,   KEY_PRINT},
70  {SDLK_PAUSE,   FALSE,  KEY_SUSPEND, KEY_SSUSPEND, KEY_SUSPEND, KEY_SUSPEND},
71  {SDLK_CLEAR,   FALSE,  KEY_CLEAR,   KEY_CLEAR,    KEY_CLEAR,   KEY_CLEAR},
72  {SDLK_BREAK,   FALSE,  KEY_BREAK,   KEY_BREAK,    KEY_BREAK,   KEY_BREAK},
73  {SDLK_HELP,    FALSE,  KEY_HELP,    KEY_SHELP,    KEY_LHELP,   KEY_HELP},
74  {SDLK_MENU,    FALSE,  KEY_OPTIONS, KEY_SOPTIONS, KEY_OPTIONS, KEY_OPTIONS},
75  {SDLK_ESCAPE,  FALSE,  0x1B,        0x1B,         0x1B,        ALT_ESC},
76  {SDLK_KP_ENTER,TRUE,   PADENTER,    PADENTER,     CTL_PADENTER,ALT_PADENTER},
77  {SDLK_KP_PLUS, TRUE,   PADPLUS,     '+',          CTL_PADPLUS, ALT_PADPLUS},
78  {SDLK_KP_MINUS,TRUE,   PADMINUS,    '-',          CTL_PADMINUS,ALT_PADMINUS},
79  {SDLK_KP_MULTIPLY,TRUE,PADSTAR,     '*',          CTL_PADSTAR, ALT_PADSTAR},
80  {SDLK_KP_DIVIDE,TRUE,  PADSLASH,    '/',          CTL_PADSLASH,ALT_PADSLASH},
81  {SDLK_KP_PERIOD,TRUE,  PADSTOP,     '.',          CTL_PADSTOP, ALT_PADSTOP},
82  {SDLK_KP0,     TRUE,   PAD0,        '0',          CTL_PAD0,    ALT_PAD0},
83  {SDLK_KP1,     TRUE,   KEY_C1,      '1',          CTL_PAD1,    ALT_PAD1},
84  {SDLK_KP2,     TRUE,   KEY_C2,      '2',          CTL_PAD2,    ALT_PAD2},
85  {SDLK_KP3,     TRUE,   KEY_C3,      '3',          CTL_PAD3,    ALT_PAD3},
86  {SDLK_KP4,     TRUE,   KEY_B1,      '4',          CTL_PAD4,    ALT_PAD4},
87  {SDLK_KP5,     TRUE,   KEY_B2,      '5',          CTL_PAD5,    ALT_PAD5},
88  {SDLK_KP6,     TRUE,   KEY_B3,      '6',          CTL_PAD6,    ALT_PAD6},
89  {SDLK_KP7,     TRUE,   KEY_A1,      '7',          CTL_PAD7,    ALT_PAD7},
90  {SDLK_KP8,     TRUE,   KEY_A2,      '8',          CTL_PAD8,    ALT_PAD8},
91  {SDLK_KP9,     TRUE,   KEY_A3,      '9',          CTL_PAD9,    ALT_PAD9},
92  {0,            0,      0,           0,            0,           0}
93 };
94
95 unsigned long PDC_get_input_fd(void)
96 {
97     PDC_LOG(("PDC_get_input_fd() - called\n"));
98
99     return 0L;  /* test this */
100 }
101
102 void PDC_set_keyboard_binary(bool on)
103 {
104     PDC_LOG(("PDC_set_keyboard_binary() - called\n"));
105 }
106
107 /* check if a key or mouse event is waiting */
108
109 bool PDC_check_key(void)
110 {
111     Uint32 current = SDL_GetTicks();
112     int haveevent = SDL_PollEvent(&event);
113
114     /* if we have an event, or 30 ms have passed without a screen 
115        update, or the timer has wrapped, update now */
116
117     if (haveevent ||
118         current < pdc_lastupdate || ((current - pdc_lastupdate) > 30))
119         PDC_update_rects();
120
121     return haveevent;
122 }
123
124 static int _process_key_event(void)
125 {
126     int i, key = 0;
127
128     pdc_key_modifiers = 0L;
129     SP->key_code = FALSE;
130
131     if (event.type == SDL_KEYUP)
132     {
133         if (SP->return_key_modifiers && event.key.keysym.sym == oldkey)
134         {
135             switch (oldkey)
136             {
137             case SDLK_RSHIFT:
138                 return KEY_SHIFT_R;
139             case SDLK_LSHIFT:
140                 return KEY_SHIFT_L;
141             case SDLK_RCTRL:
142                 return KEY_CONTROL_R;
143             case SDLK_LCTRL:
144                 return KEY_CONTROL_L;
145             case SDLK_RALT:
146                 return KEY_ALT_R;
147             case SDLK_LALT:
148                 return KEY_ALT_L;
149             default:
150                 break;
151             }
152         }
153
154         return -1;
155     }
156
157     oldkey = event.key.keysym.sym;
158
159     if (SP->save_key_modifiers)
160     {
161         if (event.key.keysym.mod & KMOD_NUM)
162             pdc_key_modifiers |= PDC_KEY_MODIFIER_NUMLOCK;
163
164         if (event.key.keysym.mod & KMOD_SHIFT)
165             pdc_key_modifiers |= PDC_KEY_MODIFIER_SHIFT;
166
167         if (event.key.keysym.mod & KMOD_CTRL)
168             pdc_key_modifiers |= PDC_KEY_MODIFIER_CONTROL;
169
170         if (event.key.keysym.mod & KMOD_ALT)
171             pdc_key_modifiers |= PDC_KEY_MODIFIER_ALT;
172     }
173
174     for (i = 0; key_table[i].keycode; i++)
175     {
176         if (key_table[i].keycode == event.key.keysym.sym)
177         {
178             if ((event.key.keysym.mod & KMOD_SHIFT) ||
179                 (key_table[i].numkeypad && (event.key.keysym.mod & KMOD_NUM)))
180             {
181                 key = key_table[i].shifted;
182             }
183             else if (event.key.keysym.mod & KMOD_CTRL)
184             {
185                 key = key_table[i].control;
186             }
187             else if (event.key.keysym.mod & KMOD_ALT)
188             {
189                 key = key_table[i].alt;
190             }
191
192             /* To get here, we ignore all other modifiers */
193
194             else
195                 key = key_table[i].normal;
196
197             SP->key_code = (key > 0x100);
198             break;
199         }
200     }
201
202     if (!key)
203     {
204         key = event.key.keysym.unicode;
205
206         if (key > 0x7f)
207             key = 0;
208     }
209
210     /* Handle ALT letters and numbers */
211
212     if (event.key.keysym.mod & KMOD_ALT)
213     {
214         if (key >= 'A' && key <= 'Z')
215         {
216             key += ALT_A - 'A';
217             SP->key_code = TRUE;
218         }
219
220         if (key >= 'a' && key <= 'z')
221         {
222             key += ALT_A - 'a';
223             SP->key_code = TRUE;
224         }
225
226         if (key >= '0' && key <= '9')
227         {
228             key += ALT_0 - '0';
229             SP->key_code = TRUE;
230         }
231     }
232
233     return key ? key : -1;
234 }
235
236 static int _process_mouse_event(void)
237 {
238     SDLMod keymods;
239     short shift_flags = 0;
240
241     memset(&pdc_mouse_status, 0, sizeof(MOUSE_STATUS));
242
243     keymods = SDL_GetModState();
244
245     if (keymods & KMOD_SHIFT)
246         shift_flags |= BUTTON_SHIFT;
247
248     if (keymods & KMOD_CTRL)
249         shift_flags |= BUTTON_CONTROL;
250
251     if (keymods & KMOD_ALT)
252         shift_flags |= BUTTON_ALT;
253
254     if (event.type == SDL_MOUSEMOTION)
255     {
256         int i;
257
258         pdc_mouse_status.x = event.motion.x / pdc_fwidth;
259         pdc_mouse_status.y = event.motion.y / pdc_fheight;
260
261         if (!event.motion.state ||
262            (pdc_mouse_status.x == old_mouse_status.x &&
263             pdc_mouse_status.y == old_mouse_status.y))
264             return -1;
265
266         pdc_mouse_status.changes = PDC_MOUSE_MOVED;
267
268         for (i = 0; i < 3; i++)
269         {
270             if (event.motion.state & SDL_BUTTON(i + 1))
271             {
272                 pdc_mouse_status.button[i] = BUTTON_MOVED | shift_flags;
273                 pdc_mouse_status.changes |= (1 << i);
274             }
275         }
276     }
277     else
278     {
279         short action = (event.button.state == SDL_PRESSED) ?
280                        BUTTON_PRESSED : BUTTON_RELEASED;
281         Uint8 btn = event.button.button;
282
283         /* handle scroll wheel */
284
285         if ((btn == 4 || btn == 5) && action == BUTTON_RELEASED)
286         {
287             pdc_mouse_status.x = pdc_mouse_status.y = -1;
288
289             pdc_mouse_status.changes = (btn == 5) ?
290                 PDC_MOUSE_WHEEL_DOWN : PDC_MOUSE_WHEEL_UP;
291
292             return KEY_MOUSE;
293         }
294
295         if (btn < 1 || btn > 3)
296             return -1;
297
298         /* check for a click -- a press followed immediately by a release */
299
300         if (action == BUTTON_PRESSED && SP->mouse_wait)
301         {
302             SDL_Event rel;
303
304             napms(SP->mouse_wait);
305
306             if (SDL_PollEvent(&rel))
307             {
308                 if (rel.type == SDL_MOUSEBUTTONUP && rel.button.button == btn)
309                     action = BUTTON_CLICKED;
310                 else
311                     SDL_PushEvent(&rel);
312             }
313         }
314
315         pdc_mouse_status.x = event.button.x / pdc_fwidth;
316         pdc_mouse_status.y = event.button.y / pdc_fheight;
317
318         btn--;
319
320         pdc_mouse_status.button[btn] = action | shift_flags;
321         pdc_mouse_status.changes = (1 << btn);
322     }
323
324     old_mouse_status = pdc_mouse_status;
325
326     return KEY_MOUSE;
327 }
328
329 /* return the next available key or mouse event */
330
331 int PDC_get_key(void)
332 {
333     switch (event.type)
334     {
335     case SDL_QUIT:
336         exit(1);
337     case SDL_VIDEORESIZE:
338         if (pdc_own_screen &&
339            (event.resize.h / pdc_fheight != LINES ||
340             event.resize.w / pdc_fwidth != COLS))
341         {
342             pdc_sheight = event.resize.h;
343             pdc_swidth = event.resize.w;
344
345             if (!SP->resized)
346             {
347                 SP->resized = TRUE;
348                 return KEY_RESIZE;
349             }
350         }
351         break;
352     case SDL_MOUSEMOTION:
353         SDL_ShowCursor(SDL_ENABLE);
354     case SDL_MOUSEBUTTONUP:
355     case SDL_MOUSEBUTTONDOWN:
356         oldkey = SDLK_SPACE;
357         if (SP->_trap_mbe)
358             return _process_mouse_event();
359         break;
360     case SDL_KEYUP:
361     case SDL_KEYDOWN:
362         PDC_mouse_set();
363         return _process_key_event();
364     }
365
366     return -1;
367 }
368
369 /* discard any pending keyboard or mouse input -- this is the core
370    routine for flushinp() */
371
372 void PDC_flushinp(void)
373 {
374     PDC_LOG(("PDC_flushinp() - called\n"));
375
376     while (PDC_check_key());
377 }
378
379 int PDC_mouse_set(void)
380 {
381     SDL_ShowCursor(SP->_trap_mbe ? SDL_ENABLE : SDL_DISABLE);
382
383     return OK;
384 }
385
386 int PDC_modifiers_set(void)
387 {
388     return OK;
389 }