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
PDC_get_input_fd(void)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
PDC_get_keyboard_info(void)103 void PDC_get_keyboard_info(void)
104 {
105 kbdinfo.cb = sizeof(kbdinfo);
106 KbdGetStatus(&kbdinfo, 0);
107 }
108
PDC_set_keyboard_default(void)109 void PDC_set_keyboard_default(void)
110 {
111 KbdSetStatus(&kbdinfo, 0);
112 }
113
114 #endif /* ifndef EMXVIDEO */
115
PDC_set_keyboard_binary(bool on)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
PDC_check_key(void)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
_process_mouse_events(void)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
PDC_get_key(void)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
PDC_flushinp(void)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
PDC_mouse_set(void)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
PDC_modifiers_set(void)514 int PDC_modifiers_set(void)
515 {
516 key_pressed = FALSE;
517
518 return OK;
519 }
520