diff -r 5b6f26637ad3 -r f4a778e096c2 predictivesearch/PcsAlgorithm/Algorithm2/src/CPcsKeyMap.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/predictivesearch/PcsAlgorithm/Algorithm2/src/CPcsKeyMap.cpp Wed Sep 01 12:29:52 2010 +0100 @@ -0,0 +1,859 @@ +/* +* 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 "CPcsAlgorithm2.h" +#include "CPcsAlgorithm2Utils.h" +#include "FindUtilChineseECE.h" +#include "CPcsDebug.h" +#include "CPcsKeyMap.h" +#include "CPsQueryItem.h" +#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, + EPanic_OverflowInPoolIndex = 5, + EPanic_InvalidKeyboardType = 6 + }; + + void Panic(TInt aReason) + { + _LIT(KPanicText, "CPcsKeyMap"); + User::Panic(KPanicText, aReason); + } +#endif // DEBUG + +} // namespace + + +// ============================== MEMBER FUNCTIONS ============================ + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::NewL +// Two Phase Construction +// ---------------------------------------------------------------------------- +CPcsKeyMap* CPcsKeyMap::NewL(CPcsAlgorithm2* aAlgorithm) + { + PRINT ( _L("Enter CPcsKeyMap::NewL") ); + + CPcsKeyMap* self = new (ELeave) CPcsKeyMap(); + CleanupStack::PushL(self); + self->ConstructL(aAlgorithm); + CleanupStack::Pop(self); + + PRINT ( _L("End CPcsKeyMap::NewL") ); + + return self; + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::CPcsKeyMap +// Constructor +// ---------------------------------------------------------------------------- +CPcsKeyMap::CPcsKeyMap() + { + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::ConstructL +// 2nd Phase Constructor +// ---------------------------------------------------------------------------- +void CPcsKeyMap::ConstructL(CPcsAlgorithm2* aAlgorithm) + { + iLanguageNotSupported.Append(ELangJapanese); + iLanguageNotSupported.Append(ELangKorean); + + iAlgorithm = aAlgorithm; + iPtiEngine = CPtiEngine::NewL(); + + SetupKeyboardTypesL(); + ConstructKeymapL(); + SetSpaceAndZeroOnSameKey(); + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::ReconstructKeymapL +// When the writing language is changed, the keymap needs reconstruct. +// ---------------------------------------------------------------------------- +void CPcsKeyMap::ReconstructKeymapL() + { + // Clear the keymap data array first when reconstruct the keymap. + ResetKeyMap(); + + // Always add English mappings first + AddKeyMapforConcreteKeyboardL( ELangEnglish ); + + // Then append the mappings of the current input language + TLanguage lang = iAlgorithm->FindUtilECE()->CurrentInputLanguage(); + if ( lang != ELangEnglish && IsLanguageSupportedL(lang) ) + { + AddKeyMapforConcreteKeyboardL( lang ); + } + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::ConstructKeymapL +// +// ---------------------------------------------------------------------------- +void CPcsKeyMap::ConstructKeymapL() + { + ConstructConcreteKeyMapL(); + + // Always add English mappings first + AddKeyMapforConcreteKeyboardL( ELangEnglish ); + + // Then append the mappings of the current input language + TLanguage lang = iAlgorithm->FindUtilECE()->CurrentInputLanguage(); + if ( lang != ELangEnglish && IsLanguageSupportedL(lang) ) + { + AddKeyMapforConcreteKeyboardL( lang ); + } + + PRINT ( _L("----------------------------------------")); + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::SetupKeyboardTypesL +// Initialise the keyboard type variables +// ---------------------------------------------------------------------------- +void CPcsKeyMap::SetupKeyboardTypesL() + { + 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 KPtiKeyboard12Key = 0x01; + const TInt KPtiKeyboardQwerty4x12 = 0x02; + const TInt KPtiKeyboardQwerty4x10 = 0x04; + const TInt KPtiKeyboardQwerty3x11 = 0x08; + const TInt KPtiKeyboardHalfQwerty = 0x10; + const TInt KPtiKeyboardCustomQwerty = 0x20; + + // Setup ITU-T mode first. + // Use always 12-key mode since all the supported devices should have at least + // virtual ITU-T available. + iItutKeyboardType = EPtiKeyboard12Key; + // TODO: ITU-T type could be set to "none" if device does not have either + // virtual keypad or hardware ITU-T available. This could be decided according + // some cenrep value, feature flag, device model, or platform version. + + // Then setup QWERTY mode. On real-life devices there should never + // be more than one QWERTY keyboard available but on emulator there can be several. + // Use the first one found in the following precedence + if ( physicalKeyboard & KPtiKeyboardQwerty3x11 ) + { + iQwertyKeyboardType = EPtiKeyboardQwerty3x11; + } + else if ( physicalKeyboard & KPtiKeyboardQwerty4x10 ) + { + iQwertyKeyboardType = EPtiKeyboardQwerty4x10; + } + else if ( physicalKeyboard & KPtiKeyboardQwerty4x12 ) + { + iQwertyKeyboardType = EPtiKeyboardQwerty4x12; + } + else if ( physicalKeyboard & KPtiKeyboardCustomQwerty ) + { + iQwertyKeyboardType = EPtiKeyboardCustomQwerty; + } + else if ( physicalKeyboard & KPtiKeyboardHalfQwerty ) + { + iQwertyKeyboardType = EPtiKeyboardHalfQwerty; + } + else + { + iQwertyKeyboardType = EPtiKeyboardNone; + } + + // Decide, which keyboard is used for the "default" matching mode. + // If there is physical ITU-T available, or there's no physical QWERTY, + // then ITU-T is default. + iItutIsDefault = (physicalKeyboard & KPtiKeyboard12Key) || + (iQwertyKeyboardType == EPtiKeyboardNone); + + PRINT1 ( _L("CPcsKeyMap::ConstructL: ITU-T Keyboard chosen for Predictive Search = %d"), iItutKeyboardType ); + PRINT1 ( _L("CPcsKeyMap::ConstructL: QWERTY Keyboard chosen for Predictive Search = %d"), iQwertyKeyboardType ); + } + + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::ConstructConcreteKeyMapL +// +// ---------------------------------------------------------------------------- +void CPcsKeyMap::ConstructConcreteKeyMapL() + { + if ( iItutKeyboardType != EPtiKeyboardNone ) + { + // Construct for Itut keyboard by default + PRINT ( _L("CPcsKeyMap::ConstructConcreteKeyMapL: Construct keymap for ITU-T")); + ConstructForItutKeyboardL(); + } + if ( iQwertyKeyboardType != EPtiKeyboardNone ) + { + // Construct for any QWERTY keyboard + PRINT1 ( _L("CPcsKeyMap::ConstructConcreteKeyMapL: Construct keymap for QWERTY keyboard type %d"), + iQwertyKeyboardType ); + ConstructForQwertyKeyboardL( iQwertyKeyboardType ); + } + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::AddKeyMapforConcreteKeyboardL +// +// ---------------------------------------------------------------------------- +void CPcsKeyMap::AddKeyMapforConcreteKeyboardL( TLanguage aLanguage ) + { + if ( iItutKeyboardType != EPtiKeyboardNone ) + { + AddKeyMapforItutL( aLanguage ); + } + + if ( iQwertyKeyboardType != EPtiKeyboardNone ) + { + AddKeyMapForQwertyKeyboardL( aLanguage, iQwertyKeyboardType ); + } + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::ResetKeyMap +// +// ---------------------------------------------------------------------------- +void CPcsKeyMap::ResetKeyMap() + { + const TInt ItutKeyMappingsCount = iItutKeyMappings.Count(); + const TInt qwertyKeyMappingsCount = iQwertyKeyMappings.Count(); + for (TInt i = 0; i < ItutKeyMappingsCount; i++) + { + iItutKeyMappings[i]->iKeyMappingArray.Reset(); + } + for (TInt i = 0; i < qwertyKeyMappingsCount; i++) + { + iQwertyKeyMappings[i]->iKeyMappingArray.Reset(); + } + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::~CPcsKeyMap +// Destructor +// ---------------------------------------------------------------------------- +CPcsKeyMap::~CPcsKeyMap() + { + ResetKeyMap(); + + // Cleanup local arrays + iLanguageNotSupported.Reset(); + iItutKeyMappings.ResetAndDestroy(); + iItutKeys.Close(); + iQwertyKeyMappings.ResetAndDestroy(); + iQwertyKeys.Close(); + delete iPtiEngine; + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::GetMixedKeyStringForQueryL +// aDestStr will have the length as the number of items in aSrcQuery. +// ---------------------------------------------------------------------------- +void CPcsKeyMap::GetMixedKeyStringForQueryL( + CPsQuery& aSrcQuery, TDes& aDestStr) const +{ + 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) const +{ + PRINT ( _L("Enter CPcsKeyMap::GetMixedKeyStringForDataL") ); + + const TInt srcDataLength = aSrcData.Length(); + for ( TInt i = 0; i < srcDataLength; ++i ) + { + TChar character( aSrcData[i] ); + character.LowerCase(); + if ( i < aSrcQuery.Count() ) + { + CPsQueryItem& currentItem = aSrcQuery.GetItemAtL(i); + TKeyboardModes curMode = ResolveKeyboardMode( currentItem.Mode() ); + TPtiKey key = KeyForCharacter( aSrcData[i], curMode ); + // If a character is not mapped to any key or it's entered in non-predictive mode, + // then append the character as exact. + if ( EPtiKeyNone == key ) + { + aDestStr.Append( character ); + } + else + { + aDestStr.Append( DefaultCharForKey(key, curMode) ); + } + } + else + { + // characters over query length are taken as exact + aDestStr.Append( character ); + } + } + + PRINT1 ( _L("CPcsKeyMap::GetMixedKeyStringForDataL: Return string: \"%S\""), + &aDestStr ); + + PRINT ( _L("End CPcsKeyMap::GetMixedKeyStringForDataL") ); +} + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::KeyForCharacter +// +// ---------------------------------------------------------------------------- +TPtiKey CPcsKeyMap::KeyForCharacter(TText aChar, TKeyboardModes aKbMode) const + { + const RPointerArray* keyMappings = KeyMappings( aKbMode ); + + // Don't return any key in the exact mode + if ( !keyMappings ) + { + return EPtiKeyNone; + } + + TInt index = KErrNotFound; + + TText lChar = User::LowerCase(aChar); + + const TInt count = keyMappings->Count() - 1; + + for (TInt i = 0; i < count; i++) + { + index = (*keyMappings)[i]->iKeyMappingArray.Find(lChar); + if (index != KErrNotFound) + { + return (*keyMappings)[i]->iKey; + } + } + + return EPtiKeyNone; + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::AddKeyMapForQwertyKeyboardL +// +// ---------------------------------------------------------------------------- +void CPcsKeyMap::AddKeyMapForQwertyKeyboardL(TLanguage aLanguage, TPtiKeyboardType aKbType) + { +#ifdef RD_INTELLIGENT_TEXT_INPUT + iPtiEngine->ActivateLanguageL(aLanguage); + iPtiEngine->SetKeyboardType(aKbType); + + // Make a language object based on current language + CPtiCoreLanguage* coreLanguage = static_cast(iPtiEngine->GetLanguage( aLanguage )); + + //Perfrom the key mappings only if the corelanguage is available + if (coreLanguage) + { + // Get the keyboard mappings for the language + CPtiKeyMapData* ptiKeyMapData = coreLanguage->RawKeyMapData(); + + const TInt qwertyKeyMappingsCount = iQwertyKeyMappings.Count() - 1; + for (TInt i = 0; i < qwertyKeyMappingsCount; i++) + { + AddDataForQwertyKeyboardL( ptiKeyMapData, aKbType, + iQwertyKeys[i], *(iQwertyKeyMappings[i]) ); + } + } +#endif // RD_INTELLIGENT_TEXT_INPUT + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::ConstructForQwertyKeyboardL +// Destructor +// ---------------------------------------------------------------------------- +void CPcsKeyMap::ConstructForQwertyKeyboardL(TPtiKeyboardType aKbType) + { +#ifdef RD_INTELLIGENT_TEXT_INPUT + CreateKeyListFromKeyBindingTable( iQwertyKeys, aKbType ); + + // Now add the keymap arrays to hold the keymap data + const TInt qwertyKeysCount = iQwertyKeys.Count(); + for (TInt i = 0; i < qwertyKeysCount; i++) + { + TKeyMappingData* keyData = new (ELeave) TKeyMappingData; + keyData->iKey = iQwertyKeys[i]; + iQwertyKeyMappings.Append(keyData); + } + + PRINT ( _L("----------------------------------------")); +#endif //RD_INTELLIGENT_TEXT_INPUT + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::AddDataForQwertyKeyboardL +// +// ---------------------------------------------------------------------------- +void CPcsKeyMap::AddDataForQwertyKeyboardL(CPtiKeyMapData* aPtiKeyMapData, + TPtiKeyboardType aKbType, + TPtiKey aKey, + TKeyMappingData& aKeyDataList) + { +#ifdef RD_INTELLIGENT_TEXT_INPUT + TPtiTextCase caseArray[] = + { + EPtiCaseUpper, + EPtiCaseLower, + EPtiCaseFnLower, + EPtiCaseFnUpper, + EPtiCaseChrLower, + EPtiCaseChrUpper + }; + + for (TInt i = 0; i < sizeof(caseArray) / sizeof(TPtiTextCase); i++) + { + TPtrC result = aPtiKeyMapData->DataForKey(aKbType, aKey, caseArray[i]); + + const TInt resultLength = result.Length(); + for (TInt j = 0; j < resultLength; j++) + aKeyDataList.iKeyMappingArray.Append(result[j]); + + PRINT2 ( _L("CPcsKeyMap: Mapping for Key %c = %S"), aKey, &result) + } +#endif //RD_INTELLIGENT_TEXT_INPUT + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::ContructForItutKeyboardL +// +// ---------------------------------------------------------------------------- +void CPcsKeyMap::ConstructForItutKeyboardL() + { + // Add the keys for Pool formation + iItutKeys.Append(EPtiKey0); + iItutKeys.Append(EPtiKey1); + iItutKeys.Append(EPtiKey2); + iItutKeys.Append(EPtiKey3); + iItutKeys.Append(EPtiKey4); + iItutKeys.Append(EPtiKey5); + iItutKeys.Append(EPtiKey6); + iItutKeys.Append(EPtiKey7); + iItutKeys.Append(EPtiKey8); + iItutKeys.Append(EPtiKey9); + // one additional pool for special characters not mapped too any keys. + // This should always be the last one in the arrary + iItutKeys.Append(EPtiKeyNone); + + // Now add the keymap arrays to hold the keymap data + const TInt ltutKeysCount = iItutKeys.Count(); + for (TInt i = 0; i < ltutKeysCount; i++) + { + TKeyMappingData *keyData = new (ELeave) TKeyMappingData; + keyData->iKey = iItutKeys[i]; + iItutKeyMappings.Append(keyData); + } + + PRINT ( _L("----------------------------------------")); + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::AddKeyMapforItutLanguageL +// +// ---------------------------------------------------------------------------- +void CPcsKeyMap::AddKeyMapforItutL(TLanguage aLanguage) + { + // Activate given language and get corresponding language object + iPtiEngine->ActivateLanguageL(aLanguage); + CPtiCoreLanguage* coreLanguage = static_cast (iPtiEngine->GetLanguage(aLanguage)); + + //Perfrom the key mappings only if the corelanguage is available + if (coreLanguage) + { + // Get the keyboard mappings for the language + CPtiKeyMapData* ptiKeyMapData = coreLanguage->RawKeyMapData(); + + const TInt ltutKeyMappingsCount = iItutKeyMappings.Count() - 1; + for (TInt i = 0; i < ltutKeyMappingsCount; i++) + { + AddDataForItutKeyboardL(ptiKeyMapData, iItutKeys[i], *(iItutKeyMappings[i])); + } + } + + if ( (aLanguage == ELangPrcChinese || aLanguage == ELangTaiwanChinese || aLanguage == ELangHongKongChinese) && + (iAlgorithm->FindUtilECE()->CurrentSearchMethod() == EAdptSearchStroke) ) + { + (*(iItutKeyMappings[1])).iKeyMappingArray.Append(0x4E00); //heng + (*(iItutKeyMappings[2])).iKeyMappingArray.Append(0x4E28); //shu + (*(iItutKeyMappings[3])).iKeyMappingArray.Append(0x4E3F); //pie + (*(iItutKeyMappings[4])).iKeyMappingArray.Append(0x4E36); //dian + (*(iItutKeyMappings[5])).iKeyMappingArray.Append(0x4E5B); //zhe + } + + } +// ---------------------------------------------------------------------------- +// CPcsKeyMap::AddDataForItutKeyboardL +// +// ---------------------------------------------------------------------------- +void CPcsKeyMap::AddDataForItutKeyboardL(CPtiKeyMapData* aPtiKeyMapData, TPtiKey aKey, TKeyMappingData& aKeyDataList) + { + TPtiTextCase caseArray[] = { EPtiCaseUpper, EPtiCaseLower }; + for (TInt i = 0; i< sizeof(caseArray) / sizeof(TPtiTextCase); i++) + { + TPtrC result = aPtiKeyMapData->DataForKey(EPtiKeyboard12Key, aKey, caseArray[i]); + const TInt resultLength = result.Length(); + for (TInt j = 0; j < resultLength; j++) + aKeyDataList.iKeyMappingArray.Append(result[j]); + PRINT2 ( _L("CPcsKeyMap: Mapping for Key %c = %S"), aKey,&result) + } + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::CreateKeyMapFromKeyBindingTable +// +// ---------------------------------------------------------------------------- +void CPcsKeyMap::CreateKeyListFromKeyBindingTable( RArray& aKeyArray, + TPtiKeyboardType aKbType ) + { + PRINT ( _L("Enter CPcsKeyMap::CreateKeyListFromKeyBindingTable") ); + + // Use Eglish mappings to list the keys on the keyboard + TRAP_IGNORE( iPtiEngine->ActivateLanguageL( ELangEnglish ) ); + CPtiCoreLanguage* ptiLang = + static_cast(iPtiEngine->GetLanguage( ELangEnglish )); + + if (ptiLang) + { + const CPtiKeyMapData* keyMapData = ptiLang->RawKeyMapData(); + const TPtiKeyBinding* table = NULL; + TInt numItems = 0; + if ( keyMapData ) + { + table = keyMapData->KeyBindingTable(aKbType, numItems); + } + else + { + PRINT( _L("CPcsKeyMap::CreateKeyListFromKeyBindingTable: #### Failed to get RawKeyMapData ####") ); + } + + 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' (0x%02X)"), + aKeyArray.Count(), key, key ); + aKeyArray.Append( key ); + } + } + } + else + { + PRINT ( _L("CPcsKeyMap::CreateKeyListFromKeyBindingTable: ##### Failed to create Key List (KeyBindingTable) #####") ); + } + } + else + { + PRINT ( _L("CPcsKeyMap::CreateKeyListFromKeyBindingTable: ##### Failed to create Key List (Language) #####") ); + } + + // one additional pool for special characters not mapped too any keys. + // This should always be the last one in the arrary + aKeyArray.Append(EPtiKeyNone); + + PRINT ( _L("End CPcsKeyMap::CreateKeyListFromKeyBindingTable") ); + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::IsLanguageSupportedL +// Returns ETrue if this language is supported +// ---------------------------------------------------------------------------- +TBool CPcsKeyMap::IsLanguageSupportedL(TUint32 aLang) + { + + TBool flag = ETrue; + const TInt languageNotSupportedCount = iLanguageNotSupported.Count(); + for (TInt i = 0; i < languageNotSupportedCount; i++) + { + if (iLanguageNotSupported[i] == aLang) + { + flag = EFalse; + } + } + + return flag; + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::PoolIdForKey +// +// ---------------------------------------------------------------------------- +TInt CPcsKeyMap::PoolIdForKey(TPtiKey aKey, TKeyboardModes aKbMode) const + { + __ASSERT_DEBUG( (aKbMode==EPredictiveItuT || aKbMode==EPredictiveQwerty), + Panic(EPanic_InvalidKeyboardType) ); + + // From logical point of view, the Pool ID is an index of the key in + // an array which is formed by concatenating QWERTY keys array in the end + // of the ITU-T keys array. + TInt poolId = KErrNotFound; + if ( aKbMode == EPredictiveItuT && iItutKeys.Count() ) + { + poolId = iItutKeys.Find(aKey); + // IF the key is not found, then it should go to the special pool, + // which is the pool of the dummy key in the ITU-T keys array + if (KErrNotFound == poolId) + { + poolId = iItutKeys.Count() - 1; + } + } + else if ( aKbMode == EPredictiveQwerty && iQwertyKeys.Count() ) + { + poolId = iQwertyKeys.Find(aKey); + // IF the key is not found, then it should go to the special pool, + // which is the pool of the dummy key in the QWERTY keys array + if (KErrNotFound == poolId) + { + poolId = iQwertyKeys.Count() - 1; + } + // Pools of QWERTY keys come after pools of ITU-T keys + poolId += iItutKeys.Count(); + } + + // Pool ID must never exceed value 63, because CPcsCache class + // stores these values as bitmask into 64 bit variable. + __ASSERT_DEBUG( poolId < 64, Panic(EPanic_OverflowInPoolIndex) ); + return poolId; + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::PoolIdForCharacter +// +// ---------------------------------------------------------------------------- +TInt CPcsKeyMap::PoolIdForCharacter( TChar aChar, TKeyboardModes aKbMode ) + { + // Pools are formed according the predictive keyboard mapping(s). + // When selecting pool for non-predictive mode, we use the pool of the + // default keyboard. The non-predictive matches should be a sub set of the + // predictive matches of the default keyboard, although strictly speaking, + // there' no guarantee for this. + if ( aKbMode == ENonPredictive || aKbMode == EPredictiveDefaultKeyboard ) + { + aKbMode = ( iItutIsDefault ? EPredictiveItuT : EPredictiveQwerty ); + } + + // If character is a Chinese word character, then we select the + // pool ID according the first character of the first spelling of the word. + TRAP_IGNORE( aChar = FirstCharFromSpellingL( aChar ) ); + + TPtiKey key = KeyForCharacter( aChar, aKbMode ); + TInt poolId = PoolIdForKey( key, aKbMode ); + + return poolId; + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::PoolCount +// +// ---------------------------------------------------------------------------- +TInt CPcsKeyMap::PoolCount() + { + return iItutKeyMappings.Count() + iQwertyKeyMappings.Count(); + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::GetSpaceAndZeroOnSameKey +// +// ---------------------------------------------------------------------------- +TBool CPcsKeyMap::GetSpaceAndZeroOnSameKey( TKeyboardModes aMode ) + { + // Resolve ambiguous keyboard mode + aMode = ResolveKeyboardMode( aMode ); + + if ( aMode == EPredictiveItuT ) + { + return iSpaceAndZeroOnSameKeyOnItut; + } + else if ( aMode == EPredictiveQwerty ) + { + return iSpaceAndZeroOnSameKeyOnQwerty; + } + else + { + return EFalse; + } + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::SetSpaceAndZeroOnSameKey +// +// ---------------------------------------------------------------------------- +void CPcsKeyMap::SetSpaceAndZeroOnSameKey() + { + static const TInt KSpace = 0x20; // ASCII for " " + static const TInt KZero = 0x30; // ASCII for "0" + + TChar charSpace(KSpace); + TChar charZero(KZero); + + TPtiKey keySpace; + TPtiKey keyZero; + + // ITU-T mode + keySpace = KeyForCharacter(charSpace, EPredictiveItuT); + keyZero = KeyForCharacter(charZero, EPredictiveItuT); + iSpaceAndZeroOnSameKeyOnItut = (keySpace == keyZero); + + // QWERTY mode + keySpace = KeyForCharacter(charSpace, EPredictiveQwerty); + keyZero = KeyForCharacter(charZero, EPredictiveQwerty); + iSpaceAndZeroOnSameKeyOnQwerty = (keySpace == keyZero); + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::CPcsKeyMap::FirstCharFromSpellingL +// +// ---------------------------------------------------------------------------- +TChar CPcsKeyMap::FirstCharFromSpellingL( TChar aChar ) const + { + TChar translated( aChar ); + TBuf<1> temp; + temp.Append( aChar ); + if ( iAlgorithm->FindUtilECE()->IsChineseWordIncluded( temp ) ) + { + RPointerArray spellList; + CleanupResetAndDestroyPushL( spellList ); + if (iAlgorithm->FindUtilECE()->DoTranslationL(aChar, spellList)) + { + translated = (*spellList[0])[0]; + } + CleanupStack::PopAndDestroy( &spellList ); // ResetAndDestroy + } + return translated; + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::KeyMappings +// +// ---------------------------------------------------------------------------- +const RPointerArray* CPcsKeyMap::KeyMappings( TKeyboardModes aMode ) const + { + const RPointerArray* mappings = NULL; + + if ( aMode == EPredictiveItuT ) + { + mappings = &iItutKeyMappings; + } + else if ( aMode == EPredictiveQwerty ) + { + mappings = &iQwertyKeyMappings; + } + else if ( aMode == ENonPredictive ) + { + mappings = NULL; + } + else + { + mappings = NULL; + __ASSERT_DEBUG( EFalse, Panic( EPanic_InvalidKeyboardType ) ); + } + + return mappings; + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::ResolveKeyboardMode +// +// ---------------------------------------------------------------------------- +TKeyboardModes CPcsKeyMap::ResolveKeyboardMode( TKeyboardModes aKbMode ) const + { + TKeyboardModes resolvedMode = aKbMode; + + // Substitute "default predictive" mode with actual mode + if ( resolvedMode == EPredictiveDefaultKeyboard ) + { + resolvedMode = ( iItutIsDefault ? EPredictiveItuT : EPredictiveQwerty ); + } + + // Substitute predictive mode with non-predictive mode if corresponding + // keyboard mappings are not available. + if ( ( resolvedMode == EPredictiveItuT && iItutKeyboardType == EPtiKeyboardNone ) || + ( resolvedMode == EPredictiveQwerty && iQwertyKeyboardType == EPtiKeyboardNone ) ) + { + PRINT1( _L("CPcsKeyMap::ResolveKeyboardMode: Mappings for requested mode %d unavailable. Falling back to non-predictive mode!"), aKbMode ); + resolvedMode = ENonPredictive; + } + + return resolvedMode; + } + +// ---------------------------------------------------------------------------- +// CPcsKeyMap::DefaultCharForKey +// +// ---------------------------------------------------------------------------- +TText CPcsKeyMap::DefaultCharForKey( TPtiKey aKey, TKeyboardModes aKbMode ) const + { + // On ITU-T, the Pti key code can be directly interpreted as unicode character. + // Thus, default characters for keys are 1,2,3,4,5,6,7,8,9,0,*,#. + TText defChar = aKey; + + // On QWERTY, using PtiKey values directly is not safe since all PtiKey values are + // not codepoints of printable Unicode characters. + // Treating these arbitrary numerical values as Unicode characters could break + // the uniqueness of keys when collated comparison is used. Also, converting same + // data multiple times to "compare format" would then break the data. + if ( aKbMode == EPredictiveQwerty ) + { + // Take first mapped character of the key and convert it to upper case. + TInt index = iQwertyKeys.Find( aKey ); + if ( index != KErrNotFound ) + { + const RArray& mappings = iQwertyKeyMappings[index]->iKeyMappingArray; + if ( mappings.Count() ) + { + defChar = User::UpperCase( mappings[0] ); + } + } + } + + return defChar; + } +// End of file