Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

xlate.c File Reference

#include "precomp.h"

Go to the source code of this file.

Functions

WORD GetModifierBits (PMODIFIERS pModifiers, LPBYTE afKeyState)
WORD GetModificationNumber (PMODIFIERS pModifiers, WORD wModBits)
BYTE VKFromVSC (PKE pke, BYTE bPrefix, LPBYTE afKeyState)
UINT InternalMapVirtualKeyEx (UINT wCode, UINT wType, PKBDTABLES pKbdTbl)
int APIENTRY _GetKeyNameText (LONG lParam, LPWSTR ccxlpStr, int cchSize)
 xxxAltGr (PKE pKe)
 xxxShiftLock (PKE pKe)
BOOL KEOEMProcs (PKE pKe)
BOOL xxxKELocaleProcs (PKE pKe)

Variables

BOOL gbAltGrDown = FALSE


Function Documentation

int APIENTRY _GetKeyNameText LONG  lParam,
LPWSTR  ccxlpStr,
int  cchSize
 

Definition at line 408 of file xlate.c.

References APIENTRY, BYTE, InternalMapVirtualKeyEx(), L, LOBYTE, NULL, tagKBDFILE::pKbdTbl, PtiCurrentShared, tagKL::spkf, tagTHREADINFO::spklActive, TRUE, UINT, and wcsncpycch().

Referenced by NtUserGetKeyNameText().

00412 { 00413 BYTE Vsc = LOBYTE(HIWORD(lParam)); 00414 PVSC_LPWSTR pKN; 00415 PTHREADINFO ptiT = PtiCurrentShared(); 00416 PKBDTABLES pKbdTbl; 00417 UINT Vk; 00418 UINT Char; 00419 00420 /* 00421 * NOTE -- lpStr can be a client-side address, so access through it 00422 * must be guarded with try blocks. 00423 */ 00424 00425 if (cchSize < 1) 00426 return 0; 00427 00428 /* 00429 * If bit 25 set (don't care about left vs. right) then: 00430 * 1) convert right-Shift into left-Shift 00431 * 2) clear the extended bit for Ctrl and Alt only (effectively converting 00432 * right-Ctrl & right-Alt into left-Ctrl & right-Alt) 00433 * For Windows '95 compatibility, the DONTCARE_BIT doesn't apply to other 00434 * extended keys (eg: NumPad cursor movement keys, NumPad Enter). Some 00435 * applications (Word '95) depend on this. #37796 00436 */ 00437 if (lParam & DONTCARE_BIT) { 00438 if (Vsc == SCANCODE_RSHIFT) { 00439 Vsc = SCANCODE_LSHIFT; 00440 } 00441 if (lParam & EXTENDED_BIT) { 00442 if ((Vsc == SCANCODE_CTRL) || (Vsc == SCANCODE_ALT)) { 00443 lParam &= ~EXTENDED_BIT; 00444 } 00445 } 00446 lParam &= ~DONTCARE_BIT; 00447 } 00448 00449 if (ptiT->spklActive == (PKL)NULL) { 00450 return 0; 00451 } 00452 pKbdTbl = ptiT->spklActive->spkf->pKbdTbl; 00453 00454 /* 00455 * Scan pKbdTbl->pKeyNames[] or pKeyNamesExt[] for matching Virtual Scan Code 00456 */ 00457 if (lParam & EXTENDED_BIT) { 00458 pKN = pKbdTbl->pKeyNamesExt; 00459 } else { 00460 pKN = pKbdTbl->pKeyNames; 00461 } 00462 00463 if (pKN) { 00464 while (pKN->vsc != 0) { 00465 if (Vsc == pKN->vsc) { 00466 00467 try { 00468 cchSize = wcsncpycch(ccxlpStr, pKN->pwsz, cchSize); 00469 cchSize--; 00470 ccxlpStr[cchSize] = L'\0'; 00471 } except(W32ExceptionHandler(TRUE, RIP_ERROR)) { 00472 return 0; 00473 } 00474 return cchSize; 00475 } 00476 pKN++; 00477 } 00478 } 00479 00480 /* 00481 * The name of the key was not found in the table, so we 00482 * now attempt to construct the key name from the character produced by 00483 * the key. Translate Scancode -> Virtual Key -> character. 00484 */ 00485 00486 /* 00487 * Translate Scancode to Virtual Key (ignoring modifier keys etc.) 00488 */ 00489 Vk = InternalMapVirtualKeyEx((UINT)Vsc, 1, pKbdTbl); 00490 if (Vk == 0) { 00491 return 0; 00492 } 00493 00494 /* 00495 * Now translate Virtual Key to character (ignoring modifier keys etc.) 00496 */ 00497 Char = InternalMapVirtualKeyEx((UINT)Vk, 2, pKbdTbl); 00498 if (Char == 0) { 00499 return 0; 00500 } 00501 00502 if (Char & 0x80000000) { 00503 LPWSTR *ppwsz; 00504 00505 ppwsz = pKbdTbl->pKeyNamesDead; 00506 if (ppwsz) { 00507 while (*ppwsz != NULL) { 00508 if (*ppwsz[0] == (WCHAR)Char) { 00509 try { 00510 cchSize = wcsncpycch(ccxlpStr, (*ppwsz)+1, cchSize); 00511 cchSize--; 00512 ccxlpStr[cchSize] = L'\0'; 00513 } except(W32ExceptionHandler(TRUE, RIP_ERROR)) { 00514 return 0; 00515 } 00516 return cchSize; 00517 } 00518 ppwsz++; 00519 } 00520 } 00521 } 00522 00523 /* 00524 * Construct a single character name (adding null-terminator if possible) 00525 */ 00526 try { 00527 ccxlpStr[0] = (WCHAR)Char; 00528 if (cchSize >= 2) { 00529 ccxlpStr[1] = L'\0'; 00530 } 00531 } except(W32ExceptionHandler(TRUE, RIP_ERROR)) { 00532 return 0; 00533 } 00534 return 1; 00535 }

