kernel/eka/ewsrv/ky_tran.cpp
changeset 0 a41df078684a
child 90 947f0dc9f7a8
child 256 c1f20ce4abcf
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32\ewsrv\ky_tran.cpp
       
    15 // The main code for setting modifiers and translating raw scanCodes into
       
    16 // keyCodes. Also traps capture-keys
       
    17 // 
       
    18 //
       
    19 
       
    20 
       
    21 #include <e32svr.h>
       
    22 #include <k32keys.h>
       
    23 #include <e32keys.h>
       
    24 #include <e32uid.h>
       
    25 
       
    26 enum	{EDummy,EKeyDataConv,EKeyDataFunc,EKeyDataSettings};
       
    27   
       
    28 EXPORT_C CKeyTranslator* CKeyTranslator::New()
       
    29 //
       
    30 // Return the actual key translator
       
    31 //
       
    32     {
       
    33 
       
    34     CKeyTranslatorX* pS=new CKeyTranslatorX;
       
    35 	if (pS && pS->Initialise()!=KErrNone)
       
    36 		{
       
    37 		delete pS;
       
    38 		pS=NULL;
       
    39 		}
       
    40     return(pS);
       
    41     }
       
    42 
       
    43 CKeyTranslatorX::CKeyTranslatorX()
       
    44 #pragma warning (disable: 4705)
       
    45 	{
       
    46 #pragma warning (default: 4705)
       
    47 
       
    48     UpdateModifiers(0);
       
    49 
       
    50 	}
       
    51 
       
    52 TInt CKeyTranslatorX::Initialise()
       
    53 	{
       
    54 	return (ChangeKeyData(_L("")));	//Set default keydata
       
    55 	}
       
    56 
       
    57 TBool CKeyTranslatorX::currentlyUpperCase(void)
       
    58 //
       
    59 // Determines whether a letter should be returned as upper case given the
       
    60 // current state of the modifiers. This is used for accented characters
       
    61 // created, for example, by entering Ctrl-1 "a". Since the keyboard may be
       
    62 // configured in different ways (e.g. shift AND capslock together may result
       
    63 // in either upper or lower case letters), a dynamic function such as this
       
    64 // is necessary
       
    65 //
       
    66 	{
       
    67 	TInt modifiersAffectingUpperCase=0;
       
    68 
       
    69 	if (iCurModifiers&EModifierCapsLock)
       
    70 		modifiersAffectingUpperCase|=EModifierCapsLock;
       
    71 
       
    72 	if (iCurModifiers&EModifierShift)
       
    73 		modifiersAffectingUpperCase|=EModifierShift;
       
    74 
       
    75 	for (TUint i=iConvTable.FirstScanCode(); i<=iConvTable.LastScanCode(); i++)
       
    76 		{
       
    77 		TChar ch=iConvTable.Convert(i, modifiersAffectingUpperCase).keyCode;
       
    78 		if (ch.IsUpper())
       
    79 			return ETrue;
       
    80 		else if (ch.IsLower())
       
    81 			return EFalse;
       
    82 		}
       
    83 	return EFalse;
       
    84 	}
       
    85 
       
    86 TUint CKeyTranslatorX::executeFunctionsAndSetState(TCharExtended aChar)
       
    87 //
       
    88 // Looks up and carries out the function required for the given
       
    89 // key-code/modifiers/state
       
    90 //
       
    91 	{
       
    92 	TUint keyCode=EKeyNull;
       
    93 	SFunc modifierFunc=iFuncTable.GetModifierFunc(aChar, iCurModifiers);
       
    94 	SFuncAndState genFuncAndNewState=iFuncTable.GetGeneralFuncAndState(aChar, iCurModifiers, iCurState,
       
    95 																			iCurCtrlDigits.GetRadix());
       
    96 
       
    97     SetModifierState((TEventModifier)modifierFunc.funcParam,(TModifierState)modifierFunc.func);
       
    98 
       
    99     if(!(iCurModifiers&(EModifierLeftAlt|EModifierRightAlt)))
       
   100         iCurModifiers&=~EModifierAlt;
       
   101     if(!(iCurModifiers&(EModifierLeftShift|EModifierRightShift)))
       
   102         iCurModifiers&=~EModifierShift;
       
   103     if(!(iCurModifiers&(EModifierLeftFunc|EModifierRightFunc)))
       
   104         iCurModifiers&=~EModifierFunc;
       
   105     if(!(iCurModifiers&(EModifierLeftCtrl|EModifierRightCtrl)))
       
   106         iCurModifiers&=~EModifierCtrl;
       
   107 
       
   108 	switch (genFuncAndNewState.func)
       
   109 		{
       
   110 	case EDoNothing:
       
   111 		break;
       
   112 	case EPassKeyThru:
       
   113 		keyCode=aChar;
       
   114 		break;
       
   115 	case EPassSpecialKeyThru:
       
   116 		iCurCtrlDigits.Reset();
       
   117 		keyCode=(currentlyUpperCase())?
       
   118 					User::UpperCase(genFuncAndNewState.funcParam):
       
   119 					genFuncAndNewState.funcParam;
       
   120 		iCurModifiers|=(EModifierSpecial);
       
   121 		break;
       
   122 	case EPassCtrlDigitsThru:
       
   123 		if (iCurCtrlDigits.WithinLimits())
       
   124 			{
       
   125 			keyCode=iCurCtrlDigits.GetDigits();
       
   126 			iCurModifiers|=(EModifierSpecial);
       
   127 			}
       
   128 		iCurCtrlDigits.Reset();
       
   129 		break;
       
   130 	case EAddOnCtrlDigit:
       
   131 		iCurCtrlDigits.AppendDigit(aChar, iCurModifiers);
       
   132 		if (iCurCtrlDigits.Terminated(iCurModifiers) && !iCurCtrlDigits.Error() && iCurCtrlDigits.WithinLimits())
       
   133 			{
       
   134 			keyCode=iCurCtrlDigits.GetDigits();
       
   135 			iCurModifiers|=(EModifierSpecial);
       
   136 			}
       
   137 		break;
       
   138 	}
       
   139 
       
   140 	switch (genFuncAndNewState.state)
       
   141 		{
       
   142 	case EStateUnchanged:
       
   143 		break;
       
   144 	case EStateDerivedFromDigitEntered:
       
   145 		iCurState=aChar.DigitValue();
       
   146 		break;
       
   147 	case EStateCtrlDigits:
       
   148 		if (iCurCtrlDigits.Terminated(iCurModifiers) || iCurCtrlDigits.Error())
       
   149 	 		{
       
   150 			iCurState=EStateNormal;
       
   151 			iCurCtrlDigits.Reset();
       
   152 			}
       
   153 		else
       
   154 			iCurState=iCurCtrlDigits.SetStateToCtrlDigits();
       
   155 		break;
       
   156 	default:
       
   157 		iCurState=genFuncAndNewState.state;
       
   158 		if (iCurState==EStateNormal)
       
   159 			iCurCtrlDigits.Reset();
       
   160 		break;
       
   161 		}
       
   162 	return keyCode;
       
   163 	}
       
   164 
       
   165 TInt CKeyTranslatorX::GetModifierState()
       
   166 //
       
   167 // Return the current modifier state
       
   168 //
       
   169     {
       
   170 
       
   171     return(iCurModifiers);
       
   172     }
       
   173 
       
   174 void CKeyTranslatorX::UpdateModifiers(TInt aModifiers)
       
   175 //
       
   176 //
       
   177 //
       
   178     {
       
   179 
       
   180     if(aModifiers == EModifierCancelRotation || aModifiers & KRotationModifiers)
       
   181         iCurModifiers &= KPersistentModifiers;	// if a Rotation modifier is being updated, only keep persistent modifiers
       
   182 	else
       
   183 	    iCurModifiers &= KPersistentModifiers|KRotationModifiers;		// if not, keep Rotation modifiers also
       
   184 	iCurModifiers |= aModifiers;
       
   185     iCurState = EStateNormal;
       
   186     }
       
   187 
       
   188 
       
   189 void CKeyTranslatorX::SetModifierState(TEventModifier aModifier,TModifierState aState)
       
   190 //
       
   191 // Change a modifier state
       
   192 //
       
   193     {
       
   194 
       
   195     switch(aState)
       
   196         {
       
   197         case ETurnOffModifier:
       
   198             iCurModifiers&=~aModifier;
       
   199             break;
       
   200         case ETurnOnModifier:
       
   201             iCurModifiers|=aModifier;
       
   202             break;
       
   203         case EToggleModifier:
       
   204             iCurModifiers^=aModifier;
       
   205         }
       
   206     }
       
   207 
       
   208 TBool CKeyTranslatorX::TranslateKey(TUint aScanCode, TBool aKeyUp,
       
   209 											const CCaptureKeys &aCaptureKeys, TKeyData &aKeyData)
       
   210 //
       
   211 // The function called for every keyup/keydown converting the aScanCode into a
       
   212 // keyCode, carrying out the function specified in the keyboard configuration
       
   213 // tables and setting the new state of the keyboard
       
   214 //
       
   215 	{
       
   216 
       
   217 #if defined(__WINS__)
       
   218 	// This code extracts the character code if there is one munged
       
   219 	// with the scan code.  Code which does not take advantage of this
       
   220 	// new facility to pass a character code as part of aScanCode should
       
   221 	// be unaffected
       
   222 	// 
       
   223 	// extract the character code
       
   224 	TUint charCode=(aScanCode&0xFFFF0000)>>16;
       
   225 	// extract the scan code
       
   226 	aScanCode&=0x0000FFFF;
       
   227 #endif
       
   228 
       
   229 	TUint oldState=iCurState;
       
   230    	TCharExtended ch;
       
   231 
       
   232     iCurModifiers&=~(EModifierPureKeycode);
       
   233 
       
   234     if(aScanCode<ESpecialKeyBase || aScanCode>=(ESpecialKeyBase+ESpecialKeyCount))
       
   235         {
       
   236     	SConvKeyData convKeyData=(iCurState==EStateNormal)?
       
   237 					iConvTable.Convert(aScanCode, iCurModifiers):
       
   238 					iConvTable.ConvertBaseCase(aScanCode, iCurModifiers);
       
   239 
       
   240     	TMaskedModifiers convModifiers;
       
   241     	convModifiers.iMask=KConvTableSettableModifiers;
       
   242     	convModifiers.iValue=convKeyData.modifiers;
       
   243 
       
   244     	MergeModifiers(iCurModifiers,convModifiers);
       
   245         ch=convKeyData.keyCode;
       
   246         }
       
   247     else
       
   248         ch=aScanCode;
       
   249 
       
   250  	if (aKeyUp)
       
   251 		iCurModifiers|=(EModifierKeyUp);
       
   252 	else
       
   253 		iCurModifiers&=~(EModifierKeyUp);
       
   254 
       
   255 	aKeyData.iKeyCode=executeFunctionsAndSetState(ch);
       
   256 
       
   257     ch=aKeyData.iKeyCode;
       
   258     // prevent modifier keys returning as keypresses
       
   259     if(ch.IsModifier())
       
   260         {
       
   261         aKeyData.iKeyCode=EKeyNull;
       
   262         iCurModifiers&=~EModifierPureKeycode;
       
   263         }
       
   264 
       
   265 	TBool ret;
       
   266 
       
   267 	ret=(aKeyData.iKeyCode!=EKeyNull);
       
   268 
       
   269 #if defined(__WINS__)
       
   270 	// see comments in __WINS__ block above
       
   271 	if (charCode)
       
   272 		{
       
   273         if (!(iCurModifiers & KRotationModifiers)) // if rotation modifiers not set we trust the WINDOWS translation
       
   274             {
       
   275 		    aKeyData.iKeyCode=charCode;
       
   276 		    iCurModifiers|=EModifierAutorepeatable;
       
   277             }
       
   278         ret = ETrue;
       
   279 		}
       
   280 #endif
       
   281 
       
   282 	if (aKeyUp
       
   283 		|| (aKeyData.iKeyCode==EKeyNull)
       
   284 		|| (iCurState!=EStateNormal)
       
   285 		|| (iCurState!=oldState))
       
   286 		{
       
   287 		iCurModifiers&=~(EModifierAutorepeatable);
       
   288 		}
       
   289 
       
   290     // convert ctrl-space to EKeyNull and clear PureKeycode modifier
       
   291     if(aKeyData.iKeyCode==EKeySpace && iCurModifiers&EModifierCtrl)
       
   292         {
       
   293         aKeyData.iKeyCode=EKeyNull;
       
   294         iCurModifiers&=~EModifierPureKeycode;
       
   295         }
       
   296 
       
   297     aKeyData.iModifiers=iCurModifiers;
       
   298 
       
   299     iCurModifiers&=(KPersistentModifiers|KRotationModifiers); // only keep persistent and rotation modifiers
       
   300 
       
   301 #if defined(__WINS__)
       
   302 	if (ret)
       
   303         {
       
   304         if (charCode && (iCurModifiers & KRotationModifiers))
       
   305             {
       
   306             TKeyData keyData = aKeyData;
       
   307             keyData.iKeyCode = charCode;
       
   308             aCaptureKeys.ProcessCaptureKeys(keyData);
       
   309 			// Pass the key capture data to the argument
       
   310 			aKeyData.iApp = keyData.iApp;
       
   311 			aKeyData.iHandle = keyData.iHandle;
       
   312 			aKeyData.iIsCaptureKey = keyData.iIsCaptureKey;
       
   313             }
       
   314         else
       
   315             aCaptureKeys.ProcessCaptureKeys(aKeyData);
       
   316         }
       
   317 #else
       
   318 	if (ret)
       
   319 		aCaptureKeys.ProcessCaptureKeys(aKeyData);
       
   320 #endif
       
   321 
       
   322 	return(ret);
       
   323 	}
       
   324 //
       
   325 // A miscellaneous collection of classes used in key translation
       
   326 //
       
   327 TCharExtended &TCharExtended::operator=(TUint aChar)
       
   328 	{
       
   329 	SetChar(aChar);
       
   330 	return *this;
       
   331 	}
       
   332 //
       
   333 TBool TCharExtended::IsDigitGivenRadix(TRadix aRadix) const
       
   334 // Returns true if the character is a digit given the aRadix
       
   335 	{
       
   336 	switch (aRadix)
       
   337 		{
       
   338 	case EBinary:
       
   339 		return (TBool)((TUint(*this)==(TUint)'0') || (TUint(*this)==(TUint)'1'));
       
   340 	case EOctal:
       
   341 		return (TBool)(IsDigit() && (TUint(*this)!=(TUint)'8') && (TUint(*this)!=(TUint)'9'));
       
   342 	case EDecimal:
       
   343 		return IsDigit();
       
   344 	case EHex:
       
   345 		return IsHexDigit();
       
   346 	default:
       
   347 		return EFalse;
       
   348 		}
       
   349 	}
       
   350 //
       
   351 TBool TCharExtended::IsModifier() const
       
   352 	{
       
   353 	switch ((TUint)(*this))
       
   354 		{
       
   355 		case EKeyLeftShift:
       
   356 		case EKeyLeftFunc:
       
   357 		case EKeyLeftCtrl:
       
   358 		case EKeyLeftAlt:
       
   359 		case EKeyRightShift:
       
   360 		case EKeyRightFunc:
       
   361 		case EKeyRightCtrl:
       
   362 		case EKeyRightAlt:
       
   363 		case EKeyCapsLock:
       
   364 		case EKeyNumLock:
       
   365 		case EKeyScrollLock:
       
   366 		case EKeyKeyboardExtend:
       
   367 			return ETrue;
       
   368 		default:
       
   369 			return EFalse;
       
   370 		}
       
   371 	}
       
   372 //
       
   373 TInt TCharExtended::DigitValue() const
       
   374 // Return the numeric value of the character if it is a digit, otherwise an errorcode
       
   375 	{
       
   376 	if (IsDigit())
       
   377 		
       
   378 		return (TInt(*this))-48;
       
   379 	else if ((TInt(*this)>='A') && (TUint(*this)<='F'))
       
   380 		return (TInt(*this))+10-'A';
       
   381 	else if ((TInt(*this)>='a') && (TUint(*this)<='f'))
       
   382 		return (TInt(*this))+10-'a';
       
   383 	else
       
   384 		return KErrArgument;
       
   385 	}
       
   386 //
       
   387 TBool TCharExtended::MatchesPattern(const TKeyCodePattern &aKeyCodePattern, TRadix aRadix) const
       
   388 // Return true if the character matches the given pattern
       
   389 	{
       
   390 	switch (aKeyCodePattern.iPattern)
       
   391 		{
       
   392 	case EAnyKey:
       
   393 		return ETrue;
       
   394 	case EAnyAlphaNumeric:
       
   395 		return IsAlphaDigit();
       
   396 	case EAnyAlpha:
       
   397 		return IsAlpha();
       
   398 	case EAnyAlphaLowerCase:
       
   399 		return IsLower();
       
   400 	case EAnyAlphaUpperCase:
       
   401 		return IsUpper();
       
   402 	case EAnyDecimalDigit:
       
   403 		return IsDigit();
       
   404 	case EAnyDigitGivenRadix:
       
   405 		return IsDigitGivenRadix(aRadix);
       
   406 	case EAnyModifierKey:
       
   407 		return IsModifier();
       
   408     case EMatchLeftOrRight:
       
   409         return (TBool)(TUint(*this)==aKeyCodePattern.iKeyCode || TUint(*this)==(aKeyCodePattern.iKeyCode+(TUint)1));
       
   410 	case EMatchKey:
       
   411 		return (TBool)(TUint(*this)==aKeyCodePattern.iKeyCode);
       
   412 	case EMatchKeyCaseInsens:
       
   413 		return (TBool)(User::LowerCase((TUint)*this)==User::LowerCase(aKeyCodePattern.iKeyCode));
       
   414 	default:
       
   415 		return EFalse;
       
   416 		}
       
   417 	}
       
   418 //
       
   419 typedef void (*TLibFnDataSetting)(TRadix &aRadix,TCtrlDigitsTermination &aCtrlDigitsTermination,TInt &aDefaultCtrlDigitsMaxCount,
       
   420 							      TInt &aMaximumCtrlDigitsMaxCount);
       
   421 
       
   422 void TCtrlDigits::Update(RLibrary aLibrary)
       
   423 	{
       
   424 
       
   425 	((TLibFnDataSetting)aLibrary.Lookup(EKeyDataSettings))(iRadix,iTermination,iMaxCount,iMaximumCtrlDigitsMaxCount);
       
   426 	iCount=0;
       
   427 	iErrorFlag=EFalse;
       
   428 	iDigits=0L;
       
   429 	};
       
   430 //
       
   431 TCtrlDigits::TCtrlDigits()
       
   432 	{
       
   433 	};
       
   434 //
       
   435 void TCtrlDigits::Reset()
       
   436 // Reset to 0
       
   437 	{
       
   438 
       
   439 	iCount=0;
       
   440 	iErrorFlag=EFalse;
       
   441 	iDigits=0L;
       
   442 	};
       
   443 //
       
   444 void TCtrlDigits::AppendDigit(TUint aKeyCode, TUint aModifiers)
       
   445 // Append the given digit to the current digits
       
   446 	{
       
   447 
       
   448 	TCharExtended ch=aKeyCode;
       
   449 	iCount++;
       
   450 	iDigits*=iRadix;
       
   451 	iDigits+=ch.DigitValue();
       
   452 	iErrorFlag=(TBool)(iErrorFlag
       
   453 					  || !ch.IsDigitGivenRadix(iRadix)
       
   454 					  || (iTermination==ETerminationByCtrlUp)
       
   455 						  && ((aModifiers&EModifierCtrl)==0));
       
   456 	}
       
   457 //
       
   458 TBool TCtrlDigits::Terminated(TInt aModifiers) const
       
   459 // Return true if the digits have been terminated and are ready to return as a keyCode
       
   460 	{
       
   461 	return (TBool)( ((iTermination==ETerminationByCount) && (iCount>=iMaxCount))
       
   462 				 || ((iTermination==ETerminationByCtrlUp) && (aModifiers&EModifierCtrl)==0)
       
   463                  || (iCount>=iMaximumCtrlDigitsMaxCount) );
       
   464 	}
       
   465 //
       
   466 TUint TCtrlDigits::SetStateToCtrlDigits() const
       
   467 // Return either "EStateCtrlDigitsUntilCount" or "EStateCtrlDigitsUntilCtrlUp"
       
   468 // according to the current termination type
       
   469 	{
       
   470 	switch (iTermination)
       
   471 		{
       
   472 	case ETerminationByCount:
       
   473 		return EStateCtrlDigitsUntilCount;
       
   474 	case ETerminationByCtrlUp:
       
   475 		return EStateCtrlDigitsUntilCtrlUp;
       
   476 	default:
       
   477 		return EStateNormal;
       
   478 		}
       
   479 	}
       
   480 //
       
   481 // Two classes that provide operations for accessing the keyboard configuration tables
       
   482 //
       
   483 typedef void (*TLibFnDataConv)(SConvTable &aConvTable, TUint &aConvTableFirstScanCode,TUint &aConvTableLastScanCode,
       
   484 							   SScanCodeBlockList &aKeypadScanCode,SKeyCodeList &aNonAutorepKeyCodes);
       
   485 //
       
   486 void TConvTable::Update(RLibrary aLibrary)
       
   487 #pragma warning (disable: 4705)
       
   488 	{
       
   489 #pragma warning (default: 4705)
       
   490 	((TLibFnDataConv)aLibrary.Lookup(EKeyDataConv))(iConvTable,iFirstScanCode,iLastScanCode,iKeypadScanCodes,iNonAutorepKeyCodes);
       
   491 	}
       
   492 //
       
   493 //
       
   494 TConvTable::TConvTable()
       
   495 #pragma warning (disable: 4705)
       
   496 	{
       
   497 #pragma warning (default: 4705)
       
   498 	}
       
   499 //
       
   500 TBool TConvTable::onKeypad(TUint aScanCode) const
       
   501 // Return True if the given aScanCode is on the keypad
       
   502 	{
       
   503 	for (TUint i=0; i<iKeypadScanCodes.numBlocks; i++)
       
   504 		if ((aScanCode>=iKeypadScanCodes.pblocks[i].firstScanCode)
       
   505 			&& (aScanCode<=iKeypadScanCodes.pblocks[i].lastScanCode))
       
   506 			{
       
   507 			return ETrue;
       
   508 			}
       
   509 
       
   510 	return EFalse;
       
   511 	}
       
   512 //
       
   513 TBool TConvTable::autorepeatable(TUint aKeyCode) const
       
   514 // Return True if the given aKeyCode is autorepeatable
       
   515 	{
       
   516 	for (TUint i=0; i<iNonAutorepKeyCodes.numKeyCodes; i++)
       
   517 		if (aKeyCode==iNonAutorepKeyCodes.pkeyCodes[i])
       
   518 			return EFalse;
       
   519 
       
   520 	return ETrue;
       
   521 	}
       
   522 //
       
   523 SConvKeyData TConvTable::Convert(TUint aScanCode, const TInt &aModifiers) const
       
   524 // Convert the given aScanCode and aModifiers into a keyCode and aModifiers
       
   525 	{
       
   526 	SConvKeyData returnVal;
       
   527 	returnVal.keyCode=EKeyNull;
       
   528 	returnVal.modifiers=0;
       
   529 
       
   530 	for (TUint i=0; i<iConvTable.numNodes; i++)
       
   531         {
       
   532 		if (MatchesMaskedValue(aModifiers,iConvTable.pnodes[i].maskedModifiers))
       
   533             {
       
   534 			for (TUint j=0; j<iConvTable.pnodes[i].numSubTables; j++)
       
   535 				{
       
   536 				TUint offset=0;
       
   537 				for (TUint k=0; k<iConvTable.pnodes[i].ppsubTables[j]->scanCodes.numBlocks; k++)
       
   538                     {
       
   539 					if ((aScanCode>=iConvTable.pnodes[i].ppsubTables[j]->scanCodes.pblocks[k].firstScanCode) &&
       
   540 						(aScanCode<=iConvTable.pnodes[i].ppsubTables[j]->scanCodes.pblocks[k].lastScanCode))
       
   541 						{
       
   542 						returnVal.keyCode=iConvTable.pnodes[i].ppsubTables[j]->pkeyCode[offset+
       
   543 										(aScanCode-iConvTable.pnodes[i].ppsubTables[j]->scanCodes.pblocks[k].firstScanCode)];
       
   544 						if (onKeypad(aScanCode))
       
   545 							returnVal.modifiers|=(EModifierKeypad);
       
   546 						if (autorepeatable(returnVal.keyCode))
       
   547 							returnVal.modifiers|=(EModifierAutorepeatable);
       
   548 
       
   549                         // check if ctrl key pressed and keycode has not been modified due to ctrl key
       
   550                         if (aModifiers&EModifierCtrl && !(iConvTable.pnodes[i].maskedModifiers.iMask&EModifierCtrl))
       
   551                             returnVal.modifiers|=(EModifierPureKeycode);
       
   552 						return returnVal;
       
   553 						}
       
   554 					else
       
   555 						offset+=iConvTable.pnodes[i].ppsubTables[j]->scanCodes.pblocks[k].lastScanCode-
       
   556 								iConvTable.pnodes[i].ppsubTables[j]->scanCodes.pblocks[k].firstScanCode+1;
       
   557                     }
       
   558 				}
       
   559             }
       
   560         }
       
   561 	return returnVal;
       
   562 	}
       
   563 //
       
   564 SConvKeyData TConvTable::ConvertBaseCase(TUint aScanCode, const TInt &aModifiers) const
       
   565 // As TConvTable::Convert above, except that all input aModifiers are ignored except for EModifierNumlock
       
   566 	{
       
   567 	if (aModifiers&EModifierNumLock)
       
   568 		return Convert(aScanCode, EModifierNumLock);
       
   569 	else
       
   570 		return Convert(aScanCode, 0);
       
   571 	}
       
   572 
       
   573 typedef void (*TLibFnDataFunc)(SFuncTables &aFuncTables);
       
   574 
       
   575 void TFuncTable::Update(RLibrary aLibrary)
       
   576 #pragma warning (disable: 4705)
       
   577 	{
       
   578 #pragma warning (default: 4705)
       
   579 	((TLibFnDataFunc)aLibrary.Lookup(EKeyDataFunc))(iFuncTables);
       
   580 	}
       
   581 //
       
   582 TFuncTable::TFuncTable()
       
   583 #pragma warning (disable: 4705)
       
   584 	{
       
   585 #pragma warning (default: 4705)
       
   586 	}
       
   587 //
       
   588 SFuncTableEntry TFuncTable::getDefault(const TCharExtended &aChar, const TInt &aModifiers) const
       
   589 // Get the default table entry. Should be called if passing through a normal function-table did
       
   590 // not trap these parameters.
       
   591 	{
       
   592     TUint i=0;
       
   593 	while(i<iFuncTables.defaultTable.numEntries)
       
   594         {
       
   595 		if (aChar.MatchesPattern(iFuncTables.defaultTable.pentries[i].keyCodePattern)
       
   596 			&& MatchesMaskedValue(aModifiers,iFuncTables.defaultTable.pentries[i].maskedModifiers))
       
   597 			{
       
   598 		   	break;
       
   599 			}
       
   600         i++;
       
   601         }
       
   602    	return iFuncTables.defaultTable.pentries[i];
       
   603 	}
       
   604 
       
   605 SFunc TFuncTable::GetModifierFunc(const TCharExtended &aChar, const TInt &aModifiers) const
       
   606 // Pass through the modifier table, returning the first table entry matching the given parameters.
       
   607 	{
       
   608 	SFuncTableEntry defaultTableEntry=getDefault(aChar, aModifiers);
       
   609 	SFunc returnVal = { 0, 0, 0 };
       
   610 	returnVal.func=defaultTableEntry.funcAndNewState.func;
       
   611 	returnVal.funcParam=defaultTableEntry.funcAndNewState.funcParam;
       
   612 
       
   613 	for (TUint i=0; i<iFuncTables.modifierTable.numEntries; i++)
       
   614 		if (aChar.MatchesPattern(iFuncTables.modifierTable.pentries[i].keyCodePattern)
       
   615 			&& MatchesMaskedValue(aModifiers,iFuncTables.modifierTable.pentries[i].maskedModifiers))
       
   616 			{
       
   617 			returnVal.func=iFuncTables.modifierTable.pentries[i].funcAndNewState.func;
       
   618 			returnVal.funcParam=iFuncTables.modifierTable.pentries[i].funcAndNewState.funcParam;
       
   619 		   	return returnVal;
       
   620 			}
       
   621    	return returnVal;
       
   622 	}
       
   623 
       
   624 SFuncAndState TFuncTable::GetGeneralFuncAndState(const TCharExtended &aChar, const TInt &aModifiers,
       
   625 																		TUint aCurState, TRadix aRadix) const
       
   626 // Pass through the table corresponding to the current keyboard state, returning the first
       
   627 // table entry matching the given parameters.
       
   628 	{
       
   629 	for (TUint i=0; i<iFuncTables.pgenFuncTables[aCurState].numEntries; i++)
       
   630 		if (aChar.MatchesPattern(iFuncTables.pgenFuncTables[aCurState].pentries[i].keyCodePattern, aRadix)
       
   631 			&& MatchesMaskedValue(aModifiers,iFuncTables.pgenFuncTables[aCurState].pentries[i].maskedModifiers))
       
   632 			{
       
   633 			return iFuncTables.pgenFuncTables[aCurState].pentries[i].funcAndNewState;
       
   634 			}
       
   635    	return getDefault(aChar, aModifiers).funcAndNewState;
       
   636 	}
       
   637 
       
   638 
       
   639 TInt CKeyTranslatorX::ChangeKeyData(const TDesC& aLibName)
       
   640 //
       
   641 // change keydata
       
   642 //
       
   643     {	
       
   644 
       
   645 	if(aLibName.Length()==0) // Back to default KeyData
       
   646 		{
       
   647 		if (!iIsdefaultKeyData)
       
   648 			{
       
   649 			_LIT(KEkData,"EKDATA.DLL");
       
   650 			TInt r=iDefaultKeyDataLib.Load(KEkData);
       
   651 			if (r!=KErrNone && r!=KErrAlreadyExists)
       
   652 				return r;
       
   653 			// Check for valid KeyboardData dll type
       
   654 			if(iDefaultKeyDataLib.Type()[2]!=KKeyboardDataUid) 
       
   655 				{	
       
   656 				iDefaultKeyDataLib.Close();
       
   657 				return(KErrCorrupt);//Only due to bad rom.
       
   658 				}
       
   659 			iConvTable.Update(iDefaultKeyDataLib);
       
   660 			iCurCtrlDigits.Update(iDefaultKeyDataLib);
       
   661 			iFuncTable.Update(iDefaultKeyDataLib);
       
   662 			iIsdefaultKeyData = ETrue;						// EKeyData status	 
       
   663 			iKeyDataLib.Close();							// Close previously loaded keydata
       
   664 			}
       
   665 		return(KErrNone);		
       
   666 		}
       
   667 //	
       
   668 	RLibrary lib;
       
   669 	TInt res=lib.Load(aLibName); 
       
   670 	if (res!=KErrNone && res!=KErrAlreadyExists)
       
   671 		return(res);
       
   672 //
       
   673 // Check for valid KeyboardData dll type
       
   674 //
       
   675 	if(lib.Type()[2]!=KKeyboardDataUid) 
       
   676 		{	
       
   677 		lib.Close();
       
   678 		return(KErrArgument);
       
   679 		}
       
   680 
       
   681 	// Close previously loaded keydata
       
   682 	if (iIsdefaultKeyData)
       
   683 		{
       
   684 		iIsdefaultKeyData = EFalse;							// EKeyData status
       
   685 		iDefaultKeyDataLib.Close();
       
   686 		}
       
   687     else
       
   688 		iKeyDataLib.Close();
       
   689 
       
   690 	iKeyDataLib=lib;
       
   691 	iConvTable.Update(lib);
       
   692 	iCurCtrlDigits.Update(lib);
       
   693 	iFuncTable.Update(lib);
       
   694 	return(KErrNone);		
       
   695     }
       
   696