00001 /****************************** Module Header ******************************\, 00002 * Module Name: kbd.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * OEM-specific tables and routines for IBM Extended 101/102 style keyboards 00007 * 00008 * History: 00009 * 30-04-91 IanJa Created. 00010 \***************************************************************************/ 00011 00012 #include "precomp.h" 00013 #pragma hdrstop 00014 00015 00016 /***************************************************************************\ 00017 * aVkToVsc[] - table associating Virtual Key codes with Virtual Scancodes 00018 * 00019 * Ordered, 0-terminated. 00020 * 00021 * This is used for those Virtual Keys that do not appear in ausVK_???[] 00022 * These are not the base Virtual Keys. They require some modifier key 00023 * depression (CTRL, ALT, SHIFT) or NumLock On to be generated. 00024 * 00025 * All the scancodes listed below should be marked KBDMULTIVK or KBDNUMPAD in 00026 * ausVK_???[]. 00027 * 00028 * This table is used by MapVirtualKey(wVk, 0). 00029 \***************************************************************************/ 00030 BYTE aVkNumpad[] = { 00031 VK_NUMPAD7, VK_NUMPAD8, VK_NUMPAD9, 0xFF, // 0x47 0x48 0x49 (0x4A) 00032 VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, 0xFF, // 0x4B 0x4C 0x4D (0x4E) 00033 VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, // 0x4F 0x50 0x51 00034 VK_NUMPAD0, VK_DECIMAL, 0 // 0x50 0x51 00035 }; 00036 00037 /***************************************************************************\ 00038 * How some Virtual Key values change when a SHIFT key is held down. 00039 \***************************************************************************/ 00040 ULONG aulShiftCvt_VK[] = { 00041 MAKELONG(VK_MULTIPLY, VK_SNAPSHOT), 00042 MAKELONG(0,0) 00043 }; 00044 00045 // JPN IMB02 00046 ULONG aulShiftControlCvt_VK_IBM02[] = { 00047 MAKELONG(VK_SCROLL, VK_CANCEL | KBDEXT), 00048 MAKELONG(VK_NUMLOCK, VK_PAUSE | KBDEXT), 00049 MAKELONG(0,0) 00050 }; 00051 00052 /***************************************************************************\ 00053 * How some Virtual Key values change when a CONTROL key is held down. 00054 \***************************************************************************/ 00055 ULONG aulControlCvt_VK[] = { 00056 MAKELONG(VK_NUMLOCK, VK_PAUSE | KBDEXT), 00057 MAKELONG(VK_SCROLL, VK_CANCEL), 00058 MAKELONG(0,0) 00059 }; 00060 00061 // JPN IBM02 00062 ULONG aulControlCvt_VK_IBM02[] = { 00063 MAKELONG(VK_PAUSE, VK_CANCEL | KBDEXT), 00064 MAKELONG(VK_SCROLL, VK_CANCEL | KBDEXT), 00065 MAKELONG(0,0) 00066 }; 00067 00068 /***************************************************************************\ 00069 * How some Virtual Key values change when an ALT key is held down. 00070 * The SHIFT and ALT keys both alter VK values the same way!! 00071 \***************************************************************************/ 00072 #define aulAltCvt_VK aulShiftCvt_VK 00073 00074 00075 /***************************************************************************\ 00076 * This table list keys that may affect Virtual Key values when held down. 00077 * 00078 * See kbd.h for a full description. 00079 * 00080 * 101/102key keyboard (type 4): 00081 * Virtual Key values vary only if CTRL is held down. 00082 * 84-86 key keyboards (type 3): 00083 * Virtual Key values vary if one of SHIFT, CTRL or ALT is held down. 00084 \***************************************************************************/ 00085 00086 VK_TO_BIT aVkToBits_VK[] = { 00087 { VK_SHIFT, KBDSHIFT }, // 0x01 00088 { VK_CONTROL, KBDCTRL }, // 0x02 00089 { VK_MENU, KBDALT }, // 0x04 00090 { 0, 0 } 00091 }; 00092 00093 // JPN IBM02 00094 VK_TO_BIT aVkToBits_VK_IBM02[] = { 00095 { VK_SHIFT, KBDSHIFT }, // 0x01 00096 { VK_CONTROL, KBDCTRL }, // 0x02 00097 { 0, 0 } 00098 }; 00099 00100 /***************************************************************************\ 00101 * Tables defining how some Virtual Key values are modified when other keys 00102 * are held down. 00103 * Translates key combinations into indices for gapulCvt_VK_101[] or for 00104 * gapulCvt_VK_84[] or for 00105 * 00106 * See kbd.h for a full description. 00107 * 00108 \***************************************************************************/ 00109 00110 MODIFIERS Modifiers_VK_STANDARD = { 00111 &aVkToBits_VK[0], 00112 4, // Maximum modifier bitmask/index 00113 { 00114 SHFT_INVALID, // no keys held down (no VKs are modified) 00115 0, // SHIFT held down 84-86 key kbd 00116 1, // CTRL held down 101/102 key kbd 00117 SHFT_INVALID, // CTRL-SHIFT held down (no VKs are modified) 00118 2 // ALT held down 84-86 key kbd 00119 } 00120 }; 00121 00122 MODIFIERS Modifiers_VK_IBM02 = { 00123 &aVkToBits_VK_IBM02[0], 00124 3, // Maximum modifier bitmask/index 00125 { 00126 SHFT_INVALID, // no modifier keys (no VK modification) 00127 SHFT_INVALID, // Shift (no VK modification) 00128 0, // Control (VK modification number 0) 00129 1 // Control Shift (VK modification number 1) 00130 } 00131 }; 00132 00133 /***************************************************************************\ 00134 * A tables of pointers indexed by the number obtained from Modify_VK. 00135 * If a pointer is non-NULL then the table it points to is searched for 00136 * Virtual Key that should have their values changed. 00137 * There are two versions: one for 84-86 key kbds, one for 101/102 key kbds. 00138 * gapulCvt_VK is initialized with the default (101/102 key kbd). 00139 \***************************************************************************/ 00140 ULONG *gapulCvt_VK_101[] = { 00141 NULL, // No VKs are changed by SHIFT being held down 00142 aulControlCvt_VK, // Some VKs are changed by CTRL being held down 00143 NULL // No VKs are changed by ALT being held down 00144 }; 00145 00146 ULONG *gapulCvt_VK_84[] = { 00147 aulShiftCvt_VK, // Some VKs are changed by SHIFT being held down 00148 aulControlCvt_VK, // Some VKs are changed by CTRL being held down 00149 aulAltCvt_VK // Some VKs are changed by ALT being held down 00150 }; 00151 00152 ULONG *gapulCvt_VK_IBM02[] = { 00153 aulControlCvt_VK_IBM02, // VK modification number 0 (Control key) 00154 aulShiftControlCvt_VK_IBM02,// VK modification number 1 (Shift Control key) 00155 }; 00156 00157 PULONG *gapulCvt_VK = gapulCvt_VK_101; 00158 00159 PMODIFIERS gpModifiers_VK = &Modifiers_VK_STANDARD; 00160 00161 /***************************************************************************\ 00162 * The table ausNumPadCvt is used to convert a cursor movement 00163 * virtual key value (obtained from ausVK_???[]) into a VK_NUMPAD 00164 * virtual key value. This translation is done when NumLock is 00165 * on and no shift keys are pressed. 00166 \***************************************************************************/ 00167 USHORT ausNumPadCvt[] = 00168 { 00169 MAKEWORD(VK_INSERT, VK_NUMPAD0), 00170 MAKEWORD(VK_END, VK_NUMPAD1), 00171 MAKEWORD(VK_DOWN, VK_NUMPAD2), 00172 MAKEWORD(VK_NEXT, VK_NUMPAD3), 00173 MAKEWORD(VK_LEFT, VK_NUMPAD4), 00174 MAKEWORD(VK_CLEAR, VK_NUMPAD5), 00175 MAKEWORD(VK_RIGHT, VK_NUMPAD6), 00176 MAKEWORD(VK_HOME, VK_NUMPAD7), 00177 MAKEWORD(VK_UP, VK_NUMPAD8), 00178 MAKEWORD(VK_PRIOR, VK_NUMPAD9), 00179 MAKEWORD(VK_DELETE, VK_DECIMAL), 00180 MAKEWORD(0, 0) 00181 }; 00182 00183 /***************************************************************************\ 00184 * xxxNumpadCursor() - handle special case Numpad Cursor-movement Keys 00185 * 00186 * If NumLock is on, and Shift is up then: 00187 * VK_INSERT -> VK_NUMPAD0 00188 * VK_END -> VK_NUMPAD1 00189 * VK_DOWN -> VK_NUMPAD2 00190 * VK_NEXT -> VK_NUMPAD3 00191 * VK_LEFT -> VK_NUMPAD4 00192 * VK_CLEAR -> VK_NUMPAD5 00193 * VK_RIGHT -> VK_NUMPAD6 00194 * VK_HOME -> VK_NUMPAD7 00195 * VK_UP -> VK_NUMPAD8 00196 * VK_PRIOR -> VK_NUMPAD9 00197 * VK_DELETE -> VK_DECIMAL (unless CTRL-ALT-DEL) 00198 * If Numlock is on, and Shift is down then precede first Numpad Cursor key 00199 * going down with a fake Shift key coming up & follow the Numpad Cursor key 00200 * coming up with with a fake Shift key going down. 00201 * 00202 * Return value: 00203 * TRUE: keep this routine active: continue passing Key Events through here 00204 * FALSE: deactivet this routine: stop sending Key Events through here. 00205 * 00206 * This function will leave the critical section only if low level hooks 00207 * are installed and the call to xxxKeyEvent is made 00208 * 00209 \***************************************************************************/ 00210 BOOL 00211 xxxNumpadCursor( 00212 PKE pKe) 00213 { 00214 static BYTE bLastNumpadCursor = 0; 00215 static USHORT VkFakedShiftUp; // VK_LSHIFT or VK_RSHIFT 00216 static BYTE VscFakedShiftUp; // 0x2A or 0x36 resp. 00217 int i; 00218 00219 CheckCritIn(); 00220 00221 if (bLastNumpadCursor) { 00222 if (bLastNumpadCursor == (BYTE)(pKe->usFlaggedVk)) { 00223 /* 00224 * Same key as last one: if coming up, or going down? 00225 */ 00226 if (pKe->usFlaggedVk & KBDBREAK) { 00227 /* 00228 * Numpad Cursor key came back up. Send this key now, and make 00229 * sure that the Shift key will then appear to go back down 00230 * again. 00231 */ 00232 xxxKeyEvent(pKe->usFlaggedVk, pKe->bScanCode, 00233 pKe->dwTime, 0, FALSE); 00234 bLastNumpadCursor = 0; 00235 pKe->usFlaggedVk = VkFakedShiftUp; 00236 pKe->bScanCode = VscFakedShiftUp; 00237 } 00238 /* 00239 * Going down: this key is repeating, so just pass it on 00240 * unaltered and keep the KEProc active 00241 */ 00242 return TRUE; 00243 } else { 00244 /* 00245 * It is a different key. Fake the Shift key back down again, 00246 * and continue (it may be another Numpad Cursor key) 00247 */ 00248 xxxKeyEvent(VkFakedShiftUp, 00249 (WORD)(VscFakedShiftUp | SCANCODE_SIMULATED), 00250 pKe->dwTime, 0, FALSE); 00251 bLastNumpadCursor = 0; 00252 } 00253 } 00254 00255 if (pKe->usFlaggedVk & KBDNUMPAD) { 00256 00257 UINT fsModifiers; 00258 /* 00259 * This is the numeric pad. 00260 * Here, if NumLock is set, we change the virtual keycodes to 00261 * numeric VK_NUMPAD codes, so the keys will be translated 00262 * as numbers etc. But if a shift key is down, we handle 00263 * these as cursor keys, but we need to make sure that these 00264 * are seen as UNSHIFTED 00265 */ 00266 00267 /* 00268 * Check for SAS. 00269 */ 00270 if (IsSAS((BYTE)(pKe->usFlaggedVk), &fsModifiers)) { 00271 return TRUE; 00272 } else if (TestRawKeyToggle(VK_NUMLOCK)) { 00273 if (TestRawKeyDown(VK_SHIFT)) { 00274 /* 00275 * key is down (bit(s) set in BIOS key state), so we are going 00276 * to keep this as a cursor key. To do this, we need to 00277 * make sure that Windows' state vector entry for VK_SHIFT is 00278 * OFF even though a shift key is actually down. 00279 */ 00280 bLastNumpadCursor = (BYTE)(pKe->usFlaggedVk); 00281 if (TestRawKeyDown(VK_RSHIFT)) { 00282 VkFakedShiftUp = VK_RSHIFT | KBDEXT; 00283 VscFakedShiftUp = 0x36; 00284 } else { 00285 VkFakedShiftUp = VK_LSHIFT; 00286 VscFakedShiftUp = 0x2A; 00287 } 00288 xxxKeyEvent((USHORT)(VkFakedShiftUp | KBDBREAK), 00289 (WORD)(VscFakedShiftUp | SCANCODE_SIMULATED), 00290 pKe->dwTime, 0, FALSE); 00291 return TRUE; 00292 } 00293 00294 /* 00295 * NumLock ON but Shift key up: Alter the Virtual Key event, 00296 * but not for injected virtual keys. 00297 */ 00298 if ((pKe->usFlaggedVk & KBDINJECTEDVK) == 0) { 00299 for (i = 0; ausNumPadCvt[i] != 0; i++) { 00300 if (LOBYTE(ausNumPadCvt[i]) == LOBYTE(pKe->usFlaggedVk)) { 00301 /* 00302 * keep extra bits, but change VK value 00303 */ 00304 pKe->usFlaggedVk &= ~0xFF; 00305 pKe->usFlaggedVk |= (UINT)(HIBYTE(ausNumPadCvt[i])); 00306 break; 00307 00308 } 00309 } 00310 } 00311 } 00312 } 00313 return TRUE; 00314 } 00315 00316 /***************************************************************************\ 00317 * 00318 * xxxICO_00() - handle special case '00' key 00319 * 00320 * LATER IanJa: should only be in ICO OEM file for kbd with '00' key 00321 * 00322 * This function will leave the critical section only if low level hooks 00323 * are installed ant the call to xxxKeyEvent is made 00324 * 00325 \***************************************************************************/ 00326 BOOL 00327 xxxICO_00( 00328 PKE pKe) 00329 { 00330 CheckCritIn(); 00331 00332 if ((pKe->usFlaggedVk & 0xFF) != VK_ICO_00) { 00333 /* 00334 * Pass the keystroke on unaltered 00335 */ 00336 return TRUE; 00337 } 00338 00339 if (pKe->usFlaggedVk & KBDBREAK) { 00340 /* 00341 * '0' key comes up 00342 */ 00343 pKe->usFlaggedVk = '0' | KBDEXT | KBDBREAK; 00344 } else { 00345 /* 00346 * '0' down, up, down 00347 */ 00348 xxxKeyEvent('0', pKe->bScanCode, pKe->dwTime, 0, FALSE); 00349 xxxKeyEvent('0' | KBDBREAK, pKe->bScanCode, pKe->dwTime, 0, FALSE); 00350 pKe->usFlaggedVk = '0' | KBDEXT; 00351 } 00352 00353 return TRUE; 00354 } 00355 00356 KEPROC aKEProcOEM[] = { 00357 xxxICO_00, // Bitmask 0x01 00358 xxxNumpadCursor, // Bitmask 0x02 00359 NULL 00360 };