WORD GetModificationNumber PMODIFIERS  pModifiers,
WORD  wModBits
 

Definition at line 47 of file xlate.c.

References CheckCritInShared.

Referenced by InternalVkKeyScanEx(), KbdNlsFuncTypeAlt(), KbdNlsFuncTypeNormal(), VKFromVSC(), and xxxInternalToUnicode().

00050 { 00051 CheckCritInShared(); 00052 if (wModBits > pModifiers->wMaxModBits) { 00053 return SHFT_INVALID; 00054 } 00055 00056 return pModifiers->ModNumber[wModBits]; 00057 }

WORD GetModifierBits PMODIFIERS  pModifiers,
LPBYTE  afKeyState
 

Definition at line 26 of file xlate.c.

References CheckCritIn, and TestKeyDownBit.

Referenced by KbdNlsFuncTypeAlt(), KbdNlsFuncTypeNormal(), VKFromVSC(), and xxxInternalToUnicode().

00029 { 00030 PVK_TO_BIT pVkToBit = pModifiers->pVkToBit; 00031 WORD wModBits = 0; 00032 00033 CheckCritIn(); 00034 00035 while (pVkToBit->Vk) { 00036 if (TestKeyDownBit(afKeyState, pVkToBit->Vk)) { 00037 wModBits |= pVkToBit->ModBits; 00038 } 00039 pVkToBit++; 00040 } 00041 return wModBits; 00042 }

UINT InternalMapVirtualKeyEx UINT  wCode,
UINT  wType,
PKBDTABLES  pKbdTbl
 

Definition at line 231 of file xlate.c.

References aVkNumpad, LOBYTE, NULL, PBYTE, UINT, and USHORT.

Referenced by _GetKeyNameText(), AdjustPushState(), and NtUserMapVirtualKeyEx().

