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 
PDC_get_input_fd(void)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 
PDC_set_keyboard_binary(bool on)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 
PDC_check_key(void)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 
_process_key_event(void)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 
_process_mouse_event(void)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 
PDC_get_key(void)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 
PDC_flushinp(void)372 void PDC_flushinp(void)
373 {
374     PDC_LOG(("PDC_flushinp() - called\n"));
375 
376     while (PDC_check_key());
377 }
378 
PDC_mouse_set(void)379 int PDC_mouse_set(void)
380 {
381     SDL_ShowCursor(SP->_trap_mbe ? SDL_ENABLE : SDL_DISABLE);
382 
383     return OK;
384 }
385 
PDC_modifiers_set(void)386 int PDC_modifiers_set(void)
387 {
388     return OK;
389 }
390