spiegel-keyman/common/engine/keyboardprocessor/src/kmx/kmx_modifiers.cpp
2018-12-18 17:03:36 +07:00

141 lines
5.4 KiB
C++

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