00235 { 00236 PVK_TO_WCHARS1 pVK; 00237 PVK_TO_WCHAR_TABLE pVKT; 00238 UINT VkRet = 0; 00239 USHORT usScanCode; 00240 PVSC_VK pVscVk; 00241 PBYTE pVkNumpad; 00242 00243 switch (wType) { 00244 case 0: 00245 00246 /* 00247 * Convert Virtual Key (wCode) to Scan Code 00248 */ 00249 if ((wCode >= VK_SHIFT) && (wCode <= VK_MENU)) { 00250 00251 /* 00252 * Convert ambiguous Shift/Control/Alt keys to left-hand keys 00253 */ 00254 wCode = (UINT)((wCode - VK_SHIFT) * 2 + VK_LSHIFT); 00255 } 00256 00257 /* 00258 * Scan through the table that maps Virtual Scancodes to Virtual Keys 00259 * for non-extended keys. 00260 */ 00261 for (usScanCode = 0; usScanCode < pKbdTbl->bMaxVSCtoVK; usScanCode++) { 00262 if ((UINT)LOBYTE(pKbdTbl->pusVSCtoVK[usScanCode]) == wCode) { 00263 return usScanCode & 0xFF; 00264 } 00265 } 00266 00267 /* 00268 * Scan through the table that maps Virtual Scancodes to Virtual Keys 00269 * for extended keys. 00270 */ 00271 for (pVscVk = pKbdTbl->pVSCtoVK_E0; pVscVk->Vk; pVscVk++) { 00272 if ((UINT)LOBYTE(pVscVk->Vk) == wCode) { 00273 return (UINT)pVscVk->Vsc; 00274 } 00275 } 00276 00277 /* 00278 * There was no match: maybe the Virtual Key can only be generated 00279 * with Numlock on. Scan through aVkNumpad[] to determine scancode. 00280 */ 00281 for (pVkNumpad = aVkNumpad; *pVkNumpad != 0; pVkNumpad++) { 00282 if ((UINT)(*pVkNumpad) == wCode) { 00283 return (UINT)(pVkNumpad - aVkNumpad) + SCANCODE_NUMPAD_FIRST; 00284 } 00285 } 00286 00287 return 0; // No match found! 00288 00289 case 1: 00290 case 3: 00291 00292 /* 00293 * Convert Scan Code (wCode) to Virtual Key, disregarding modifier keys 00294 * and NumLock key etc. Returns 0 for no corresponding Virtual Key 00295 */ 00296 if (wCode < (UINT)(pKbdTbl->bMaxVSCtoVK)) { 00297 VkRet = (UINT)LOBYTE(pKbdTbl->pusVSCtoVK[wCode]); 00298 } else { 00299 /* 00300 * Scan the E0 prefix table for a match 00301 */ 00302 for (pVscVk = pKbdTbl->pVSCtoVK_E0; pVscVk->Vk; pVscVk++) { 00303 if ((UINT)pVscVk->Vsc == wCode) { 00304 VkRet = (UINT)LOBYTE(pVscVk->Vk); 00305 break; 00306 } 00307 } 00308 } 00309 00310 if ((wType == 1) && (VkRet >= VK_LSHIFT) && (VkRet <= VK_RMENU)) { 00311 00312 /* 00313 * Convert left/right Shift/Control/Alt keys to ambiguous keys 00314 * (neither left nor right) 00315 */ 00316 VkRet = (UINT)((VkRet - VK_LSHIFT) / 2 + VK_SHIFT); 00317 } 00318 00319 if (VkRet == 0xFF) { 00320 VkRet = 0; 00321 } 00322 return VkRet; 00323 00324 case 2: 00325 00326 /* 00327 * Bogus Win3.1 functionality: despite SDK documenation, return uppercase for 00328 * VK_A through VK_Z 00329 */ 00330 if ((wCode >= (WORD)'A') && (wCode <= (WORD)'Z')) { 00331 return wCode; 00332 } 00333 00334 // HIWORD is no loner the wchar, due to app compat problems #287134 00335 // We should not return the wchar from pti->wchInjected that cached 00336 // at GetMessage time. 00337 // (delete this commented-out section by end of March 1999 - IanJa) 00338 // 00339 // if (LOWORD(wCode) == VK_PACKET) { 00340 // return HIWORD(wCode); 00341 // } 00342 00343 /* 00344 * Convert Virtual Key (wCode) to ANSI. 00345 * Search each Shift-state table in turn, looking for the Virtual Key. 00346 */ 00347 for (pVKT = pKbdTbl->pVkToWcharTable; pVKT->pVkToWchars != NULL; pVKT++) { 00348 pVK = pVKT->pVkToWchars; 00349 while (pVK->VirtualKey != 0) { 00350 if ((UINT)pVK->VirtualKey == wCode) { 00351 00352 /* 00353 * Match found: return the unshifted character 00354 */ 00355 if (pVK->wch[0] == WCH_DEAD) { 00356 00357 /* 00358 * It is a dead character: the next entry contains its 00359 * value. Set the high bit to indicate dead key 00360 * (undocumented behaviour) 00361 */ 00362 pVK = (PVK_TO_WCHARS1)((PBYTE)pVK + pVKT->cbSize); 00363 return pVK->wch[0] | (UINT)0x80000000; 00364 } else if (pVK->wch[0] == WCH_NONE) { 00365 return 0; // 9013 00366 } 00367 if (pVK->wch[0] == WCH_NONE) { 00368 return 0; 00369 } 00370 return pVK->wch[0]; 00371 } 00372 pVK = (PVK_TO_WCHARS1)((PBYTE)pVK + pVKT->cbSize); 00373 } 00374 } 00375 } 00376 00377 /* 00378 * Can't find translation, or wType was invalid 00379 */ 00380 return 0; 00381 }

BOOL KEOEMProcs PKE  pKe  ) 
 

Definition at line 635 of file xlate.c.

References aKEProcOEM, BOOL, CheckCritIn, FALSE, NULL, and TRUE.

Referenced by xxxProcessKeyEvent().

00636 { 00637 int i; 00638 00639 CheckCritIn(); 00640 00641 for (i = 0; aKEProcOEM[i] != NULL; i++) { 00642 if (!aKEProcOEM[i](pKe)) { 00643 /* 00644 * Eat the key event 00645 */ 00646 return FALSE; 00647 } 00648 } 00649 00650 /* 00651 * Pass the (possibly altered) key event on. 00652 */ 00653 return TRUE; 00654 }

BYTE VKFromVSC PKE  pke,
BYTE  bPrefix,
LPBYTE  afKeyState
 

Definition at line 73 of file xlate.c.

References BOOL, BYTE, CheckCritIn, FALSE, gafRawKeyState, gapulCvt_VK, GetActiveHKL(), GetModificationNumber(), GetModifierBits(), gpKbdTbl, gpModifiers_VK, gptiForeground, IS_IME_ENABLED, LOBYTE, NULL, tagKBDFILE::pKbdTbl, tagKL::spkf, tagTHREADINFO::spklActive, TRUE, and USHORT.

Referenced by ProcessKeyboardInput(), and xxxInternalKeyEventDirect().

00078 { 00079 USHORT usVKey; 00080 PVSC_VK pVscVk; 00081 PKBDTABLES pKbdTbl; 00082 static BOOL fVkPause; 00083 00084 CheckCritIn(); 00085 DBG_UNREFERENCED_PARAMETER(afKeyState); 00086 00087 /* 00088 * Initialize as an unknown VK (unrecognised scancode) 00089 */ 00090 pke->usFlaggedVk = usVKey = 0xFF; 00091 00092 /* HACK ALERT 00093 * For Korean 103 keyboard: 00094 * Check this is Korean keyboard layout or not. 00095 */ 00096 if (IS_IME_ENABLED() && 00097 KOREAN_KBD_LAYOUT(GetActiveHKL())) { 00098 if ((pke->bScanCode == 0x71) || (pke->bScanCode == 0x72)) { 00099 pke->bScanCode |= 0x80; 00100 bPrefix = 0xE0; 00101 } else { 00102 pke->bScanCode &= 0x7F; 00103 } 00104 } else { 00105 pke->bScanCode &= 0x7F; 00106 } 00107 00108 if (gptiForeground == NULL) { 00109 RIPMSG0(RIP_VERBOSE, "VKFromVSC: NULL gptiForeground\n"); 00110 pKbdTbl = gpKbdTbl; 00111 } else { 00112 if (gptiForeground->spklActive) { 00113 pKbdTbl = gptiForeground->spklActive->spkf->pKbdTbl; 00114 } else { 00115 RIPMSG0(RIP_VERBOSE, "VKFromVSC: NULL spklActive\n"); 00116 pKbdTbl = gpKbdTbl; 00117 } 00118 } 00119 if (bPrefix == 0) { 00120 if (pke->bScanCode < pKbdTbl->bMaxVSCtoVK) { 00121 /* 00122 * direct index into non-prefix table 00123 */ 00124 usVKey = pKbdTbl->pusVSCtoVK[pke->bScanCode]; 00125 if (usVKey == 0) { 00126 return 0xFF; 00127 } 00128 } else { 00129 /* 00130 * unexpected scancode 00131 */ 00132 RIPMSG2(RIP_VERBOSE, "unrecognized scancode 0x%x, prefix %x", 00133 pke->bScanCode, bPrefix); 00134 return 0xFF; 00135 } 00136 } else { 00137 /* 00138 * Scan the E0 or E1 prefix table for a match 00139 */ 00140 if (bPrefix == 0xE0) { 00141 /* 00142 * Set the KBDEXT (extended key) bit in case the scancode is not 00143 * found in the table (eg: FUJITSU POS keyboard #65436) 00144 */ 00145 usVKey |= KBDEXT; 00146 /* 00147 * Ignore the SHIFT keystrokes generated by the hardware 00148 */ 00149 if ((pke->bScanCode == SCANCODE_LSHIFT) || 00150 (pke->bScanCode == SCANCODE_RSHIFT)) { 00151 return 0; 00152 } 00153 pVscVk = pKbdTbl->pVSCtoVK_E0; 00154 } else if (bPrefix == 0xE1) { 00155 pVscVk = pKbdTbl->pVSCtoVK_E1; 00156 } else { 00157 /* 00158 * Unrecognized prefix (from ScancodeMap?) produces an 00159 * unextended and unrecognized VK. 00160 */ 00161 return 0xFF; 00162 } 00163 while (pVscVk->Vk) { 00164 if (pVscVk->Vsc == pke->bScanCode) { 00165 usVKey = pVscVk->Vk; 00166 break; 00167 } 00168 pVscVk++; 00169 } 00170 } 00171 00172 /* 00173 * Scancode set 1 returns PAUSE button as E1 1D 45 (E1 Ctrl NumLock) 00174 * so convert E1 Ctrl to VK_PAUSE, and remember to discard the NumLock 00175 */ 00176 if (fVkPause) { 00177 /* 00178 * This is the "45" part of the Pause scancode sequence. 00179 * Discard this key event: it is a false NumLock 00180 */ 00181 fVkPause = FALSE; 00182 return 0; 00183 } 00184 if (usVKey == VK_PAUSE) { 00185 /* 00186 * This is the "E1 1D" part of the Pause scancode sequence. 00187 * Alter the scancode to the value Windows expects for Pause, 00188 * and remember to discard the "45" scancode that will follow 00189 */ 00190 pke->bScanCode = 0x45; 00191 fVkPause = TRUE; 00192 } 00193 00194 /* 00195 * Convert to a different VK if some modifier keys are depressed. 00196 */ 00197 if (usVKey & KBDMULTIVK) { 00198 WORD nMod; 00199 PULONG pul; 00200 00201 nMod = GetModificationNumber( 00202 gpModifiers_VK, 00203 GetModifierBits(gpModifiers_VK, gafRawKeyState)); 00204 00205 /* 00206 * Scan gapulCvt_VK[nMod] for matching VK. 00207 */ 00208 if ((nMod != SHFT_INVALID) && ((pul = gapulCvt_VK[nMod]) != NULL)) { 00209 while (*pul != 0) { 00210 if (LOBYTE(*pul) == LOBYTE(usVKey)) { 00211 pke->usFlaggedVk = (USHORT)HIWORD(*pul); 00212 return (BYTE)pke->usFlaggedVk; 00213 } 00214 pul++; 00215 } 00216 } 00217 } 00218 00219 pke->usFlaggedVk = usVKey; 00220 return (BYTE)usVKey; 00221 }

xxxAltGr PKE  pKe  ) 
 

