/* 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 }