| /* Public Domain Curses */ |
| |
| #if defined(__EMX__) || defined(__WATCOMC__) || defined(__IBMC__) || \ |
| defined(__TURBOC__) |
| # define HAVE_SIGNAL |
| # include <signal.h> |
| #endif |
| |
| #include "pdcos2.h" |
| |
| RCSID("$Id: pdckbd.c,v 1.89 2008/07/14 04:24:51 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 EMXVIDEO |
| # include <termios.h> |
| static int tahead = -1; |
| #else |
| static KBDINFO kbdinfo; /* default keyboard mode */ |
| static HMOU mouse_handle = 0; |
| static MOUSE_STATUS old_mouse_status; |
| static USHORT old_shift = 0; |
| static bool key_pressed = FALSE; |
| static int mouse_events = 0; |
| #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; |
| |
| unsigned long PDC_get_input_fd(void) |
| { |
| PDC_LOG(("PDC_get_input_fd() - called\n")); |
| |
| return (unsigned long)fileno(stdin); |
| } |
| |
| #ifndef EMXVIDEO |
| |
| void PDC_get_keyboard_info(void) |
| { |
| kbdinfo.cb = sizeof(kbdinfo); |
| KbdGetStatus(&kbdinfo, 0); |
| } |
| |
| void PDC_set_keyboard_default(void) |
| { |
| KbdSetStatus(&kbdinfo, 0); |
| } |
| |
| #endif /* ifndef EMXVIDEO */ |
| |
| void PDC_set_keyboard_binary(bool on) |
| { |
| PDC_LOG(("PDC_set_keyboard_binary() - called\n")); |
| |
| #ifndef EMXVIDEO |
| if (on) |
| { |
| kbdinfo.fsMask &= ~(KEYBOARD_ASCII_MODE); |
| kbdinfo.fsMask |= KEYBOARD_BINARY_MODE; |
| } |
| else |
| { |
| kbdinfo.fsMask &= ~(KEYBOARD_BINARY_MODE); |
| kbdinfo.fsMask |= KEYBOARD_ASCII_MODE; |
| } |
| |
| KbdSetStatus(&kbdinfo, 0); |
| #endif |
| |
| #ifdef HAVE_SIGNAL |
| signal(SIGBREAK, on ? SIG_IGN : SIG_DFL); |
| #endif |
| } |
| |
| /* check if a key or mouse event is waiting */ |
| |
| bool PDC_check_key(void) |
| { |
| #if !defined(_MSC_VER) && !defined(EMXVIDEO) |
| KBDKEYINFO keyInfo = {0}; |
| #endif |
| |
| #ifdef EMXVIDEO |
| if (tahead == -1) /* Nothing typed yet */ |
| { |
| tahead = _read_kbd(0, 0, 0); |
| |
| /* Read additional */ |
| |
| if (tahead == 0) |
| tahead = _read_kbd(0, 1, 0) << 8; |
| } |
| |
| return (tahead != -1); |
| #else |
| # ifndef _MSC_VER |
| |
| KbdGetStatus(&kbdinfo, 0); |
| |
| if (mouse_handle) |
| { |
| MOUQUEINFO queue; |
| |
| MouGetNumQueEl(&queue, mouse_handle); |
| mouse_events = queue.cEvents; |
| |
| if (mouse_events) |
| return TRUE; |
| } |
| |
| if (old_shift && !kbdinfo.fsState) /* modifier released */ |
| { |
| if (!key_pressed && SP->return_key_modifiers) |
| return TRUE; |
| } |
| else if (!old_shift && kbdinfo.fsState) /* modifier pressed */ |
| key_pressed = FALSE; |
| |
| old_shift = kbdinfo.fsState; |
| |
| KbdPeek(&keyInfo, 0); /* peek at keyboard */ |
| return (keyInfo.fbStatus != 0); |
| # else |
| return kbhit(); |
| # endif |
| #endif |
| } |
| |
| #ifndef EMXVIDEO |
| |
| static int _process_mouse_events(void) |
| { |
| MOUEVENTINFO event; |
| static const USHORT button_mask[] = {6, 96, 24}, |
| move_mask[] = {2, 32, 8}, |
| press_mask[] = {4, 64, 16}; |
| USHORT count = 1; |
| short shift_flags = 0; |
| int i; |
| |
| MouReadEventQue(&event, &count, mouse_handle); |
| mouse_events--; |
| |
| for (i = 0; i < 3; i++) |
| { |
| pdc_mouse_status.button[i] = |
| ((event.fs & move_mask[i]) ? BUTTON_MOVED : 0) | |
| ((event.fs & press_mask[i]) ? BUTTON_PRESSED : 0); |
| |
| /* PRESS events are sometimes mistakenly reported as MOVE |
| events. A MOVE should always follow a PRESS, so treat a MOVE |
| immediately after a RELEASE as a PRESS. */ |
| |
| if ((pdc_mouse_status.button[i] == BUTTON_MOVED) && |
| (old_mouse_status.button[i] == BUTTON_RELEASED)) |
| { |
| pdc_mouse_status.button[i] = BUTTON_PRESSED; |
| } |
| |
| if (pdc_mouse_status.button[i] == BUTTON_PRESSED && SP->mouse_wait) |
| { |
| /* Check for a click -- a PRESS followed immediately by a |
| release */ |
| |
| if (!mouse_events) |
| { |
| MOUQUEINFO queue; |
| |
| napms(SP->mouse_wait); |
| |
| MouGetNumQueEl(&queue, mouse_handle); |
| mouse_events = queue.cEvents; |
| } |
| |
| if (mouse_events) |
| { |
| MouReadEventQue(&event, &count, mouse_handle); |
| |
| if (!(event.fs & button_mask[i])) |
| pdc_mouse_status.button[i] = BUTTON_CLICKED; |
| } |
| } |
| } |
| |
| pdc_mouse_status.x = event.col; |
| pdc_mouse_status.y = event.row; |
| |
| pdc_mouse_status.changes = 0; |
| |
| for (i = 0; i < 3; i++) |
| { |
| if (old_mouse_status.button[i] != pdc_mouse_status.button[i]) |
| pdc_mouse_status.changes |= (1 << i); |
| |
| if (pdc_mouse_status.button[i] == BUTTON_MOVED) |
| { |
| /* Discard non-moved "moves" */ |
| |
| if (pdc_mouse_status.x == old_mouse_status.x && |
| pdc_mouse_status.y == old_mouse_status.y) |
| return -1; |
| |
| /* Motion events always flag the button as changed */ |
| |
| pdc_mouse_status.changes |= (1 << i); |
| pdc_mouse_status.changes |= PDC_MOUSE_MOVED; |
| break; |
| } |
| } |
| |
| old_mouse_status = pdc_mouse_status; |
| |
| /* Treat click events as release events for comparison purposes */ |
| |
| for (i = 0; i < 3; i++) |
| { |
| if (old_mouse_status.button[i] == BUTTON_CLICKED) |
| old_mouse_status.button[i] = BUTTON_RELEASED; |
| } |
| |
| /* Check for SHIFT/CONTROL/ALT */ |
| |
| if (kbdinfo.fsState & KBDSTF_ALT) |
| shift_flags |= BUTTON_ALT; |
| |
| if (kbdinfo.fsState & KBDSTF_CONTROL) |
| shift_flags |= BUTTON_CONTROL; |
| |
| if (kbdinfo.fsState & (KBDSTF_LEFTSHIFT|KBDSTF_RIGHTSHIFT)) |
| shift_flags |= BUTTON_SHIFT; |
| |
| if (shift_flags) |
| { |
| for (i = 0; i < 3; i++) |
| { |
| if (pdc_mouse_status.changes & (1 << i)) |
| pdc_mouse_status.button[i] |= shift_flags; |
| } |
| } |
| |
| old_shift = kbdinfo.fsState; |
| key_pressed = TRUE; |
| |
| SP->key_code = TRUE; |
| return KEY_MOUSE; |
| } |
| |
| #endif |
| |
| /* return the next available key or mouse event */ |
| |
| int PDC_get_key(void) |
| { |
| int key, scan; |
| #ifndef EMXVIDEO |
| KBDKEYINFO keyInfo = {0}; |
| #endif |
| |
| #ifdef EMXVIDEO |
| if (tahead == -1) |
| { |
| tahead = _read_kbd(0, 1, 0); |
| |
| /* Read additional */ |
| |
| if (tahead == 0) |
| tahead = _read_kbd(0, 1, 0) << 8; |
| } |
| |
| key = tahead & 0xff; |
| scan = tahead >> 8; |
| pdc_key_modifiers = 0L; |
| |
| tahead = -1; |
| #else |
| pdc_key_modifiers = 0L; |
| |
| if (mouse_handle && mouse_events) |
| return _process_mouse_events(); |
| |
| if (old_shift && !kbdinfo.fsState) |
| { |
| key = -1; |
| |
| if (old_shift & KBDSTF_LEFTALT) |
| { |
| key = KEY_ALT_L; |
| } |
| else if (old_shift & KBDSTF_RIGHTALT) |
| { |
| key = KEY_ALT_R; |
| } |
| else if (old_shift & KBDSTF_LEFTCONTROL) |
| { |
| key = KEY_CONTROL_L; |
| } |
| else if (old_shift & KBDSTF_RIGHTCONTROL) |
| { |
| key = KEY_CONTROL_R; |
| } |
| else if (old_shift & KBDSTF_LEFTSHIFT) |
| { |
| key = KEY_SHIFT_L; |
| } |
| else if (old_shift & KBDSTF_RIGHTSHIFT) |
| { |
| key = KEY_SHIFT_R; |
| } |
| |
| key_pressed = FALSE; |
| old_shift = kbdinfo.fsState; |
| |
| SP->key_code = TRUE; |
| return key; |
| } |
| |
| KbdCharIn(&keyInfo, IO_WAIT, 0); /* get a character */ |
| |
| key = keyInfo.chChar; |
| scan = keyInfo.chScan; |
| |
| if (SP->save_key_modifiers) |
| { |
| if (keyInfo.fsState & KBDSTF_ALT) |
| pdc_key_modifiers |= PDC_KEY_MODIFIER_ALT; |
| |
| if (keyInfo.fsState & KBDSTF_CONTROL) |
| pdc_key_modifiers |= PDC_KEY_MODIFIER_CONTROL; |
| |
| if (keyInfo.fsState & KBDSTF_NUMLOCK_ON) |
| pdc_key_modifiers |= PDC_KEY_MODIFIER_NUMLOCK; |
| |
| if (keyInfo.fsState & (KBDSTF_LEFTSHIFT|KBDSTF_RIGHTSHIFT)) |
| pdc_key_modifiers |= PDC_KEY_MODIFIER_SHIFT; |
| } |
| #endif |
| 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 (keyInfo.fsState & (KBDSTF_LEFTSHIFT|KBDSTF_RIGHTSHIFT)) |
| { |
| 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")); |
| |
| #ifdef EMXVIDEO |
| tcflush(0, TCIFLUSH); |
| #else |
| if (mouse_handle) |
| MouFlushQue(mouse_handle); |
| |
| KbdFlushBuffer(0); |
| #endif |
| } |
| |
| int PDC_mouse_set(void) |
| { |
| #ifndef EMXVIDEO |
| |
| unsigned long mbe = SP->_trap_mbe; |
| |
| if (mbe && !mouse_handle) |
| { |
| memset(&old_mouse_status, 0, sizeof(MOUSE_STATUS)); |
| MouOpen(NULL, &mouse_handle); |
| if (mouse_handle) |
| MouDrawPtr(mouse_handle); |
| } |
| else if (!mbe && mouse_handle) |
| { |
| MouClose(mouse_handle); |
| mouse_handle = 0; |
| } |
| |
| if (mbe && mouse_handle) |
| { |
| USHORT mask = ((mbe & (BUTTON1_PRESSED | BUTTON1_CLICKED | |
| BUTTON1_MOVED)) ? 6 : 0) | |
| |
| ((mbe & (BUTTON3_PRESSED | BUTTON3_CLICKED | |
| BUTTON3_MOVED)) ? 24 : 0) | |
| |
| ((mbe & (BUTTON2_PRESSED | BUTTON2_CLICKED | |
| BUTTON2_MOVED)) ? 96 : 0); |
| |
| MouSetEventMask(&mask, mouse_handle); |
| } |
| #endif |
| return OK; |
| } |
| |
| int PDC_modifiers_set(void) |
| { |
| key_pressed = FALSE; |
| |
| return OK; |
| } |