Definition at line 547 of file xlate.c.

References FALSE, gbAltGrDown, NULL, TestRawKeyDown, TRUE, and xxxKeyEvent().

Referenced by xxxKELocaleProcs().

00549 { 00550 UserAssert(pKe != NULL); 00551 00552 if ((pKe->usFlaggedVk & 0xFF) != VK_RMENU) { 00553 return TRUE; 00554 } 00555 00556 if (!(pKe->usFlaggedVk & KBDBREAK)) { 00557 /* 00558 * If neither CTRL key is down, then fake one going down so that 00559 * the right hand ALT key is converted to CTRL + ALT. 00560 */ 00561 if (!TestRawKeyDown(VK_CONTROL)) { 00562 gbAltGrDown = TRUE; 00563 xxxKeyEvent(VK_LCONTROL, 0x1D | SCANCODE_SIMULATED, 00564 pKe->dwTime, 0, FALSE); 00565 } 00566 } else { 00567 /* 00568 * If the physical Left Ctrl key is not really down, fake the 00569 * Left Ctrl key coming back up (undo earlier faked Left Ctrl down) 00570 */ 00571 gbAltGrDown = FALSE; 00572 if (!TestRawKeyDown(VK_LCONTROL)) { 00573 xxxKeyEvent(VK_LCONTROL | KBDBREAK, 0x1D | SCANCODE_SIMULATED, 00574 pKe->dwTime, 0, FALSE); 00575 } 00576 } 00577 return TRUE; 00578 }

