predictivesearch/PcsAlgorithm/Algorithm1/src/CPcsKeyMap.cpp
changeset 0 e686773b3f54
child 15 e8e3147d53eb
--- /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 <CPcsDefs.h>
+#include <bldvariant.hrh>
+#include <PtiDefs.h>
+#include <PtiKeyMappings.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,
+   };
+
+    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<TInt>& 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<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 != 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<TInt> 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<CPtiQwertyKeyMappings*>(ptiKeyMappings)->KeyMapData();
+            break;
+
+        case EPtiKeyboard12Key:
+            keyMapData = static_cast<CPtiKeyMappings*>(ptiKeyMappings)->KeyMapData();
+            break;
+
+        case EPtiKeyboardHalfQwerty:
+            keyMapData = static_cast<CPtiHalfQwertyKeyMappings*>(ptiKeyMappings)->KeyMapData();
+            break;
+
+        default:
+            keyMapData = static_cast<CPtiKeyMappings*>(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<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 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<TInt> 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<CPtiCoreLanguage*>(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<TUint>* 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<CPtiQwertyKeyMappings*>(&aPtiKeyMappings))->GetDataForKey(aKey, aResult, aTextCase);
+            break;
+
+        case EPtiKeyboard12Key:
+            (static_cast<CPtiKeyMappings*>(&aPtiKeyMappings))->GetDataForKey(aKey, aResult, aTextCase);
+            break;
+
+        case EPtiKeyboardHalfQwerty:
+            (static_cast<CPtiHalfQwertyKeyMappings*>(&aPtiKeyMappings))->GetDataForKey(aKey, aResult, aTextCase);
+            break;
+
+        default:
+            (static_cast<CPtiKeyMappings*>(&aPtiKeyMappings))->GetDataForKey(aKey, aResult, aTextCase);
+            break;
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsKeyMap::AddDataForKeyL
+//
+// ----------------------------------------------------------------------------
+void CPcsKeyMap::AddCharactersToKey(MPtiKeyMappings& aPtiKeyMappings,
+                                    TPtiKey aKey,
+                                    TPtiTextCase aTextCase,
+                                    TKeyMappingData& aKeyDataList,
+                                    RArray<TUint>& 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