Keyboard/mouse event proc thunk creation moved out of if1632/thunk.c.
[wine] / windows / keyboard.c
1 /*
2  * KEYBOARD driver
3  *
4  * Copyright 1993 Bob Amstadt
5  * Copyright 1996 Albrecht Kleine 
6  * Copyright 1997 David Faure
7  * Copyright 1998 Morten Welinder
8  * Copyright 1998 Ulrich Weigand
9  *
10  */
11
12 #include <stdlib.h>
13 #include <string.h>
14 #include <ctype.h>
15
16 #include "winuser.h"
17 #include "wine/keyboard16.h"
18 #include "win.h"
19 #include "heap.h"
20 #include "keyboard.h"
21 #include "message.h"
22 #include "callback.h"
23 #include "builtin16.h"
24 #include "debugtools.h"
25 #include "struct32.h"
26 #include "winerror.h"
27
28 DECLARE_DEBUG_CHANNEL(event)
29 DECLARE_DEBUG_CHANNEL(keyboard)
30
31 /**********************************************************************/
32
33 KEYBOARD_DRIVER *KEYBOARD_Driver = NULL;
34
35 static LPKEYBD_EVENT_PROC DefKeybEventProc = NULL;
36 LPBYTE pKeyStateTable = NULL;
37
38 /***********************************************************************
39  *           KEYBOARD_Inquire                   (KEYBOARD.1)
40  */
41 WORD WINAPI KEYBOARD_Inquire(LPKBINFO kbInfo) 
42 {
43   kbInfo->Begin_First_Range = 0;
44   kbInfo->End_First_Range = 0;
45   kbInfo->Begin_Second_Range = 0;
46   kbInfo->End_Second_Range = 0;
47   kbInfo->StateSize = 16; 
48   
49   return sizeof(KBINFO);
50 }
51
52 /***********************************************************************
53  *           KEYBOARD_Enable                    (KEYBOARD.2)
54  */
55 VOID WINAPI KEYBOARD_Enable( LPKEYBD_EVENT_PROC lpKeybEventProc, 
56                              LPBYTE lpKeyState )
57 {
58   static BOOL initDone = FALSE;
59
60   THUNK_Free( (FARPROC)DefKeybEventProc );
61   
62   DefKeybEventProc = lpKeybEventProc;
63   pKeyStateTable = lpKeyState;
64   
65   /* all states to false */
66   memset( lpKeyState, 0, sizeof(lpKeyState) );
67   
68   if (!initDone) KEYBOARD_Driver->pInit();
69   initDone = TRUE;
70 }
71
72 static VOID WINAPI KEYBOARD_CallKeybdEventProc( FARPROC16 proc,
73                                                 BYTE bVk, BYTE bScan,
74                                                 DWORD dwFlags, DWORD dwExtraInfo )
75 {
76     CONTEXT86 context;
77
78     memset( &context, 0, sizeof(context) );
79     CS_reg(&context)  = SELECTOROF( proc );
80     EIP_reg(&context) = OFFSETOF( proc );
81     AH_reg(&context)  = (dwFlags & KEYEVENTF_KEYUP)? 0x80 : 0;
82     AL_reg(&context)  = bVk;
83     BH_reg(&context)  = (dwFlags & KEYEVENTF_EXTENDEDKEY)? 1 : 0;
84     BL_reg(&context)  = bScan;
85     SI_reg(&context)  = LOWORD( dwExtraInfo );
86     DI_reg(&context)  = HIWORD( dwExtraInfo );
87
88     CallTo16RegisterShort( &context, 0 );
89 }
90
91 VOID WINAPI WIN16_KEYBOARD_Enable( FARPROC16 proc, LPBYTE lpKeyState )
92 {
93     LPKEYBD_EVENT_PROC thunk = 
94       (LPKEYBD_EVENT_PROC)THUNK_Alloc( proc, (RELAY)KEYBOARD_CallKeybdEventProc );
95
96     KEYBOARD_Enable( thunk, lpKeyState );
97 }
98
99 /***********************************************************************
100  *           KEYBOARD_Disable                   (KEYBOARD.3)
101  */
102 VOID WINAPI KEYBOARD_Disable(VOID)
103 {
104   THUNK_Free( (FARPROC)DefKeybEventProc );
105   
106   DefKeybEventProc = NULL;
107   pKeyStateTable = NULL;
108 }
109
110 /***********************************************************************
111  *           KEYBOARD_SendEvent
112  */
113 void KEYBOARD_SendEvent( BYTE bVk, BYTE bScan, DWORD dwFlags,
114                          DWORD posX, DWORD posY, DWORD time )
115 {
116   WINE_KEYBDEVENT wke;
117   int iWndsLocks;
118   
119   if ( !DefKeybEventProc ) return;
120   
121   TRACE_(event)("(%d,%d,%04lX)\n", bVk, bScan, dwFlags );
122   
123   wke.magic = WINE_KEYBDEVENT_MAGIC;
124   wke.posX  = posX;
125   wke.posY  = posY;
126   wke.time  = time;
127   
128   /* To avoid deadlocks, we have to suspend all locks on windows structures
129      before the program control is passed to the keyboard driver */
130   iWndsLocks = WIN_SuspendWndsLock();
131   DefKeybEventProc( bVk, bScan, dwFlags, (DWORD)&wke );
132   WIN_RestoreWndsLock(iWndsLocks);
133 }
134
135 /**********************************************************************
136  *           SetSpeed16      (KEYBOARD.7)
137  */
138 WORD WINAPI SetSpeed16(WORD unused)
139 {
140     FIXME_(keyboard)("(%04x): stub\n",unused);
141     return 0xffff;
142 }
143
144 /**********************************************************************
145  *           ScreenSwitchEnable      (KEYBOARD.100)
146  */
147 VOID WINAPI ScreenSwitchEnable16(WORD unused)
148 {
149   FIXME_(keyboard)("(%04x): stub\n",unused);
150 }
151
152 /**********************************************************************
153  *           OemKeyScan      (KEYBOARD.128)(USER32.401)
154  */
155 DWORD WINAPI OemKeyScan(WORD wOemChar)
156 {
157   TRACE_(keyboard)("*OemKeyScan (%d)\n",wOemChar);
158
159   return wOemChar;
160 }
161
162 /**********************************************************************
163  *      VkKeyScan                       [KEYBOARD.129]
164  */
165 /* VkKeyScan translates an ANSI character to a virtual-key and shift code
166  * for the current keyboard.
167  * high-order byte yields :
168  *      0       Unshifted
169  *      1       Shift
170  *      2       Ctrl
171  *      3-5     Shift-key combinations that are not used for characters
172  *      6       Ctrl-Alt
173  *      7       Ctrl-Alt-Shift
174  *      I.e. :  Shift = 1, Ctrl = 2, Alt = 4.
175  * FIXME : works ok except for dead chars :
176  * VkKeyScan '^'(0x5e, 94) ... got keycode 00 ... returning 00
177  * VkKeyScan '`'(0x60, 96) ... got keycode 00 ... returning 00
178  */
179
180 WORD WINAPI VkKeyScan16(CHAR cChar)
181 {
182   return KEYBOARD_Driver->pVkKeyScan(cChar);
183 }
184
185 /******************************************************************************
186  *      GetKeyboardType16      (KEYBOARD.130)
187  */
188 INT16 WINAPI GetKeyboardType16(INT16 nTypeFlag)
189 {
190   TRACE_(keyboard)("(%d)\n",nTypeFlag);
191   switch(nTypeFlag)
192     {
193     case 0:      /* Keyboard type */
194       return 4;    /* AT-101 */
195       break;
196     case 1:      /* Keyboard Subtype */
197       return 0;    /* There are no defined subtypes */
198       break;
199     case 2:      /* Number of F-keys */
200       return 12;   /* We're doing an 101 for now, so return 12 F-keys */
201       break;
202     default:     
203       WARN_(keyboard)("Unknown type\n");
204       return 0;    /* The book says 0 here, so 0 */
205     }
206 }
207
208 /******************************************************************************
209  *      MapVirtualKey16      (KEYBOARD.131)
210  *
211  * MapVirtualKey translates keycodes from one format to another
212  */
213 UINT16 WINAPI MapVirtualKey16(UINT16 wCode, UINT16 wMapType)
214 {
215   return KEYBOARD_Driver->pMapVirtualKey(wCode,wMapType);
216 }
217
218 /****************************************************************************
219  *      GetKBCodePage16   (KEYBOARD.132)
220  */
221 INT16 WINAPI GetKBCodePage16(void)
222 {
223   TRACE_(keyboard)("(void)\n");
224   return 850;
225 }
226
227 /****************************************************************************
228  *      GetKeyNameText16   (KEYBOARD.133)
229  */
230 INT16 WINAPI GetKeyNameText16(LONG lParam, LPSTR lpBuffer, INT16 nSize)
231 {
232   return KEYBOARD_Driver->pGetKeyNameText(lParam, lpBuffer, nSize);
233 }
234
235 /****************************************************************************
236  *      ToAscii   (KEYBOARD.4)
237  *
238  * The ToAscii function translates the specified virtual-key code and keyboard
239  * state to the corresponding Windows character or characters.
240  *
241  * If the specified key is a dead key, the return value is negative. Otherwise,
242  * it is one of the following values:
243  * Value        Meaning
244  * 0    The specified virtual key has no translation for the current state of the keyboard.
245  * 1    One Windows character was copied to the buffer.
246  * 2    Two characters were copied to the buffer. This usually happens when a
247  *      dead-key character (accent or diacritic) stored in the keyboard layout cannot
248  *      be composed with the specified virtual key to form a single character.
249  *
250  * FIXME : should do the above (return 2 for non matching deadchar+char combinations)
251  *
252  */
253 INT16 WINAPI ToAscii16(UINT16 virtKey,UINT16 scanCode, LPBYTE lpKeyState, 
254                        LPVOID lpChar, UINT16 flags) 
255 {
256     return KEYBOARD_Driver->pToAscii(
257         virtKey, scanCode, lpKeyState, lpChar, flags
258     );
259 }
260
261 /***********************************************************************
262  *              KEYBOARD_GetBeepActive
263  */
264 BOOL KEYBOARD_GetBeepActive()
265 {
266   return KEYBOARD_Driver->pGetBeepActive();
267 }
268
269 /***********************************************************************
270  *              KEYBOARD_SetBeepActive
271  */
272 void KEYBOARD_SetBeepActive(BOOL bActivate)
273 {
274   KEYBOARD_Driver->pSetBeepActive(bActivate);
275 }
276
277 /***********************************************************************
278  *              KEYBOARD_Beep
279  */
280 void KEYBOARD_Beep(void)
281 {
282   KEYBOARD_Driver->pBeep();
283 }
284