BOOL xxxKELocaleProcs PKE  pKe  ) 
 

Definition at line 662 of file xlate.c.

References BOOL, CheckCritIn, FALSE, gbAltGrDown, gdwKeyboardAttributes, gpKbdTbl, TRUE, xxxAltGr(), and xxxShiftLock().

Referenced by xxxProcessKeyEvent().

00663 { 00664 CheckCritIn(); 00665 00666 /* 00667 * AltGr is a layout-specific behavior 00668 * Modifier keys are sent up as necessary in xxxInternalActivateKeyboardLayout 00669 * (#139178), so left-Ctrl won't be left stuck down if we switch from an 00670 * AltGr keyboard to a non-AltGr keybord while the AltGr is held down. 00671 */ 00672 if ((gpKbdTbl->fLocaleFlags & KLLF_ALTGR) || gbAltGrDown) { 00673 if (!xxxAltGr(pKe)) { 00674 return FALSE; 00675 } 00676 } 00677 00678 /* 00679 * ShiftLock/CapsLock is per-user (global) behavior as well as (for 00680 * backward compatibility) per-layout behavior. 00681 */ 00682 if ((gdwKeyboardAttributes & KLLF_SHIFTLOCK) || 00683 (gpKbdTbl->fLocaleFlags & KLLF_SHIFTLOCK)) { 00684 if (!xxxShiftLock(pKe)) { 00685 return FALSE; 00686 } 00687 } 00688 00689 /* 00690 * Other special Key Event processors 00691 */ 00692 00693 return TRUE; 00694 }

