/* Copyright: Copyright (C) 2003-2018 SIL International. Authors: mcdurdin */ #include "kmx_processor.h" using namespace km::kbp; using namespace kmx; #define MAX_RSHIFT 24 #define MAX_KSHIFT 18 static KMX_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 KMX_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 KMX_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 */ }; /* * KMX_BOOL IsEquivalentShift( KMX_UINT rshift, KMX_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. */ KMX_BOOL KMX_Processor::IsEquivalentShift(KMX_UINT rshift, KMX_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? // switch(states[rshift][kshift]) { case 0: return FALSE; case 1: return TRUE; case 2: return m_environment.baseLayoutGivesCtrlRAltForRAlt(); // This state is used when TSF gives us a bogus RALT instead of LCtrl+RAlt case 4: return m_environment.simulateAltGr(); // I4583 case 6: return m_environment.baseLayoutGivesCtrlRAltForRAlt() || m_environment.simulateAltGr(); // I4583 } return FALSE; // should never happen }