predictivesearch/PcsAlgorithm/Algorithm2/src/CPcsAlgorithm2Helper.cpp
branchRCL_3
changeset 63 f4a778e096c2
child 64 c1e8ba0c2b16
child 85 38bb213f60ba
equal deleted inserted replaced
62:5b6f26637ad3 63:f4a778e096c2
       
     1 /*
       
     2 * Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: Predictive Contact Search Algorithm 1 helper class
       
    15 *
       
    16 */
       
    17 
       
    18 // INCLUDES
       
    19 #include <PbkGlobalSettingFactory.h>
       
    20 #include "FindUtilChineseECE.h"
       
    21 #include "CPcsAlgorithm2.h"
       
    22 #include "CPcsAlgorithm2Helper.h"
       
    23 #include "CPcsAlgorithm2Utils.h"
       
    24 #include "CPcsDebug.h"
       
    25 #include "CPcsCache.h"
       
    26 #include "CPcsKeyMap.h"
       
    27 #include "CPsData.h"
       
    28 #include "CPsQuery.h"
       
    29 #include "CPsQueryItem.h"
       
    30 #include "CPsDataPluginInterface.h"
       
    31 #include "CPcsPoolElement.h"
       
    32 
       
    33 
       
    34 // ============================== MEMBER FUNCTIONS ============================
       
    35 
       
    36 // ----------------------------------------------------------------------------
       
    37 // CPcsAlgorithm2Helper::NewL
       
    38 // Two Phase Construction
       
    39 // ----------------------------------------------------------------------------
       
    40 CPcsAlgorithm2Helper* CPcsAlgorithm2Helper::NewL(CPcsAlgorithm2* aAlgorithm)
       
    41     {
       
    42     PRINT ( _L("Enter CPcsAlgorithm2Helper::NewL") );
       
    43 
       
    44     CPcsAlgorithm2Helper* self = new (ELeave) CPcsAlgorithm2Helper();
       
    45     CleanupStack::PushL(self);
       
    46     self->ConstructL(aAlgorithm);
       
    47     CleanupStack::Pop(self);
       
    48 
       
    49     PRINT ( _L("End CPcsAlgorithm2Helper::NewL") );
       
    50 
       
    51     return self;
       
    52     }
       
    53 
       
    54 // ----------------------------------------------------------------------------
       
    55 // CPcsAlgorithm2Helper::CPcsAlgorithm2Helper
       
    56 // Two Phase Construction
       
    57 // ----------------------------------------------------------------------------
       
    58 CPcsAlgorithm2Helper::CPcsAlgorithm2Helper()
       
    59     {
       
    60     PRINT ( _L("Enter CPcsAlgorithm2Helper::CPcsAlgorithm2") );
       
    61     PRINT ( _L("End CPcsAlgorithm2Helper::CPcsAlgorithm2") );
       
    62     iMaxCount = 0;
       
    63     }
       
    64 
       
    65 // ----------------------------------------------------------------------------
       
    66 // CPcsAlgorithm2Helper::ConstructL
       
    67 // Two Phase Construction
       
    68 // ----------------------------------------------------------------------------
       
    69 void CPcsAlgorithm2Helper::ConstructL(CPcsAlgorithm2* aAlgorithm)
       
    70     {
       
    71     PRINT ( _L("Enter CPcsAlgorithm2Helper::ConstructL") );
       
    72 
       
    73     iAlgorithm = aAlgorithm;
       
    74     iKeyMap = iAlgorithm->GetKeyMap();
       
    75 
       
    76     iPbkSettings = PbkGlobalSettingFactory::CreatePersistentSettingL();
       
    77     iPbkSettings->ConnectL( MPbkGlobalSetting::EGeneralSettingCategory );
       
    78     iPbkSettings->RegisterObserverL( this );
       
    79     UpdateNameOrderL();
       
    80     
       
    81     PRINT ( _L("End CPcsAlgorithm2Helper::ConstructL") );
       
    82     }
       
    83 
       
    84 // ----------------------------------------------------------------------------
       
    85 // CPcsAlgorithm2Helper::~CPcsAlgorithm2Helper
       
    86 // Destructor
       
    87 // ----------------------------------------------------------------------------
       
    88 CPcsAlgorithm2Helper::~CPcsAlgorithm2Helper()
       
    89     {
       
    90     PRINT ( _L("Enter CPcsAlgorithm2Helper::~CPcsAlgorithm2Helper") );
       
    91     iSearchResultsArr.ResetAndDestroy();
       
    92     PRINT ( _L("End CPcsAlgorithm2Helper::~CPcsAlgorithm2Helper") );
       
    93     }
       
    94 
       
    95 // ----------------------------------------------------------------------------
       
    96 // CPcsAlgorithm2Helper::SearchSingleL
       
    97 // Search function for input with both ITU-T and QWERTY mode
       
    98 // ----------------------------------------------------------------------------
       
    99 void CPcsAlgorithm2Helper::SearchSingleL(const CPsSettings& aSettings,
       
   100                                          CPsQuery& aPsQuery, 
       
   101                                          TBool aIsSearchInGroup,
       
   102                                          const RArray<TInt>& aContactsInGroup,
       
   103                                          RPointerArray<CPsData>& aSearchResults,
       
   104                                          RPointerArray<CPsPattern>& aSearchSeqs)
       
   105     {
       
   106     PRINT ( _L("Enter CPcsAlgorithm2Helper::SearchSingleL") );
       
   107 
       
   108     //__LATENCY_MARK ( _L("CPcsAlgorithm2Helper::SearchSingleL") );
       
   109 
       
   110     iMaxCount = aSettings.MaxResults();
       
   111     
       
   112     // Create filtering helper for the required sort type
       
   113     TSortType sortType = aSettings.GetSortType();
       
   114     CPcsAlgorithm2FilterHelper* filterHelper =
       
   115             CPcsAlgorithm2FilterHelper::NewL(sortType);
       
   116     CleanupStack::PushL( filterHelper );
       
   117     
       
   118     // Search from cache based on first character
       
   119     const CPsQueryItem& firstCharItem = aPsQuery.GetItemAtL(0);
       
   120     TInt cachePoolId = iKeyMap->PoolIdForCharacter( firstCharItem.Character(), firstCharItem.Mode() );
       
   121 
       
   122     // Reset the result set array for new search
       
   123     iSearchResultsArr.ResetAndDestroy();
       
   124 
       
   125     // Get the data stores
       
   126     RPointerArray<TDesC> dataStores;
       
   127     CleanupResetAndDestroyPushL( dataStores );
       
   128     aSettings.SearchUrisL(dataStores);
       
   129 
       
   130     // Get the required display fields from the client
       
   131     RArray<TInt> requiredDataFields;
       
   132     CleanupClosePushL( requiredDataFields );
       
   133     aSettings.DisplayFieldsL(requiredDataFields);
       
   134 
       
   135     // Perform search for each required data store
       
   136     RPointerArray<CPcsPoolElement> elements;
       
   137     CleanupClosePushL( elements );
       
   138     const TInt dataStoresCount = dataStores.Count();
       
   139 
       
   140     for (TInt dsIndex = 0; dsIndex < dataStoresCount; dsIndex++)
       
   141         {
       
   142         RPointerArray<CPsData>* temp = new (ELeave) RPointerArray<CPsData> ();
       
   143         CleanupStack::PushL( temp );
       
   144         iSearchResultsArr.AppendL( temp );
       
   145         CleanupStack::Pop( temp );
       
   146 
       
   147         // Get the contents for this data store
       
   148         TInt arrayIndex = iAlgorithm->GetCacheIndex(*(dataStores[dsIndex]));
       
   149         if (arrayIndex < 0)
       
   150             {
       
   151             continue;
       
   152             }
       
   153         CPcsCache* cache = iAlgorithm->GetCache(arrayIndex);
       
   154         cache->GetContactsForKeyL(cachePoolId, elements);
       
   155 
       
   156         // Get the supported data fields for this data store
       
   157         RArray<TInt> supportedDataFields;
       
   158         CleanupClosePushL( supportedDataFields );
       
   159         cache->GetDataFields(supportedDataFields);
       
   160 
       
   161         // Get the filtered data fields for this data store
       
   162         TUint8 filteredDataMatch = CPcsAlgorithm2Utils::FilterDataFieldsL(requiredDataFields,
       
   163                                                                           supportedDataFields);
       
   164 
       
   165         // Perform filtering
       
   166         FilterResultsSingleL(filterHelper,
       
   167                              elements,
       
   168                              aPsQuery,
       
   169                              filteredDataMatch,
       
   170                              aIsSearchInGroup,
       
   171                              aContactsInGroup);
       
   172 
       
   173         // If alphabetical sorting, get the results for this datastore
       
   174         if (sortType == EAlphabetical)
       
   175             {
       
   176             filterHelper->GetResults(*(iSearchResultsArr[dsIndex]));
       
   177             }
       
   178 
       
   179         elements.Reset();
       
   180         CleanupStack::PopAndDestroy( &supportedDataFields ); // Close
       
   181         }
       
   182 
       
   183     CleanupStack::PopAndDestroy( &elements );           // Close
       
   184     CleanupStack::PopAndDestroy( &requiredDataFields ); // Close
       
   185     CleanupStack::PopAndDestroy( &dataStores );         // ResetAndDestroy
       
   186 
       
   187     // If alphabetical sorting, merge the result sets of all datastores
       
   188     if (sortType == EAlphabetical)
       
   189         {
       
   190         // Form the complete searchResults array
       
   191         CPcsAlgorithm2Utils::FormCompleteSearchResultsL(iSearchResultsArr,
       
   192                                                         aSearchResults);
       
   193         }
       
   194     else
       
   195         {
       
   196         // Results are already sorted pattern based
       
   197         filterHelper->GetResults(aSearchResults);
       
   198         }
       
   199 
       
   200     // Get the sorted match sequence list
       
   201     filterHelper->GetPatternsL(aSearchSeqs);
       
   202 
       
   203     PRINT1 ( _L("Number of search results = %d"), aSearchResults.Count() );
       
   204 
       
   205     // Cleanup
       
   206     const TInt searchResultsArrCount = iSearchResultsArr.Count();
       
   207     for (TInt i = 0; i < searchResultsArrCount; i++)
       
   208         {
       
   209         iSearchResultsArr[i]->Reset();
       
   210         }
       
   211     iSearchResultsArr.ResetAndDestroy();
       
   212 
       
   213     CleanupStack::PopAndDestroy( filterHelper );
       
   214 
       
   215     //__LATENCY_MARKEND ( _L("CPcsAlgorithm2Helper::SearchSingleL") );
       
   216 
       
   217     PRINT ( _L("End CPcsAlgorithm2Helper::SearchSingleL") );
       
   218     }
       
   219 
       
   220 // ----------------------------------------------------------------------------
       
   221 // CPcsAlgorithm2Helper::SearchMatchSeqL
       
   222 // Function to search matching sequences in the input text
       
   223 // ----------------------------------------------------------------------------
       
   224 void CPcsAlgorithm2Helper::SearchMatchSeqL(CPsQuery& aPsQuery,
       
   225                                            const TDesC& aData,
       
   226                                            RPointerArray<TDesC>& aMatchSet,
       
   227                                            RArray<TPsMatchLocation>& aMatchLocation )
       
   228     {
       
   229     PRINT ( _L("Enter CPcsAlgorithm2Helper::SearchMatchSeqL") );
       
   230 
       
   231     RArray<TInt> matchPos;
       
   232     CleanupClosePushL( matchPos );
       
   233     RArray<TInt> matchLen;
       
   234     CleanupClosePushL( matchLen );
       
   235     if ( iAlgorithm->FindUtilECE()->MatchRefineL( aData, aPsQuery, matchPos, matchLen, ETrue ) )
       
   236         {
       
   237         ASSERT( matchPos.Count() == matchLen.Count() );
       
   238         const TInt matchPosCount = matchPos.Count();
       
   239         for ( TInt i = 0 ; i < matchPosCount ; ++i )
       
   240             {
       
   241             TPsMatchLocation tempLocation;
       
   242     
       
   243             // check for directionality of the text
       
   244             TBool found(EFalse);
       
   245             TPtrC matchingPart = aData.Mid( matchPos[i], matchLen[i] );
       
   246             TBidiText::TDirectionality dir = TBidiText::TextDirectionality(matchingPart, &found);
       
   247     
       
   248             tempLocation.index = matchPos[i];
       
   249             tempLocation.length = matchLen[i];
       
   250             tempLocation.direction = dir;
       
   251     
       
   252             // Add the match location to the data structure array
       
   253             aMatchLocation.Append(tempLocation);
       
   254             
       
   255             // Add the matched sequence to set, not allowing duplicates
       
   256             CPcsAlgorithm2Utils::AppendMatchToSeqL( aMatchSet, matchingPart );
       
   257             }
       
   258         }
       
   259     CleanupStack::PopAndDestroy( &matchLen );
       
   260     CleanupStack::PopAndDestroy( &matchPos );
       
   261 
       
   262     PRINT ( _L("End CPcsAlgorithm2Helper::SearchMatchSeqL") );
       
   263     }
       
   264 
       
   265 // ----------------------------------------------------------------------------
       
   266 // CPcsAlgorithm2Helper::FilterResultsSingleL
       
   267 // Subset search function
       
   268 // ----------------------------------------------------------------------------
       
   269 void CPcsAlgorithm2Helper::FilterResultsSingleL(CPcsAlgorithm2FilterHelper* aAlgorithmFilterHelper,
       
   270                                                 RPointerArray<CPcsPoolElement>& aSearchSet,
       
   271                                                 CPsQuery& aSearchQuery,
       
   272                                                 TUint8 aFilteredDataMatch,
       
   273                                                 TBool aIsSearchInGroup,
       
   274                                                 const RArray<TInt>& aContactsInGroup)
       
   275     {
       
   276     PRINT ( _L("Enter CPcsAlgorithm2::FilterResultsSingleL") );
       
   277 
       
   278     TInt maxcount = 0;
       
   279     CFindUtilChineseECE* pFindUtilEce = iAlgorithm->FindUtilECE();
       
   280 
       
   281     // Assume that all the elements is aSearchSet are from the same database.
       
   282     // Get firstname index and lastname index for that database.
       
   283     // If both are found, then name fields are matched a bit differently compared
       
   284     // to rest of the fields.
       
   285     TInt fnIndex( KErrNotFound );
       
   286     TInt lnIndex( KErrNotFound );
       
   287     TBool fullNameSearch( EFalse );
       
   288     if ( aSearchSet.Count() )
       
   289         {
       
   290         TInt dbUriId = aSearchSet[0]->GetPsData()->UriId();
       
   291         CPcsCache* cache = iAlgorithm->GetCache( dbUriId );
       
   292         fnIndex = cache->GetFirstNameIndex();
       
   293         lnIndex = cache->GetLastNameIndex();
       
   294 
       
   295         // Ensure that firstname and lastname are among the fields to be searched
       
   296         TUint8 fnBitmask = 1 << fnIndex;
       
   297         TUint8 lnBitmask = 1 << lnIndex;
       
   298         if ( (aFilteredDataMatch & fnBitmask) && 
       
   299              (aFilteredDataMatch & lnBitmask) )
       
   300             {
       
   301             fullNameSearch = ETrue;
       
   302             // Remove firstname and lastname from the set of fields to search
       
   303             // so that they will not be searched twice.
       
   304             aFilteredDataMatch &= ~fnBitmask;
       
   305             aFilteredDataMatch &= ~lnBitmask;
       
   306             }
       
   307         }
       
   308     
       
   309     // Parse thru each search set elements and filter the results
       
   310     const TInt searchSetCount = aSearchSet.Count();
       
   311     for (TInt index = 0; index < searchSetCount; index++)
       
   312         {
       
   313         CPcsPoolElement* poolElement = static_cast<CPcsPoolElement*> (aSearchSet[index]);
       
   314         CPsData* psData = poolElement->GetPsData();
       
   315         psData->ClearDataMatches();
       
   316 
       
   317         // Skip the contact if we are doing a group search and contact doesn't belong to the group
       
   318         if ( aIsSearchInGroup && 
       
   319              aContactsInGroup.Find( psData->Id() ) == KErrNotFound )
       
   320             {
       
   321             continue;
       
   322             }
       
   323         
       
   324         // Buffer for matched character sequence. Currently, we don't return
       
   325         // accurate pattern but just first character from the matching point.
       
   326         // Current clients don't actually use this data for anything.
       
   327         TBuf<1> matchingData;
       
   328         
       
   329         TBool matched = EFalse;
       
   330 
       
   331         // Parse thru each data field and filter the results
       
   332         // -------------------------------------------------
       
   333         
       
   334         // Name fields are handled separately to enable searching with query like
       
   335         // "LastnameFirstname". Searching fullname by query string 
       
   336         // only for the pool elements matching with the firstname or lastname
       
   337         if ( fullNameSearch && ( poolElement->IsDataMatch(fnIndex) || 
       
   338             poolElement->IsDataMatch(lnIndex) ))
       
   339             {
       
   340             HBufC* fullName = CreateNameBufLC( *psData, fnIndex, lnIndex );
       
   341 
       
   342             // FindUtil can take care of matching queries like "Firstname", "Lastname", 
       
   343             // and "LastnameFirstname".
       
   344             matched = pFindUtilEce->MatchRefineL( *fullName, aSearchQuery );
       
   345             if (matched)
       
   346                 {
       
   347                 matchingData = fullName->Left(1);
       
   348                 psData->SetDataMatch( fnIndex );
       
   349                 psData->SetDataMatch( lnIndex );
       
   350                 }
       
   351             
       
   352             CleanupStack::PopAndDestroy( fullName );
       
   353             }
       
   354 
       
   355         // Find from the rest of the fields if no match found so far. 
       
   356         // Name fields are already removed from aFilteredDataMatch if we did separate full name search.
       
   357         const TInt dataElementCount = psData->DataElementCount();
       
   358         for ( TInt dataIndex = 0; dataIndex < dataElementCount && !matched ; dataIndex++ )
       
   359             {
       
   360             // Filter off data fields not required in search
       
   361             TUint8 bitIndex = 1 << dataIndex;
       
   362             TUint8 filter = bitIndex & aFilteredDataMatch;
       
   363             if ( filter == 0x0 )
       
   364                 {
       
   365                 // Move to next data
       
   366                 continue;
       
   367                 }
       
   368 
       
   369             if ( poolElement->IsDataMatch(dataIndex) )
       
   370                 {
       
   371                 TPtrC fieldData( *psData->Data(dataIndex) );
       
   372                 matched = pFindUtilEce->MatchRefineL( fieldData, aSearchQuery );
       
   373                 if (matched)
       
   374                     {
       
   375                     matchingData = fieldData.Left(1);
       
   376                     psData->SetDataMatch( dataIndex );
       
   377                     }
       
   378                 }
       
   379             }
       
   380 
       
   381 
       
   382         // Add to results if match is found
       
   383         if ( matched )
       
   384             {
       
   385             RPointerArray<TDesC> tempMatchSeq;
       
   386             CleanupClosePushL( tempMatchSeq );
       
   387 
       
   388             // Wrap matched character sequence to array.
       
   389             matchingData.UpperCase();
       
   390             tempMatchSeq.AppendL(&matchingData);
       
   391             
       
   392             // Add the result
       
   393             aAlgorithmFilterHelper->AddL( psData, tempMatchSeq );
       
   394             maxcount++;
       
   395             
       
   396             // Cleanup the match sequence array as 
       
   397             // they are stored in pattern details structure
       
   398             CleanupStack::PopAndDestroy( &tempMatchSeq ); // Close
       
   399             
       
   400             // TODO: Match seqs could be extracted from actual
       
   401             //       match locations by using the other overload of
       
   402             //       CFindUtilChineseECE::MatchRefineL().
       
   403             //       Currently, match seq data is not used by clients.
       
   404             }
       
   405         
       
   406           if ( iMaxCount != -1 && maxcount > iMaxCount )
       
   407               {
       
   408               return;
       
   409               }
       
   410         }
       
   411 
       
   412     PRINT ( _L("End CPcsAlgorithm2Helper::FilterResultsSingleL") );
       
   413     }
       
   414 
       
   415 // ----------------------------------------------------------------------------
       
   416 // CPcsAlgorithm2Helper::SortSearchSeqsL()
       
   417 // 
       
   418 // ----------------------------------------------------------------------------
       
   419 void CPcsAlgorithm2Helper::SortSearchSeqsL(RPointerArray<TDesC>& aSearchSeqs)
       
   420     {
       
   421     // Sort the search seqs
       
   422     TLinearOrder<TDesC> rule( CPcsAlgorithm2Utils::MyCompareC );
       
   423     aSearchSeqs.Sort(rule);
       
   424     }
       
   425 
       
   426 // ---------------------------------------------------------------------------
       
   427 // CPcsAlgorithm2Helper::CreteNameBufLC
       
   428 // Update name order according to Phonebook setting
       
   429 // ---------------------------------------------------------------------------
       
   430 HBufC* CPcsAlgorithm2Helper::CreateNameBufLC( const CPsData& aContactData, 
       
   431         TInt aFirstNameIndex, TInt aLastNameIndex ) const
       
   432     {
       
   433     const TDesC& firstName( *aContactData.Data(aFirstNameIndex) );
       
   434     const TDesC& lastName( *aContactData.Data(aLastNameIndex) );
       
   435     CFindUtilChineseECE* pFindUtilEce = iAlgorithm->FindUtilECE();
       
   436     HBufC* fullName = NULL;
       
   437     
       
   438     if ( pFindUtilEce->IsChineseWordIncluded( lastName ) || 
       
   439         pFindUtilEce->IsChineseWordIncluded( firstName ) )
       
   440         {
       
   441         fullName = HBufC::NewLC( lastName.Length() + firstName.Length()  + 1 );
       
   442         TPtr fullNamePtr = fullName->Des();
       
   443     
       
   444         // Form the full name according the Phonebook name order setting. Typically,
       
   445         // the order is always lastname-firstname in Chinese variants. However, at least
       
   446         // currently it is possible to change this from Contacts app if UI language has
       
   447         // been set to English.
       
   448         if ( iNameOrder == ELastnameFirstname )
       
   449             {
       
   450             fullNamePtr.Append( lastName );
       
   451             //Holds the first char of first name of a contact
       
   452             TBuf<10> firstChar;   
       
   453             firstChar.Zero();
       
   454             
       
   455             if(firstName.Length())
       
   456                 {
       
   457                 firstChar.Append(firstName[0]);   
       
   458                 // There is no space between LastName and FirstName in Chinese Name
       
   459                 // except that the firstChar of FirstName isn't Chinese character
       
   460                 if ( !pFindUtilEce->IsChineseWordIncluded( firstChar ) )
       
   461                     {
       
   462                     fullNamePtr.Append( KSpace );
       
   463                     }
       
   464                 fullNamePtr.Append( firstName ); 
       
   465                 }
       
   466             }
       
   467         else
       
   468             {
       
   469             fullNamePtr.Append( firstName );
       
   470             //Holds the first char of last name of a contact
       
   471             TBuf<10> firstChar;   
       
   472             firstChar.Zero();
       
   473             
       
   474             if(lastName.Length())
       
   475                 {
       
   476                 firstChar.Append(lastName[0]);
       
   477                 // There is no space between LastName and FirstName in Chinese Name
       
   478                 // except that the firstChar of Lastname isn't Chinese character  
       
   479                 if ( !pFindUtilEce->IsChineseWordIncluded( firstChar ) )
       
   480                     {
       
   481                     fullNamePtr.Append( KSpace );
       
   482                     }
       
   483                 fullNamePtr.Append( lastName ); 
       
   484                 }
       
   485             }
       
   486         }
       
   487     else
       
   488         {
       
   489         fullName = HBufC::NewLC( lastName.Length() + firstName.Length() + 1 );
       
   490         TPtr fullNamePtr = fullName->Des();
       
   491     
       
   492         // Form the full name according the Phonebook name order setting. Typically,
       
   493         // the order is always lastname-firstname in Chinese variants. However, at least
       
   494         // currently it is possible to change this from Contacts app if UI language has
       
   495         // been set to English.
       
   496         if ( iNameOrder == ELastnameFirstname )
       
   497             {
       
   498             fullNamePtr.Append( lastName );
       
   499             fullNamePtr.Append( KSpace );
       
   500             fullNamePtr.Append( firstName );
       
   501             }
       
   502         else
       
   503             {
       
   504             fullNamePtr.Append( firstName );
       
   505             fullNamePtr.Append( KSpace );
       
   506             fullNamePtr.Append( lastName );
       
   507             }
       
   508         }
       
   509     
       
   510     return fullName;
       
   511     }
       
   512 
       
   513 // ---------------------------------------------------------------------------
       
   514 // CPcsAlgorithm2Helper::UpdateNameOrderL
       
   515 // Update name order according to Phonebook setting
       
   516 // ---------------------------------------------------------------------------
       
   517 void CPcsAlgorithm2Helper::UpdateNameOrderL()
       
   518     {
       
   519     /*
       
   520     * Phonebook name ordering flag, integer value, possible values:
       
   521     * 0: name order Lastname Firstname
       
   522     * 1: name order Firstname Lastname
       
   523     * 2: name order undefined
       
   524     */
       
   525     TInt nameOrderSetting;
       
   526     iPbkSettings->Get( MPbkGlobalSetting::ENameOrdering, nameOrderSetting );
       
   527     
       
   528     switch ( nameOrderSetting )
       
   529         {
       
   530         case 0:
       
   531             {
       
   532             iNameOrder = ELastnameFirstname;
       
   533             break;
       
   534             }
       
   535         case 1:
       
   536             {
       
   537             iNameOrder = EFirstnameLastname;
       
   538             break;
       
   539             }
       
   540         case 2:
       
   541         default:
       
   542             {
       
   543             // Decide name order based on UI language: lastname-firstname
       
   544             // for Chinese, firstname-lastname for the rest of languages.
       
   545             TLanguage uiLang = User::Language();
       
   546             if ( uiLang == ELangPrcChinese || 
       
   547                  uiLang == ELangHongKongChinese ||
       
   548                  uiLang == ELangTaiwanChinese )
       
   549                 {
       
   550                 iNameOrder = ELastnameFirstname;
       
   551                 }
       
   552             else
       
   553                 {
       
   554                 iNameOrder = EFirstnameLastname;
       
   555                 }
       
   556             }
       
   557         }
       
   558     }
       
   559 
       
   560 // ---------------------------------------------------------------------------
       
   561 // CPcsAlgorithm2Helper::SettingChangedL
       
   562 // From MPbkGlobalSettingObserver
       
   563 // ---------------------------------------------------------------------------
       
   564 void CPcsAlgorithm2Helper::SettingChangedL( MPbkGlobalSetting::TPbkGlobalSetting aKey )
       
   565     {
       
   566     if ( aKey == MPbkGlobalSetting::ENameOrdering )
       
   567         {
       
   568         UpdateNameOrderL();
       
   569         }
       
   570     }
       
   571 
       
   572 // End of file
       
   573 
       
   574