📄 laymgr.cpp
字号:
WriteToCharBuffer(wch, cChars, pChars, &cchValid);
}
}
++dwChar;
}
break;
}
// Advance to the next row
pLigature = (const LIGATURE1*)
(((const BYTE*) pLigature) + cbLigatureRow);
}
}
return cchValid;
}
// Returns number of characters placed in pChars.
static
UINT32
GetCharacters(
PINPUT_LANGUAGE_INFO pili,
const VK_TO_WCHAR_TABLE *pVkToWcharTable,
const VK_TO_WCHARS1 *pVkToWChars,
WORD wModNum,
KEY_STATE_FLAGS ShiftFlags,
UINT32 *pChars,
UINT32 cChars
)
{
SETFNAME(_T("GetCharacters"));
DEBUGCHK(pili);
DEBUGCHK(pVkToWcharTable);
PREFAST_DEBUGCHK(pVkToWChars);
DEBUGCHK(pChars);
DEBUGCHK(cChars);
UINT32 cchValid = 0;
if (wModNum != SHFT_INVALID) {
if (wModNum < pVkToWcharTable->nModifications) {
WORD wch = pVkToWChars->wch[wModNum];
if (wch == WCH_NONE) {
// No character for this key combination
}
else if (wch == WCH_DEAD) {
// Use the next VkToWChars entry if this is a
// dead character.
pVkToWChars = (PVK_TO_WCHARS1)
(((const BYTE*) pVkToWChars) + pVkToWcharTable->cbSize);
DEBUGCHK(pVkToWChars->VirtualKey == VK__none_);
wch = pVkToWChars->wch[wModNum];
if (pili->wchDeadChar == 0) {
if (ShiftFlags & KeyStateDownFlag) {
pili->wchDeadChar = wch;
DEBUGMSG(ZONE_INPUTLANG, (_T("%s: New dead char 0x%04x\r\n"),
pszFname, wch));
}
}
else {
if ( (pili->il.pDeadKey != NULL) &&
(pili->wchDeadChar != 0) ) {
cchValid = ProcessDeadKeys(&pili->wchDeadChar, pili->il.pDeadKey,
wch, pChars, cChars, ShiftFlags);
}
else {
WriteToCharBuffer(wch, cChars, pChars, &cchValid);
}
}
}
else if (wch == WCH_LGTR) {
cchValid = ProcessLigature(pili, pVkToWChars->VirtualKey,
ShiftFlags, wModNum, pChars, cChars);
}
else {
WriteToCharBuffer(wch, cChars, pChars, &cchValid);
}
}
else {
// Maybe this key is special when ctrl is down.
WORD wch = GetControlledChar(pVkToWChars->VirtualKey, ShiftFlags);
if (wch) {
WriteToCharBuffer(wch, cChars, pChars, &cchValid);
}
}
}
DEBUGCHK(cchValid <= cChars);
return cchValid;
}
//----------------------------------------------------------------------------
//
// VKeyToUnicode
//
// Converts a VirtualKey to a Unicode character based on its ShiftFlags.
//
// Returns number of characters placed in pChars.
//
//----------------------------------------------------------------------------
static
UINT32
VKeyToUnicode(
PINPUT_LANGUAGE_INFO pili,
UINT32 uiVk,
KEY_STATE_FLAGS ShiftFlags,
UINT32 *pChars,
UINT32 cChars
)
{
SETFNAME(_T("VKeyToUnicode"));
PREFAST_DEBUGCHK(pili != NULL);
DEBUGCHK(pili->il.pVkToWcharTable != NULL);
DEBUGCHK(pili->rgModToShift != NULL);
DEBUGCHK(pChars != NULL);
DEBUGCHK(cChars > 0);
DEBUGCHK(IsLocked());
DEBUGCHK(uiVk != VK__none_); // 0xff is used for dead keys in tables
UINT32 cchValid = 0;
const VK_TO_WCHAR_TABLE *pVkToWcharTable = pili->il.pVkToWcharTable;
// Find the correct table and row for this VKEY
const VK_TO_WCHARS1 *pVkToWChars =
SearchVkToWCharTables(uiVk, &pVkToWcharTable);
if (pVkToWChars != NULL) {
PREFAST_DEBUGCHK(pVkToWcharTable);
// Get the correct set of modifier bits
const MODIFIERS *pCharModifiers = pili->il.pCharModifiers;
const MODIFIER_TO_SHIFT *pModToShift = pili->rgModToShift;
WORD wModBits = GetModifierBits(pCharModifiers, pModToShift, ShiftFlags);
ProcessModBitsForAttributes(pVkToWcharTable->cbSize, ShiftFlags,
&wModBits, &pVkToWChars);
// Find the index/modifier number for this set of shift flags.
WORD wModNum = GetModificationNumber(pCharModifiers, wModBits);
cchValid = GetCharacters(pili, pVkToWcharTable, pVkToWChars, wModNum,
ShiftFlags, pChars, cChars);
}
DEBUGCHK(cchValid <= cChars);
return cchValid;
}
//----------------------------------------------------------------------------
//
// KeybdDriverKeyStateToShiftFlags
//
// Collapse the shift state from a given key state array into a single
// element.
//
// Notes:
//
// For the given virtual key, the current flags from the key state array are
// put into the low bits of the output flags.
//
//----------------------------------------------------------------------------
static
void
KeybdDriverKeyStateToShiftFlags(
KEY_STATE KeyState, // Key state array.
UINT32 VKey, // Virtual key.
const VK_TO_SHIFT *pVkToShiftState,
const VK_TO_SHIFT *pVkToToggledState,
KEY_STATE_FLAGS *pShiftStateFlags // Location to put collapsed shift state.
)
{
KEY_STATE_FLAGS ShiftFlags = 0;
PREFAST_DEBUGCHK(pShiftStateFlags != NULL);
PREFAST_DEBUGCHK(pVkToShiftState != NULL);
PREFAST_DEBUGCHK(pVkToToggledState != NULL);
// Process the key down modifiers
while (pVkToShiftState->uiVk != 0) {
if (KeyStateIsDown(KeyState[pVkToShiftState->uiVk])) {
ShiftFlags |= pVkToShiftState->KeyStateFlags;
}
++pVkToShiftState;
}
// Process the toggled modifiers
while (pVkToToggledState->uiVk != 0) {
if (KeyStateIsToggled(KeyState[pVkToToggledState->uiVk])) {
ShiftFlags |= pVkToToggledState->KeyStateFlags;
}
++pVkToToggledState;
}
// Set the low order bits to reflect the current key.
DEBUGCHK((ShiftFlags & 0xFF) == 0);
*pShiftStateFlags = ShiftFlags | KeyState[VKey];
return;
}
//----------------------------------------------------------------------------
//
// MapCommonVKeyToLVKey
//
// Map common virtual keys to its left virtual key.
//
// Return Value:
//
// The left vkey.
//
//----------------------------------------------------------------------------
static
UINT32
MapCommonVKeyToLVKey(
UINT32 vkey
)
{
if ( vkey == VK_SHIFT )
vkey = VK_LSHIFT;
else if ( vkey == VK_CONTROL )
vkey = VK_LCONTROL;
else if ( vkey == VK_MENU )
vkey = VK_LMENU;
// VK_LWIN and VK_RWIN do not have a merged key.
return vkey;
}
//----------------------------------------------------------------------------
//
// MapLRVKeyToCommonVKey
//
// Map left and right virtual keys to their common vkey.
//
// Return Value:
//
// The common vkey.
//
//----------------------------------------------------------------------------
static
UINT32
MapLRVKeyToCommonVKey(
UINT32 vkey
)
{
if ( ( vkey == VK_LCONTROL ) ||
( vkey == VK_RCONTROL ) )
vkey = VK_CONTROL;
else if ( ( vkey == VK_LMENU ) ||
( vkey == VK_RMENU ) )
vkey = VK_MENU;
else if ( ( vkey == VK_LSHIFT ) ||
( vkey == VK_RSHIFT ) )
vkey = VK_SHIFT;
// VK_LWIN and VK_RWIN do not have a merged key.
return vkey;
}
//----------------------------------------------------------------------------
//
// NewKeyStateFlags
//
// Figure out the new key state flags based on the current state and the
// event.
//
// Return Value:
// The new flag settings.
//
//----------------------------------------------------------------------------
static
UINT32
NewKeyStateFlags(
KEY_STATE_FLAGS CurrentState,
KEY_STATE_FLAGS KeyEventFlags
)
{
// Just interested in down/up flag.
KeyEventFlags &= KeyStateDownFlag;
// First update the key state for the specific key.
// Remember the previous state.
if ( KeyStateIsDown(CurrentState) )
CurrentState |= KeyStatePrevDownFlag;
else
CurrentState &= ~KeyStatePrevDownFlag;
// Set the new state.
if ( KeyEventFlags )
CurrentState |= KeyStateDownFlag | KeyStateGetAsyncDownFlag;
else
CurrentState &= ~KeyStateDownFlag;
// Toggle flag only changes on down transition, not auto repeat.
if ( KeyStateIsDownTransition(CurrentState) )
CurrentState ^= KeyStateToggledFlag;
return CurrentState;
}
// Can we start an Alt+Num sequence?
static
inline
BOOL
AltNumOkToStart(
KEY_STATE_FLAGS ShiftFlags
)
{
BOOL fRet = TRUE;
if ( ShiftFlags & ( KeyShiftAnyCtrlFlag |
KeyShiftLeftWinFlag |
KeyShiftRightWinFlag |
KeyShiftAnyShiftFlag ) ) {
fRet = FALSE;
}
return fRet;
}
// Process an Alt+Num sequence.
// Returns FALSE if this is not an Alt+Num sequence.
static
BOOL
AltNumKeyEvent(
UINT32 VirtualKey,
KEY_STATE_FLAGS KeyEvent,
KEY_STATE_FLAGS *pShiftFlags,
UINT32 *pCharacterBuffer
)
{
#define C_ALT_NUM_VK 5
PREFAST_DEBUGCHK(pShiftFlags != NULL);
PREFAST_DEBUGCHK(pCharacterBuffer != NULL);
static BOOL bAltNumAltDownTransition;
static BOOL bAltNumInProgress;
static BOOL bAltNumHex;
static UINT cAltNumVk;
static UINT vkAltNum[C_ALT_NUM_VK];
KEY_STATE_FLAGS ShiftFlags = *pShiftFlags;
BOOL bGeneratedCharacter = FALSE;
UINT32 chGenerated;
UINT uiBase;
UINT i;
UINT32 vk;
if ( VirtualKey == VK_MENU )
{
if ( KeyEvent & KeyStateDownFlag )
{
// Down transition with no other keys?
if ( !( KeyEvent & KeyStatePrevDownFlag ) &&
( AltNumOkToStart(ShiftFlags) ) )
{
// Now armed to looked for number keys.
bAltNumAltDownTransition = TRUE;
bAltNumInProgress = FALSE;
bAltNumHex = FALSE;
cAltNumVk = 0;
}
}
else // Alt key up
{
bAltNumAltDownTransition = FALSE;
if ( bAltNumInProgress )
{
bAltNumInProgress = FALSE;
if ( cAltNumVk > 1 )
{
chGenerated = 0;
if ( bAltNumHex )
{
uiBase = 16;
}
else
{
uiBase = 10;
}
for ( i = 0;
i < cAltNumVk;
i++ )
{
vk = vkAltNum[i];
if ( ( vk >= VK_NUMPAD0 ) && ( vk <= VK_NUMPAD9 ) )
{
vk -= VK_NUMPAD0;
}
else if ( bAltNumHex &&
( ( vk >= VK_A ) && ( vk <= VK_F ) ) )
{
vk -= VK_A;
vk += 10;
}
else
{
break; // bad character
}
chGenerated *= uiBase;
chGenerated += vk;
}
bGeneratedCharacter = TRUE;
*pCharacterBuffer = chGenerated;
}
else
{
// Alt+N app startup here.
}
}
}
}
else if ( ( bAltNumAltDownTransition ) &&
( KeyEvent & KeyStateDownFlag ) )
{
if ( ( VirtualKey >= VK_NUMPAD0 ) && ( VirtualKey <= VK_NUMPAD9 ) )
{
// We were armed to look for number keys and we found one, so now we
// are actually in progress.
bAltNumInProgress = TRUE;
if ( cAltNumVk < C_ALT_NUM_VK )
{
vkAltNum[cAltNumVk++] = VirtualKey;
}
}
else if ( ( bAltNumHex ) &&
( ( VirtualKey >= VK_A ) && ( VirtualKey <= VK_F ) ) )
{
// Hex characters are split out separately for convenience in case the design changes.
bAltNumInProgress = TRUE;
if ( cAltNumVk < C_ALT_NUM_VK )
{
vkAltNum[cAltNumVk++] = VirtualKey;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -