predictivesearch/PcsAlgorithm/Algorithm1/src/CPcsKeyMap.cpp
branchRCL_3
changeset 63 f4a778e096c2
child 64 c1e8ba0c2b16
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/predictivesearch/PcsAlgorithm/Algorithm1/src/CPcsKeyMap.cpp	Wed Sep 01 12:29:52 2010 +0100
@@ -0,0 +1,1200 @@
+/*
+* 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 <CPcsDefs.h>
+#include <bldvariant.hrh>
+#include <PtiEngine.h>
+#include <PtiKeyMapData.h>
+#include <AknFepInternalCRKeys.h>
+#include <AvkonInternalCRKeys.h>
+#include <centralrepository.h>
+#include <CPsQuery.h>
+#include <CPsQueryItem.h>
+
+// 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()
+    {
+    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);
+    iLanguageNotSupported.Append(ELangKorean);
+
+    TPtiKeyboardType physicalItutKbType;
+    TPtiKeyboardType physicalQwertyKbType;    
+    GetPhysicalKeyboardTypesL( physicalItutKbType, physicalQwertyKbType );
+
+    iItutKeyboardType = EPtiKeyboard12Key; // We want to support Virtual Itu-T in most devices
+    CreateKeyMappingL( EPredictiveItuT ); // Create structure for holding characters<-->key mappings
+    if (iItutKeys.Count() == 0)
+        {
+        iItutKeyboardType = EPtiKeyboardNone;
+        }
+
+    iQwertyKeyboardType = physicalQwertyKbType;
+    if (physicalQwertyKbType != EPtiKeyboardNone)
+        {
+        CreateKeyMappingL( EPredictiveQwerty ); // Create structure for holding characters<-->key mappings
+        if (iQwertyKeys.Count() == 0)
+            {
+            iQwertyKeyboardType = EPtiKeyboardNone;
+            }
+        }
+
+    // Set the Default Predictive keyboard mode. If Qwerty keyboard exists, it is always physical.
+    iPredictiveDefaultKeyboardMode =
+        (IsItutPredictiveAvailable() && physicalItutKbType != EPtiKeyboardNone) || !IsQwertyPredictiveAvailable() ?
+            EPredictiveItuT : EPredictiveQwerty;
+
+    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 );
+
+    // 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 < iItutKeyMaps.Count(); i++)
+        {
+        for (TInt j = 0; j < TKeyMappingData::EKeyMapNumberArr; j++)
+            {
+            iItutKeyMaps[i]->iKeyMapCharArr[j].Close();
+            }
+        }
+    iItutKeyMaps.ResetAndDestroy();
+    
+    for (TInt i = 0; i < iQwertyKeyMaps.Count(); i++)
+        {
+        for (TInt j = 0; j < TKeyMappingData::EKeyMapNumberArr; j++)
+            {
+            iQwertyKeyMaps[i]->iKeyMapCharArr[j].Close();
+            }
+        }
+    iQwertyKeyMaps.ResetAndDestroy();
+    
+    iItutKeys.Close();
+    iQwertyKeys.Close();
+
+    PRINT ( _L("End CPcsKeyMap::~CPcsKeyMap") );
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsKeyMap::IsItutPredictiveAvailable
+// 
+// ----------------------------------------------------------------------------
+TBool CPcsKeyMap::IsItutPredictiveAvailable() const
+    {
+    return ( iItutKeyboardType != EPtiKeyboardNone );
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsKeyMap::IsQwertyPredictiveAvailable
+// 
+// ----------------------------------------------------------------------------
+TBool CPcsKeyMap::IsQwertyPredictiveAvailable() const
+    {
+    return ( iQwertyKeyboardType != EPtiKeyboardNone );
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsKeyMap::IsModePredictive
+// 
+// ----------------------------------------------------------------------------
+TBool CPcsKeyMap::IsModePredictive( TKeyboardModes aKbMode )
+    {
+    return ( (EPredictiveDefaultKeyboard == aKbMode) ||
+             (EPredictiveItuT == aKbMode) ||
+             (EPredictiveQwerty == aKbMode) );
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsKeyMap::ResolveKeyboardMode
+// Resolve EPredictiveDefaultKeyboard or ENonPredictive mode to EPredictiveItuT
+// or EPredictiveQwerty mode
+// ----------------------------------------------------------------------------
+TKeyboardModes CPcsKeyMap::ResolveKeyboardMode( TKeyboardModes aKbMode,
+                                                TKeyboardModes aKbModeToResolve ) const
+    {    
+    // Substitute "default predictive" mode with actual mode
+    if ( (aKbMode == aKbModeToResolve) &&
+         ((aKbMode == ENonPredictive) || (aKbMode == EPredictiveDefaultKeyboard)) )
+        {
+        return iPredictiveDefaultKeyboardMode;
+        }
+    else
+        {
+        return aKbMode;
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// 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") );
+
+    for ( TInt i = 0; i < aSrcData.Length(); ++i )
+        {
+        TChar character( aSrcData[i] );
+        character.LowerCase();
+        if ( i < aSrcQuery.Count() )
+            {
+            CPsQueryItem& currentItem = aSrcQuery.GetItemAtL(i);
+            TPtiKey key = KeyForCharacterMultiMatch( aSrcData[i], currentItem.Mode() );
+            // If a character is not mapped to any key or it's entered in non-predictive mode,
+            // then 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 );
+                }
+            }
+        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, TUint aIntChar) const
+    {
+    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(const RArray<TInt>& aPoolIndexArr, 
+                                               const TChar& aChar,
+                                               const RArray<TPtiKey>& aPtiKeys,
+                                               const RPointerArray<TKeyMappingData>& aKeyMappings) const
+    {
+    PRINT ( _L("CPcsKeyMap::CheckPotentialErrorConditions: ===================================================") );
+    PRINT ( _L("CPcsKeyMap::CheckPotentialErrorConditions: Checking potential error conditions") );
+    PRINT ( _L("CPcsKeyMap::CheckPotentialErrorConditions: ---------------------------------------------------") );
+
+    _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<TUint, TKeyMappingData::EKeyMapNumberArr> countArr;
+
+    for ( TInt j = TKeyMappingData::EKeyMapSingleCharArr; j <= TKeyMappingData::EKeyMapOthersLangArr; j++ )
+        {
+        countArr[j] = 0;
+        for ( TInt i = 0; i < aPoolIndexArr.Count(); i++ )
+            {
+            if ( KErrNotFound != aKeyMappings[aPoolIndexArr[i]]->iKeyMapCharArr[j].Find((TUint) aChar) )
+                {
+                PRINT5 ( _L("CPcsKeyMap::CheckPotentialErrorConditions: Char '%c' (0x%04X) %S for pool %d with key '%c'"),
+                        (TUint) aChar, (TUint) aChar, &charArrStr[j], aPoolIndexArr[i], aPtiKeys[aPoolIndexArr[i]] );
+                countArr[j]++;
+                }
+            }
+        }
+
+    PRINT ( _L("CPcsKeyMap::CheckPotentialErrorConditions: ===================================================") );
+    
+#ifdef __WINS__
+    /*
+    The reference 4x10 QWERTY mappings of 9.2 emulator have each number mapped to two keys.
+    That kind of mappings can't be handled correctly, so panic in debug would basically be correct.
+    However, assertions are commented out for now to be able to do some testing.
+    
+    // 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, TKeyboardModes aKbMode ) const
+    {    
+    aKbMode = ResolveKeyboardMode( aKbMode, EPredictiveDefaultKeyboard ); 
+
+    // Select key arrays to use according to keyboard mode
+    const RArray<TPtiKey>* ptiKeyArray;
+    const RPointerArray<TKeyMappingData>* keyMappingArray;
+    TPtiKeyboardType kbType;
+    GetPredictiveKeyboardData( aKbMode, ptiKeyArray, keyMappingArray, kbType );
+    if ( !ptiKeyArray || !keyMappingArray || ptiKeyArray->Count() == 0 )
+        {
+        // No mappings available. This may be, for example, because aKbMode is non-predictive.
+        // Return no mapping in that case to indicate that character should be treated in
+        // non-predictive way.
+        return EPtiKeyNone;
+        }
+    
+    // Set an array of pool index matches (more matches are possible)
+    RArray<TInt> poolIndexArr;
+    for ( TInt i = 0; i < keyMappingArray->Count(); i++ )
+        {
+        if ( CharacterForKeyMappingExists(*(*keyMappingArray)[i], (TUint) aChar) )
+            {
+            poolIndexArr.Append(i);
+
+            PRINT4 ( _L("CPcsKeyMap::KeyForCharacterMultiMatch: Char '%c' (0x%04X) found in pool %d with key '%c'"),
+                    (TUint) aChar, (TUint) aChar, i, (*ptiKeyArray)[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' (0x%04X) NOT found from any pool"),
+                 (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, (*ptiKeyArray)[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 == kbType)
+            {
+            for ( TInt i = 0; i < poolIndexArr.Count() ; i++ )
+                {
+                if ( EPtiKey1 == (*ptiKeyArray)[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, (*ptiKeyArray)[poolIndex] );
+                }
+            }
+
+#ifdef _DEBUG
+        CheckPotentialErrorConditions(poolIndexArr, aChar, *ptiKeyArray, *keyMappingArray);
+#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 = (*keyMappingArray)[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, (*ptiKeyArray)[poolIndex] );
+                        
+                            break;
+                            }
+                        }
+                    }
+                }
+            }
+                    
+        } // else -> ( poolIndexArr.Count() > 1 )
+
+    // Set the key value from the pool index
+    TPtiKey key = EPtiKeyNone;
+    if ( KErrNotFound != poolIndex )
+        {
+        key = (*ptiKeyArray)[poolIndex];
+        }
+    
+    poolIndexArr.Close();
+    return key;
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsKeyMap::PoolIdForKey
+//
+// ----------------------------------------------------------------------------
+TInt CPcsKeyMap::PoolIdForKey(const TPtiKey aKey, TKeyboardModes aKbMode)
+    {
+    aKbMode = ResolveKeyboardMode( aKbMode, EPredictiveDefaultKeyboard ); 
+
+    // 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 && IsItutPredictiveAvailable() )
+        {
+        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 && IsQwertyPredictiveAvailable() )
+        {
+        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(const 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 is no guarantee for this.
+    aKbMode = ResolveKeyboardMode( aKbMode, ENonPredictive ); 
+
+    TPtiKey key = KeyForCharacterMultiMatch( aChar, aKbMode );
+
+    TInt poolId = PoolIdForKey(key, aKbMode);
+
+    return poolId;
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsKeyMap::PoolCount
+//
+// ----------------------------------------------------------------------------
+TInt CPcsKeyMap::PoolCount()
+    {
+    return iItutKeyMaps.Count() + iQwertyKeyMaps.Count();
+    }
+
+// ----------------------------------------------------------------------------
+// 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 = KeyForCharacterMultiMatch(charSpace, EPredictiveItuT);
+    keyZero = KeyForCharacterMultiMatch(charZero, EPredictiveItuT);
+    iSpaceAndZeroOnSameKeyOnItut = (keySpace == keyZero && keyZero != EPtiKeyNone);
+    PRINT1 ( _L("CPcsKeyMap::iSpaceAndZeroOnSameKeyOnItut = %d"), iSpaceAndZeroOnSameKeyOnItut );
+    
+    // QWERTY mode
+    keySpace = KeyForCharacterMultiMatch(charSpace, EPredictiveQwerty);
+    keyZero = KeyForCharacterMultiMatch(charZero, EPredictiveQwerty);
+    iSpaceAndZeroOnSameKeyOnQwerty = (keySpace == keyZero && keyZero != EPtiKeyNone);
+    PRINT1 ( _L("CPcsKeyMap::iSpaceAndZeroOnSameKeyOnQwerty = %d"), iSpaceAndZeroOnSameKeyOnQwerty );
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsKeyMap::GetSpaceAndZeroOnSameKey
+// 
+// ----------------------------------------------------------------------------
+TBool CPcsKeyMap::GetSpaceAndZeroOnSameKey( TKeyboardModes aKbMode )
+    {
+    TBool result = EFalse;
+
+    aKbMode = ResolveKeyboardMode( aKbMode, EPredictiveDefaultKeyboard );
+
+    if ( aKbMode == EPredictiveItuT )
+        {
+        result = iSpaceAndZeroOnSameKeyOnItut;
+        }
+    else if ( aKbMode == EPredictiveQwerty )
+        {
+        result = iSpaceAndZeroOnSameKeyOnQwerty;
+        }
+
+    return result;
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsKeyMap::GetPhysicalKeyboardTypesL
+// Initialise the keyboard type variables
+// ----------------------------------------------------------------------------
+void CPcsKeyMap::GetPhysicalKeyboardTypesL( TPtiKeyboardType& aItutKbType,
+                                            TPtiKeyboardType& aQwertyKbType )
+    {
+    TInt physicalKeyboard = 0;
+    CRepository* aknFepRepository = CRepository::NewL( KCRUidAknFep );
+    aknFepRepository->Get( KAknFepPhysicalKeyboards, physicalKeyboard );
+    delete aknFepRepository;
+
+    PRINT1 ( _L("CPcsKeyMap::GetPhysicalKeyboardTypesL: 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; 
+
+    // Get ITU-T mode first.
+    // Use always 12-key mode since all the supported devices should have at least
+    // virtual ITU-T available.
+    // It will be set to EPtiKeyboardNone if getting the key list will fail.
+    if ( physicalKeyboard & KPtiKeyboard12Key )
+        {
+        aItutKbType = EPtiKeyboard12Key;
+        }
+    else
+        {
+        aItutKbType = EPtiKeyboardNone;
+        }
+    
+    // Then get 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
+    // It will be set to EPtiKeyboardNone if getting the key list will fail.
+    if ( physicalKeyboard & KPtiKeyboardQwerty3x11 )
+        {
+        aQwertyKbType = EPtiKeyboardQwerty3x11;
+        }
+    else if ( physicalKeyboard & KPtiKeyboardQwerty4x10 )
+        {
+        aQwertyKbType = EPtiKeyboardQwerty4x10;
+        }
+    else if ( physicalKeyboard & KPtiKeyboardQwerty4x12 )
+        {
+        aQwertyKbType = EPtiKeyboardQwerty4x12;
+        }
+    else if ( physicalKeyboard & KPtiKeyboardCustomQwerty )
+        {
+        aQwertyKbType = EPtiKeyboardCustomQwerty;
+        }
+    else if ( physicalKeyboard & KPtiKeyboardHalfQwerty )
+        {
+        aQwertyKbType = EPtiKeyboardHalfQwerty;
+        }
+    else
+        {
+        aQwertyKbType = EPtiKeyboardNone;
+        }
+        
+    PRINT1 ( _L("CPcsKeyMap::GetPhysicalKeyboardTypesL: Physical ITU-T Keyboard = %d"), aItutKbType );
+    PRINT1 ( _L("CPcsKeyMap::GetPhysicalKeyboardTypesL: Physical QWERTY Keyboard = %d"), aQwertyKbType );
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsKeyMap::AppendEntryWithFakeKeyToKeyList
+// Add pool with unused id for for key
+// ----------------------------------------------------------------------------
+void CPcsKeyMap::AppendEntryWithFakeKeyToKeyList( RArray<TPtiKey>& aKeyArray )
+    {
+    TUint keyUInt = (TUint) EPtiKeyNone + 1;
+
+    while ( KErrNotFound != aKeyArray.Find( (TPtiKey) keyUInt) )
+        {
+        keyUInt++;
+        }
+
+    TPtiKey key = (TPtiKey) keyUInt;
+    aKeyArray.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"),
+            aKeyArray.Count()-1, key );
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsKeyMap::CreateKeyMapFromKeyBindingTable
+//
+// ----------------------------------------------------------------------------
+void CPcsKeyMap::CreateKeyListFromKeyBindingTable( RArray<TPtiKey>& aKeyArray, 
+        TPtiKeyboardType aKbType, CPtiEngine* aPtiEngine )
+    {
+    PRINT ( _L("Enter CPcsKeyMap::CreateKeyListFromKeyBindingTable") );
+
+    PRINT1 ( _L("CPcsKeyMap::CreateKeyListFromKeyBindingTable: Creating KeyList for TPtiKeyboardType=%d"),
+             aKbType  );
+
+    // 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<CPtiCoreLanguage*>(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<CPtiCoreLanguage*>(aPtiEngine->GetLanguage( ELangEnglish ));
+        }
+
+    if (currLanguage)
+        {
+        TInt langCode = currLanguage->LanguageCode();
+        TRAP_IGNORE( aPtiEngine->ActivateLanguageL( langCode ) );
+        const CPtiKeyMapData* keyMapData = currLanguage->RawKeyMapData();
+        const TPtiKeyBinding* table = NULL;
+        TInt numItems = 0;
+        if ( keyMapData )
+            {
+            table = keyMapData->KeyBindingTable(aKbType, numItems);
+            }
+        else
+            {
+            PRINT1( _L("CPcsKeyMap::CreateKeyListFromKeyBindingTable: #### Failed to get RawKeyMapData for language %d ####"), langCode );
+            }
+        
+        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 );
+                    }
+                }
+            // Add a fake key at the end if the KeyList is not empty
+            if (aKeyArray.Count() > 0)
+                {
+                AppendEntryWithFakeKeyToKeyList(aKeyArray);
+                }
+            }
+        else
+            {
+            PRINT ( _L("CPcsKeyMap::CreateKeyListFromKeyBindingTable: ##### Failed to create Key List (KeyBindingTable) #####") );
+            }
+        }
+    else
+        {
+        PRINT ( _L("CPcsKeyMap::CreateKeyListFromKeyBindingTable: ##### Failed to create Key List (Language) #####") );
+        }
+
+    PRINT ( _L("End CPcsKeyMap::CreateKeyListFromKeyBindingTable") );
+}
+
+// ----------------------------------------------------------------------------
+// CPcsKeyMap::IsLanguageSupported
+// Returns ETrue if this language is supported
+// ----------------------------------------------------------------------------
+TBool CPcsKeyMap::IsLanguageSupported(TInt aLang)
+    {
+    TBool supported = 
+#ifdef __WINS__
+            // Only few languages for emulator 
+            ( ELangEnglish == aLang || 
+              ELangRussian == aLang || 
+              ELangHebrew == aLang || 
+              ELangFinnish == aLang ) &&
+#endif // __WINS__
+            ( KErrNotFound == iLanguageNotSupported.Find((TLanguage)aLang) );
+                
+    return supported;
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsKeyMap::CreateKeyMappingL
+//
+// ----------------------------------------------------------------------------
+void CPcsKeyMap::CreateKeyMappingL( TKeyboardModes aKbMode )
+    {
+    PRINT ( _L("Enter CPcsKeyMap::CreateKeyMappingL") );
+
+    __ASSERT_DEBUG( (aKbMode==EPredictiveItuT || aKbMode==EPredictiveQwerty),
+                    Panic(EPanic_InvalidKeyboardType) );
+
+    // Select the arrays we are operating on
+    RArray<TPtiKey>* ptiKeysArray;
+    RPointerArray<TKeyMappingData>* keyMappingArray;
+    TPtiKeyboardType kbType;
+    GetPredictiveKeyboardData( aKbMode, ptiKeysArray, keyMappingArray, kbType );
+    if ( kbType == EPtiKeyboardNone )
+        {
+        PRINT1( _L("CPcsKeyMap::CreateKeyMappingL: ##### No Keyboard available for mode %d => skipping #####"), aKbMode );
+        return;
+        }
+    
+    // Instantiate the engine
+    CPtiEngine* ptiEngine = CPtiEngine::NewL(ETrue);
+    CleanupStack::PushL( ptiEngine );
+
+    ptiEngine->SetKeyboardType( kbType );
+
+    CreateKeyListFromKeyBindingTable( *ptiKeysArray, kbType, ptiEngine );
+
+    if ( ptiKeysArray->Count() > 0 )
+        {
+        // Now add the keymap arrays to hold the keymap data
+        for (TInt i = 0; i < ptiKeysArray->Count(); i++)
+            {
+            TKeyMappingData *keyData = new(ELeave) TKeyMappingData;
+            keyMappingArray->Append(keyData);
+            }
+    
+        // Get the available Languages on the phone
+        RArray<TInt> languagesOnThisPhone;
+        CleanupClosePushL( 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]) )
+                {
+                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 );
+            TRAPD( leaveCode, AddKeyMappingForLanguageL(ptiEngine, languageToUse, kbType, *ptiKeysArray, *keyMappingArray) );
+            if ( leaveCode )
+                {
+                PRINT2 ( _L("CPcsKeyMap::CreateKeyMappingL: ##### Adding mappings for language %d failed, leave code = %d #####"),
+                         languageToUse, leaveCode );
+                }
+    
+            PRINT ( _L("CPcsKeyMap::CreateKeyMappingL: ===================================================") );
+            }
+    
+        CleanupStack::PopAndDestroy( &languagesOnThisPhone );
+        }
+
+    CleanupStack::PopAndDestroy( ptiEngine );
+
+    PRINT ( _L("End CPcsKeyMap::CreateKeyMappingL") );
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsKeyMap::AddKeyMappingForActiveLanguageL
+//
+// ----------------------------------------------------------------------------
+void CPcsKeyMap::AddKeyMappingForLanguageL(
+        CPtiEngine* aPtiEngine, 
+        TLanguage aLanguage,
+        TPtiKeyboardType aKbType,
+        const RArray<TPtiKey>& aPtiKeys,
+        RPointerArray<TKeyMappingData>& aResultMapping )
+{
+    PRINT ( _L("Enter CPcsKeyMap::AddKeyMappingForLanguageL") );
+
+    TInt err = aPtiEngine->ActivateLanguageL( aLanguage );
+    if ( err )
+        {
+        PRINT2 ( _L("##### CPcsKeyMap::AddKeyMappingForLanguageL failed to activate language %d, error=%d) #####"),
+                aLanguage, err );
+        User::Leave( err );
+        }
+
+    // Make a language object based on the language
+    CPtiCoreLanguage* language = static_cast<CPtiCoreLanguage*>(aPtiEngine->GetLanguage( aLanguage ));
+
+    if (language)
+        {
+        for (TInt i = 0; i < aResultMapping.Count() - 1; i++)
+            {
+            TPtiKey key = aPtiKeys[i];
+
+            PRINT ( _L("CPcsKeyMap::AddKeyMappingForLanguageL: ===================================================") );
+            PRINT4 ( _L("CPcsKeyMap::AddKeyMappingForLanguageL: Adding chars for Key '%c' (0x%02X) for Keyboard Type %d and Language %d"),
+                     key, key, aKbType, aLanguage );
+
+            // Get the pointer to the language class (UI, English, Others)
+            RArray<TUint>* keyMapLang;
+            if (aLanguage == iUILanguage)
+                {
+                keyMapLang = &(aResultMapping[i]->iKeyMapCharArr[TKeyMappingData::EKeyMapUILangArr]);
+                PRINT1 ( _L("CPcsKeyMap::AddKeyMappingForLanguageL: Language %d is the UI language"), aLanguage );
+                }
+            else if (aLanguage == ELangEnglish)
+                {
+                // If (iUILanguage == ELangEnglish) ok to be in previous if case
+                keyMapLang = &(aResultMapping[i]->iKeyMapCharArr[TKeyMappingData::EKeyMapEnglishLangArr]);
+                PRINT1 ( _L("CPcsKeyMap::AddKeyMappingForLanguageL: Language %d is English language"), aLanguage );
+                }
+            else
+                {
+                keyMapLang = &(aResultMapping[i]->iKeyMapCharArr[TKeyMappingData::EKeyMapOthersLangArr]);
+                PRINT1 ( _L("CPcsKeyMap::AddKeyMappingForLanguageL: Language %d is in the Other languages"), aLanguage );
+                }
+            
+            PRINT ( _L("CPcsKeyMap::AddKeyMappingForLanguageL: ---------------------------------------------------") );
+
+            TBool isSingleCharForKey = ETrue;
+            TUint singleChar = 0;
+
+            // EPtiCaseUpper must be the 1st TPtiTextCase for iUILanguage
+            AddCharactersToKey( *language, aKbType, key, EPtiCaseUpper, *aResultMapping[i], *keyMapLang, isSingleCharForKey, singleChar );
+            AddCharactersToKey( *language, aKbType, key, EPtiCaseLower, *aResultMapping[i], *keyMapLang, isSingleCharForKey, singleChar );
+
+            // 1. No other TPtiTextCase values for ITUT keyboard
+            // 2. No language variants handling for ITUT keyboard
+            if ( EPtiKeyboard12Key != aKbType )
+                {
+                AddCharactersToKey( *language, aKbType, key, EPtiCaseFnLower,  *aResultMapping[i], *keyMapLang, isSingleCharForKey, singleChar );
+                AddCharactersToKey( *language, aKbType, key, EPtiCaseFnUpper,  *aResultMapping[i], *keyMapLang, isSingleCharForKey, singleChar );
+                AddCharactersToKey( *language, aKbType, key, EPtiCaseChrLower, *aResultMapping[i], *keyMapLang, isSingleCharForKey, singleChar );
+                AddCharactersToKey( *language, aKbType, key, EPtiCaseChrUpper, *aResultMapping[i], *keyMapLang, isSingleCharForKey, singleChar );
+
+                // Support for key guessing given the char in some phone language variants
+                if ( (isSingleCharForKey) && (0 != singleChar) )
+                    {
+                    aResultMapping[i]->iKeyMapCharArr[TKeyMappingData::EKeyMapSingleCharArr].Append(singleChar); // singleChar is in LowerCase
+                    aResultMapping[i]->iKeyMapCharArr[TKeyMappingData::EKeyMapSingleCharArr].Append(User::UpperCase(singleChar));
+
+                    PRINT ( _L("CPcsKeyMap::AddKeyMappingForLanguageL: ---------------------------------------------------") );
+                    PRINT5 ( _L("CPcsKeyMap::AddKeyMappingForLanguageL: For Language %d and key '%c' of pool %d single char is '%c' (0x%04X)"),
+                            aLanguage, key, i, singleChar, singleChar );
+                    }
+                }
+            }
+        PRINT ( _L("CPcsKeyMap::AddKeyMappingForLanguageL: ===================================================") );
+        }
+
+    PRINT ( _L("End CPcsKeyMap::AddKeyMappingForLanguageL") );
+}
+
+// ----------------------------------------------------------------------------
+// CPcsKeyMap::GetCharactersForKey
+//
+// ----------------------------------------------------------------------------
+void CPcsKeyMap::GetCharactersForKey(CPtiCoreLanguage& aPtiLanguage,
+                                     TPtiKeyboardType aKbType,
+                                     TPtiKey aKey,
+                                     TPtiTextCase aTextCase,
+                                     TDes& aResult)
+    {
+    const CPtiKeyMapData* keyMapData = aPtiLanguage.RawKeyMapData();
+    if  ( keyMapData )
+        {
+        TPtrC dataPtr = keyMapData->DataForKey( aKbType, aKey, aTextCase );
+        // truncate results if supplied buffer is not large enough
+        aResult = dataPtr.Left( aResult.MaxLength() );
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsKeyMap::AddDataForKeyL
+//
+// ----------------------------------------------------------------------------
+void CPcsKeyMap::AddCharactersToKey(CPtiCoreLanguage& aPtiLanguage,
+                                    TPtiKeyboardType aKbType,
+                                    TPtiKey aKey,
+                                    TPtiTextCase aTextCase,
+                                    TKeyMappingData& aKeyDataList,
+                                    RArray<TUint>& aKeyMapLang,
+                                    TBool& aIsSingleCharForKey,
+                                    TUint& aSingleChar)
+    {
+    PRINT ( _L("Enter CPcsKeyMap::AddCharactersToKey") );
+
+    TBuf<255> result;
+    GetCharactersForKey(aPtiLanguage, aKbType, aKey, aTextCase, result);
+
+    PRINT3 ( _L("CPcsKeyMap::AddCharactersToKey: Get mapping chars for Key '%c' (0x%02X) and TextCase %d"),
+             aKey, aKey, aTextCase );
+    PRINT1 ( _L("CPcsKeyMap::AddCharactersToKey: Got chars: \"%S\""), &result );
+
+    for ( TInt i = 0; i < result.Length(); i++ )
+        {
+        TText character = result[i];
+        if ( !CharacterForKeyMappingExists(aKeyDataList, character ) )
+            {
+            PRINT2 ( _L("CPcsKeyMap::AddCharactersToKey: ----- Appending char to list: '%c' (0x%04X)"), character, character );
+            aKeyMapLang.Append(character);
+            }
+        else
+            {
+            PRINT2 ( _L("CPcsKeyMap::AddCharactersToKey: ***** NOT Appending char to list: '%c' (0x%04X)"), character, character );
+            }
+
+        // No language variants handling for ITUT keyboard
+        if ( EPtiKeyboard12Key != aKbType )
+            {
+            // Support for key guessing given the char in some phone language variants
+            if ( aIsSingleCharForKey )
+                {
+                if ( 0 == aSingleChar )
+                    {
+                    aSingleChar = User::LowerCase(character);
+                    }
+                else
+                    {
+                    TInt newChar = User::LowerCase(character);
+                    if (newChar != aSingleChar)
+                        {
+                        aSingleChar = 0;
+                        aIsSingleCharForKey = EFalse;
+                        }
+                    }
+                }
+            }
+        }
+
+    PRINT ( _L("CPcsKeyMap::AddCharactersToKey: ---------------------------------------------------") );
+
+    PRINT ( _L("End CPcsKeyMap::AddCharactersToKey") );
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsKeyMap::GetPredictiveKeyboardData
+//
+// ----------------------------------------------------------------------------
+void CPcsKeyMap::GetPredictiveKeyboardData( TKeyboardModes aKbMode, 
+                                            RArray<TPtiKey>*& aPtiKeys, 
+                                            RPointerArray<TKeyMappingData>*& aKeyMappings, 
+                                            TPtiKeyboardType& aKbType )
+    {
+    // Get the data from constant version of this function
+    const RArray<TPtiKey>* constKeys;
+    const RPointerArray<TKeyMappingData>* constMappings;
+    GetPredictiveKeyboardData( aKbMode, constKeys, constMappings, aKbType );
+    
+    // Convert pointers to non-const
+    aPtiKeys = const_cast< RArray<TPtiKey>* >( constKeys );
+    aKeyMappings = const_cast< RPointerArray<TKeyMappingData>* >( constMappings );
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsKeyMap::GetPredictiveKeyboardData
+//
+// ----------------------------------------------------------------------------
+void CPcsKeyMap::GetPredictiveKeyboardData( TKeyboardModes aKbMode, 
+                                            const RArray<TPtiKey>*& aPtiKeys, 
+                                            const RPointerArray<TKeyMappingData>*& aKeyMappings, 
+                                            TPtiKeyboardType& aKbType ) const
+    {
+    PRINT1 ( _L("CPcsKeyMap::GetPredictiveKeyboardData: aKbMode=%d "), aKbMode );
+    
+    // EPredictiveItuT or EPredictiveQwerty mode to ENonPredictive mode if keyboard is not mapped
+    if ( aKbMode == EPredictiveItuT && !IsItutPredictiveAvailable() )
+        {
+        aKbMode = ENonPredictive;
+        }
+    if ( aKbMode == EPredictiveQwerty && !IsQwertyPredictiveAvailable() )
+        {
+        aKbMode = ENonPredictive;
+        }
+
+    // Get Predictive Keyboard Data
+    switch (aKbMode)
+        {
+        case EPredictiveItuT:
+            aPtiKeys = &iItutKeys;
+            aKeyMappings = &iItutKeyMaps;
+            aKbType = iItutKeyboardType;
+            break;
+
+        case EPredictiveQwerty:
+            aPtiKeys = &iQwertyKeys;
+            aKeyMappings = &iQwertyKeyMaps;
+            aKbType = iQwertyKeyboardType;
+            break;
+
+        case ENonPredictive:
+            aPtiKeys = NULL;
+            aKeyMappings = NULL;
+            aKbType = EPtiKeyboardNone;
+            break;
+
+        // EPredictiveDefaultKeyboard must have been resolved previously
+        // to EPredictiveItuT or EPredictiveQwerty mode
+        case EPredictiveDefaultKeyboard: 
+        default:
+            aPtiKeys = NULL;
+            aKeyMappings = NULL;
+            aKbType = EPtiKeyboardNone;
+            __ASSERT_DEBUG( EFalse, Panic( EPanic_InvalidKeyboardType ) );
+            break;
+        }
+    }
+
+// End of file