|  | /* | 
|  | * KEYBOARD driver | 
|  | * | 
|  | * 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 "windef.h" | 
|  | #include "winbase.h" | 
|  | #include "wingdi.h" | 
|  | #include "winuser.h" | 
|  | #include "wine/keyboard16.h" | 
|  | #include "win.h" | 
|  | #include "heap.h" | 
|  | #include "keyboard.h" | 
|  | #include "user.h" | 
|  | #include "message.h" | 
|  | #include "callback.h" | 
|  | #include "builtin16.h" | 
|  | #include "debugtools.h" | 
|  | #include "winerror.h" | 
|  |  | 
|  | DEFAULT_DEBUG_CHANNEL(keyboard); | 
|  | DECLARE_DEBUG_CHANNEL(event); | 
|  |  | 
|  | /**********************************************************************/ | 
|  |  | 
|  | static LPKEYBD_EVENT_PROC DefKeybEventProc = NULL; | 
|  | LPBYTE pKeyStateTable = NULL; | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		Inquire (KEYBOARD.1) | 
|  | */ | 
|  | WORD WINAPI KEYBOARD_Inquire(LPKBINFO kbInfo) | 
|  | { | 
|  | kbInfo->Begin_First_Range = 0; | 
|  | kbInfo->End_First_Range = 0; | 
|  | kbInfo->Begin_Second_Range = 0; | 
|  | kbInfo->End_Second_Range = 0; | 
|  | kbInfo->StateSize = 16; | 
|  |  | 
|  | return sizeof(KBINFO); | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		Enable (KEYBOARD.2) | 
|  | */ | 
|  | VOID WINAPI KEYBOARD_Enable( LPKEYBD_EVENT_PROC lpKeybEventProc, | 
|  | LPBYTE lpKeyState ) | 
|  | { | 
|  | static BOOL initDone = FALSE; | 
|  |  | 
|  | THUNK_Free( (FARPROC)DefKeybEventProc ); | 
|  |  | 
|  | DefKeybEventProc = lpKeybEventProc; | 
|  | pKeyStateTable = lpKeyState; | 
|  |  | 
|  | /* all states to false */ | 
|  | memset( lpKeyState, 0, 256 ); | 
|  |  | 
|  | if (!initDone) USER_Driver.pInitKeyboard(); | 
|  | initDone = TRUE; | 
|  | } | 
|  |  | 
|  | /**********************************************************************/ | 
|  |  | 
|  | static VOID WINAPI KEYBOARD_CallKeybdEventProc( FARPROC16 proc, | 
|  | BYTE bVk, BYTE bScan, | 
|  | DWORD dwFlags, DWORD dwExtraInfo ) | 
|  | { | 
|  | CONTEXT86 context; | 
|  |  | 
|  | memset( &context, 0, sizeof(context) ); | 
|  | context.SegCs = SELECTOROF( proc ); | 
|  | context.Eip   = OFFSETOF( proc ); | 
|  | context.Eax   = bVk | ((dwFlags & KEYEVENTF_KEYUP)? 0x8000 : 0); | 
|  | context.Ebx   = bScan | ((dwFlags & KEYEVENTF_EXTENDEDKEY) ? 0x100 : 0); | 
|  | context.Esi   = LOWORD( dwExtraInfo ); | 
|  | context.Edi   = HIWORD( dwExtraInfo ); | 
|  |  | 
|  | wine_call_to_16_regs_short( &context, 0 ); | 
|  | } | 
|  |  | 
|  | /**********************************************************************/ | 
|  |  | 
|  | VOID WINAPI WIN16_KEYBOARD_Enable( FARPROC16 proc, LPBYTE lpKeyState ) | 
|  | { | 
|  | LPKEYBD_EVENT_PROC thunk = | 
|  | (LPKEYBD_EVENT_PROC)THUNK_Alloc( proc, (RELAY)KEYBOARD_CallKeybdEventProc ); | 
|  |  | 
|  | KEYBOARD_Enable( thunk, lpKeyState ); | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		Disable (KEYBOARD.3) | 
|  | */ | 
|  | VOID WINAPI KEYBOARD_Disable(VOID) | 
|  | { | 
|  | THUNK_Free( (FARPROC)DefKeybEventProc ); | 
|  |  | 
|  | DefKeybEventProc = NULL; | 
|  | pKeyStateTable = NULL; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *           KEYBOARD_SendEvent | 
|  | */ | 
|  | void KEYBOARD_SendEvent( BYTE bVk, BYTE bScan, DWORD dwFlags, | 
|  | DWORD posX, DWORD posY, DWORD time ) | 
|  | { | 
|  | WINE_KEYBDEVENT wke; | 
|  | int iWndsLocks; | 
|  |  | 
|  | if ( !DefKeybEventProc ) return; | 
|  |  | 
|  | TRACE_(event)("(%d,%d,%04lX)\n", bVk, bScan, dwFlags ); | 
|  |  | 
|  | wke.magic = WINE_KEYBDEVENT_MAGIC; | 
|  | wke.posX  = posX; | 
|  | wke.posY  = posY; | 
|  | wke.time  = time; | 
|  |  | 
|  | /* To avoid deadlocks, we have to suspend all locks on windows structures | 
|  | before the program control is passed to the keyboard driver */ | 
|  | iWndsLocks = WIN_SuspendWndsLock(); | 
|  | DefKeybEventProc( bVk, bScan, dwFlags, (DWORD)&wke ); | 
|  | WIN_RestoreWndsLock(iWndsLocks); | 
|  | } | 
|  |  | 
|  | /********************************************************************** | 
|  | *		SetSpeed (KEYBOARD.7) | 
|  | */ | 
|  | WORD WINAPI SetSpeed16(WORD unused) | 
|  | { | 
|  | FIXME("(%04x): stub\n", unused); | 
|  | return 0xffff; | 
|  | } | 
|  |  | 
|  | /********************************************************************** | 
|  | *		ScreenSwitchEnable (KEYBOARD.100) | 
|  | */ | 
|  | VOID WINAPI ScreenSwitchEnable16(WORD unused) | 
|  | { | 
|  | FIXME("(%04x): stub\n", unused); | 
|  | } | 
|  |  | 
|  | /********************************************************************** | 
|  | *		OemKeyScan (KEYBOARD.128) | 
|  | *		OemKeyScan (USER32.@) | 
|  | */ | 
|  | DWORD WINAPI OemKeyScan(WORD wOemChar) | 
|  | { | 
|  | TRACE("*OemKeyScan (%d)\n", wOemChar); | 
|  |  | 
|  | return wOemChar; | 
|  | } | 
|  |  | 
|  | /********************************************************************** | 
|  | *		VkKeyScan (KEYBOARD.129) | 
|  | * | 
|  | * VkKeyScan translates an ANSI character to a virtual-key and shift code | 
|  | * for the current keyboard. | 
|  | * high-order byte yields : | 
|  | *	0	Unshifted | 
|  | *	1	Shift | 
|  | *	2	Ctrl | 
|  | *	3-5	Shift-key combinations that are not used for characters | 
|  | *	6	Ctrl-Alt | 
|  | *	7	Ctrl-Alt-Shift | 
|  | *	I.e. :	Shift = 1, Ctrl = 2, Alt = 4. | 
|  | * FIXME : works ok except for dead chars : | 
|  | * VkKeyScan '^'(0x5e, 94) ... got keycode 00 ... returning 00 | 
|  | * VkKeyScan '`'(0x60, 96) ... got keycode 00 ... returning 00 | 
|  | */ | 
|  |  | 
|  | WORD WINAPI VkKeyScan16(CHAR cChar) | 
|  | { | 
|  | return USER_Driver.pVkKeyScan(cChar); | 
|  | } | 
|  |  | 
|  | /****************************************************************************** | 
|  | *		GetKeyboardType (KEYBOARD.130) | 
|  | */ | 
|  | INT16 WINAPI GetKeyboardType16(INT16 nTypeFlag) | 
|  | { | 
|  | TRACE("(%d)\n", nTypeFlag); | 
|  | switch(nTypeFlag) | 
|  | { | 
|  | case 0:      /* Keyboard type */ | 
|  | return 4;    /* AT-101 */ | 
|  | break; | 
|  | case 1:      /* Keyboard Subtype */ | 
|  | return 0;    /* There are no defined subtypes */ | 
|  | break; | 
|  | case 2:      /* Number of F-keys */ | 
|  | return 12;   /* We're doing an 101 for now, so return 12 F-keys */ | 
|  | break; | 
|  | default: | 
|  | WARN("Unknown type\n"); | 
|  | return 0;    /* The book says 0 here, so 0 */ | 
|  | } | 
|  | } | 
|  |  | 
|  | /****************************************************************************** | 
|  | *		MapVirtualKey (KEYBOARD.131) | 
|  | * | 
|  | * MapVirtualKey translates keycodes from one format to another | 
|  | */ | 
|  | UINT16 WINAPI MapVirtualKey16(UINT16 wCode, UINT16 wMapType) | 
|  | { | 
|  | return USER_Driver.pMapVirtualKey(wCode,wMapType); | 
|  | } | 
|  |  | 
|  | /**************************************************************************** | 
|  | *		GetKBCodePage (KEYBOARD.132) | 
|  | */ | 
|  | INT16 WINAPI GetKBCodePage16(void) | 
|  | { | 
|  | return GetKBCodePage(); | 
|  | } | 
|  |  | 
|  | /**************************************************************************** | 
|  | *		GetKeyNameText (KEYBOARD.133) | 
|  | */ | 
|  | INT16 WINAPI GetKeyNameText16(LONG lParam, LPSTR lpBuffer, INT16 nSize) | 
|  | { | 
|  | return USER_Driver.pGetKeyNameText(lParam, lpBuffer, nSize); | 
|  | } | 
|  |  | 
|  | /**************************************************************************** | 
|  | *		ToAscii (KEYBOARD.4) | 
|  | * | 
|  | * The ToAscii function translates the specified virtual-key code and keyboard | 
|  | * state to the corresponding Windows character or characters. | 
|  | * | 
|  | * If the specified key is a dead key, the return value is negative. Otherwise, | 
|  | * it is one of the following values: | 
|  | * Value	Meaning | 
|  | * 0	The specified virtual key has no translation for the current state of the keyboard. | 
|  | * 1	One Windows character was copied to the buffer. | 
|  | * 2	Two characters were copied to the buffer. This usually happens when a | 
|  | *      dead-key character (accent or diacritic) stored in the keyboard layout cannot | 
|  | *      be composed with the specified virtual key to form a single character. | 
|  | * | 
|  | * FIXME : should do the above (return 2 for non matching deadchar+char combinations) | 
|  | * | 
|  | */ | 
|  | INT16 WINAPI ToAscii16(UINT16 virtKey,UINT16 scanCode, LPBYTE lpKeyState, | 
|  | LPVOID lpChar, UINT16 flags) | 
|  | { | 
|  | return ToAscii( virtKey, scanCode, lpKeyState, lpChar, flags ); | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		MessageBeep (USER.104) | 
|  | */ | 
|  | void WINAPI MessageBeep16( UINT16 i ) | 
|  | { | 
|  | MessageBeep( i ); | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		MessageBeep (USER32.@) | 
|  | */ | 
|  | BOOL WINAPI MessageBeep( UINT i ) | 
|  | { | 
|  | BOOL active = TRUE; | 
|  | SystemParametersInfoA( SPI_GETBEEP, 0, &active, FALSE ); | 
|  | if (active) USER_Driver.pBeep(); | 
|  | return TRUE; | 
|  | } |