| /* Public Domain Curses */ |
| |
| /* MS C doesn't return flags from int86() */ |
| #ifdef MSC |
| # define USE_KBHIT |
| #endif |
| |
| #ifdef USE_KBHIT |
| # include <conio.h> |
| #endif |
| |
| #include "pdcdos.h" |
| |
| RCSID("$Id: pdckbd.c,v 1.87 2008/07/13 16:08:17 wmcbrine Exp $") |
| |
| /*man-start************************************************************** |
| |
| Name: pdckbd |
| |
| Synopsis: |
| unsigned long PDC_get_input_fd(void); |
| |
| Description: |
| PDC_get_input_fd() returns the file descriptor that PDCurses |
| reads its input from. It can be used for select(). |
| |
| Portability X/Open BSD SYS V |
| PDC_get_input_fd - - - |
| |
| **man-end****************************************************************/ |
| |
| #ifdef __DJGPP__ |
| # include <fcntl.h> |
| # include <io.h> |
| # include <signal.h> |
| #endif |
| |
| /************************************************************************ |
| * Table for key code translation of function keys in keypad mode * |
| * These values are for strict IBM keyboard compatibles only * |
| ************************************************************************/ |
| |
| static short key_table[] = |
| { |
| -1, ALT_ESC, -1, 0, |
| -1, -1, -1, -1, |
| -1, -1, -1, -1, |
| -1, -1, ALT_BKSP, KEY_BTAB, |
| ALT_Q, ALT_W, ALT_E, ALT_R, |
| ALT_T, ALT_Y, ALT_U, ALT_I, |
| ALT_O, ALT_P, ALT_LBRACKET, ALT_RBRACKET, |
| ALT_ENTER, -1, ALT_A, ALT_S, |
| ALT_D, ALT_F, ALT_G, ALT_H, |
| ALT_J, ALT_K, ALT_L, ALT_SEMICOLON, |
| ALT_FQUOTE, ALT_BQUOTE, -1, ALT_BSLASH, |
| ALT_Z, ALT_X, ALT_C, ALT_V, |
| ALT_B, ALT_N, ALT_M, ALT_COMMA, |
| ALT_STOP, ALT_FSLASH, -1, ALT_PADSTAR, |
| -1, -1, -1, KEY_F(1), |
| KEY_F(2), KEY_F(3), KEY_F(4), KEY_F(5), |
| KEY_F(6), KEY_F(7), KEY_F(8), KEY_F(9), |
| KEY_F(10), -1, -1, KEY_HOME, |
| KEY_UP, KEY_PPAGE, ALT_PADMINUS, KEY_LEFT, |
| KEY_B2, KEY_RIGHT, ALT_PADPLUS, KEY_END, |
| KEY_DOWN, KEY_NPAGE, KEY_IC, KEY_DC, |
| KEY_F(13), KEY_F(14), KEY_F(15), KEY_F(16), |
| KEY_F(17), KEY_F(18), KEY_F(19), KEY_F(20), |
| KEY_F(21), KEY_F(22), KEY_F(25), KEY_F(26), |
| KEY_F(27), KEY_F(28), KEY_F(29), KEY_F(30), |
| KEY_F(31), KEY_F(32), KEY_F(33), KEY_F(34), |
| KEY_F(37), KEY_F(38), KEY_F(39), KEY_F(40), |
| KEY_F(41), KEY_F(42), KEY_F(43), KEY_F(44), |
| KEY_F(45), KEY_F(46), -1, CTL_LEFT, |
| CTL_RIGHT, CTL_END, CTL_PGDN, CTL_HOME, |
| ALT_1, ALT_2, ALT_3, ALT_4, |
| ALT_5, ALT_6, ALT_7, ALT_8, |
| ALT_9, ALT_0, ALT_MINUS, ALT_EQUAL, |
| CTL_PGUP, KEY_F(11), KEY_F(12), KEY_F(23), |
| KEY_F(24), KEY_F(35), KEY_F(36), KEY_F(47), |
| KEY_F(48), CTL_UP, CTL_PADMINUS, CTL_PADCENTER, |
| CTL_PADPLUS, CTL_DOWN, CTL_INS, CTL_DEL, |
| CTL_TAB, CTL_PADSLASH, CTL_PADSTAR, ALT_HOME, |
| ALT_UP, ALT_PGUP, -1, ALT_LEFT, |
| -1, ALT_RIGHT, -1, ALT_END, |
| ALT_DOWN, ALT_PGDN, ALT_INS, ALT_DEL, |
| ALT_PADSLASH, ALT_TAB, ALT_PADENTER, -1 |
| }; |
| |
| unsigned long pdc_key_modifiers = 0L; |
| |
| static struct {unsigned short pressed, released;} button[3]; |
| |
| static bool mouse_avail = FALSE, mouse_vis = FALSE, mouse_moved = FALSE, |
| mouse_button = FALSE, key_pressed = FALSE; |
| |
| static unsigned char mouse_scroll = 0; |
| static PDCREGS ms_regs, old_ms; |
| static unsigned short shift_status, old_shift = 0; |
| static unsigned char keyboard_function = 0xff, shift_function = 0xff, |
| check_function = 0xff; |
| |
| static const unsigned short button_map[3] = {0, 2, 1}; |
| |
| unsigned long PDC_get_input_fd(void) |
| { |
| PDC_LOG(("PDC_get_input_fd() - called\n")); |
| |
| return (unsigned long)fileno(stdin); |
| } |
| |
| void PDC_set_keyboard_binary(bool on) |
| { |
| PDC_LOG(("PDC_set_keyboard_binary() - called\n")); |
| |
| #ifdef __DJGPP__ |
| setmode(fileno(stdin), on ? O_BINARY : O_TEXT); |
| signal(SIGINT, on ? SIG_IGN : SIG_DFL); |
| #endif |
| } |
| |
| /* check if a key or mouse event is waiting */ |
| |
| bool PDC_check_key(void) |
| { |
| PDCREGS regs; |
| |
| if (shift_function == 0xff) |
| { |
| int scan; |
| |
| /* get shift status for all keyboards */ |
| |
| regs.h.ah = 0x02; |
| PDCINT(0x16, regs); |
| scan = regs.h.al; |
| |
| /* get shift status for enhanced keyboards */ |
| |
| regs.h.ah = 0x12; |
| PDCINT(0x16, regs); |
| |
| if (scan == regs.h.al && getdosmembyte(0x496) == 0x10) |
| { |
| keyboard_function = 0x10; |
| check_function = 0x11; |
| shift_function = 0x12; |
| } |
| else |
| { |
| keyboard_function = 0; |
| check_function = 1; |
| shift_function = 2; |
| } |
| } |
| |
| regs.h.ah = shift_function; |
| PDCINT(0x16, regs); |
| |
| shift_status = regs.W.ax; |
| |
| if (mouse_vis) |
| { |
| unsigned short i; |
| |
| ms_regs.W.ax = 3; |
| PDCINT(0x33, ms_regs); |
| |
| mouse_button = FALSE; |
| |
| for (i = 0; i < 3; i++) |
| { |
| regs.W.ax = 6; |
| regs.W.bx = button_map[i]; |
| PDCINT(0x33, regs); |
| button[i].released = regs.W.bx; |
| if (regs.W.bx) |
| { |
| ms_regs.W.cx = regs.W.cx; |
| ms_regs.W.dx = regs.W.dx; |
| mouse_button = TRUE; |
| } |
| |
| regs.W.ax = 5; |
| regs.W.bx = button_map[i]; |
| PDCINT(0x33, regs); |
| button[i].pressed = regs.W.bx; |
| if (regs.W.bx) |
| { |
| ms_regs.W.cx = regs.W.cx; |
| ms_regs.W.dx = regs.W.dx; |
| mouse_button = TRUE; |
| } |
| } |
| |
| mouse_scroll = ms_regs.h.bh; |
| |
| mouse_moved = !mouse_button && ms_regs.h.bl && |
| ms_regs.h.bl == old_ms.h.bl && |
| (((ms_regs.W.cx ^ old_ms.W.cx) >> 3) || |
| ((ms_regs.W.dx ^ old_ms.W.dx) >> 3)); |
| |
| if (mouse_scroll || mouse_button || mouse_moved) |
| return TRUE; |
| } |
| |
| if (old_shift && !shift_status) /* modifier released */ |
| { |
| if (!key_pressed && SP->return_key_modifiers) |
| return TRUE; |
| } |
| else if (!old_shift && shift_status) /* modifier pressed */ |
| key_pressed = FALSE; |
| |
| old_shift = shift_status; |
| |
| #ifndef USE_KBHIT |
| regs.h.ah = check_function; |
| PDCINT(0x16, regs); |
| |
| return !(regs.W.flags & 64); |
| #else |
| return kbhit(); |
| #endif |
| } |
| |
| static int _process_mouse_events(void) |
| { |
| int i; |
| short shift_flags = 0; |
| |
| memset(&pdc_mouse_status, 0, sizeof(pdc_mouse_status)); |
| |
| key_pressed = TRUE; |
| old_shift = shift_status; |
| SP->key_code = TRUE; |
| |
| /* Set shift modifiers */ |
| |
| if (shift_status & 3) |
| shift_flags |= BUTTON_SHIFT; |
| |
| if (shift_status & 4) |
| shift_flags |= BUTTON_CONTROL; |
| |
| if (shift_status & 8) |
| shift_flags |= BUTTON_ALT; |
| |
| /* Scroll wheel support for CuteMouse */ |
| |
| if (mouse_scroll) |
| { |
| pdc_mouse_status.changes = mouse_scroll & 0x80 ? |
| PDC_MOUSE_WHEEL_UP : PDC_MOUSE_WHEEL_DOWN; |
| |
| pdc_mouse_status.x = -1; |
| pdc_mouse_status.y = -1; |
| |
| return KEY_MOUSE; |
| } |
| |
| if (mouse_moved) |
| { |
| pdc_mouse_status.changes = PDC_MOUSE_MOVED; |
| |
| for (i = 0; i < 3; i++) |
| { |
| if (ms_regs.h.bl & (1 << button_map[i])) |
| { |
| pdc_mouse_status.button[i] = BUTTON_MOVED | shift_flags; |
| pdc_mouse_status.changes |= (1 << i); |
| } |
| } |
| } |
| else /* button event */ |
| { |
| for (i = 0; i < 3; i++) |
| { |
| if (button[i].pressed) |
| { |
| /* Check for a click -- a PRESS followed |
| immediately by a release */ |
| |
| if (!button[i].released) |
| { |
| if (SP->mouse_wait) |
| { |
| PDCREGS regs; |
| |
| napms(SP->mouse_wait); |
| |
| regs.W.ax = 6; |
| regs.W.bx = button_map[i]; |
| PDCINT(0x33, regs); |
| |
| pdc_mouse_status.button[i] = regs.W.bx ? |
| BUTTON_CLICKED : BUTTON_PRESSED; |
| } |
| else |
| pdc_mouse_status.button[i] = BUTTON_PRESSED; |
| } |
| else |
| pdc_mouse_status.button[i] = BUTTON_CLICKED; |
| } |
| |
| if (button[i].pressed || button[i].released) |
| { |
| pdc_mouse_status.button[i] |= shift_flags; |
| pdc_mouse_status.changes |= (1 << i); |
| } |
| } |
| } |
| |
| pdc_mouse_status.x = ms_regs.W.cx >> 3; |
| pdc_mouse_status.y = ms_regs.W.dx >> 3; |
| |
| old_ms = ms_regs; |
| |
| return KEY_MOUSE; |
| } |
| |
| /* return the next available key or mouse event */ |
| |
| int PDC_get_key(void) |
| { |
| PDCREGS regs; |
| int key, scan; |
| |
| pdc_key_modifiers = 0; |
| |
| if (mouse_vis && (mouse_scroll || mouse_button || mouse_moved)) |
| return _process_mouse_events(); |
| |
| /* Return modifiers as keys? */ |
| |
| if (old_shift && !shift_status) |
| { |
| key = -1; |
| |
| if (old_shift & 1) |
| key = KEY_SHIFT_R; |
| |
| if (old_shift & 2) |
| key = KEY_SHIFT_L; |
| |
| if (shift_function == 0x12) |
| { |
| if (old_shift & 0x400) |
| key = KEY_CONTROL_R; |
| |
| if (old_shift & 0x100) |
| key = KEY_CONTROL_L; |
| |
| if (old_shift & 0x800) |
| key = KEY_ALT_R; |
| |
| if (old_shift & 0x200) |
| key = KEY_ALT_L; |
| } |
| else |
| { |
| if (old_shift & 4) |
| key = KEY_CONTROL_R; |
| |
| if (old_shift & 8) |
| key = KEY_ALT_R; |
| } |
| |
| key_pressed = FALSE; |
| old_shift = shift_status; |
| |
| SP->key_code = TRUE; |
| return key; |
| } |
| |
| regs.h.ah = keyboard_function; |
| PDCINT(0x16, regs); |
| key = regs.h.al; |
| scan = regs.h.ah; |
| |
| if (SP->save_key_modifiers) |
| { |
| if (shift_status & 3) |
| pdc_key_modifiers |= PDC_KEY_MODIFIER_SHIFT; |
| |
| if (shift_status & 4) |
| pdc_key_modifiers |= PDC_KEY_MODIFIER_CONTROL; |
| |
| if (shift_status & 8) |
| pdc_key_modifiers |= PDC_KEY_MODIFIER_ALT; |
| |
| if (shift_status & 0x20) |
| pdc_key_modifiers |= PDC_KEY_MODIFIER_NUMLOCK; |
| } |
| |
| if (scan == 0x1c && key == 0x0a) /* ^Enter */ |
| key = CTL_ENTER; |
| else if (scan == 0xe0 && key == 0x0d) /* PadEnter */ |
| key = PADENTER; |
| else if (scan == 0xe0 && key == 0x0a) /* ^PadEnter */ |
| key = CTL_PADENTER; |
| else if (scan == 0x37 && key == 0x2a) /* Star */ |
| key = PADSTAR; |
| else if (scan == 0x4a && key == 0x2d) /* Minus */ |
| key = PADMINUS; |
| else if (scan == 0x4e && key == 0x2b) /* Plus */ |
| key = PADPLUS; |
| else if (scan == 0xe0 && key == 0x2f) /* Slash */ |
| key = PADSLASH; |
| else if (key == 0x00 || (key == 0xe0 && scan > 53 && scan != 86)) |
| key = (scan > 0xa7) ? -1 : key_table[scan]; |
| |
| if (shift_status & 3) |
| { |
| switch (key) |
| { |
| case KEY_HOME: /* Shift Home */ |
| key = KEY_SHOME; |
| break; |
| case KEY_UP: /* Shift Up */ |
| key = KEY_SUP; |
| break; |
| case KEY_PPAGE: /* Shift PgUp */ |
| key = KEY_SPREVIOUS; |
| break; |
| case KEY_LEFT: /* Shift Left */ |
| key = KEY_SLEFT; |
| break; |
| case KEY_RIGHT: /* Shift Right */ |
| key = KEY_SRIGHT; |
| break; |
| case KEY_END: /* Shift End */ |
| key = KEY_SEND; |
| break; |
| case KEY_DOWN: /* Shift Down */ |
| key = KEY_SDOWN; |
| break; |
| case KEY_NPAGE: /* Shift PgDn */ |
| key = KEY_SNEXT; |
| break; |
| case KEY_IC: /* Shift Ins */ |
| key = KEY_SIC; |
| break; |
| case KEY_DC: /* Shift Del */ |
| key = KEY_SDC; |
| } |
| } |
| |
| key_pressed = TRUE; |
| SP->key_code = ((unsigned)key >= 256); |
| |
| return key; |
| } |
| |
| /* discard any pending keyboard or mouse input -- this is the core |
| routine for flushinp() */ |
| |
| void PDC_flushinp(void) |
| { |
| PDC_LOG(("PDC_flushinp() - called\n")); |
| |
| /* Force the BIOS keyboard buffer head and tail pointers to be |
| the same... Real nasty trick... */ |
| |
| setdosmemword(0x41a, getdosmemword(0x41c)); |
| } |
| |
| int PDC_mouse_set(void) |
| { |
| PDCREGS regs; |
| unsigned long mbe = SP->_trap_mbe; |
| |
| if (mbe && !mouse_avail) |
| { |
| regs.W.ax = 0; |
| PDCINT(0x33, regs); |
| |
| mouse_avail = !!(regs.W.ax); |
| } |
| |
| if (mbe) |
| { |
| if (mouse_avail && !mouse_vis) |
| { |
| memset(&old_ms, 0, sizeof(old_ms)); |
| |
| regs.W.ax = 1; |
| PDCINT(0x33, regs); |
| |
| mouse_vis = TRUE; |
| } |
| } |
| else |
| { |
| if (mouse_avail && mouse_vis) |
| { |
| regs.W.ax = 2; |
| PDCINT(0x33, regs); |
| |
| mouse_vis = FALSE; |
| } |
| } |
| |
| return (mouse_avail || !mbe) ? OK : ERR; |
| } |
| |
| int PDC_modifiers_set(void) |
| { |
| key_pressed = FALSE; |
| |
| return OK; |
| } |