1 /* Public Domain Curses */
2
3 /* MS C doesn't return flags from int86() */
4 #ifdef MSC
5 # define USE_KBHIT
6 #endif
7
8 #ifdef USE_KBHIT
9 # include <conio.h>
10 #endif
11
12 #include "pdcdos.h"
13
14 RCSID("$Id: pdckbd.c,v 1.87 2008/07/13 16:08:17 wmcbrine Exp $")
15
16 /*man-start**************************************************************
17
18 Name: pdckbd
19
20 Synopsis:
21 unsigned long PDC_get_input_fd(void);
22
23 Description:
24 PDC_get_input_fd() returns the file descriptor that PDCurses
25 reads its input from. It can be used for select().
26
27 Portability X/Open BSD SYS V
28 PDC_get_input_fd - - -
29
30 **man-end****************************************************************/
31
32 #ifdef __DJGPP__
33 # include <fcntl.h>
34 # include <io.h>
35 # include <signal.h>
36 #endif
37
38 /************************************************************************
39 * Table for key code translation of function keys in keypad mode *
40 * These values are for strict IBM keyboard compatibles only *
41 ************************************************************************/
42
43 static short key_table[] =
44 {
45 -1, ALT_ESC, -1, 0,
46 -1, -1, -1, -1,
47 -1, -1, -1, -1,
48 -1, -1, ALT_BKSP, KEY_BTAB,
49 ALT_Q, ALT_W, ALT_E, ALT_R,
50 ALT_T, ALT_Y, ALT_U, ALT_I,
51 ALT_O, ALT_P, ALT_LBRACKET, ALT_RBRACKET,
52 ALT_ENTER, -1, ALT_A, ALT_S,
53 ALT_D, ALT_F, ALT_G, ALT_H,
54 ALT_J, ALT_K, ALT_L, ALT_SEMICOLON,
55 ALT_FQUOTE, ALT_BQUOTE, -1, ALT_BSLASH,
56 ALT_Z, ALT_X, ALT_C, ALT_V,
57 ALT_B, ALT_N, ALT_M, ALT_COMMA,
58 ALT_STOP, ALT_FSLASH, -1, ALT_PADSTAR,
59 -1, -1, -1, KEY_F(1),
60 KEY_F(2), KEY_F(3), KEY_F(4), KEY_F(5),
61 KEY_F(6), KEY_F(7), KEY_F(8), KEY_F(9),
62 KEY_F(10), -1, -1, KEY_HOME,
63 KEY_UP, KEY_PPAGE, ALT_PADMINUS, KEY_LEFT,
64 KEY_B2, KEY_RIGHT, ALT_PADPLUS, KEY_END,
65 KEY_DOWN, KEY_NPAGE, KEY_IC, KEY_DC,
66 KEY_F(13), KEY_F(14), KEY_F(15), KEY_F(16),
67 KEY_F(17), KEY_F(18), KEY_F(19), KEY_F(20),
68 KEY_F(21), KEY_F(22), KEY_F(25), KEY_F(26),
69 KEY_F(27), KEY_F(28), KEY_F(29), KEY_F(30),
70 KEY_F(31), KEY_F(32), KEY_F(33), KEY_F(34),
71 KEY_F(37), KEY_F(38), KEY_F(39), KEY_F(40),
72 KEY_F(41), KEY_F(42), KEY_F(43), KEY_F(44),
73 KEY_F(45), KEY_F(46), -1, CTL_LEFT,
74 CTL_RIGHT, CTL_END, CTL_PGDN, CTL_HOME,
75 ALT_1, ALT_2, ALT_3, ALT_4,
76 ALT_5, ALT_6, ALT_7, ALT_8,
77 ALT_9, ALT_0, ALT_MINUS, ALT_EQUAL,
78 CTL_PGUP, KEY_F(11), KEY_F(12), KEY_F(23),
79 KEY_F(24), KEY_F(35), KEY_F(36), KEY_F(47),
80 KEY_F(48), CTL_UP, CTL_PADMINUS, CTL_PADCENTER,
81 CTL_PADPLUS, CTL_DOWN, CTL_INS, CTL_DEL,
82 CTL_TAB, CTL_PADSLASH, CTL_PADSTAR, ALT_HOME,
83 ALT_UP, ALT_PGUP, -1, ALT_LEFT,
84 -1, ALT_RIGHT, -1, ALT_END,
85 ALT_DOWN, ALT_PGDN, ALT_INS, ALT_DEL,
86 ALT_PADSLASH, ALT_TAB, ALT_PADENTER, -1
87 };
88
89 unsigned long pdc_key_modifiers = 0L;
90
91 static struct {unsigned short pressed, released;} button[3];
92
93 static bool mouse_avail = FALSE, mouse_vis = FALSE, mouse_moved = FALSE,
94 mouse_button = FALSE, key_pressed = FALSE;
95
96 static unsigned char mouse_scroll = 0;
97 static PDCREGS ms_regs, old_ms;
98 static unsigned short shift_status, old_shift = 0;
99 static unsigned char keyboard_function = 0xff, shift_function = 0xff,
100 check_function = 0xff;
101
102 static const unsigned short button_map[3] = {0, 2, 1};
103
PDC_get_input_fd(void)104 unsigned long PDC_get_input_fd(void)
105 {
106 PDC_LOG(("PDC_get_input_fd() - called\n"));
107
108 return (unsigned long)fileno(stdin);
109 }
110
PDC_set_keyboard_binary(bool on)111 void PDC_set_keyboard_binary(bool on)
112 {
113 PDC_LOG(("PDC_set_keyboard_binary() - called\n"));
114
115 #ifdef __DJGPP__
116 setmode(fileno(stdin), on ? O_BINARY : O_TEXT);
117 signal(SIGINT, on ? SIG_IGN : SIG_DFL);
118 #endif
119 }
120
121 /* check if a key or mouse event is waiting */
122
PDC_check_key(void)123 bool PDC_check_key(void)
124 {
125 PDCREGS regs;
126
127 if (shift_function == 0xff)
128 {
129 int scan;
130
131 /* get shift status for all keyboards */
132
133 regs.h.ah = 0x02;
134 PDCINT(0x16, regs);
135 scan = regs.h.al;
136
137 /* get shift status for enhanced keyboards */
138
139 regs.h.ah = 0x12;
140 PDCINT(0x16, regs);
141
142 if (scan == regs.h.al && getdosmembyte(0x496) == 0x10)
143 {
144 keyboard_function = 0x10;
145 check_function = 0x11;
146 shift_function = 0x12;
147 }
148 else
149 {
150 keyboard_function = 0;
151 check_function = 1;
152 shift_function = 2;
153 }
154 }
155
156 regs.h.ah = shift_function;
157 PDCINT(0x16, regs);
158
159 shift_status = regs.W.ax;
160
161 if (mouse_vis)
162 {
163 unsigned short i;
164
165 ms_regs.W.ax = 3;
166 PDCINT(0x33, ms_regs);
167
168 mouse_button = FALSE;
169
170 for (i = 0; i < 3; i++)
171 {
172 regs.W.ax = 6;
173 regs.W.bx = button_map[i];
174 PDCINT(0x33, regs);
175 button[i].released = regs.W.bx;
176 if (regs.W.bx)
177 {
178 ms_regs.W.cx = regs.W.cx;
179 ms_regs.W.dx = regs.W.dx;
180 mouse_button = TRUE;
181 }
182
183 regs.W.ax = 5;
184 regs.W.bx = button_map[i];
185 PDCINT(0x33, regs);
186 button[i].pressed = regs.W.bx;
187 if (regs.W.bx)
188 {
189 ms_regs.W.cx = regs.W.cx;
190 ms_regs.W.dx = regs.W.dx;
191 mouse_button = TRUE;
192 }
193 }
194
195 mouse_scroll = ms_regs.h.bh;
196
197 mouse_moved = !mouse_button && ms_regs.h.bl &&
198 ms_regs.h.bl == old_ms.h.bl &&
199 (((ms_regs.W.cx ^ old_ms.W.cx) >> 3) ||
200 ((ms_regs.W.dx ^ old_ms.W.dx) >> 3));
201
202 if (mouse_scroll || mouse_button || mouse_moved)
203 return TRUE;
204 }
205
206 if (old_shift && !shift_status) /* modifier released */
207 {
208 if (!key_pressed && SP->return_key_modifiers)
209 return TRUE;
210 }
211 else if (!old_shift && shift_status) /* modifier pressed */
212 key_pressed = FALSE;
213
214 old_shift = shift_status;
215
216 #ifndef USE_KBHIT
217 regs.h.ah = check_function;
218 PDCINT(0x16, regs);
219
220 return !(regs.W.flags & 64);
221 #else
222 return kbhit();
223 #endif
224 }
225
_process_mouse_events(void)226 static int _process_mouse_events(void)
227 {
228 int i;
229 short shift_flags = 0;
230
231 memset(&pdc_mouse_status, 0, sizeof(pdc_mouse_status));
232
233 key_pressed = TRUE;
234 old_shift = shift_status;
235 SP->key_code = TRUE;
236
237 /* Set shift modifiers */
238
239 if (shift_status & 3)
240 shift_flags |= BUTTON_SHIFT;
241
242 if (shift_status & 4)
243 shift_flags |= BUTTON_CONTROL;
244
245 if (shift_status & 8)
246 shift_flags |= BUTTON_ALT;
247
248 /* Scroll wheel support for CuteMouse */
249
250 if (mouse_scroll)
251 {
252 pdc_mouse_status.changes = mouse_scroll & 0x80 ?
253 PDC_MOUSE_WHEEL_UP : PDC_MOUSE_WHEEL_DOWN;
254
255 pdc_mouse_status.x = -1;
256 pdc_mouse_status.y = -1;
257
258 return KEY_MOUSE;
259 }
260
261 if (mouse_moved)
262 {
263 pdc_mouse_status.changes = PDC_MOUSE_MOVED;
264
265 for (i = 0; i < 3; i++)
266 {
267 if (ms_regs.h.bl & (1 << button_map[i]))
268 {
269 pdc_mouse_status.button[i] = BUTTON_MOVED | shift_flags;
270 pdc_mouse_status.changes |= (1 << i);
271 }
272 }
273 }
274 else /* button event */
275 {
276 for (i = 0; i < 3; i++)
277 {
278 if (button[i].pressed)
279 {
280 /* Check for a click -- a PRESS followed
281 immediately by a release */
282
283 if (!button[i].released)
284 {
285 if (SP->mouse_wait)
286 {
287 PDCREGS regs;
288
289 napms(SP->mouse_wait);
290
291 regs.W.ax = 6;
292 regs.W.bx = button_map[i];
293 PDCINT(0x33, regs);
294
295 pdc_mouse_status.button[i] = regs.W.bx ?
296 BUTTON_CLICKED : BUTTON_PRESSED;
297 }
298 else
299 pdc_mouse_status.button[i] = BUTTON_PRESSED;
300 }
301 else
302 pdc_mouse_status.button[i] = BUTTON_CLICKED;
303 }
304
305 if (button[i].pressed || button[i].released)
306 {
307 pdc_mouse_status.button[i] |= shift_flags;
308 pdc_mouse_status.changes |= (1 << i);
309 }
310 }
311 }
312
313 pdc_mouse_status.x = ms_regs.W.cx >> 3;
314 pdc_mouse_status.y = ms_regs.W.dx >> 3;
315
316 old_ms = ms_regs;
317
318 return KEY_MOUSE;
319 }
320
321 /* return the next available key or mouse event */
322
PDC_get_key(void)323 int PDC_get_key(void)
324 {
325 PDCREGS regs;
326 int key, scan;
327
328 pdc_key_modifiers = 0;
329
330 if (mouse_vis && (mouse_scroll || mouse_button || mouse_moved))
331 return _process_mouse_events();
332
333 /* Return modifiers as keys? */
334
335 if (old_shift && !shift_status)
336 {
337 key = -1;
338
339 if (old_shift & 1)
340 key = KEY_SHIFT_R;
341
342 if (old_shift & 2)
343 key = KEY_SHIFT_L;
344
345 if (shift_function == 0x12)
346 {
347 if (old_shift & 0x400)
348 key = KEY_CONTROL_R;
349
350 if (old_shift & 0x100)
351 key = KEY_CONTROL_L;
352
353 if (old_shift & 0x800)
354 key = KEY_ALT_R;
355
356 if (old_shift & 0x200)
357 key = KEY_ALT_L;
358 }
359 else
360 {
361 if (old_shift & 4)
362 key = KEY_CONTROL_R;
363
364 if (old_shift & 8)
365 key = KEY_ALT_R;
366 }
367
368 key_pressed = FALSE;
369 old_shift = shift_status;
370
371 SP->key_code = TRUE;
372 return key;
373 }
374
375 regs.h.ah = keyboard_function;
376 PDCINT(0x16, regs);
377 key = regs.h.al;
378 scan = regs.h.ah;
379
380 if (SP->save_key_modifiers)
381 {
382 if (shift_status & 3)
383 pdc_key_modifiers |= PDC_KEY_MODIFIER_SHIFT;
384
385 if (shift_status & 4)
386 pdc_key_modifiers |= PDC_KEY_MODIFIER_CONTROL;
387
388 if (shift_status & 8)
389 pdc_key_modifiers |= PDC_KEY_MODIFIER_ALT;
390
391 if (shift_status & 0x20)
392 pdc_key_modifiers |= PDC_KEY_MODIFIER_NUMLOCK;
393 }
394
395 if (scan == 0x1c && key == 0x0a) /* ^Enter */
396 key = CTL_ENTER;
397 else if (scan == 0xe0 && key == 0x0d) /* PadEnter */
398 key = PADENTER;
399 else if (scan == 0xe0 && key == 0x0a) /* ^PadEnter */
400 key = CTL_PADENTER;
401 else if (scan == 0x37 && key == 0x2a) /* Star */
402 key = PADSTAR;
403 else if (scan == 0x4a && key == 0x2d) /* Minus */
404 key = PADMINUS;
405 else if (scan == 0x4e && key == 0x2b) /* Plus */
406 key = PADPLUS;
407 else if (scan == 0xe0 && key == 0x2f) /* Slash */
408 key = PADSLASH;
409 else if (key == 0x00 || (key == 0xe0 && scan > 53 && scan != 86))
410 key = (scan > 0xa7) ? -1 : key_table[scan];
411
412 if (shift_status & 3)
413 {
414 switch (key)
415 {
416 case KEY_HOME: /* Shift Home */
417 key = KEY_SHOME;
418 break;
419 case KEY_UP: /* Shift Up */
420 key = KEY_SUP;
421 break;
422 case KEY_PPAGE: /* Shift PgUp */
423 key = KEY_SPREVIOUS;
424 break;
425 case KEY_LEFT: /* Shift Left */
426 key = KEY_SLEFT;
427 break;
428 case KEY_RIGHT: /* Shift Right */
429 key = KEY_SRIGHT;
430 break;
431 case KEY_END: /* Shift End */
432 key = KEY_SEND;
433 break;
434 case KEY_DOWN: /* Shift Down */
435 key = KEY_SDOWN;
436 break;
437 case KEY_NPAGE: /* Shift PgDn */
438 key = KEY_SNEXT;
439 break;
440 case KEY_IC: /* Shift Ins */
441 key = KEY_SIC;
442 break;
443 case KEY_DC: /* Shift Del */
444 key = KEY_SDC;
445 }
446 }
447
448 key_pressed = TRUE;
449 SP->key_code = ((unsigned)key >= 256);
450
451 return key;
452 }
453
454 /* discard any pending keyboard or mouse input -- this is the core
455 routine for flushinp() */
456
PDC_flushinp(void)457 void PDC_flushinp(void)
458 {
459 PDC_LOG(("PDC_flushinp() - called\n"));
460
461 /* Force the BIOS keyboard buffer head and tail pointers to be
462 the same... Real nasty trick... */
463
464 setdosmemword(0x41a, getdosmemword(0x41c));
465 }
466
PDC_mouse_set(void)467 int PDC_mouse_set(void)
468 {
469 PDCREGS regs;
470 unsigned long mbe = SP->_trap_mbe;
471
472 if (mbe && !mouse_avail)
473 {
474 regs.W.ax = 0;
475 PDCINT(0x33, regs);
476
477 mouse_avail = !!(regs.W.ax);
478 }
479
480 if (mbe)
481 {
482 if (mouse_avail && !mouse_vis)
483 {
484 memset(&old_ms, 0, sizeof(old_ms));
485
486 regs.W.ax = 1;
487 PDCINT(0x33, regs);
488
489 mouse_vis = TRUE;
490 }
491 }
492 else
493 {
494 if (mouse_avail && mouse_vis)
495 {
496 regs.W.ax = 2;
497 PDCINT(0x33, regs);
498
499 mouse_vis = FALSE;
500 }
501 }
502
503 return (mouse_avail || !mbe) ? OK : ERR;
504 }
505
PDC_modifiers_set(void)506 int PDC_modifiers_set(void)
507 {
508 key_pressed = FALSE;
509
510 return OK;
511 }
512