| /* |
| * USER Input processing |
| * |
| * Copyright 1993 Bob Amstadt |
| * Copyright 1996 Albrecht Kleine |
| * Copyright 1997 David Faure |
| * Copyright 1998 Morten Welinder |
| * Copyright 1998 Ulrich Weigand |
| * |
| */ |
| |
| #include <stdlib.h> |
| #include <string.h> |
| #include <ctype.h> |
| #include <assert.h> |
| |
| #include "winuser.h" |
| #include "wine/winbase16.h" |
| #include "wine/winuser16.h" |
| #include "wine/keyboard16.h" |
| #include "win.h" |
| #include "heap.h" |
| #include "input.h" |
| #include "keyboard.h" |
| #include "mouse.h" |
| #include "message.h" |
| #include "sysmetrics.h" |
| #include "debug.h" |
| #include "debugtools.h" |
| #include "struct32.h" |
| #include "winerror.h" |
| #include "task.h" |
| |
| static BOOL InputEnabled = TRUE; |
| static BOOL SwappedButtons = FALSE; |
| |
| BOOL MouseButtonsStates[3]; |
| BOOL AsyncMouseButtonsStates[3]; |
| BYTE InputKeyStateTable[256]; |
| BYTE QueueKeyStateTable[256]; |
| BYTE AsyncKeyStateTable[256]; |
| |
| typedef union |
| { |
| struct |
| { |
| unsigned long count : 16; |
| unsigned long code : 8; |
| unsigned long extended : 1; |
| unsigned long unused : 2; |
| unsigned long win_internal : 2; |
| unsigned long context : 1; |
| unsigned long previous : 1; |
| unsigned long transition : 1; |
| } lp1; |
| unsigned long lp2; |
| } KEYLP; |
| |
| /*********************************************************************** |
| * keybd_event (USER32.583) |
| */ |
| void WINAPI keybd_event( BYTE bVk, BYTE bScan, |
| DWORD dwFlags, DWORD dwExtraInfo ) |
| { |
| DWORD posX, posY, time, extra; |
| WORD message; |
| KEYLP keylp; |
| keylp.lp2 = 0; |
| |
| if (!InputEnabled) return; |
| |
| /* |
| * If we are called by the Wine keyboard driver, use the additional |
| * info pointed to by the dwExtraInfo argument. |
| * Otherwise, we need to determine that info ourselves (probably |
| * less accurate, but we can't help that ...). |
| */ |
| if ( !IsBadReadPtr( (LPVOID)dwExtraInfo, sizeof(WINE_KEYBDEVENT) ) |
| && ((WINE_KEYBDEVENT *)dwExtraInfo)->magic == WINE_KEYBDEVENT_MAGIC ) |
| { |
| WINE_KEYBDEVENT *wke = (WINE_KEYBDEVENT *)dwExtraInfo; |
| posX = wke->posX; |
| posY = wke->posY; |
| time = wke->time; |
| extra = 0; |
| } |
| else |
| { |
| DWORD keyState; |
| time = GetTickCount(); |
| extra = dwExtraInfo; |
| |
| if ( !EVENT_QueryPointer( &posX, &posY, &keyState )) |
| return; |
| } |
| |
| |
| keylp.lp1.count = 1; |
| keylp.lp1.code = bScan; |
| keylp.lp1.extended = (dwFlags & KEYEVENTF_EXTENDEDKEY) != 0; |
| keylp.lp1.win_internal = 0; /* this has something to do with dialogs, |
| * don't remember where I read it - AK */ |
| /* it's '1' under windows, when a dialog box appears |
| * and you press one of the underlined keys - DF*/ |
| |
| if ( dwFlags & KEYEVENTF_KEYUP ) |
| { |
| BOOL sysKey = (InputKeyStateTable[VK_MENU] & 0x80) |
| && !(InputKeyStateTable[VK_CONTROL] & 0x80) |
| && !(dwFlags & KEYEVENTF_WINE_FORCEEXTENDED); /* for Alt from AltGr */ |
| |
| InputKeyStateTable[bVk] &= ~0x80; |
| keylp.lp1.previous = 1; |
| keylp.lp1.transition = 1; |
| message = sysKey ? WM_SYSKEYUP : WM_KEYUP; |
| } |
| else |
| { |
| keylp.lp1.previous = (InputKeyStateTable[bVk] & 0x80) != 0; |
| keylp.lp1.transition = 0; |
| |
| if (!(InputKeyStateTable[bVk] & 0x80)) |
| InputKeyStateTable[bVk] ^= 0x01; |
| InputKeyStateTable[bVk] |= 0x80; |
| |
| message = (InputKeyStateTable[VK_MENU] & 0x80) |
| && !(InputKeyStateTable[VK_CONTROL] & 0x80) |
| ? WM_SYSKEYDOWN : WM_KEYDOWN; |
| } |
| |
| if ( message == WM_SYSKEYDOWN || message == WM_SYSKEYUP ) |
| keylp.lp1.context = (InputKeyStateTable[VK_MENU] & 0x80) != 0; /* 1 if alt */ |
| |
| |
| TRACE(key, " wParam=%04X, lParam=%08lX\n", bVk, keylp.lp2 ); |
| TRACE(key, " InputKeyState=%X\n", InputKeyStateTable[bVk] ); |
| |
| hardware_event( message, bVk, keylp.lp2, posX, posY, time, extra ); |
| } |
| |
| /*********************************************************************** |
| * mouse_event (USER32.584) |
| */ |
| void WINAPI mouse_event( DWORD dwFlags, DWORD dx, DWORD dy, |
| DWORD cButtons, DWORD dwExtraInfo ) |
| { |
| DWORD posX, posY, keyState, time, extra; |
| |
| if (!InputEnabled) return; |
| |
| /* |
| * If we are called by the Wine mouse driver, use the additional |
| * info pointed to by the dwExtraInfo argument. |
| * Otherwise, we need to determine that info ourselves (probably |
| * less accurate, but we can't help that ...). |
| */ |
| if ( !IsBadReadPtr( (LPVOID)dwExtraInfo, sizeof(WINE_MOUSEEVENT) ) |
| && ((WINE_MOUSEEVENT *)dwExtraInfo)->magic == WINE_MOUSEEVENT_MAGIC ) |
| { |
| WINE_MOUSEEVENT *wme = (WINE_MOUSEEVENT *)dwExtraInfo; |
| keyState = wme->keyState; |
| time = wme->time; |
| extra = (DWORD)wme->hWnd; |
| |
| assert( dwFlags & MOUSEEVENTF_ABSOLUTE ); |
| posX = (dx * SYSMETRICS_CXSCREEN) >> 16; |
| posY = (dy * SYSMETRICS_CYSCREEN) >> 16; |
| } |
| else |
| { |
| time = GetTickCount(); |
| extra = dwExtraInfo; |
| |
| if ( !EVENT_QueryPointer( &posX, &posY, &keyState )) |
| return; |
| |
| if ( dwFlags & MOUSEEVENTF_MOVE ) |
| { |
| if ( dwFlags & MOUSEEVENTF_ABSOLUTE ) |
| { |
| posX = (dx * SYSMETRICS_CXSCREEN) >> 16; |
| posY = (dy * SYSMETRICS_CYSCREEN) >> 16; |
| } |
| else |
| { |
| posX += dx; |
| posY += dy; |
| } |
| /* We have to actually move the cursor */ |
| SetCursorPos( posX, posY ); |
| } |
| } |
| |
| if ( dwFlags & MOUSEEVENTF_MOVE ) |
| { |
| hardware_event( WM_MOUSEMOVE, |
| keyState, 0L, posX, posY, time, extra ); |
| } |
| if ( dwFlags & (!SwappedButtons? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_RIGHTDOWN) ) |
| { |
| MouseButtonsStates[0] = AsyncMouseButtonsStates[0] = TRUE; |
| hardware_event( WM_LBUTTONDOWN, |
| keyState, 0L, posX, posY, time, extra ); |
| } |
| if ( dwFlags & (!SwappedButtons? MOUSEEVENTF_LEFTUP : MOUSEEVENTF_RIGHTUP) ) |
| { |
| MouseButtonsStates[0] = FALSE; |
| hardware_event( WM_LBUTTONUP, |
| keyState, 0L, posX, posY, time, extra ); |
| } |
| if ( dwFlags & (!SwappedButtons? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_LEFTDOWN) ) |
| { |
| MouseButtonsStates[2] = AsyncMouseButtonsStates[2] = TRUE; |
| hardware_event( WM_RBUTTONDOWN, |
| keyState, 0L, posX, posY, time, extra ); |
| } |
| if ( dwFlags & (!SwappedButtons? MOUSEEVENTF_RIGHTUP : MOUSEEVENTF_LEFTUP) ) |
| { |
| MouseButtonsStates[2] = FALSE; |
| hardware_event( WM_RBUTTONUP, |
| keyState, 0L, posX, posY, time, extra ); |
| } |
| if ( dwFlags & MOUSEEVENTF_MIDDLEDOWN ) |
| { |
| MouseButtonsStates[1] = AsyncMouseButtonsStates[1] = TRUE; |
| hardware_event( WM_MBUTTONDOWN, |
| keyState, 0L, posX, posY, time, extra ); |
| } |
| if ( dwFlags & MOUSEEVENTF_MIDDLEUP ) |
| { |
| MouseButtonsStates[1] = FALSE; |
| hardware_event( WM_MBUTTONUP, |
| keyState, 0L, posX, posY, time, extra ); |
| } |
| } |
| |
| /********************************************************************** |
| * EnableHardwareInput (USER.331) |
| */ |
| BOOL16 WINAPI EnableHardwareInput16(BOOL16 bEnable) |
| { |
| BOOL16 bOldState = InputEnabled; |
| FIXME(event,"(%d) - stub\n", bEnable); |
| InputEnabled = bEnable; |
| return bOldState; |
| } |
| |
| |
| /*********************************************************************** |
| * SwapMouseButton16 (USER.186) |
| */ |
| BOOL16 WINAPI SwapMouseButton16( BOOL16 fSwap ) |
| { |
| BOOL16 ret = SwappedButtons; |
| SwappedButtons = fSwap; |
| return ret; |
| } |
| |
| |
| /*********************************************************************** |
| * SwapMouseButton32 (USER32.537) |
| */ |
| BOOL WINAPI SwapMouseButton( BOOL fSwap ) |
| { |
| BOOL ret = SwappedButtons; |
| SwappedButtons = fSwap; |
| return ret; |
| } |
| |
| /********************************************************************** |
| * EVENT_Capture |
| * |
| * We need this to be able to generate double click messages |
| * when menu code captures mouse in the window without CS_DBLCLK style. |
| */ |
| HWND EVENT_Capture(HWND hwnd, INT16 ht) |
| { |
| HWND capturePrev = 0, captureWnd = 0; |
| MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0; |
| WND* wndPtr = 0; |
| INT16 captureHT = 0; |
| |
| /* Get the messageQ for the current thread */ |
| if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() ))) |
| { |
| WARN( win, "\tCurrent message queue not found. Exiting!\n" ); |
| goto CLEANUP; |
| } |
| |
| /* Get the current capture window from the perQ data of the current message Q */ |
| capturePrev = PERQDATA_GetCaptureWnd( pCurMsgQ->pQData ); |
| |
| if (!hwnd) |
| { |
| captureWnd = 0L; |
| captureHT = 0; |
| } |
| else |
| { |
| wndPtr = WIN_FindWndPtr( hwnd ); |
| if (wndPtr) |
| { |
| TRACE(win, "(0x%04x)\n", hwnd ); |
| captureWnd = hwnd; |
| captureHT = ht; |
| } |
| } |
| |
| /* Update the perQ capture window and send messages */ |
| if( capturePrev != captureWnd ) |
| { |
| if (wndPtr) |
| { |
| /* Retrieve the message queue associated with this window */ |
| pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ ); |
| if ( !pMsgQ ) |
| { |
| WARN( win, "\tMessage queue not found. Exiting!\n" ); |
| goto CLEANUP; |
| } |
| |
| /* Make sure that message queue for the window we are setting capture to |
| * shares the same perQ data as the current threads message queue. |
| */ |
| if ( pCurMsgQ->pQData != pMsgQ->pQData ) |
| goto CLEANUP; |
| } |
| |
| PERQDATA_SetCaptureWnd( pCurMsgQ->pQData, captureWnd ); |
| PERQDATA_SetCaptureInfo( pCurMsgQ->pQData, captureHT ); |
| |
| if( capturePrev ) |
| { |
| WND* wndPtr = WIN_FindWndPtr( capturePrev ); |
| if( wndPtr && (wndPtr->flags & WIN_ISWIN32) ) |
| SendMessageA( capturePrev, WM_CAPTURECHANGED, 0L, hwnd); |
| WIN_ReleaseWndPtr(wndPtr); |
| } |
| } |
| |
| CLEANUP: |
| /* Unlock the queues before returning */ |
| if ( pMsgQ ) |
| QUEUE_Unlock( pMsgQ ); |
| if ( pCurMsgQ ) |
| QUEUE_Unlock( pCurMsgQ ); |
| |
| WIN_ReleaseWndPtr(wndPtr); |
| return capturePrev; |
| } |
| |
| |
| /********************************************************************** |
| * SetCapture16 (USER.18) |
| */ |
| HWND16 WINAPI SetCapture16( HWND16 hwnd ) |
| { |
| return (HWND16)EVENT_Capture( hwnd, HTCLIENT ); |
| } |
| |
| |
| /********************************************************************** |
| * SetCapture32 (USER32.464) |
| */ |
| HWND WINAPI SetCapture( HWND hwnd ) |
| { |
| return EVENT_Capture( hwnd, HTCLIENT ); |
| } |
| |
| |
| /********************************************************************** |
| * ReleaseCapture (USER.19) (USER32.439) |
| */ |
| BOOL WINAPI ReleaseCapture(void) |
| { |
| return (EVENT_Capture( 0, 0 ) != 0); |
| } |
| |
| |
| /********************************************************************** |
| * GetCapture16 (USER.236) |
| */ |
| HWND16 WINAPI GetCapture16(void) |
| { |
| return (HWND16)GetCapture(); |
| } |
| |
| /********************************************************************** |
| * GetCapture32 (USER32.208) |
| */ |
| HWND WINAPI GetCapture(void) |
| { |
| MESSAGEQUEUE *pCurMsgQ = 0; |
| HWND hwndCapture = 0; |
| |
| /* Get the messageQ for the current thread */ |
| if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() ))) |
| { |
| TRACE( win, "GetCapture32: Current message queue not found. Exiting!\n" ); |
| return 0; |
| } |
| |
| /* Get the current capture window from the perQ data of the current message Q */ |
| hwndCapture = PERQDATA_GetCaptureWnd( pCurMsgQ->pQData ); |
| |
| QUEUE_Unlock( pCurMsgQ ); |
| return hwndCapture; |
| } |
| |
| /********************************************************************** |
| * GetKeyState (USER.106) |
| */ |
| INT16 WINAPI GetKeyState16(INT16 vkey) |
| { |
| return GetKeyState(vkey); |
| } |
| |
| /********************************************************************** |
| * GetKeyState (USER32.249) |
| * |
| * 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) |
| */ |
| INT16 WINAPI GetKeyState(INT vkey) |
| { |
| INT retval; |
| |
| switch (vkey) |
| { |
| case VK_LBUTTON : /* VK_LBUTTON is 1 */ |
| retval = MouseButtonsStates[0] ? 0x8000 : 0; |
| break; |
| case VK_MBUTTON : /* VK_MBUTTON is 4 */ |
| retval = MouseButtonsStates[1] ? 0x8000 : 0; |
| break; |
| case VK_RBUTTON : /* VK_RBUTTON is 2 */ |
| retval = MouseButtonsStates[2] ? 0x8000 : 0; |
| break; |
| default : |
| if (vkey >= 'a' && vkey <= 'z') |
| vkey += 'A' - 'a'; |
| retval = ( (WORD)(QueueKeyStateTable[vkey] & 0x80) << 8 ) | |
| (WORD)(QueueKeyStateTable[vkey] & 0x01); |
| } |
| /* TRACE(key, "(0x%x) -> %x\n", vkey, retval); */ |
| return retval; |
| } |
| |
| /********************************************************************** |
| * GetKeyboardState (USER.222)(USER32.254) |
| * |
| * 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 WINAPI GetKeyboardState(LPBYTE lpKeyState) |
| { |
| TRACE(key, "(%p)\n", lpKeyState); |
| if (lpKeyState != NULL) { |
| QueueKeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] ? 0x80 : 0; |
| QueueKeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] ? 0x80 : 0; |
| QueueKeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] ? 0x80 : 0; |
| memcpy(lpKeyState, QueueKeyStateTable, 256); |
| } |
| } |
| |
| /********************************************************************** |
| * SetKeyboardState (USER.223)(USER32.484) |
| */ |
| VOID WINAPI SetKeyboardState(LPBYTE lpKeyState) |
| { |
| TRACE(key, "(%p)\n", lpKeyState); |
| if (lpKeyState != NULL) { |
| memcpy(QueueKeyStateTable, lpKeyState, 256); |
| MouseButtonsStates[0] = (QueueKeyStateTable[VK_LBUTTON] != 0); |
| MouseButtonsStates[1] = (QueueKeyStateTable[VK_MBUTTON] != 0); |
| MouseButtonsStates[2] = (QueueKeyStateTable[VK_RBUTTON] != 0); |
| } |
| } |
| |
| /********************************************************************** |
| * GetAsyncKeyState32 (USER32.207) |
| * |
| * 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. |
| */ |
| WORD WINAPI GetAsyncKeyState(INT nKey) |
| { |
| short retval; |
| |
| switch (nKey) { |
| case VK_LBUTTON: |
| retval = (AsyncMouseButtonsStates[0] ? 0x0001 : 0) | |
| (MouseButtonsStates[0] ? 0x8000 : 0); |
| break; |
| case VK_MBUTTON: |
| retval = (AsyncMouseButtonsStates[1] ? 0x0001 : 0) | |
| (MouseButtonsStates[1] ? 0x8000 : 0); |
| break; |
| case VK_RBUTTON: |
| retval = (AsyncMouseButtonsStates[2] ? 0x0001 : 0) | |
| (MouseButtonsStates[2] ? 0x8000 : 0); |
| break; |
| default: |
| retval = AsyncKeyStateTable[nKey] | |
| ((InputKeyStateTable[nKey] & 0x80) ? 0x8000 : 0); |
| break; |
| } |
| |
| /* all states to false */ |
| memset( AsyncMouseButtonsStates, 0, sizeof(AsyncMouseButtonsStates) ); |
| memset( AsyncKeyStateTable, 0, sizeof(AsyncKeyStateTable) ); |
| |
| TRACE(key, "(%x) -> %x\n", nKey, retval); |
| return retval; |
| } |
| |
| /********************************************************************** |
| * GetAsyncKeyState16 (USER.249) |
| */ |
| WORD WINAPI GetAsyncKeyState16(INT16 nKey) |
| { |
| return GetAsyncKeyState(nKey); |
| } |
| |
| /********************************************************************** |
| * KBD_translate_accelerator |
| * |
| * FIXME: should send some WM_INITMENU or/and WM_INITMENUPOPUP -messages |
| */ |
| static BOOL KBD_translate_accelerator(HWND hWnd,LPMSG msg, |
| BYTE fVirt,WORD key,WORD cmd) |
| { |
| BOOL sendmsg = FALSE; |
| |
| if(msg->wParam == key) |
| { |
| if (msg->message == WM_CHAR) { |
| if ( !(fVirt & FALT) && !(fVirt & FVIRTKEY) ) |
| { |
| TRACE(accel,"found accel for WM_CHAR: ('%c')\n", |
| msg->wParam&0xff); |
| sendmsg=TRUE; |
| } |
| } else { |
| if(fVirt & FVIRTKEY) { |
| INT mask = 0; |
| TRACE(accel,"found accel for virt_key %04x (scan %04x)\n", |
| msg->wParam,0xff & HIWORD(msg->lParam)); |
| if(GetKeyState(VK_SHIFT) & 0x8000) mask |= FSHIFT; |
| if(GetKeyState(VK_CONTROL) & 0x8000) mask |= FCONTROL; |
| if(GetKeyState(VK_MENU) & 0x8000) mask |= FALT; |
| if(mask == (fVirt & (FSHIFT | FCONTROL | FALT))) |
| sendmsg=TRUE; |
| else |
| TRACE(accel,", but incorrect SHIFT/CTRL/ALT-state\n"); |
| } |
| else |
| { |
| if (!(msg->lParam & 0x01000000)) /* no special_key */ |
| { |
| if ((fVirt & FALT) && (msg->lParam & 0x20000000)) |
| { /* ^^ ALT pressed */ |
| TRACE(accel,"found accel for Alt-%c\n", msg->wParam&0xff); |
| sendmsg=TRUE; |
| } |
| } |
| } |
| } |
| |
| if (sendmsg) /* found an accelerator, but send a message... ? */ |
| { |
| INT16 iSysStat,iStat,mesg=0; |
| HMENU16 hMenu; |
| |
| if (msg->message == WM_KEYUP || msg->message == WM_SYSKEYUP) |
| mesg=1; |
| else |
| if (GetCapture()) |
| mesg=2; |
| else |
| if (!IsWindowEnabled(hWnd)) |
| mesg=3; |
| else |
| { |
| WND* wndPtr = WIN_FindWndPtr(hWnd); |
| |
| hMenu = (wndPtr->dwStyle & WS_CHILD) ? 0 : (HMENU)wndPtr->wIDmenu; |
| iSysStat = (wndPtr->hSysMenu) ? GetMenuState(GetSubMenu16(wndPtr->hSysMenu, 0), |
| cmd, MF_BYCOMMAND) : -1 ; |
| iStat = (hMenu) ? GetMenuState(hMenu, |
| cmd, MF_BYCOMMAND) : -1 ; |
| |
| WIN_ReleaseWndPtr(wndPtr); |
| |
| 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 ) |
| { |
| TRACE(accel,", sending %s, wParam=%0x\n", |
| mesg==WM_COMMAND ? "WM_COMMAND" : "WM_SYSCOMMAND", |
| cmd); |
| SendMessageA(hWnd, mesg, cmd, 0x00010000L); |
| } |
| else |
| { |
| /* some reasons for NOT sending the WM_{SYS}COMMAND message: |
| * #0: unknown (please report!) |
| * #1: for WM_KEYUP,WM_SYSKEYUP |
| * #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 |
| */ |
| TRACE(accel,", but won't send WM_{SYS}COMMAND, reason is #%d\n",mesg); |
| if(mesg==0) |
| ERR(accel, " unknown reason - please report!"); |
| } |
| return TRUE; |
| } |
| } |
| return FALSE; |
| } |
| |
| /********************************************************************** |
| * TranslateAccelerator32 (USER32.551)(USER32.552)(USER32.553) |
| */ |
| INT WINAPI TranslateAccelerator(HWND hWnd, HACCEL hAccel, LPMSG msg) |
| { |
| /* YES, Accel16! */ |
| LPACCEL16 lpAccelTbl = (LPACCEL16)LockResource16(hAccel); |
| int i; |
| |
| TRACE(accel,"hwnd=0x%x hacc=0x%x msg=0x%x wp=0x%x lp=0x%lx\n", hWnd, hAccel, msg->message, msg->wParam, msg->lParam); |
| |
| if (hAccel == 0 || msg == NULL || |
| (msg->message != WM_KEYDOWN && |
| msg->message != WM_KEYUP && |
| msg->message != WM_SYSKEYDOWN && |
| msg->message != WM_SYSKEYUP && |
| msg->message != WM_CHAR)) { |
| WARN(accel, "erraneous input parameters\n"); |
| SetLastError(ERROR_INVALID_PARAMETER); |
| return 0; |
| } |
| |
| TRACE(accel, "TranslateAccelerators hAccel=%04x, hWnd=%04x," |
| "msg->hwnd=%04x, msg->message=%04x\n", |
| hAccel,hWnd,msg->hwnd,msg->message); |
| |
| i = 0; |
| do |
| { |
| if (KBD_translate_accelerator(hWnd,msg,lpAccelTbl[i].fVirt, |
| lpAccelTbl[i].key,lpAccelTbl[i].cmd)) |
| return 1; |
| } while ((lpAccelTbl[i++].fVirt & 0x80) == 0); |
| WARN(accel, "couldn't translate accelerator key\n"); |
| return 0; |
| } |
| |
| /********************************************************************** |
| * TranslateAccelerator16 (USER.178) |
| */ |
| INT16 WINAPI TranslateAccelerator16(HWND16 hWnd, HACCEL16 hAccel, LPMSG16 msg) |
| { |
| LPACCEL16 lpAccelTbl = (LPACCEL16)LockResource16(hAccel); |
| int i; |
| MSG msg32; |
| |
| if (hAccel == 0 || msg == NULL || |
| (msg->message != WM_KEYDOWN && |
| msg->message != WM_KEYUP && |
| msg->message != WM_SYSKEYDOWN && |
| msg->message != WM_SYSKEYUP && |
| msg->message != WM_CHAR)) { |
| WARN(accel, "erraneous input parameters\n"); |
| SetLastError(ERROR_INVALID_PARAMETER); |
| return 0; |
| } |
| |
| TRACE(accel, "TranslateAccelerators hAccel=%04x, hWnd=%04x,\ |
| msg->hwnd=%04x, msg->message=%04x\n", hAccel,hWnd,msg->hwnd,msg->message); |
| STRUCT32_MSG16to32(msg,&msg32); |
| |
| |
| i = 0; |
| do |
| { |
| if (KBD_translate_accelerator(hWnd,&msg32,lpAccelTbl[i].fVirt, |
| lpAccelTbl[i].key,lpAccelTbl[i].cmd)) |
| return 1; |
| } while ((lpAccelTbl[i++].fVirt & 0x80) == 0); |
| WARN(accel, "couldn't translate accelerator key\n"); |
| return 0; |
| } |
| |
| |
| /********************************************************************** |
| * VkKeyScanA (USER32.573) |
| */ |
| WORD WINAPI VkKeyScanA(CHAR cChar) |
| { |
| return VkKeyScan16(cChar); |
| } |
| |
| /****************************************************************************** |
| * VkKeyScanW (USER32.576) |
| */ |
| WORD WINAPI VkKeyScanW(WCHAR cChar) |
| { |
| return VkKeyScanA((CHAR)cChar); /* FIXME: check unicode */ |
| } |
| |
| /********************************************************************** |
| * VkKeyScanExA (USER32.574) |
| */ |
| WORD WINAPI VkKeyScanExA(CHAR cChar, HKL dwhkl) |
| { |
| /* FIXME: complete workaround this is */ |
| return VkKeyScan16(cChar); |
| } |
| |
| /****************************************************************************** |
| * VkKeyScanExW (USER32.575) |
| */ |
| WORD WINAPI VkKeyScanExW(WCHAR cChar, HKL dwhkl) |
| { |
| /* FIXME: complete workaround this is */ |
| return VkKeyScanA((CHAR)cChar); /* FIXME: check unicode */ |
| } |
| |
| /****************************************************************************** |
| * GetKeyboardType32 (USER32.255) |
| */ |
| INT WINAPI GetKeyboardType(INT nTypeFlag) |
| { |
| return GetKeyboardType16(nTypeFlag); |
| } |
| |
| /****************************************************************************** |
| * MapVirtualKey32A (USER32.383) |
| */ |
| UINT WINAPI MapVirtualKeyA(UINT code, UINT maptype) |
| { |
| return MapVirtualKey16(code,maptype); |
| } |
| |
| /****************************************************************************** |
| * MapVirtualKey32W (USER32.385) |
| */ |
| UINT WINAPI MapVirtualKeyW(UINT code, UINT maptype) |
| { |
| return MapVirtualKey16(code,maptype); |
| } |
| |
| /****************************************************************************** |
| * MapVirtualKeyEx32A (USER32.384) |
| */ |
| UINT WINAPI MapVirtualKeyEx32A(UINT code, UINT maptype, HKL hkl) |
| { |
| if (hkl) |
| FIXME(keyboard,"(%d,%d,0x%08lx), hkl unhandled!\n",code,maptype,(DWORD)hkl); |
| return MapVirtualKey16(code,maptype); |
| } |
| |
| /**************************************************************************** |
| * GetKBCodePage32 (USER32.246) |
| */ |
| UINT WINAPI GetKBCodePage(void) |
| { |
| return GetKBCodePage16(); |
| } |
| |
| /**************************************************************************** |
| * GetKeyboardLayoutName16 (USER.477) |
| */ |
| INT16 WINAPI GetKeyboardLayoutName16(LPSTR pwszKLID) |
| { |
| return GetKeyboardLayoutNameA(pwszKLID); |
| } |
| |
| /*********************************************************************** |
| * GetKeyboardLayout (USER32.250) |
| * |
| * FIXME: - device handle for keyboard layout defaulted to |
| * the language id. This is the way Windows default works. |
| * - the thread identifier (dwLayout) is also ignored. |
| */ |
| HKL WINAPI GetKeyboardLayout(DWORD dwLayout) |
| { |
| HKL layout; |
| layout = GetSystemDefaultLCID(); /* FIXME */ |
| layout |= (layout<<16); /* FIXME */ |
| TRACE(keyboard,"returning %08x\n",layout); |
| return layout; |
| } |
| |
| /**************************************************************************** |
| * GetKeyboardLayoutName32A (USER32.252) |
| */ |
| INT WINAPI GetKeyboardLayoutNameA(LPSTR pwszKLID) |
| { |
| sprintf(pwszKLID, "%08x",GetKeyboardLayout(0)); |
| return 1; |
| } |
| |
| /**************************************************************************** |
| * GetKeyboardLayoutName32W (USER32.253) |
| */ |
| INT WINAPI GetKeyboardLayoutNameW(LPWSTR pwszKLID) |
| { |
| LPSTR buf = HEAP_xalloc( GetProcessHeap(), 0, strlen("00000409")+1); |
| int res = GetKeyboardLayoutNameA(buf); |
| lstrcpyAtoW(pwszKLID,buf); |
| HeapFree( GetProcessHeap(), 0, buf ); |
| return res; |
| } |
| |
| /**************************************************************************** |
| * GetKeyNameText32A (USER32.247) |
| */ |
| INT WINAPI GetKeyNameTextA(LONG lParam, LPSTR lpBuffer, INT nSize) |
| { |
| return GetKeyNameText16(lParam,lpBuffer,nSize); |
| } |
| |
| /**************************************************************************** |
| * GetKeyNameText32W (USER32.248) |
| */ |
| INT WINAPI GetKeyNameTextW(LONG lParam, LPWSTR lpBuffer, INT nSize) |
| { |
| LPSTR buf = HEAP_xalloc( GetProcessHeap(), 0, nSize ); |
| int res = GetKeyNameTextA(lParam,buf,nSize); |
| |
| lstrcpynAtoW(lpBuffer,buf,nSize); |
| HeapFree( GetProcessHeap(), 0, buf ); |
| return res; |
| } |
| |
| /**************************************************************************** |
| * ToAscii32 (USER32.546) |
| */ |
| INT WINAPI ToAscii( UINT virtKey,UINT scanCode,LPBYTE lpKeyState, |
| LPWORD lpChar,UINT flags ) |
| { |
| return ToAscii16(virtKey,scanCode,lpKeyState,lpChar,flags); |
| } |
| |
| /**************************************************************************** |
| * ToAscii32 (USER32.547) |
| */ |
| INT WINAPI ToAsciiEx( UINT virtKey, UINT scanCode, LPBYTE lpKeyState, |
| LPWORD lpChar, UINT flags, HKL dwhkl ) |
| { |
| /* FIXME: need true implementation */ |
| return ToAscii16(virtKey,scanCode,lpKeyState,lpChar,flags); |
| } |
| |
| /********************************************************************** |
| * ActivateKeyboardLayout32 (USER32.1) |
| * |
| * Call ignored. WINE supports only system default keyboard layout. |
| */ |
| HKL WINAPI ActivateKeyboardLayout(HKL hLayout, UINT flags) |
| { |
| TRACE(keyboard, "(%d, %d)\n", hLayout, flags); |
| ERR(keyboard,"Only default system keyboard layout supported. Call ignored.\n"); |
| return 0; |
| } |
| |
| |
| /*********************************************************************** |
| * GetKeyboardLayoutList (USER32.251) |
| * |
| * FIXME: Supports only the system default language and layout and |
| * returns only 1 value. |
| * |
| * Return number of values available if either input parm is |
| * 0, per MS documentation. |
| * |
| */ |
| INT WINAPI GetKeyboardLayoutList(INT nBuff,HKL *layouts) |
| { |
| TRACE(keyboard,"(%d,%p)\n",nBuff,layouts); |
| if (!nBuff || !layouts) |
| return 1; |
| if (layouts) |
| layouts[0] = GetKeyboardLayout(0); |
| return 1; |
| } |
| |
| |
| /*********************************************************************** |
| * RegisterHotKey (USER32.433) |
| */ |
| BOOL WINAPI RegisterHotKey(HWND hwnd,INT id,UINT modifiers,UINT vk) { |
| FIXME(keyboard,"(0x%08x,%d,0x%08x,%d): stub\n",hwnd,id,modifiers,vk); |
| return TRUE; |
| } |
| |
| /*********************************************************************** |
| * UnregisterHotKey (USER32.565) |
| */ |
| BOOL WINAPI UnregisterHotKey(HWND hwnd,INT id) { |
| FIXME(keyboard,"(0x%08x,%d): stub\n",hwnd,id); |
| return TRUE; |
| } |
| |
| |
| /*********************************************************************** |
| * ToUnicode32 (USER32.548) |
| */ |
| INT WINAPI ToUnicode( |
| UINT wVirtKey, |
| UINT wScanCode, |
| PBYTE lpKeyState, |
| LPWSTR pwszBuff, |
| int cchBuff, |
| UINT wFlags) { |
| |
| FIXME(keyboard,": stub\n"); |
| return 0; |
| } |
| |
| /*********************************************************************** |
| * LoadKeyboardLayout32A (USER32.367) |
| * Call ignored. WINE supports only system default keyboard layout. |
| */ |
| HKL WINAPI LoadKeyboardLayoutA(LPCSTR pwszKLID, UINT Flags) |
| { |
| TRACE(keyboard, "(%s, %d)\n", pwszKLID, Flags); |
| ERR(keyboard,"Only default system keyboard layout supported. Call ignored.\n"); |
| return 0; |
| } |
| |
| /*********************************************************************** |
| * LoadKeyboardLayout32W (USER32.368) |
| */ |
| HKL WINAPI LoadKeyboardLayoutW(LPCWSTR pwszKLID, UINT Flags) |
| { |
| LPSTR buf = HEAP_xalloc( GetProcessHeap(), 0, strlen("00000409")+1); |
| int res; |
| lstrcpynWtoA(buf,pwszKLID,8); |
| buf[8] = 0; |
| res = LoadKeyboardLayoutA(buf, Flags); |
| HeapFree( GetProcessHeap(), 0, buf ); |
| return res; |
| } |