os/kernelhwsrv/kernel/eka/ewsrv/ky_tran.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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