| /* |
| * Keyboard related functions |
| * |
| * Copyright 1993 Bob Amstadt |
| * Copyright 1996 Albrecht Kleine |
| */ |
| |
| #include <stdio.h> |
| #include <string.h> |
| #include "win.h" |
| #include "windows.h" |
| #include "accel.h" |
| #include "debug.h" |
| |
| extern BOOL MouseButtonsStates[3]; |
| extern BOOL AsyncMouseButtonsStates[3]; |
| extern BYTE InputKeyStateTable[256]; |
| BYTE AsyncKeyStateTable[256]; |
| |
| extern BYTE QueueKeyStateTable[256]; |
| |
| /********************************************************************** |
| * GetKeyState [USER.106] |
| * An application calls the GetKeyState function in response to a |
| * keyboard-input message. This function retrieves the state of the key |
| * at the time the input message was generated. (SDK 3.1 Vol 2. p 390) |
| */ |
| INT GetKeyState(INT keycode) |
| { |
| INT retval; |
| |
| if (keycode >= 'a' && keycode <= 'z') |
| keycode += 'A' - 'a'; |
| switch(keycode) { |
| case VK_LBUTTON: |
| retval = MouseButtonsStates[0]; |
| case VK_MBUTTON: |
| retval = MouseButtonsStates[1]; |
| case VK_RBUTTON: |
| retval = MouseButtonsStates[2]; |
| default: |
| retval = ( (INT)(QueueKeyStateTable[keycode] & 0x80) << 8 ) | |
| (INT)(QueueKeyStateTable[keycode] & 0x01); |
| } |
| |
| dprintf_key(stddeb, "GetKeyState(%x) -> %x\n", keycode, retval); |
| return retval; |
| } |
| |
| /********************************************************************** |
| * GetKeyboardState [USER.222] |
| * An application calls the GetKeyboardState function in response to a |
| * keyboard-input message. This function retrieves the state of the keyboard |
| * at the time the input message was generated. (SDK 3.1 Vol 2. p 387) |
| */ |
| void GetKeyboardState(BYTE *lpKeyState) |
| { |
| if (lpKeyState != NULL) { |
| QueueKeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] >> 8; |
| QueueKeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] >> 8; |
| QueueKeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] >> 8; |
| memcpy(lpKeyState, QueueKeyStateTable, 256); |
| } |
| } |
| |
| /********************************************************************** |
| * SetKeyboardState [USER.223] |
| */ |
| void SetKeyboardState(BYTE *lpKeyState) |
| { |
| if (lpKeyState != NULL) { |
| memcpy(QueueKeyStateTable, lpKeyState, 256); |
| MouseButtonsStates[0] = QueueKeyStateTable[VK_LBUTTON]? 0x8000: 0; |
| MouseButtonsStates[1] = QueueKeyStateTable[VK_MBUTTON]? 0x8000: 0; |
| MouseButtonsStates[2] = QueueKeyStateTable[VK_RBUTTON]? 0x8000: 0; |
| } |
| } |
| |
| /********************************************************************** |
| * GetAsyncKeyState (USER.249) |
| * |
| * Determine if a key is or was pressed. retval has high-order |
| * bit set to 1 if currently pressed, low-order bit set to 1 if key has |
| * been pressed. |
| * |
| * This uses the variable AsyncMouseButtonsStates and |
| * AsyncKeyStateTable (set in event.c) which have the mouse button |
| * number or key number (whichever is applicable) set to true if the |
| * mouse or key had been depressed since the last call to |
| * GetAsyncKeyState. |
| */ |
| int GetAsyncKeyState(int nKey) |
| { |
| short retval; |
| |
| switch (nKey) { |
| case VK_LBUTTON: |
| retval = AsyncMouseButtonsStates[0] | |
| MouseButtonsStates[0]? 0x0001: 0; |
| break; |
| case VK_MBUTTON: |
| retval = AsyncMouseButtonsStates[1] | |
| MouseButtonsStates[1]? 0x0001: 0; |
| break; |
| case VK_RBUTTON: |
| retval = AsyncMouseButtonsStates[2] | |
| MouseButtonsStates[2]? 0x0001: 0; |
| break; |
| default: |
| retval = AsyncKeyStateTable[nKey] | |
| (InputKeyStateTable[nKey] ? 0x8000 : 0); |
| break; |
| } |
| |
| memset( AsyncMouseButtonsStates, 0, 3 ); /* all states to false */ |
| memset( AsyncKeyStateTable, 0, 256 ); |
| |
| dprintf_key(stddeb, "GetAsyncKeyState(%x) -> %x\n", nKey, retval); |
| return retval; |
| } |
| |
| |
| /********************************************************************** |
| * TranslateAccelerator [USER.178] |
| * |
| * FIXME: should send some WM_INITMENU or/and WM_INITMENUPOPUP -messages |
| */ |
| INT16 TranslateAccelerator(HWND hWnd, HACCEL16 hAccel, LPMSG16 msg) |
| { |
| ACCELHEADER *lpAccelTbl; |
| int i; |
| BOOL sendmsg; |
| |
| if (hAccel == 0 || msg == NULL) return 0; |
| if (msg->message != WM_KEYDOWN && |
| msg->message != WM_KEYUP && |
| msg->message != WM_SYSKEYDOWN && |
| msg->message != WM_SYSKEYUP && |
| msg->message != WM_CHAR) return 0; |
| |
| dprintf_accel(stddeb, "TranslateAccelerators hAccel=%04x, hWnd=%04x,\ |
| msg->hwnd=%04x, msg->message=%04x\n", hAccel,hWnd,msg->hwnd,msg->message); |
| |
| lpAccelTbl = (LPACCELHEADER)GlobalLock16(hAccel); |
| for (sendmsg= i = 0; i < lpAccelTbl->wCount; i++) |
| { |
| if(msg->wParam == lpAccelTbl->tbl[i].wEvent) |
| { |
| if (msg->message == WM_CHAR) |
| { |
| if ( !(lpAccelTbl->tbl[i].type & ALT_ACCEL) && |
| !(lpAccelTbl->tbl[i].type & VIRTKEY_ACCEL) ) |
| { |
| dprintf_accel(stddeb,"found accel for WM_CHAR: ('%c')",msg->wParam&0xff); |
| sendmsg=TRUE; |
| } |
| } |
| else |
| { |
| if(lpAccelTbl->tbl[i].type & VIRTKEY_ACCEL) |
| { |
| INT mask = 0; |
| dprintf_accel(stddeb,"found accel for virt_key %04x (scan %04x)", |
| msg->wParam,0xff & HIWORD(msg->lParam)); |
| if(GetKeyState(VK_SHIFT) & 0x8000) mask |= SHIFT_ACCEL; |
| if(GetKeyState(VK_CONTROL) & 0x8000) mask |= CONTROL_ACCEL; |
| if(GetKeyState(VK_MENU) & 0x8000) mask |= ALT_ACCEL; |
| if(mask == (lpAccelTbl->tbl[i].type & |
| (SHIFT_ACCEL | CONTROL_ACCEL | ALT_ACCEL))) |
| sendmsg=TRUE; |
| else |
| dprintf_accel(stddeb,", but incorrect SHIFT/CTRL/ALT-state\n"); |
| } |
| else |
| { |
| if (!(msg->lParam & 0x01000000)) /* no special_key */ |
| { |
| if ((lpAccelTbl->tbl[i].type & ALT_ACCEL) && (msg->lParam & 0x20000000)) |
| { /* ^^ ALT pressed */ |
| dprintf_accel(stddeb,"found accel for Alt-%c", msg->wParam&0xff); |
| sendmsg=TRUE; |
| } |
| } |
| } |
| } |
| |
| if (sendmsg) /* found an accelerator, but send a message... ? */ |
| { |
| INT16 iSysStat,iStat,mesg=0; |
| HMENU16 hSysMenu,hMenu; |
| |
| if (msg->message == WM_KEYUP || msg->message == WM_SYSKEYUP) |
| mesg=1; |
| else |
| if (GetCapture16()) |
| mesg=2; |
| else |
| if (!IsWindowEnabled(hWnd)) |
| mesg=3; |
| else |
| { |
| hMenu=GetMenu(hWnd); |
| hSysMenu=GetSystemMenu(hWnd,FALSE); |
| if (hSysMenu) |
| iSysStat=GetMenuState(hSysMenu,lpAccelTbl->tbl[i].wIDval,MF_BYCOMMAND); |
| else |
| iSysStat=-1; |
| if (hMenu) |
| iStat=GetMenuState(hMenu,lpAccelTbl->tbl[i].wIDval,MF_BYCOMMAND); |
| else |
| iStat=-1; |
| if (iSysStat!=-1) |
| { |
| if (iSysStat & (MF_DISABLED|MF_GRAYED)) |
| mesg=4; |
| else |
| mesg=WM_SYSCOMMAND; |
| } |
| else |
| { |
| if (iStat!=-1) |
| { |
| if (IsIconic(hWnd)) |
| mesg=5; |
| else |
| { |
| if (iStat & (MF_DISABLED|MF_GRAYED)) |
| mesg=6; |
| else |
| mesg=WM_COMMAND; |
| } |
| } |
| else |
| mesg=WM_COMMAND; |
| } |
| } |
| if ( mesg==WM_COMMAND || mesg==WM_SYSCOMMAND ) |
| { |
| dprintf_accel(stddeb,", sending %s, wParam=%0x\n", |
| mesg==WM_COMMAND ? "WM_COMMAND" : "WM_SYSCOMMAND", |
| lpAccelTbl->tbl[i].wIDval); |
| SendMessage16(hWnd, mesg, lpAccelTbl->tbl[i].wIDval,0x00010000L); |
| } |
| else |
| { |
| /* some reasons for NOT sending the WM_{SYS}COMMAND message: |
| * #0: unknown (please report!) |
| * #1: for WM_KEYUP,WM_SYKEYUP |
| * #2: mouse is captured |
| * #3: window is disabled |
| * #4: it's a disabled system menu option |
| * #5: it's a menu option, but window is iconic |
| * #6: it's a menu option, but disabled |
| */ |
| dprintf_accel(stddeb,", but won't send WM_{SYS}COMMAND, reason is #%d\n",mesg); |
| } |
| GlobalUnlock16(hAccel); |
| return 1; |
| } |
| } |
| } |
| GlobalUnlock16(hAccel); |
| return 0; |
| } |