xxxShiftLock PKE  pKe  ) 
 

Definition at line 586 of file xlate.c.

References FALSE, NULL, TestAsyncKeyStateToggle, TRUE, USHORT, and xxxKeyEvent().

Referenced by xxxKELocaleProcs().

00588 { 00589 USHORT Vk; 00590 00591 UserAssert(pKe != NULL); 00592 00593 /* 00594 * We only mess with downstrokes: return TRUE to let it pass unmolested. 00595 */ 00596 if (pKe->usFlaggedVk & KBDBREAK) { 00597 return TRUE; 00598 } 00599 00600 Vk = pKe->usFlaggedVk & 0xFF; 00601 00602 /* 00603 * If CapsLock is pressed when CapsLock is already on, lose the keystroke. 00604 */ 00605 if ((Vk == VK_CAPITAL) && TestAsyncKeyStateToggle(VK_CAPITAL)) { 00606 return FALSE; 00607 } 00608 00609 /* 00610 * If a Shift key goes down when CapsLock is on, turn CapsLock off 00611 * by simulating a click on the CapsLock key. 00612 * Let the Shift down through FIRST, since it might be part of an 00613 * input lang toggle (tough luck that this toggle turns off CapsLock!) 00614 */ 00615 if (((Vk == VK_LSHIFT) || (Vk == VK_RSHIFT) || (Vk == VK_SHIFT)) && 00616 TestAsyncKeyStateToggle(VK_CAPITAL)) { 00617 xxxKeyEvent(pKe->usFlaggedVk, pKe->bScanCode, 00618 pKe->dwTime, 0, FALSE); 00619 xxxKeyEvent(VK_CAPITAL, 0x3A | SCANCODE_SIMULATED, 00620 pKe->dwTime, 0, FALSE); 00621 xxxKeyEvent(VK_CAPITAL | KBDBREAK, 0x3A | SCANCODE_SIMULATED, 00622 pKe->dwTime, 0, FALSE); 00623 return FALSE; 00624 } 00625 00626 return TRUE; 00627 }


Variable Documentation

BOOL gbAltGrDown = FALSE
 

Definition at line 545 of file xlate.c.

Referenced by xxxAltGr(), and xxxKELocaleProcs().


Generated on Sat May 15 19:46:11 2004 for test by doxygen 1.3.7