mirror of
https://github.com/keymanapp/keyman.git
synced 2026-10-09 07:27:29 +00:00
160 lines
6.3 KiB
C++
160 lines
6.3 KiB
C++
/*
|
||
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
|
||
}
|
||
|
||
|