/* 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; }