diff -r 000000000000 -r e686773b3f54 predictivesearch/PcsAlgorithm/Algorithm1/src/CPcsKeyMap.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/predictivesearch/PcsAlgorithm/Algorithm1/src/CPcsKeyMap.cpp Tue Feb 02 10:12:17 2010 +0200 @@ -0,0 +1,1039 @@ +/* +* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Retrieves the character map for each of the numeric keys. +* Uses services provided by the PTI Engine. +* +*/ + +// INCLUDE FILES +#include "CPcsDebug.h" +#include "CPcsKeyMap.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Unnamed namespace for local definitions +namespace { + +#ifdef _DEBUG + enum TPanicCode + { + EPanicPreCond_MultipleSingleCharMatching = 1, + EPanicPreCond_MultipleUIPriorityMatching = 2, + EPanicPreCond_MultipleEnglishPriorityMatching = 3, + EPanicPreCond_MultipleOthersPriorityMatching = 4, + }; + + void Panic(TInt aReason) + { + _LIT(KPanicText, "CPcsKeyMap"); + User::Panic(KPanicText, aReason); + } +#endif // DEBUG + +} // namespace + +// ============================== MEMBER FUNCTIONS ============================ + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::NewL +// Two Phase Construction +// ---------------------------------------------------------------------------- +CPcsKeyMap* CPcsKeyMap::NewL() + { + PRINT ( _L("Enter CPcsKeyMap::NewL") ); + + CPcsKeyMap* self = new ( ELeave ) CPcsKeyMap(); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + + PRINT ( _L("End CPcsKeyMap::NewL") ); + + return self; + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::CPcsKeyMap +// Constructor +// ---------------------------------------------------------------------------- +CPcsKeyMap::CPcsKeyMap() + { + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::ConstructL +// 2nd Phase Constructor +// ---------------------------------------------------------------------------- +void CPcsKeyMap::ConstructL() + { + PRINT ( _L("Enter CPcsKeyMap::ConstructL") ); + + // UI Language + iUILanguage = User::Language(); + + // List of non-supported languages for this Algorithm + iLanguageNotSupported.Append(ELangJapanese); + iLanguageNotSupported.Append(ELangPrcChinese); + iLanguageNotSupported.Append(ELangHongKongChinese); + iLanguageNotSupported.Append(ELangTaiwanChinese); + +#ifdef RD_INTELLIGENT_TEXT_INPUT + + TInt physicalKeyboard = 0; + CRepository* aknFepRepository = CRepository::NewL( KCRUidAknFep ); + aknFepRepository->Get( KAknFepPhysicalKeyboards, physicalKeyboard ); + delete aknFepRepository; + + PRINT1 ( _L("CPcsKeyMap::ConstructL: Physical keyboard support flag = 0x%02X"), physicalKeyboard ); + + // Constants follow the definition of KAknFepPhysicalKeyboards + const TInt ptiKeyboard12Key = 0x01; + //const TInt ptiKeyboardQwerty4x12 = 0x02; // Not used at the moment + const TInt ptiKeyboardQwerty4x10 = 0x04; + const TInt ptiKeyboardQwerty3x11 = 0x08; + const TInt ptiKeyboardHalfQwerty = 0x10; + //const TInt ptiKeyboardCustomQwerty = 0x20; // Not used at the moment + + // The following if contains the order of precedence given for keyboards + // i.e. one phone has both "ITUT 12 Key" and "Qwerty 4x10" physical keyboards + if ( physicalKeyboard & ptiKeyboard12Key ) + { + iKeyboardType = EPtiKeyboard12Key; + } + else if ( physicalKeyboard & ptiKeyboardHalfQwerty ) + { + iKeyboardType = EPtiKeyboardHalfQwerty; + } + else if ( physicalKeyboard & ptiKeyboardQwerty4x10 ) + { + iKeyboardType = EPtiKeyboardQwerty4x10; + } + else if ( physicalKeyboard & ptiKeyboardQwerty3x11 ) + { + iKeyboardType = EPtiKeyboardQwerty3x11; + } + else +#endif // RD_INTELLIGENT_TEXT_INPUT + { + iKeyboardType = EPtiKeyboard12Key; // default + } + + PRINT1 ( _L("CPcsKeyMap::ConstructL: Keyboard chosen for Predictive Search = %d"), iKeyboardType ); + + // Create structure for holding characters<-->key mappings + CreateKeyMappingL(); + + // Sets attribute for holding info if "0" and " " are on the same key + // Needed for decision if the "0" should be considered as a possible separator + SetSpaceAndZeroOnSameKey(); + + PRINT ( _L("CPcsKeyMap::ConstructL: ----------------------------------------")); + + PRINT ( _L("End CPcsKeyMap::ConstructL") ); + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::~CPcsKeyMap +// Destructor +// ---------------------------------------------------------------------------- +CPcsKeyMap::~CPcsKeyMap() + { + PRINT ( _L("Enter CPcsKeyMap::~CPcsKeyMap") ); + + // Cleanup local arrays + iLanguageNotSupported.Reset(); + + for (TInt i = 0; i < PoolCount(); i++) + { + for (TInt j = 0; j < TKeyMappingData::EKeyMapNumberArr; j++) + { + iKeyMapPtrArr[i]->iKeyMapCharArr[j].Close(); + } + } + iKeyMapPtrArr.ResetAndDestroy(); + iKeysArr.Close(); + + PRINT ( _L("End CPcsKeyMap::~CPcsKeyMap") ); + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::GetMixedKeyStringForQueryL +// aDestStr will have the length as the number of items in aSrcQuery. +// ---------------------------------------------------------------------------- +void CPcsKeyMap::GetMixedKeyStringForQueryL(CPsQuery& aSrcQuery, TDes& aDestStr) +{ + PRINT ( _L("Enter CPcsKeyMap::GetMixedKeyStringForQueryL") ); + + GetMixedKeyStringForDataL( aSrcQuery, aSrcQuery.QueryAsStringLC(), aDestStr ); + CleanupStack::PopAndDestroy(); //result of QueryAsStringLC + + PRINT ( _L("End CPcsKeyMap::GetMixedKeyStringForQueryL") ); +} + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::GetMixedKeyStringForDataL +// aDestStr will have the same length as aSrcData. aSrcQuery can be shorter. +// ---------------------------------------------------------------------------- +void CPcsKeyMap::GetMixedKeyStringForDataL( + CPsQuery& aSrcQuery, const TDesC& aSrcData, TDes& aDestStr) +{ + PRINT ( _L("Enter CPcsKeyMap::GetMixedKeyStringForDataL") ); + + for ( TInt i = 0; i < aSrcData.Length(); ++i ) + { + TChar character( aSrcData[i] ); + character.LowerCase(); + if ( i < aSrcQuery.Count() ) + { + CPsQueryItem& currentItem = aSrcQuery.GetItemAtL(i); + switch ( currentItem.Mode() ) + { + case EItut: + { + TPtiKey key = KeyForCharacterMultiMatch(aSrcData[i]); + // If a character is not mapped to numeric key append the character + if ( EPtiKeyNone == key ) + { + PRINT3 ( _L("CPcsKeyMap::GetMixedKeyStringForDataL: Char at index %d not mapped to a key, appending char '%c' (#%d)"), + i, (TUint) character, (TUint) character ); + + aDestStr.Append( character ); + } + else + { + aDestStr.Append( key ); + } + } + break; + case EQwerty: + //fall through + default: + PRINT2 ( _L("CPcsKeyMap::GetMixedKeyStringForDataL: Char '%c' (#%d) is taken exact (non predictive in query)"), + (TUint) character, (TUint) character ); + aDestStr.Append( character ); + break; + } + } + else + { + PRINT2 ( _L("CPcsKeyMap::GetMixedKeyStringForDataL: Char '%c' (#%d) is taken exact (over query length)"), + (TUint) character, (TUint) character ); + + aDestStr.Append( character ); + } + } + + PRINT1 ( _L("CPcsKeyMap::GetMixedKeyStringForDataL: Return string: \"%S\""), + &aDestStr ); + + PRINT ( _L("End CPcsKeyMap::GetMixedKeyStringForDataL") ); +} + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::CharacterForKeyMappingExists +// Returns true if the character is mapped to the key +// ---------------------------------------------------------------------------- +TBool CPcsKeyMap::CharacterForKeyMappingExists(TKeyMappingData& aKeyMap, const TUint aIntChar) + { + TBool found = EFalse; + + for (TInt j = TKeyMappingData::EKeyMapUILangArr; j <= TKeyMappingData::EKeyMapOthersLangArr; j++) + { + if ( KErrNotFound != aKeyMap.iKeyMapCharArr[j].Find(aIntChar) ) + { + found = ETrue; + break; + } + + } + + return found; + } + +#ifdef _DEBUG +// ---------------------------------------------------------------------------- +// CPcsKeyMap::CheckPotentialErrorConditions +// +// ---------------------------------------------------------------------------- +void CPcsKeyMap::CheckPotentialErrorConditions(RArray& aPoolIndexArr, const TChar& aChar) + { + PRINT ( _L("CPcsKeyMap::KeyForCharacterMultiMatch: ===================================================") ); + PRINT ( _L("CPcsKeyMap::KeyForCharacterMultiMatch: Checking potential error conditions") ); + PRINT ( _L("CPcsKeyMap::KeyForCharacterMultiMatch: ---------------------------------------------------") ); + + _LIT(KTextCharArr0, "is single char"); + _LIT(KTextCharArr1, "has \"UI\" priority"); + _LIT(KTextCharArr2, "has \"English\" priority"); + _LIT(KTextCharArr3, "has \"Others\" priority"); + const TPtrC charArrStr[] = + { KTextCharArr0(), KTextCharArr1(), KTextCharArr2(), KTextCharArr3() }; + + TFixedArray countArr; + + for ( TInt j = TKeyMappingData::EKeyMapSingleCharArr; j <= TKeyMappingData::EKeyMapOthersLangArr; j++ ) + { + countArr[j] = 0; + for ( TInt i = 0; i < aPoolIndexArr.Count(); i++ ) + { + if ( KErrNotFound != iKeyMapPtrArr[aPoolIndexArr[i]]->iKeyMapCharArr[j].Find((TUint) aChar) ) + { + PRINT5 ( _L("CPcsKeyMap::KeyForCharacterMultiMatch: Char '%c' (#%d) %S for pool %d with key '%c'"), + (TUint) aChar, (TUint) aChar, &charArrStr[j], aPoolIndexArr[i], iKeysArr[aPoolIndexArr[i]] ); + countArr[j]++; + } + } + } + + PRINT ( _L("CPcsKeyMap::KeyForCharacterMultiMatch: ===================================================") ); + +#ifdef __WINS__ + // Check in debug mode if we have wrong situations + __ASSERT_DEBUG( (countArr[TKeyMappingData::EKeyMapSingleCharArr] > 1), Panic(EPanicPreCond_MultipleSingleCharMatching) ); + __ASSERT_DEBUG( (countArr[TKeyMappingData::EKeyMapUILangArr] > 1), Panic(EPanicPreCond_MultipleUIPriorityMatching) ); + __ASSERT_DEBUG( (countArr[TKeyMappingData::EKeyMapEnglishLangArr] > 1), Panic(EPanicPreCond_MultipleEnglishPriorityMatching) ); + __ASSERT_DEBUG( (countArr[TKeyMappingData::EKeyMapOthersLangArr] > 1), Panic(EPanicPreCond_MultipleOthersPriorityMatching) ); +#endif // __WINS__ + } +#endif // _DEBUG + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::KeyForCharacterMultiMatch +// Considers possible that the same character can be in more pools. +// This case was verified at least in the following verified cases: +// - For some language version (i.e. Scandinavian with keys 'ä', 'å', 'ö'. +// - For some special characters in ITU-T 12 keys keyboards. +// Example: '$' is under key '1' and '7', '£' is under key '1' and '5'. +// In case the character is in more pools the selection strategy is the following: +// - 1st choice: if the keyboard is EPtiKeyboard12Key exclude the pool with '1'. +// - 2nd choice: choose the 1st pool that has for a language the char as single char. +// - 3rd choice: choose the 1st pool that has the char mapped for the UI language. +// - 4th choice: choose the 1st pool that has the char mapped for the English language. +// - 5th choice: choose the 1st pool that has the char mapped for the Other languages. +// ---------------------------------------------------------------------------- +TPtiKey CPcsKeyMap::KeyForCharacterMultiMatch(const TChar& aChar) + { + // Set an array of pool index matches (more matches are possible) + RArray poolIndexArr; + for ( TInt i = 0; i < PoolCount(); i++ ) + { + if ( CharacterForKeyMappingExists(*iKeyMapPtrArr[i], (TUint) aChar) ) + { + poolIndexArr.Append(i); + + PRINT4 ( _L("CPcsKeyMap::KeyForCharacterMultiMatch: Char '%c' (#%d) found in pool %d with key '%c'"), + (TUint) aChar, (TUint) aChar, i, iKeysArr[i] ); + } + } + + /* Choose the pool index depending on the number of matches. + * If there are 2 or more matches, then the choice of the pool index depends on + * a serie of conditions. + */ + TInt poolIndex = KErrNotFound; + + // Character not found in any pool + if ( poolIndexArr.Count() == 0 ) + { + PRINT2 ( _L("CPcsKeyMap::KeyForCharacterMultiMatch: Char '%c' (#%d) NOT found in all pools"), + (TUint) aChar, (TUint) aChar ); + } + + // Character found in one pool (normal case) + else if ( poolIndexArr.Count() == 1 ) + { + poolIndex = poolIndexArr[0]; + + PRINT2 ( _L("CPcsKeyMap::KeyForCharacterMultiMatch: Chosen (for unique match) pool %d with key '%c'"), + poolIndex, iKeysArr[poolIndex] ); + } + + /* Character found in more pools, this can happen in some known conditions: + * - In some variants 'Ä' is in key 'A' and in key 'Ä' + * - In ITUT keyboard '$' is in keys '1' and '7'. This happens for more chars. + * - For different languages in N97 '/' is in different keys. + */ + else // ( poolIndexArr.Count() > 1 ) + { + + /* If keybord is ITUT we exclude the key '1' from the posibility of being choosen, + * infact some characters can be typed by key '1' and another key. + * For example: + * '$' is under key '1' and '7', + * '£' is under key '1' and '5'. + * + * This is needed when the client passes updated chars to the engine. + * i.e.: Existing contact are "!Mat" and "$Nathan", + * User types '7' and client passes '7' or 'p' matching only contact "$Nathan", + * In next query user types '2' and client passes '$2' or '$a' matching "!Mat" and "$Nathan". + * This is wrong, as "!Mat" should not be matched. + * When the client will not pass updated chars to the engine, but the original (i.e.: "72" or "pa"), + * this piece of code shall be removed. + * With "client" it is referred to MCL contacts client. + */ + if (EPtiKeyboard12Key == iKeyboardType) + { + for ( TInt i = 0; i < poolIndexArr.Count() ; i++ ) + { + if ( EPtiKey1 == iKeysArr[poolIndexArr[i]] ) + { + poolIndexArr.Remove(i); + + PRINT ( _L("CPcsKeyMap::KeyForCharacterMultiMatch: Key '1' excluded (for multi match - EPtiKeyboard12Key)") ); + break; + } + } + if ( poolIndexArr.Count() == 1 ) + { + poolIndex = poolIndexArr[0]; + + PRINT2 ( _L("CPcsKeyMap::KeyForCharacterMultiMatch: Chosen (for unique match after removing key '1') pool %d with key '%c'"), + poolIndex, iKeysArr[poolIndex] ); + } + } + +#ifdef _DEBUG + CheckPotentialErrorConditions(poolIndexArr, aChar); +#endif // _DEBUG + + // Search the char in the char arrays in priority order, the 1st match is taken + for ( TInt j = TKeyMappingData::EKeyMapSingleCharArr; j <= TKeyMappingData::EKeyMapOthersLangArr; j++ ) + { + if ( KErrNotFound == poolIndex ) + { + TInt positionLeftMostOnKeys = KErrNotFound; + + for ( TInt i = 0; i < poolIndexArr.Count(); i++ ) + { + TInt position = iKeyMapPtrArr[poolIndexArr[i]]->iKeyMapCharArr[j].Find((TUint) aChar); + if ( KErrNotFound != position ) + { + // Get the key that has the char in the leftmost index. + // We consider that the char can be mapped in more than one key (this is really + // the case for instance in some Scandinavian variants). + // With this guess there is more possibility that we choose the key where the + // char is physically printed on the keyboard key. + // In order for this guessing strategy to work, chars for TPtiTextCase EPtiCaseUpper + // have to be added to the char arrays before any other TPtiTextCase. + if ( TKeyMappingData::EKeyMapUILangArr == j ) + { + if ( ( KErrNotFound == positionLeftMostOnKeys ) || ( position < positionLeftMostOnKeys ) ) + { + poolIndex = poolIndexArr[i]; + positionLeftMostOnKeys = position; + } + + } + // Get the 1st key that has the char mapped to it + else + { + poolIndex = poolIndexArr[i]; + + PRINT3 ( _L("CPcsKeyMap::KeyForCharacterMultiMatch: Chosen (for multi match - char arr: %d) pool %d with key '%c'"), + j, poolIndex, iKeysArr[poolIndex] ); + + break; + } + } + } + } + } + + } // else -> ( poolIndexArr.Count() > 1 ) + + // Set the key value from the pool index + TPtiKey key = EPtiKeyNone; + if ( KErrNotFound != poolIndex ) + { + key = iKeysArr[poolIndex]; + } + + poolIndexArr.Close(); + return key; + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::PoolIdForKey +// +// ---------------------------------------------------------------------------- +TInt CPcsKeyMap::PoolIdForKey(const TPtiKey aKey) + { + TInt poolId = iKeysArr.Find(aKey); + + // IF the key is not found, then it should go to the special pool, + // which is the last pool of iKeyMapPtrArr + if (KErrNotFound == poolId) + { + poolId = PoolCount() - 1; + } + + return poolId; + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::PoolIdForCharacter +// +// ---------------------------------------------------------------------------- +TInt CPcsKeyMap::PoolIdForCharacter(const TChar& aChar) + { + TPtiKey key = KeyForCharacterMultiMatch(aChar); + + TInt poolId = PoolIdForKey(key); + + return poolId; + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::PoolCount +// +// ---------------------------------------------------------------------------- +TInt CPcsKeyMap::PoolCount() + { + return iKeyMapPtrArr.Count(); + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::SetSpaceAndZeroOnSameKey +// +// ---------------------------------------------------------------------------- +void CPcsKeyMap::SetSpaceAndZeroOnSameKey() + { + const TInt KSpace = 32; // ASCII for " " + const TInt KZero = 48; // ASCII for "0" + + TChar charSpace(KSpace); + TChar charZero(KZero); + + TPtiKey keySpace = KeyForCharacterMultiMatch(charSpace); + TPtiKey keyZero = KeyForCharacterMultiMatch(charZero); + + iSpaceAndZeroOnSameKey = (keySpace == keyZero); + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::GetSpaceAndZeroOnSameKey +// +// ---------------------------------------------------------------------------- +TBool CPcsKeyMap::GetSpaceAndZeroOnSameKey() + { + return iSpaceAndZeroOnSameKey; + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::GetKeyboardKeyMapping +// Helper function to get Key Mappings depending on keyboard type +// ---------------------------------------------------------------------------- +MPtiKeyMappings* CPcsKeyMap::GetKeyboardKeyMapping(CPtiCoreLanguage& aCurrLanguage) + { + MPtiKeyMappings* ptiKeyMappings; + + switch ( iKeyboardType ) + { + case EPtiKeyboardQwerty4x12: + case EPtiKeyboardQwerty4x10: + case EPtiKeyboardQwerty3x11: + case EPtiKeyboardCustomQwerty: + ptiKeyMappings = aCurrLanguage.GetQwertyKeymappings(); + break; + + case EPtiKeyboard12Key: + ptiKeyMappings = aCurrLanguage.GetKeymappings(); + break; + + case EPtiKeyboardHalfQwerty: + ptiKeyMappings = aCurrLanguage.GetHalfQwertyKeymappings(); + break; + + default: + ptiKeyMappings = aCurrLanguage.GetKeymappings(); + break; + } + + return ptiKeyMappings; + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::GetKeyMapData +// +// ---------------------------------------------------------------------------- +CPtiKeyMapData* CPcsKeyMap::GetKeyMapData(CPtiCoreLanguage& aCurrLanguage) + { + MPtiKeyMappings* ptiKeyMappings = GetKeyboardKeyMapping( aCurrLanguage ); + + CPtiKeyMapData* keyMapData; + + switch ( iKeyboardType ) + { + case EPtiKeyboardQwerty4x12: + case EPtiKeyboardQwerty4x10: + case EPtiKeyboardQwerty3x11: + case EPtiKeyboardCustomQwerty: + keyMapData = static_cast(ptiKeyMappings)->KeyMapData(); + break; + + case EPtiKeyboard12Key: + keyMapData = static_cast(ptiKeyMappings)->KeyMapData(); + break; + + case EPtiKeyboardHalfQwerty: + keyMapData = static_cast(ptiKeyMappings)->KeyMapData(); + break; + + default: + keyMapData = static_cast(ptiKeyMappings)->KeyMapData(); + break; + } + + return keyMapData; + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::AppendEntryWithFakeKeyToKeyList +// Add pool with unused id for for key +// ---------------------------------------------------------------------------- +void CPcsKeyMap::AppendEntryWithFakeKeyToKeyList() + { + TUint keyUInt = (TUint) EPtiKeyNone + 1; + + while ( KErrNotFound != iKeysArr.Find( (TPtiKey) keyUInt) ) + { + keyUInt++; + } + + TPtiKey key = (TPtiKey) keyUInt; + iKeysArr.Append( key ); + + // This should always be the last one in the array + PRINT2 ( _L("CPcsKeyMap::AppendEntryWithFakeKeyToKeyList: Added additional last pool %d with key id #%d"), + iKeysArr.Count()-1, key ); + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::CreateKeyMapFromITUTHardcodedKeys +// +// ---------------------------------------------------------------------------- +void CPcsKeyMap::CreateKeyListFromITUTHardcodedKeys() + { + PRINT ( _L("Enter CPcsKeyMap::CreateKeyListFromITUTHardcodedKeys") ); + + iKeysArr.Append( EPtiKey0 ); + iKeysArr.Append( EPtiKey1 ); + iKeysArr.Append( EPtiKey2 ); + iKeysArr.Append( EPtiKey3 ); + iKeysArr.Append( EPtiKey4 ); + iKeysArr.Append( EPtiKey5 ); + iKeysArr.Append( EPtiKey6 ); + iKeysArr.Append( EPtiKey7 ); + iKeysArr.Append( EPtiKey8 ); + iKeysArr.Append( EPtiKey9 ); + + AppendEntryWithFakeKeyToKeyList(); + + PRINT ( _L("End CPcsKeyMap::CreateKeyListFromITUTHardcodedKeys") ); + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::CreateKeyMapFromKeyBindingTable +// +// ---------------------------------------------------------------------------- +void CPcsKeyMap::CreateKeyListFromKeyBindingTable( CPtiEngine* aPtiEngine ) + { + PRINT ( _L("Enter CPcsKeyMap::CreateKeyListFromKeyBindingTable") ); + + // Get the user language + TLanguage keyMapLanguage = iUILanguage; + PRINT1 ( _L("CPcsKeyMap::CreateKeyListFromKeyBindingTable: Current User Language is %d"), + keyMapLanguage ); + + // If the user language is not supported, then we use ELangEnglish as default + if (!IsLanguageSupported((TInt) keyMapLanguage)) + { + PRINT2 ( _L("CPcsKeyMap::CreateKeyListFromKeyBindingTable: Language %d is not supported, defaulting to %d"), + keyMapLanguage, ELangEnglish ); + + keyMapLanguage = ELangEnglish; + } + + CPtiCoreLanguage* currLanguage = static_cast(aPtiEngine->GetLanguage( keyMapLanguage )); + + // If we fail to get the language, we try again trying with ELangEnglish + if ( (!currLanguage) && (ELangEnglish != keyMapLanguage) ) + { + PRINT1 ( _L("CPcsKeyMap::CreateKeyListFromKeyBindingTable: Failed to get Current Language, trying with %d"), + ELangEnglish ); + + currLanguage = static_cast(aPtiEngine->GetLanguage( ELangEnglish )); + } + + if (currLanguage) + { + TInt numItems = 0; + const TPtiKeyBinding* table = GetKeyMapData(*currLanguage)->KeyBindingTable(iKeyboardType, numItems); + + PRINT1 ( _L("CPcsKeyMap::CreateKeyListFromKeyBindingTable: Num of Items in KeyBindingTable is %d"), numItems ); + + // Get from the key table the keys for constructing the pools + if (table) + { + for (TInt i = 0; i < numItems; i++) + { + TPtiKey key = (TPtiKey) table[i].iScanCode; + // Get all keys with same EPtiCaseLower or EPtiCaseUpper case + // Only for one of the casing to avoid repetitions + if ( (EPtiKeyNone != key) && (EPtiCaseLower == table[i].iCase) ) + { + PRINT3 ( _L("CPcsKeyMap::CreateKeyListFromKeyBindingTable: Adding pool %d with key '%c' (%d)"), + iKeysArr.Count(), key, key ); + iKeysArr.Append( key ); + } + } + } + else + { + PRINT ( _L("CPcsKeyMap::CreateKeyListFromKeyBindingTable: ##### Failed to create Key List (KeyBindingTable) #####") ); + } + } + else + { + PRINT ( _L("CPcsKeyMap::CreateKeyListFromKeyBindingTable: ##### Failed to create Key List (Language) #####") ); + } + + AppendEntryWithFakeKeyToKeyList(); + + PRINT ( _L("End CPcsKeyMap::CreateKeyListFromKeyBindingTable") ); +} + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::CreateKeyListL +// +// ---------------------------------------------------------------------------- +void CPcsKeyMap::CreateKeyListL( CPtiEngine* aPtiEngine ) + { + PRINT ( _L("Enter CPcsKeyMap::CreateKeyListL") ); + + switch ( iKeyboardType ) + { + case EPtiKeyboardQwerty4x12: + case EPtiKeyboardQwerty4x10: + case EPtiKeyboardQwerty3x11: + case EPtiKeyboardCustomQwerty: + CreateKeyListFromKeyBindingTable( aPtiEngine ); + break; + + case EPtiKeyboard12Key: + CreateKeyListFromITUTHardcodedKeys( ); + break; + + case EPtiKeyboardHalfQwerty: + CreateKeyListFromKeyBindingTable( aPtiEngine ); + break; + + default: + CreateKeyListFromKeyBindingTable( aPtiEngine ); + break; + } + + PRINT ( _L("End CPcsKeyMap::CreateKeyListL") ); + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::IsLanguageSupported +// Returns ETrue if this language is supported +// ---------------------------------------------------------------------------- +TBool CPcsKeyMap::IsLanguageSupported(TInt aLang) + { + return (KErrNotFound == iLanguageNotSupported.Find((TLanguage) aLang)); + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::CreateKeyMappingL +// +// ---------------------------------------------------------------------------- +void CPcsKeyMap::CreateKeyMappingL() + { + PRINT ( _L("Enter CPcsKeyMap::CreateKeyMappingL") ); + + // Instantiate the engine + CPtiEngine* ptiEngine = CPtiEngine::NewL(ETrue); + CleanupStack::PushL( ptiEngine ); + + ptiEngine->SetKeyboardType( iKeyboardType ); + + CreateKeyListL( ptiEngine ); + + // Now add the keymap arrays to hold the keymap data + for (TInt i = 0; i < iKeysArr.Count(); i++) + { + TKeyMappingData *keyData = new(ELeave) TKeyMappingData; + iKeyMapPtrArr.Append(keyData); + } + + // Get the available Languages on the phone + RArray LanguagesOnThisPhone; + ptiEngine->GetAvailableLanguagesL(LanguagesOnThisPhone); + PRINT2 ( _L("CPcsKeyMap::CreateKeyMappingL: Languages on this phone %d, maximum is set to %d"), + LanguagesOnThisPhone.Count(), KMaxNbrOfLangKeymapping ); + + // Remove the non-supported languages + for (TInt i = 0; i < LanguagesOnThisPhone.Count(); /* do not increment i */) + { + if ( (IsLanguageSupported(LanguagesOnThisPhone[i])) +#ifdef __WINS__ + && (ELangEnglish == LanguagesOnThisPhone[i]) // Only English for emulator +#endif // __WINS__ + ) + { + i++; + } + else + { + PRINT1 ( _L("CPcsKeyMap::CreateKeyMappingL: Removing not supported Language %d"), + LanguagesOnThisPhone[i] ); + LanguagesOnThisPhone.Remove(i); + } + } + + // Set current UI language as 1st language and English as 2nd language, + // if present in AvailableLanguages + TInt langIndex; + if ( KErrNotFound != (langIndex = LanguagesOnThisPhone.Find(ELangEnglish)) ) + { + LanguagesOnThisPhone.Remove(langIndex); + LanguagesOnThisPhone.Insert(ELangEnglish, 0); + } + if ( KErrNotFound != (langIndex = LanguagesOnThisPhone.Find(iUILanguage)) ) + { + LanguagesOnThisPhone.Remove(langIndex); + LanguagesOnThisPhone.Insert(iUILanguage, 0); + } + + // Set max number of languages for Key Map + TInt count = LanguagesOnThisPhone.Count(); + if (count > KMaxNbrOfLangKeymapping) + { + PRINT2 ( _L("CPcsKeyMap::CreateKeyMappingL: Supported Languages on this phone %d, limiting to %d"), + count, KMaxNbrOfLangKeymapping ); + count = KMaxNbrOfLangKeymapping; + } + + // Add Key Map for the languages + for (TInt i = 0; i < count; i++) + { + TLanguage languageToUse = (TLanguage) LanguagesOnThisPhone[i]; + + PRINT1 ( _L("CPcsKeyMap::CreateKeyMappingL: Constructing Key Map for Language %d"), languageToUse ); + TInt errStatus = ptiEngine->ActivateLanguageL(languageToUse); + if (KErrNone == errStatus) + { + TRAP_IGNORE(AddKeyMappingForActiveLanguageL(ptiEngine, languageToUse)); + } + else + { + PRINT1 ( _L("CPcsKeyMap::CreateKeyMappingL: ##### Unable to activate Language %d #####"), + languageToUse ); + } + + // Close the currently activated language + ptiEngine->CloseCurrentLanguageL(); + + PRINT ( _L("CPcsKeyMap::CreateKeyMappingL: ===================================================") ); + } + + LanguagesOnThisPhone.Close(); + + CleanupStack::PopAndDestroy( ptiEngine ); + + PRINT ( _L("End CPcsKeyMap::CreateKeyMappingL") ); + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::AddKeyMappingForActiveLanguageL +// +// ---------------------------------------------------------------------------- +void CPcsKeyMap::AddKeyMappingForActiveLanguageL(CPtiEngine* aPtiEngine, TLanguage aLanguage) +{ + PRINT ( _L("Enter CPcsKeyMap::AddKeyMappingForActiveLanguageL") ); + + // Make a language object based on the language + CPtiCoreLanguage* activeLanguage = static_cast(aPtiEngine->GetLanguage( aLanguage )); + + if (activeLanguage) + { + // Get the keyboard Mappings for the Active Language + MPtiKeyMappings* ptiKeyMappings = GetKeyboardKeyMapping( *activeLanguage ); + + for (TInt i = 0; i < PoolCount() - 1; i++) + { + TPtiKey key = iKeysArr[i]; + + PRINT ( _L("CPcsKeyMap::AddKeyMappingForActiveLanguageL: ===================================================") ); + PRINT4 ( _L("CPcsKeyMap::AddKeyMappingForActiveLanguageL: Adding characters for Key '%c' (%d) at Pool %d and Language %d"), + (TInt) key, (TInt) key, PoolIdForKey(key), aLanguage ); + + // Get the pointer to the language class (UI, English, Others) + RArray* keyMapLang; + if (aLanguage == iUILanguage) + { + keyMapLang = &(iKeyMapPtrArr[i]->iKeyMapCharArr[TKeyMappingData::EKeyMapUILangArr]); + PRINT1 ( _L("CPcsKeyMap::AddKeyMappingForActiveLanguageL: Language %d is the UI language"), aLanguage ); + } + else if (aLanguage == ELangEnglish) + { + // If (iUILanguage == ELangEnglish) ok to be in previous if case + keyMapLang = &(iKeyMapPtrArr[i]->iKeyMapCharArr[TKeyMappingData::EKeyMapEnglishLangArr]); + PRINT1 ( _L("CPcsKeyMap::AddKeyMappingForActiveLanguageL: Language %d is English language"), aLanguage ); + } + else + { + keyMapLang = &(iKeyMapPtrArr[i]->iKeyMapCharArr[TKeyMappingData::EKeyMapOthersLangArr]); + PRINT1 ( _L("CPcsKeyMap::AddKeyMappingForActiveLanguageL: Language %d is in the Other languages"), aLanguage ); + } + + PRINT ( _L("CPcsKeyMap::AddKeyMappingForActiveLanguageL: ---------------------------------------------------") ); + + TBool isSingleCharForKey = ETrue; + TUint singleChar = 0; + + // EPtiCaseUpper must be the 1st TPtiTextCase for iUILanguage + AddCharactersToKey( *ptiKeyMappings, key, EPtiCaseUpper, *iKeyMapPtrArr[i], *keyMapLang, isSingleCharForKey, singleChar ); + AddCharactersToKey( *ptiKeyMappings, key, EPtiCaseLower, *iKeyMapPtrArr[i], *keyMapLang, isSingleCharForKey, singleChar ); + + // 1. No other TPtiTextCase values for ITUT keyboard + // 2. No language variants handling for ITUT keyboard + if ( EPtiKeyboard12Key != iKeyboardType ) + { + AddCharactersToKey( *ptiKeyMappings, key, EPtiCaseFnLower, *iKeyMapPtrArr[i], *keyMapLang, isSingleCharForKey, singleChar ); + AddCharactersToKey( *ptiKeyMappings, key, EPtiCaseFnUpper, *iKeyMapPtrArr[i], *keyMapLang, isSingleCharForKey, singleChar ); + AddCharactersToKey( *ptiKeyMappings, key, EPtiCaseChrLower, *iKeyMapPtrArr[i], *keyMapLang, isSingleCharForKey, singleChar ); + AddCharactersToKey( *ptiKeyMappings, key, EPtiCaseChrUpper, *iKeyMapPtrArr[i], *keyMapLang, isSingleCharForKey, singleChar ); + + // Support for key guessing given the char in some phone language variants + if ( (isSingleCharForKey) && (0 != singleChar) ) + { + iKeyMapPtrArr[i]->iKeyMapCharArr[TKeyMappingData::EKeyMapSingleCharArr].Append(singleChar); // singleChar is in LowerCase + iKeyMapPtrArr[i]->iKeyMapCharArr[TKeyMappingData::EKeyMapSingleCharArr].Append(User::UpperCase(singleChar)); + + PRINT ( _L("CPcsKeyMap::AddKeyMappingForActiveLanguageL: ---------------------------------------------------") ); + PRINT5 ( _L("CPcsKeyMap::AddKeyMappingForActiveLanguageL: For Language %d and key '%c' of pool %d single char is '%c' (#%d)"), + aLanguage, (TInt) key, i, singleChar, singleChar ); + } + } + } + PRINT ( _L("CPcsKeyMap::AddKeyMappingForActiveLanguageL: ===================================================") ); + } + + PRINT ( _L("End CPcsKeyMap::AddKeyMappingForActiveLanguageL") ); +} + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::GetCharactersForKey +// +// ---------------------------------------------------------------------------- +void CPcsKeyMap::GetCharactersForKey(MPtiKeyMappings& aPtiKeyMappings, + TPtiKey aKey, + TPtiTextCase aTextCase, + TDes& aResult) + { + switch ( iKeyboardType ) + { + case EPtiKeyboardQwerty4x12: + case EPtiKeyboardQwerty4x10: + case EPtiKeyboardQwerty3x11: + case EPtiKeyboardCustomQwerty: + (static_cast(&aPtiKeyMappings))->GetDataForKey(aKey, aResult, aTextCase); + break; + + case EPtiKeyboard12Key: + (static_cast(&aPtiKeyMappings))->GetDataForKey(aKey, aResult, aTextCase); + break; + + case EPtiKeyboardHalfQwerty: + (static_cast(&aPtiKeyMappings))->GetDataForKey(aKey, aResult, aTextCase); + break; + + default: + (static_cast(&aPtiKeyMappings))->GetDataForKey(aKey, aResult, aTextCase); + break; + } + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::AddDataForKeyL +// +// ---------------------------------------------------------------------------- +void CPcsKeyMap::AddCharactersToKey(MPtiKeyMappings& aPtiKeyMappings, + TPtiKey aKey, + TPtiTextCase aTextCase, + TKeyMappingData& aKeyDataList, + RArray& aKeyMapLang, + TBool& aIsSingleCharForKey, + TUint& aSingleChar) + { + PRINT ( _L("Enter CPcsKeyMap::AddCharactersToKey") ); + + TBuf<255> result; + GetCharactersForKey(aPtiKeyMappings, aKey, aTextCase, result); + + PRINT3 ( _L("CPcsKeyMap::AddCharactersToKey: Get mapping chars for Key '%c' (%d) and TextCase %d"), + (TInt) aKey, (TInt) aKey, aTextCase ); + PRINT1 ( _L("CPcsKeyMap::AddCharactersToKey: Got chars: \"%S\""), &result ); + + for ( TInt i = 0; i < result.Length(); i++ ) + { + if ( !CharacterForKeyMappingExists(aKeyDataList, (TUint) result[i]) ) + { + PRINT1 ( _L("CPcsKeyMap::AddCharactersToKey: ----- Appending char to list: '%c'"), result[i] ); + aKeyMapLang.Append(result[i]); + } + else + { + PRINT1 ( _L("CPcsKeyMap::AddCharactersToKey: ***** NOT Appending char to list: '%c'"), result[i] ); + } + + // No language variants handling for ITUT keyboard + if ( EPtiKeyboard12Key != iKeyboardType ) + { + // Support for key guessing given the char in some phone language variants + if ( aIsSingleCharForKey ) + { + if ( 0 == aSingleChar ) + { + aSingleChar = User::LowerCase(result[i]); + } + else + { + TInt newChar = User::LowerCase(result[i]); + if (newChar != aSingleChar) + { + aSingleChar = 0; + aIsSingleCharForKey = EFalse; + } + } + } + } + } + + PRINT ( _L("CPcsKeyMap::AddCharactersToKey: ---------------------------------------------------") ); + + PRINT ( _L("End CPcsKeyMap::AddCharactersToKey") ); + } + +// End of file