spiegel-keyman/windows/src/engine/keyman32/keystate.cpp
2019-01-08 20:41:29 +11:00

160 lines
6.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
Name: keystate
Copyright: Copyright (C) SIL International.
Documentation:
Description:
Create Date: 11 Mar 2009
Modified Date: 6 Feb 2015
Authors: mcdurdin
Related Files:
Dependencies:
Bugs:
Todo:
Notes:
History: 11 Mar 2009 - mcdurdin - I1894 - Fix threading bugs introduced in I1888
11 Dec 2009 - mcdurdin - I934 - x64 - Initial version
12 Mar 2010 - mcdurdin - I934 - x64 - Complete
12 Mar 2010 - mcdurdin - I2229 - Remove hints and warnings
04 May 2010 - mcdurdin - I2351 - Robustness - verify _td return value
03 Feb 2015 - mcdurdin - I4551 - V9.0 - If Ctrl+Alt simulates RAlt is on, then Ctrl+Alt rules don’t work at all (both should work).
06 Feb 2015 - mcdurdin - I4583 - V9.0 - Remove altgr lookup test from keyman32 and put it into the registry
*/
#include "pch.h" // I4551
#define MAX_RSHIFT 24
#define MAX_KSHIFT 18
static DWORD legalKeyStates[MAX_KSHIFT] = {
0, LCTRLFLAG, RCTRLFLAG, LALTFLAG, LALTFLAG|LCTRLFLAG, LALTFLAG|RCTRLFLAG, RALTFLAG, RALTFLAG|LCTRLFLAG, RALTFLAG|RCTRLFLAG,
K_SHIFTFLAG, K_SHIFTFLAG|LCTRLFLAG, K_SHIFTFLAG|RCTRLFLAG, K_SHIFTFLAG|LALTFLAG, K_SHIFTFLAG|LALTFLAG|LCTRLFLAG, K_SHIFTFLAG|LALTFLAG|RCTRLFLAG, K_SHIFTFLAG|RALTFLAG, K_SHIFTFLAG|RALTFLAG|LCTRLFLAG, K_SHIFTFLAG|RALTFLAG|RCTRLFLAG
};
static DWORD legalRuleStates[MAX_RSHIFT] = {
0, LCTRLFLAG, RCTRLFLAG, LALTFLAG, LALTFLAG|LCTRLFLAG, LALTFLAG|RCTRLFLAG, RALTFLAG, RALTFLAG|LCTRLFLAG, RALTFLAG|RCTRLFLAG,
K_SHIFTFLAG, K_SHIFTFLAG|LCTRLFLAG, K_SHIFTFLAG|RCTRLFLAG, K_SHIFTFLAG|LALTFLAG, K_SHIFTFLAG|LALTFLAG|LCTRLFLAG, K_SHIFTFLAG|LALTFLAG|RCTRLFLAG, K_SHIFTFLAG|RALTFLAG, K_SHIFTFLAG|RALTFLAG|LCTRLFLAG, K_SHIFTFLAG|RALTFLAG|RCTRLFLAG,
K_CTRLFLAG, K_ALTFLAG, K_CTRLFLAG|K_ALTFLAG, K_SHIFTFLAG|K_CTRLFLAG, K_SHIFTFLAG|K_ALTFLAG, K_SHIFTFLAG|K_CTRLFLAG|K_ALTFLAG
};
// Simulate RALT -> LCtrl+RAlt -> columns marked with *
//
// Truth table: matching key states
// 1 = yes match always
// 2 = RAlt mapped as LCtrl+RAlt by keyboard driver
// 4 = Simulate RAlt with Ctrl+Alt
//
// x = key states, y = rule states
// CAPITAL LETTERS = RIGHT KEY, LOWER CASE LETTERS = LEFT KEY
static BYTE states[MAX_RSHIFT][MAX_KSHIFT] = {
// Simulate RAlt ==> * *
// 0 c C a ac aC A Ac AC s sc sC sa sac saC sA sAc sAC <-- Key states
/* 0 */ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* c */ { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* C */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* a */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* ac */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* aC */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* A */ { 0, 0, 0, 0, 4, 4, 1, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* Ac */ { 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Note: RALT will also trigger LCtrl+RAlt because we cannot distinguish reliably through TSF???
/* AC */ { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* s */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
/* sc */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
/* sC */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
/* sa */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
/* sac */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 },
/* saC */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 },
/* sA */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 1, 6, 4 },
/* sAc */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 },
/* sAC */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
/* Either Ctrl/Alt rules */
// 0 c C a ac aC A Ac AC s sc sC sa sac saC sA sAc sAC <-- Key states
/* C */ { 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* A */ { 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* CA */ { 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* SC */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 },
/* SA */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0 },
/* SCA */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1 }
/* ^ rule states */
};
/*
* BOOL IsEquivalentShift( UINT rshift, UINT kshift );
*
* Parameters: rshift Rule shift state flag set to compare.
* kshift Current shift state flag set to compare.
*
* Returns: TRUE if the shift states are equivalent.
*
* IsEquivalentShift will compare rshift and kshift and check the generic
* K_CTRLFLAG and K_ALTFLAG as well as specific keys correctly.
*/
BOOL IsEquivalentShift(UINT rshift, UINT kshift) {
//
// The rule shift must have ISVIRTUALKEY bit set for virt.keys
//
if(rshift == 0) return FALSE;
//
// Test CAPS-specific rules
//
if( (rshift & NOTCAPITALFLAG) && (kshift & CAPITALFLAG) ) return FALSE;
if( (rshift & CAPITALFLAG) && !(kshift & CAPITALFLAG) ) return FALSE;
//
// Ignore CAPS, NUM and SCROLL
//
rshift &= K_MODIFIERFLAG;
kshift &= K_MODIFIERFLAG;
//
// Find rule state index and key state index
// If not found, it's not a supported combination, e.g. LCTRL|RCTRL
// TODO: unwind these loops if you're feeling optimistic
//
int i;
for(i = 0; i < MAX_RSHIFT; i++) {
if(rshift == legalRuleStates[i]) {
rshift = i;
break;
}
}
if(i == MAX_RSHIFT) return FALSE;
for(i = 0; i < MAX_KSHIFT; i++) {
if(kshift == legalKeyStates[i]) {
kshift = i;
break;
}
}
if(i == MAX_KSHIFT) return FALSE;
//
// Time of truth: is it a valid state?
//
PKEYMAN64THREADDATA _td = ThreadGlobals();
if(!_td) return FALSE;
switch(states[rshift][kshift]) {
case 0: return FALSE;
case 1: return TRUE;
case 2: return KeyboardGivesCtrlRAltForRAlt(); // This state is used when TSF gives us a bogus RALT instead of LCtrl+RAlt
case 4: return Globals::get_SimulateAltGr(); // I4583
case 6: return KeyboardGivesCtrlRAltForRAlt() || Globals::get_SimulateAltGr(); // I4583
}
return FALSE; // should never happen
}