uiutils/Findutil/src/FindUtilWestern.cpp
changeset 0 2f259fa3e83a
child 4 8ca85d2f0db7
child 14 3320e4e6e8bb
equal deleted inserted replaced
-1:000000000000 0:2f259fa3e83a
       
     1 /*
       
     2 * Copyright (c) 2002-2005 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:         Western Find Utilities implementation file.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 
       
    21 
       
    22 
       
    23 
       
    24 
       
    25 
       
    26 #include "FindUtilWestern.h"
       
    27 #include <collate.h>
       
    28 #include <PtiIndicDefs.h>
       
    29 #include "FindUtilKorean.h"
       
    30 #include <avkon.rsg>
       
    31 #include <stringloader.h>
       
    32 const TInt KLitTab('\t');
       
    33 const TInt KLitSpace(' ');
       
    34 const TInt KLitHyphen('-');
       
    35 const TInt KLitLineFeed(8233);
       
    36 const TInt KLitStar('*');
       
    37 const TInt KLitQuestion('?');
       
    38 
       
    39 const TInt KMatchingBufferLength(256);
       
    40 const TInt KAknStringBufferSize = 256;
       
    41 
       
    42 namespace {
       
    43 
       
    44 // ---------------------------------------------------------------------------
       
    45 // IsFindWordSeparator
       
    46 // ---------------------------------------------------------------------------
       
    47 //
       
    48 inline TBool IsFindWordSeparator(TChar aCh)
       
    49     {
       
    50     return aCh == KLitSpace || aCh == KLitHyphen || aCh == KLitTab || aCh == KLitLineFeed;
       
    51     }
       
    52 
       
    53 
       
    54 
       
    55 void ReplaceCharacters(TDes &aDes, const TDesC &aChars, TChar aReplacement)
       
    56     //
       
    57     // Running time O(aDes.Length() * aChars.Length())
       
    58     // Does not change length of the string.
       
    59     // 
       
    60     {
       
    61     TInt src = 0;
       
    62     TInt srclength = aDes.Length();
       
    63     while(src < srclength)
       
    64         {
       
    65         TChar c = aDes[src];
       
    66         if (aChars.LocateF(c) != KErrNotFound)
       
    67             aDes[src] = TUint16(aReplacement);
       
    68         ++src;
       
    69         }
       
    70     }
       
    71 
       
    72 inline TInt MyFindC(const TDesC &aItemString, const TDesC &aSearchText)
       
    73     {
       
    74     TBuf<200> searchText;
       
    75     TBuf<200> itemString;
       
    76     searchText.Append(aSearchText);
       
    77     // The replacecharacters are to disable regexp matching provided
       
    78     // by MatchC().
       
    79 	_LIT(KQuestion,"?");
       
    80 	_LIT(KStar,"*");
       
    81     ReplaceCharacters(searchText, KQuestion, TChar('\t'));
       
    82     ReplaceCharacters(searchText, KStar, TChar('\r'));
       
    83     searchText.Append(KStar);
       
    84     if (aItemString.Length() < 200)
       
    85         itemString.Append(aItemString);
       
    86     else
       
    87         itemString.Append(aItemString.Left(200));
       
    88     ReplaceCharacters(itemString, KQuestion, TChar('\t'));
       
    89     ReplaceCharacters(itemString, KStar, TChar('\r'));
       
    90 
       
    91 
       
    92     TInt length = itemString.Length();
       
    93     for(int i=0;i<length;i++)
       
    94         {
       
    95         if (i==0 || IsFindWordSeparator(aItemString[i-1]))
       
    96             {
       
    97             if (itemString.Mid(i).MatchC(searchText) != KErrNotFound)
       
    98                 {
       
    99                 return i;
       
   100                 }
       
   101             }
       
   102         }
       
   103     return KErrNotFound;
       
   104     }
       
   105 inline TBool IsFindMatchClassic(const TDesC& aItemString, const TDesC& aSearchText, TInt /*aInputLang = 0*/)
       
   106     {
       
   107     TPtrC itemptr = aItemString;
       
   108     TPtrC searchptr = aSearchText;
       
   109 
       
   110     TBool match = EFalse;
       
   111     
       
   112     for(;;) 
       
   113         {
       
   114         // Loop invariant: itemptr is next character from ' ' or '-'
       
   115         // Loop invariant: seachptr is at beginning of searched item
       
   116     
       
   117         TInt val = MyFindC(itemptr,searchptr);
       
   118         if (val == 0)
       
   119             {
       
   120             match = ETrue;
       
   121             break;
       
   122             }
       
   123         if (val != KErrNotFound && IsFindWordSeparator(itemptr[val-1]))
       
   124             {
       
   125             match = ETrue;
       
   126             break;
       
   127             }
       
   128 
       
   129         // find the word separator characters from list item
       
   130         TInt spacepos = itemptr.LocateF(TChar(' '));
       
   131         TInt minuspos = itemptr.LocateF(TChar('-'));
       
   132         TInt tabpos = itemptr.LocateF(TChar('\t'));
       
   133         if (spacepos != KErrNotFound)
       
   134             {
       
   135             itemptr.Set(itemptr.Mid(spacepos+1));
       
   136             }
       
   137         else if (minuspos != KErrNotFound)
       
   138             {
       
   139             itemptr.Set(itemptr.Mid(minuspos+1));
       
   140             }
       
   141         else if (tabpos != KErrNotFound)
       
   142             {
       
   143             itemptr.Set(itemptr.Mid(tabpos+1));
       
   144             }
       
   145         else
       
   146             {
       
   147             match = EFalse;
       
   148             break;
       
   149             }
       
   150         if (itemptr.Length() == 0)
       
   151             {
       
   152             match = EFalse;
       
   153             break;
       
   154             }
       
   155 
       
   156         }
       
   157     return match;
       
   158     }
       
   159 
       
   160 // ---------------------------------------------------------------------------
       
   161 // IsFindMatch
       
   162 // ---------------------------------------------------------------------------
       
   163 //
       
   164 inline TBool IsFindMatch(const TDesC& aItemString, const TDesC& aSearchText, TInt aInputLang = 0)
       
   165     {
       
   166     TBuf<200> searchText;
       
   167     TInt itemStringLength = aItemString.Length();
       
   168     
       
   169     if ( aSearchText.Length() < 200 )
       
   170         {
       
   171         searchText.Append( aSearchText );
       
   172         }
       
   173     else
       
   174         {
       
   175         searchText.Append( aSearchText.Left(199) );
       
   176         }
       
   177     
       
   178     // To disable the wildchar matching provided by MatchC
       
   179     if (aSearchText.Locate( KLitQuestion ) != KErrNotFound)
       
   180         {
       
   181         return IsFindMatchClassic(aItemString, aSearchText, aInputLang);
       
   182         }
       
   183     if (aSearchText.Locate( KLitStar ) != KErrNotFound)
       
   184         {
       
   185         return IsFindMatchClassic(aItemString, aSearchText, aInputLang);
       
   186         }
       
   187 
       
   188     searchText.Append( KLitStar );
       
   189         
       
   190     TInt result = KErrNone;
       
   191    
       
   192     for( TInt i = 0; i < itemStringLength; i++ )
       
   193         {
       
   194         if ( i==0 || IsFindWordSeparator( aItemString[i-1] ) )
       
   195             {
       
   196             
       
   197             if(aInputLang == ELangHindi
       
   198 #ifdef RD_MARATHI
       
   199                 || aInputLang == ELangMarathi
       
   200 #endif
       
   201 
       
   202 #ifdef RD_HINDI_PHONETIC_INPUT
       
   203                 || aInputLang == KLangHindiPhonetic
       
   204 #endif            
       
   205             )
       
   206             {
       
   207             TUint flag = ( TCollationMethod::EIgnoreNone | TCollationMethod::EFoldCase | TCollationMethod::EIgnoreCombining );
       
   208         	TCollationMethod m = *Mem::GetDefaultMatchingTable();
       
   209   			m.iFlags |= flag;
       
   210         	result = aItemString.Mid(i).MatchC( searchText, &m, 3);
       
   211             }
       
   212             else
       
   213             {
       
   214             	result = aItemString.Mid(i).MatchC( searchText );
       
   215             }
       
   216                         	
       
   217             if(result != KErrNotFound)
       
   218             	{
       
   219             		return ETrue;
       
   220             	}
       
   221             }
       
   222         }
       
   223         
       
   224     return EFalse;
       
   225 	}	
       
   226 }
       
   227 
       
   228 // ============================ MEMBER FUNCTIONS ===============================
       
   229 
       
   230 // -----------------------------------------------------------------------------
       
   231 // CFindUtilWestern::CFindUtilWestern
       
   232 // C++ default constructor can NOT contain any code, that
       
   233 // might leave.
       
   234 // -----------------------------------------------------------------------------
       
   235 //
       
   236 CFindUtilWestern::CFindUtilWestern()
       
   237     {
       
   238     iRepository = NULL;
       
   239     iNotifyHandler = NULL;
       
   240     }
       
   241 
       
   242 // Destructor
       
   243 CFindUtilWestern::~CFindUtilWestern()
       
   244     {
       
   245     if ( iNotifyHandler )
       
   246         {
       
   247         iNotifyHandler->StopListening();
       
   248         delete iNotifyHandler;
       
   249         iNotifyHandler=NULL;
       
   250         }
       
   251     if(iRepository)
       
   252         {
       
   253         delete iRepository;
       
   254         iRepository = NULL;    
       
   255         }    	
       
   256     if ( iFindUtilKorean )
       
   257         {
       
   258     	delete iFindUtilKorean;
       
   259     	iFindUtilKorean = NULL;
       
   260         }
       
   261     if( iDigraphChars )       
       
   262         {
       
   263         delete iDigraphChars;
       
   264         }
       
   265     }
       
   266 
       
   267 
       
   268 void CFindUtilWestern::OpenL()
       
   269 	{
       
   270 	CFindUtilBase::OpenL();
       
   271     
       
   272     if(!iRepository)
       
   273     	{
       
   274 		iRepository = CRepository::NewL(KCRUidAknFep);
       
   275 		iRepository->Get(KAknFepInputTxtLang, iInputLanguage);
       
   276 	    }
       
   277 	if(!iNotifyHandler)
       
   278 	    {
       
   279 		iNotifyHandler = CCenRepNotifyHandler::NewL( *this, 
       
   280                                               *iRepository,
       
   281                                               CCenRepNotifyHandler::EIntKey,
       
   282                                               KAknFepInputTxtLang );
       
   283 		iNotifyHandler->StartListeningL();
       
   284 	    }	
       
   285 //TSW: LYEE-7Q2GRV  
       
   286 	if(!iFindUtilKorean)
       
   287 	    {
       
   288         iFindUtilKorean = CFindUtilKorean::NewL();
       
   289 	    }
       
   290 	}
       
   291 	
       
   292 void CFindUtilWestern::HandleNotifyInt( TUint32 aId, TInt aNewValue )
       
   293 	{
       
   294 	if(aId == KAknFepInputTxtLang)
       
   295 	    iInputLanguage = aNewValue;
       
   296 	}
       
   297 	
       
   298 // -----------------------------------------------------------------------------
       
   299 // CFindUtilWestern::Match
       
   300 // (other items were commented in a header).
       
   301 // -----------------------------------------------------------------------------
       
   302 //
       
   303 
       
   304 TBool CFindUtilWestern::Match(const TDesC& aContactsField, const TDesC& aWord)
       
   305     {
       
   306     if ( iFindUtilKorean->IsKoreanLanguage( aContactsField ) || iFindUtilKorean->IsKoreanLanguage( aWord ) )
       
   307         {
       
   308         return iFindUtilKorean->Match( aContactsField, aWord );	
       
   309         }
       
   310     else
       
   311     	{
       
   312     TInt numChar = 1;
       
   313     	if (!aContactsField.Length())
       
   314         	{
       
   315                 _LIT( KNone, "*" );
       
   316     	        if( aWord.CompareC(KNone()) == 0 )
       
   317                     {
       
   318     	            return ETrue;
       
   319                     }
       
   320                 else
       
   321                     {
       
   322         	    return EFalse;
       
   323                     }
       
   324         	}        
       
   325     	if((aWord.Length() > 1) && aWord[aWord.Length()-2] == 0x200B)
       
   326     		{
       
   327     		numChar = 2;
       
   328     		}    	
       
   329     	if ( IsFindMatch(aContactsField, aWord.Left(aWord.Length()-numChar), iInputLanguage) )
       
   330         	{
       
   331         	return ETrue;
       
   332         	}
       
   333   		return EFalse;
       
   334    		}
       
   335     }
       
   336 
       
   337 
       
   338 // -----------------------------------------------------------------------------
       
   339 // CFindUtilWestern::MatchRefineL
       
   340 // (other items were commented in a header).
       
   341 // -----------------------------------------------------------------------------
       
   342 //
       
   343 TBool CFindUtilWestern::MatchRefineL( const TDesC& aItemString, const TDesC& aSearchText )
       
   344     {
       
   345     if ( iFindUtilKorean->IsKoreanLanguage( aItemString ) || iFindUtilKorean->IsKoreanLanguage( aSearchText ) )
       
   346         {
       
   347         return iFindUtilKorean->MatchRefineL( aItemString, aSearchText );	
       
   348         }
       
   349     else
       
   350     {
       
   351     if ( aItemString.Length() == 0 )
       
   352         {
       
   353         return EFalse;
       
   354         }
       
   355 
       
   356     if ( aSearchText.Length() == 0 )
       
   357         {
       
   358         return ETrue;
       
   359         }
       
   360     return IsFindMatch( aItemString, aSearchText, iInputLanguage );
       
   361     	}
       
   362     }
       
   363 
       
   364 // -----------------------------------------------------------------------------
       
   365 // CFindUtilWestern::IsWordValidForMatching
       
   366 // (other items were commented in a header).
       
   367 // -----------------------------------------------------------------------------
       
   368 //
       
   369 TBool CFindUtilWestern::IsWordValidForMatching(const TDesC& /*aWord*/)
       
   370     {
       
   371     return ETrue;
       
   372     }
       
   373 
       
   374 
       
   375 // ========================= FOR ADAPTIVE FIND ================================
       
   376 
       
   377 // -----------------------------------------------------------------------------
       
   378 // For Vietnamese AS
       
   379 // 
       
   380 // -----------------------------------------------------------------------------
       
   381 //
       
   382 inline TChar ReplaceVietnameseChar( const TChar aCh )   
       
   383     {
       
   384     TChar Char = aCh.GetUpperCase();
       
   385     if ( (Char >= 0x00C0 && Char <= 0x00C3) || Char == 0x102  ||
       
   386          ((Char >= 0x1EA0 && Char <= 0x1EB6) && Char%2 == 0) )  
       
   387         {
       
   388         Char = 0x0041; // A
       
   389         return Char; 
       
   390         }        
       
   391     if ( (Char >= 0x00C8 && Char <= 0x00CA) || 
       
   392         ((Char >= 0x1EB8 && Char <= 0x1EC6) && Char%2 == 0) )
       
   393         {
       
   394         Char = 0x0045; // E
       
   395         return Char; 
       
   396         }               
       
   397     if ( Char == 0x00CC || Char == 0x00CD || Char == 0x0128 || 
       
   398          Char == 0x1EC8 || Char == 0x1ECA  )
       
   399         {
       
   400         Char = 0x0049; // I
       
   401         return Char; 
       
   402         }    
       
   403     if ( (Char >= 0x00D2 && Char <= 0x00D5 ) || Char == 0x1ECE || Char == 0x1ECC ||
       
   404         ((Char >= 0x1ED0 && Char <= 0x1ED8) && Char%2 == 0)) 
       
   405         {
       
   406         Char = 0x004F; // O
       
   407         return Char; 
       
   408         }            
       
   409     if ( Char == 0x1EDA || Char == 0x1EDC || Char == 0x1EDE || 
       
   410          Char == 0x1EE0 || Char == 0x1EE2  )
       
   411         {
       
   412         Char = 0x01A0; // O-horn
       
   413         return Char; 
       
   414         }          
       
   415     if ( Char == 0x00DA || Char == 0x00D9 || Char == 0x0168 || 
       
   416          Char == 0x1EE4 || Char == 0x1EE6  )
       
   417         {
       
   418         Char = 0x0055; // U
       
   419         return Char; 
       
   420         }         
       
   421      if ( (Char >= 0x1EE8 && Char <= 0x1EF0) && Char%2 == 0 )
       
   422         {
       
   423         Char = 0x01AF; // U-horn        
       
   424         return Char; 
       
   425         }         
       
   426      if ( ((Char >= 0x1EF2 && Char <= 0x1EF8) && Char%2 == 0) || Char == 0x00DD ) 
       
   427         {
       
   428         Char = 0x0059; // Y
       
   429         return Char; 
       
   430         }              
       
   431     return Char;
       
   432     } 
       
   433     
       
   434  /**
       
   435  * Checks current character is it special character from Vietnamese language . 
       
   436  *
       
   437  * @since 5.0
       
   438  * @return @c ETrue If it is accent from Vietnamese language, otherwise EFalse. 
       
   439  */	
       
   440 inline TBool IsVietnameseSpecialCharacter( TChar aCh )
       
   441     {   
       
   442     if ( ( aCh >= 0x0300 && aCh <= 0x0303 ) ||       
       
   443         aCh == 0x0306 || aCh == 0x0309 || aCh == 0x0323 || aCh == 0x031B )
       
   444         {
       
   445         return ETrue;            
       
   446         }  
       
   447     return EFalse;
       
   448     }
       
   449        
       
   450 /**
       
   451  * Update next characters if find pane state was changed.
       
   452  *
       
   453  * @since 5.0
       
   454  * @param aNextChars reference to the next characters for the adaptive search grid
       
   455  * @param aCh Criteria from the search field.    
       
   456  */
       
   457 inline void UpdateNextCharsL( HBufC*& aNextChars, TChar aCh )
       
   458     {
       
   459         TChar ch_temp = aCh;          
       
   460     
       
   461     TLanguage lang = User::Language();  
       
   462     if ( lang == ELangVietnamese )
       
   463 	   {
       
   464 	   aCh = ReplaceVietnameseChar ( ch_temp );
       
   465 	   }
       
   466     
       
   467     if( ( aNextChars->Locate(aCh.GetLowerCase() ) == KErrNotFound ) &&
       
   468         ( aNextChars->Locate(aCh.GetUpperCase() ) == KErrNotFound ) )
       
   469         {               
       
   470         if( aNextChars->Des().Length() == aNextChars->Des().MaxLength() )
       
   471             {
       
   472             aNextChars = aNextChars->ReAllocL( aNextChars->Des().MaxLength()+10 );
       
   473             TInt length1 = aNextChars->Des().Length();
       
   474             TInt maxlength1 = aNextChars->Des().MaxLength();
       
   475             }       
       
   476         aNextChars->Des().Append( aCh );            
       
   477         }
       
   478     }
       
   479 
       
   480 // -----------------------------------------------------------------------------
       
   481 // For Devanagari AS
       
   482 // Checks if aCh denotes a consonant with nukta. 
       
   483 // @return ETrue if aCh is a consonant with nukta EFalse otherwise.
       
   484 // -----------------------------------------------------------------------------
       
   485 //
       
   486 inline TBool IsIndicCombinedChar( const TChar aCh )
       
   487     {   
       
   488     if ( aCh < 0x0900 || aCh > 0x0980 )
       
   489         {
       
   490         return EFalse;
       
   491         }
       
   492     else
       
   493         {
       
   494         return ( aCh == 0x0929 || aCh == 0x0931 || aCh == 0x0934 || 
       
   495                 (aCh >= 0x0958 && aCh <= 0x095F) );
       
   496         }
       
   497     }
       
   498 
       
   499 // -----------------------------------------------------------------------------
       
   500 // For Devanagari AS
       
   501 // Returns the correcponding character without nukta
       
   502 // @param aCh - character to be stripped of nukta
       
   503 // @return corresponding character with nukta
       
   504 // -----------------------------------------------------------------------------
       
   505 //
       
   506 inline TChar RemoveIndicNukta( const TChar aCh )
       
   507     {
       
   508     switch (aCh)
       
   509         {
       
   510         case 0x0929 : return 0x0928; //vocallic 'nna' to 'na'
       
   511         case 0x0931 : return 0x0930; //vocallic 'rra' to 'ra'
       
   512         case 0x0934 : return 0x0933; //vocallic 'lllla' to 'lla'
       
   513         case 0x0958 : return 0x0915; //vocallic 'qa' to 'ka'
       
   514         case 0x0959 : return 0x0916; //vocallic 'khha' to 'kha'
       
   515         case 0x095A : return 0x0917; //vocallic 'ghha' to 'ga'
       
   516         case 0x095B : return 0x091C; //letter 'za' to 'ja'
       
   517         case 0x095C : return 0x0921; //vocallic 'dddha' to 'da'
       
   518         case 0x095D : return 0x0922; //vocallic 'rha' to 'ddha'
       
   519         case 0x095E : return 0x092B; //letter 'fa' to 'pha'
       
   520         case 0x095F : return 0x092F; //letter 'yya' to 'ya'        
       
   521         default : return aCh;
       
   522         }
       
   523     }
       
   524 
       
   525 // -----------------------------------------------------------------------------
       
   526 // For Devanagari AS
       
   527 // Checks if the given character is a Indic consonant.
       
   528 // @param aSearchChar - character to be checked.  
       
   529 // @return ETrue if this is an independent character EFalse otherwise       
       
   530 // -----------------------------------------------------------------------------
       
   531 //  
       
   532 inline TBool IsIndicConsonant( const TChar aSearchChar )
       
   533     {    
       
   534 	if  (
       
   535 	    ( aSearchChar >= 0x0915 && aSearchChar <= 0x0939 ) ||
       
   536 	    ( aSearchChar >= 0x0958 && aSearchChar <= 0x0961 )
       
   537 	    )
       
   538         {
       
   539         return ETrue;
       
   540         }
       
   541     else 
       
   542         {
       
   543         return EFalse;
       
   544         }
       
   545     }
       
   546     
       
   547 // -----------------------------------------------------------------------------
       
   548 // For Devanagari AS
       
   549 // Checks if the given character is a Indic matra.
       
   550 // @param aSearchChar - character to be checked.  
       
   551 // @return ETrue if this is an matra EFalse otherwise  
       
   552 // -----------------------------------------------------------------------------
       
   553 //  
       
   554 inline TBool IsIndicMatra( const TChar aSearchChar )
       
   555     {   
       
   556     if ( aSearchChar >= 0x093E && aSearchChar <= 0x094C )
       
   557         {
       
   558         return ETrue;
       
   559         }
       
   560     else 
       
   561         {
       
   562         return EFalse;
       
   563         }
       
   564     }
       
   565     
       
   566 // -----------------------------------------------------------------------------
       
   567 // For Devanagari AS
       
   568 // Checks if the given character is a Devanagari independent character.
       
   569 // @param aSearchChar - character to be checked.  
       
   570 // @return ETrue if this is an independent character EFalse otherwise  
       
   571 // -----------------------------------------------------------------------------
       
   572 //
       
   573 inline TBool IsIndicIndependentChar( const TChar aSearchChar )
       
   574     {    
       
   575 	if (( aSearchChar >= 0x0905 && aSearchChar <= 0x0939 ) ||
       
   576 	    ( aSearchChar >= 0x0958 && aSearchChar <= 0x0961 ))
       
   577         {
       
   578         return ETrue;
       
   579         }
       
   580     else 
       
   581         {
       
   582         return EFalse;
       
   583         }
       
   584     }    
       
   585     
       
   586 // -----------------------------------------------------------------------------
       
   587 // For Devanagari AS
       
   588 // Checks if the passed string denotes one of the four special
       
   589 // Devanagari ligatures - refer UI specs for the description of special ligatures
       
   590 // @param aCharString - The string containing set of characters to be checked
       
   591 // @return ETrue if a special ligature is found EFalse otherwise   
       
   592 // -----------------------------------------------------------------------------
       
   593 //  
       
   594 inline TBool IsSpecialIndicLigature( const TDesC& aCharString )
       
   595     {
       
   596     TBool ret = EFalse;
       
   597     if( aCharString.Length() >= 3 )
       
   598         {      
       
   599         if( (((aCharString[0] == 0x915) && (aCharString[1] == 0x94D)&& (aCharString[2] == 0x937)) ||
       
   600              ((aCharString[0] == 0x91C) && (aCharString[1] == 0x94D)&& (aCharString[2] == 0x91E)) ||
       
   601              ((aCharString[0] == 0x936) && (aCharString[1] == 0x94D)&& (aCharString[2] == 0x930)) ||
       
   602              ((aCharString[0] == 0x924) && (aCharString[1] == 0x94D)&& (aCharString[2] == 0x930))) )
       
   603             {
       
   604             ret = ETrue;
       
   605             }
       
   606          }
       
   607     return ret;
       
   608     }    
       
   609    
       
   610 // -----------------------------------------------------------------------------
       
   611 // For Devanagari AS
       
   612 // Counts the number of Indic syllables in the search string
       
   613 // For the purpose of supporting mixed language entries, we count each
       
   614 // non-Devanagari charcter as a single syllable. 
       
   615 // Also replaces the place holder '-' with '*' for searching 
       
   616 // @param aSearchText - The search string entered so far
       
   617 // @param aSearchTextLength - Number of characters in string excluding '*'
       
   618 // @return the number of Devanagari syllables in aCriteria   
       
   619 // -----------------------------------------------------------------------------
       
   620 //  
       
   621 inline TInt IndicSyllableCount( HBufC* aSearchText, TInt& aSearchTextLength )
       
   622 	{
       
   623 	TInt syllableCount = 0;
       
   624 	TPtr ptrSearchText = aSearchText->Des();
       
   625 	TInt strLength = ptrSearchText.Length();
       
   626 	for(TInt index=0 ; index < strLength ; index++)
       
   627 		{
       
   628 		if( (index) && ptrSearchText[index] == KLitHyphen && 
       
   629 		        IsIndicIndependentChar(ptrSearchText[index-1]) )
       
   630 			{
       
   631 			syllableCount++;
       
   632 			ptrSearchText[index] = KLitStar;
       
   633 			--aSearchTextLength;
       
   634 			}
       
   635 		else if ( !IsIndicIndependentChar(ptrSearchText[index]) && ptrSearchText[index]!=0x094D )
       
   636 			{
       
   637 			//For any other non Indic-independent-character that was entered 
       
   638 			//through adaptive grid, we consider it as a seperate syllable. 
       
   639 			++syllableCount;
       
   640 			}
       
   641 		}
       
   642 	return syllableCount;
       
   643 	}    
       
   644 	
       
   645 // -----------------------------------------------------------------------------
       
   646 // For Devanagari AS
       
   647 // Checks if aCriteria[aCurrentIndex] is a fallback rendered character.
       
   648 // @param aCriteria - string in which we need to check.
       
   649 // @param aCurrentIndex - position in string of character to be checked
       
   650 // @return ETrue if aCriteria is a rendered character EFalse otherwise.
       
   651 // -----------------------------------------------------------------------------
       
   652 //  
       
   653 inline TBool IsFallbackRenderedCharacter( const TDesC& aCriteria, TInt aCurrentIndex )
       
   654     {    
       
   655     if ( aCriteria[aCurrentIndex] >= 0x0900 && aCriteria[aCurrentIndex] <= 0x0980)
       
   656         {
       
   657         // Check for invalid Nuktas:
       
   658         if ( aCriteria[aCurrentIndex] == 0x093C )
       
   659             {
       
   660             // A Nukta is valid only if placed after a consonant 
       
   661             if ( !IsIndicConsonant(aCriteria[(aCurrentIndex-1)]) )
       
   662                 {
       
   663                 return ETrue;
       
   664                 }
       
   665             }
       
   666         // Check for invalid Matras: 
       
   667         else if ( IsIndicMatra(aCriteria[aCurrentIndex]) )
       
   668             {
       
   669             // These can only be placed after a consonant or a valid nukta
       
   670             TChar prevChar = aCriteria[(aCurrentIndex-1)];            
       
   671             if ( !(IsIndicConsonant(prevChar) || prevChar == 0x093C) )
       
   672                 {
       
   673                 return ETrue;
       
   674                 }
       
   675             }
       
   676         // Check for invalid Modifiers:
       
   677         else if ( aCriteria[aCurrentIndex] >= 0x0901 && aCriteria[aCurrentIndex] <= 0x0903)
       
   678             {
       
   679             //These are valid only if placed after an independent vowel or a 
       
   680             //consonant or a valid nukta or a valid matra.
       
   681             TChar prevChar = aCriteria[(aCurrentIndex-1)];
       
   682             //if prev character is nukta or matra, it would have been already validated
       
   683             if ( !(IsIndicIndependentChar(prevChar) || prevChar == 0x093C 
       
   684                     || IsIndicMatra(prevChar) ) )
       
   685                 {
       
   686                 return ETrue;
       
   687                 }
       
   688             }
       
   689         // Check for invalid Halant/Virama:
       
   690         else if ( aCriteria[aCurrentIndex] == 0x094D )
       
   691             {
       
   692             //This is valid only if placed immediately after a consonant or a valid nukta
       
   693             TChar prevChar = aCriteria[(aCurrentIndex-1)];
       
   694             //if prev character is nukta, it would have been already validated
       
   695             if ( !(IsIndicConsonant(prevChar) || prevChar == 0x093C) )
       
   696                 {
       
   697                 return ETrue;
       
   698                 }
       
   699             }
       
   700         } //end of "if devanagari character range"    
       
   701     return EFalse;
       
   702     }
       
   703     
       
   704 // -----------------------------------------------------------------------------
       
   705 // For Devanagari AS
       
   706 // Mark the end boundary of syllables in input string
       
   707 // @param aCriteria - The search/input string entered so far
       
   708 // @param aStart - The start boundary of syllable to be marked
       
   709 // @return the end boundary of the syllable  
       
   710 // -----------------------------------------------------------------------------
       
   711 //  
       
   712 inline TInt IndicSyllableEnd( TInt& aStart, const TDesC& aCriteria )
       
   713 	{
       
   714 	TInt maxLength = aCriteria.Length();
       
   715 	TInt endMarker(-1);
       
   716 	if(aStart >= (maxLength-1))
       
   717 		{		
       
   718 		aStart = endMarker = maxLength-1;
       
   719 		}
       
   720 	else 
       
   721 		{			
       
   722 		TInt nextCharIndex = aStart + 1 ;
       
   723 		TChar startingChar = aCriteria[aStart];
       
   724 		if ( IsIndicIndependentChar(startingChar) )
       
   725 			{
       
   726 			//Check if syllable contains a special ligature		
       
   727 			if(  aStart < (maxLength-2) && IsSpecialIndicLigature(aCriteria.Mid(aStart, 3)) ) 
       
   728 				{
       
   729 				//Move nextCharIndex till after the 3rd symbol of special ligature.
       
   730 				nextCharIndex+=2;
       
   731 				}					
       
   732 			//check for the next character that is a matra/halant/nukta/modifier
       
   733 			//Currently this check only for Devanagari characters. If other Indic language support
       
   734 			//is required, we will need to add to this list.
       
   735 			while( (nextCharIndex<maxLength) && 
       
   736 			      ( ( IsIndicMatra(aCriteria[nextCharIndex]) ) //matra
       
   737 		          ||( aCriteria[nextCharIndex] == 0x094D ) //Devanagari halant
       
   738 		          ||( aCriteria[nextCharIndex] == 0x093C ) //Devanagari nukta 
       
   739 			      ||( aCriteria[nextCharIndex] >= 0x0901 && aCriteria[nextCharIndex] <= 0x0903 ))) //Devanagari modifier			      
       
   740 			    {
       
   741 				//check if this is a fallback rendered character. Increment index only if it isn't:
       
   742 				if ( !IsFallbackRenderedCharacter(aCriteria, nextCharIndex) )
       
   743 				    {
       
   744 				    ++nextCharIndex;
       
   745 				    }
       
   746 				else
       
   747 				    {
       
   748 				    break;
       
   749 				    }
       
   750 				}
       
   751 			}		
       
   752 		//nextCharIndex should now be pointing to either the start of the next syllable
       
   753 		//or a non-Devanagari-letter. 
       
   754 		//End marker of current syllable should be placed just before the nextCharIndex
       
   755 		endMarker = nextCharIndex-1;		
       
   756 		}		
       
   757 	return endMarker;			
       
   758 	}
       
   759 
       
   760 // -----------------------------------------------------------------------------
       
   761 // For Devanagari AS
       
   762 // Parses through each Devanagari-syllable in the input string.
       
   763 // It will stop when we have gone through aInputSyllableCount number of syllables. 
       
   764 // @param aCriteria - The search string entered so far
       
   765 // @param aStart - The start boundary of the last parsed syllable 
       
   766 // @param aEnd - The end boundary of the last parsed syllable  
       
   767 // -----------------------------------------------------------------------------
       
   768 //  
       
   769 inline void IndicSyllableBoundary( TInt& aStart, TInt& aEnd, TInt aInputSyllableCount, 
       
   770     const TDesC &aCriteria )
       
   771 	{
       
   772 	TInt boundaryCount = 0;
       
   773 	TInt tStart = aStart = 0;
       
   774 	while( boundaryCount != aInputSyllableCount )
       
   775 		{
       
   776 		aEnd = IndicSyllableEnd(tStart, aCriteria);	
       
   777 		boundaryCount++;
       
   778 		aStart = tStart;
       
   779 		tStart = aEnd+1;	
       
   780 		}
       
   781 	}
       
   782 
       
   783 // -----------------------------------------------------------------------------
       
   784 // For Devanagari AS
       
   785 // Checks if aItemString contains atleast one Indic letter
       
   786 // @param aItemString - string to be checked
       
   787 // @return ETrue if aItemString contains Devanagari letter EFalse otherwise.
       
   788 // -----------------------------------------------------------------------------
       
   789 //  
       
   790 inline TBool IsIndicWord( const TDesC& aItemString )
       
   791 	{
       
   792 	TInt strLength = aItemString.Length();
       
   793 	for ( TInt index = 0; index < strLength; ++index )
       
   794 		{	
       
   795 		if ( (aItemString[index] >= 0x900) && (aItemString[index] <= 0x980) )
       
   796 			return ETrue;
       
   797 		}
       
   798 	return EFalse;
       
   799 	}
       
   800 
       
   801 // -----------------------------------------------------------------------------
       
   802 // For Devanagari AS
       
   803 // Checks if the last character from aNextChars can be displayed on 
       
   804 // the adaptive search grid or not. For now, this filters out the Devanagari 
       
   805 // vowels and other special symbol which are represented by the placeholder '-'.
       
   806 // @param aNextChars list of characters to be displayed on adaptive search grid
       
   807 // @return ETrue last character is valid for AS Grid, else EFalse.  
       
   808 // -----------------------------------------------------------------------------
       
   809 //  
       
   810 inline TBool IsValidNextChars( const TDesC &aNextChars )
       
   811 	{
       
   812 	TBool ret = ETrue;
       
   813 	if(aNextChars.Length()>0)
       
   814 		{
       
   815 		TChar ch = aNextChars[aNextChars.Length()-1];
       
   816 		if( (ch >= 0x0901 && ch <= 0x0903) || (ch >= 0x093C && ch <= 0x094D) )
       
   817 			{
       
   818 			ret = EFalse;
       
   819 			}	   
       
   820         }
       
   821 	return ret;
       
   822 	}
       
   823 
       
   824 
       
   825 // -----------------------------------------------------------------------------
       
   826 // For Devanagari AS
       
   827 // (other items were commented in a header).
       
   828 // -----------------------------------------------------------------------------
       
   829 //  
       
   830 inline void UpdateNextCharsL( HBufC*& aNextChars, const TDesC& aItemString )
       
   831 	{
       
   832 	TChar searchChar = aItemString[0];
       
   833     //Check if this is an Indic special ligature
       
   834     if ( IsIndicConsonant(searchChar) && aItemString.Length() > 2
       
   835             && IsSpecialIndicLigature(aItemString) 
       
   836             && KErrNotFound == (*aNextChars).Find(aItemString.Mid(0,3)) )
       
   837         {
       
   838         //Check if we have enough space for 3 more characters
       
   839         if( aNextChars->Des().Length() >= aNextChars->Des().MaxLength()-3 )
       
   840             {
       
   841             aNextChars = aNextChars->ReAllocL( aNextChars->Des().MaxLength()+10 );
       
   842             }       
       
   843         aNextChars->Des().Append( aItemString.Mid(0,3) );        
       
   844         }
       
   845     else
       
   846         {
       
   847         //check if this is an Indic combined Char
       
   848         if ( IsIndicCombinedChar(searchChar) )
       
   849             {
       
   850             searchChar = RemoveIndicNukta( searchChar );
       
   851             }
       
   852         //Now update the nextChars string
       
   853         TInt strLength = aNextChars->Length();
       
   854         for ( TInt i(0); i < strLength ; ++i )
       
   855             {
       
   856             if ( IsSpecialIndicLigature( (*aNextChars).Mid( i ) ) )
       
   857                 {
       
   858                 //As aItemString is not a special ligature (checked above)
       
   859                 //we can move directly to the 3rd character from here
       
   860                 i+=2;
       
   861                 }
       
   862             else if ( searchChar.GetUpperCase() == (*aNextChars)[i] ||
       
   863                         searchChar.GetLowerCase() == (*aNextChars)[i] )
       
   864                 {
       
   865                 //already exists - do nothing
       
   866                 return;
       
   867                 }
       
   868             //else continue the loop
       
   869             }
       
   870         //So this character is not yet in the list of nextChars.
       
   871         if ( aNextChars->Des().Length() == aNextChars->Des().MaxLength() )
       
   872             {
       
   873             aNextChars = aNextChars->ReAllocL( aNextChars->Des().MaxLength()+10 );
       
   874             }       
       
   875         aNextChars->Des().Append( searchChar );   
       
   876         }
       
   877    	}
       
   878 
       
   879 /**
       
   880  * Update next chars from the list box item text, when search field is empty.
       
   881  * This need to be done for update next characters for adaptive grid
       
   882  * works faster then calling IsAdaptiveFindMatch().   
       
   883  *
       
   884  * @since 5.0
       
   885  * @param aNextChars reference to the next characters for the adaptive search grid
       
   886  * @param aItemString List box item text.
       
   887  */
       
   888  
       
   889 inline void UpdateNextCharsFromString( HBufC*& aNextChars, const TDesC& aItemString )
       
   890 	{   
       
   891 	 TInt itemStringLength = aItemString.Length();
       
   892 	 
       
   893 	 for( TInt i = 0; i < itemStringLength; i++ )
       
   894         {
       
   895         if ( i == 0 || IsFindWordSeparator( aItemString[i-1] ) )
       
   896             {  
       
   897             //If this is an Indic letter 
       
   898             if ( aItemString[i] >= 0x0900 && aItemString[i] <= 0x0980 )
       
   899                 {
       
   900                 TRAP_IGNORE( UpdateNextCharsL( aNextChars, aItemString.Mid(i) ) );
       
   901                 }
       
   902             else  if (!(IsVietnameseSpecialCharacter( aItemString[i])))
       
   903                 {
       
   904                 TRAP_IGNORE( UpdateNextCharsL( aNextChars, aItemString[i] ) );
       
   905                 }
       
   906             }
       
   907 		}
       
   908 	}
       
   909 	
       
   910 inline TBool IsAdaptiveFindMatchClassic( const TDesC& aItemString, const TDesC& aSearchText )
       
   911     {
       
   912     TPtrC itemptr = aItemString;
       
   913     TPtrC searchptr = aSearchText;
       
   914 
       
   915     TBool match = EFalse;
       
   916     
       
   917     for(;;) 
       
   918         {
       
   919         // Loop invariant: itemptr is next character from ' ' or '-'
       
   920         // Loop invariant: seachptr is at beginning of searched item
       
   921     
       
   922         TInt val = MyFindC(itemptr,searchptr);
       
   923         if (val == 0)
       
   924             {
       
   925             match = ETrue;
       
   926             break;
       
   927             }
       
   928         if (val != KErrNotFound && IsFindWordSeparator(itemptr[val-1]))
       
   929             {
       
   930             match = ETrue;
       
   931             break;
       
   932             }
       
   933 
       
   934         // find the word separator characters from list item
       
   935         TInt spacepos = itemptr.LocateF(TChar(' '));
       
   936         TInt minuspos = itemptr.LocateF(TChar('-'));
       
   937         TInt tabpos = itemptr.LocateF(TChar('\t'));
       
   938         if (spacepos != KErrNotFound)
       
   939             {
       
   940             itemptr.Set(itemptr.Mid(spacepos+1));
       
   941             }
       
   942         else if (minuspos != KErrNotFound)
       
   943             {
       
   944             itemptr.Set(itemptr.Mid(minuspos+1));
       
   945             }
       
   946         else if (tabpos != KErrNotFound)
       
   947             {
       
   948             itemptr.Set(itemptr.Mid(tabpos+1));
       
   949             }
       
   950         else
       
   951             {
       
   952             match = EFalse;
       
   953             break;
       
   954             }
       
   955         if (itemptr.Length() == 0)
       
   956             {
       
   957             match = EFalse;
       
   958             break;
       
   959             }
       
   960 
       
   961         }
       
   962     return match;
       
   963     }	
       
   964 
       
   965 /**
       
   966  * Checks the current character for special character from Thai language . 
       
   967  *
       
   968  * @since 5.0
       
   969  * @return @c ETrue If tone mark or diatric from Thai language otherwise EFalse. 
       
   970  */	
       
   971 inline TBool IsThaiSpecialCharacter( TChar aCh )
       
   972     {    
       
   973     if( ( aCh > 0xE46 && aCh < 0xE4F ) ||  aCh == 0xE3A )
       
   974 		{
       
   975 		return ETrue;
       
   976 		}       
       
   977 	return EFalse;
       
   978     }
       
   979 
       
   980 /**
       
   981  * Checks if @c aItemText matches @c aSearchText in the sense described in
       
   982  * S60.  Calls UpdateNextCharsL() if findutil is not supported.
       
   983  *
       
   984  * @since 5.0
       
   985  * @param aItemText list box item text.
       
   986  * @param aSearchText search text.
       
   987  * @param aNextChars reference to the next characters for the adaptive search grid
       
   988  * @param aDigraphs digraphs and trigraph text.
       
   989  * 
       
   990  * @return @c ETrue if list box item text matches aSearchText EFalse otherwise.
       
   991  */
       
   992 inline TBool IsAdaptiveFindMatch( const TDesC& aItemString, 
       
   993 	const TDesC& aSearchText, HBufC*& aNextChars, TInt /*aInputLang*/, const TDesC& aDigraphs )
       
   994 	{	    	
       
   995 	HBufC16* searchText = NULL;
       
   996 	TRAPD( error, searchText = HBufC16::NewL( KMatchingBufferLength ) );
       
   997 	TBool wildchar = EFalse;
       
   998 	if ( error == KErrNone )
       
   999 	    {
       
  1000 	    TInt itemStringLength = aItemString.Length();
       
  1001         TInt searchTextLength = aSearchText.Length();    
       
  1002         
       
  1003         if ( searchTextLength < KMatchingBufferLength )
       
  1004         	{
       
  1005         	searchText->Des().Append( aSearchText );
       
  1006         	}
       
  1007         else
       
  1008         	{
       
  1009         	searchText->Des().Append( aSearchText.Left(KMatchingBufferLength-1) );
       
  1010         	}  
       
  1011         	 
       
  1012          // To disable the wildchar matching provided by MatchC
       
  1013         if ( aSearchText.Locate( KLitQuestion ) != KErrNotFound || 
       
  1014              aSearchText.Locate( KLitStar ) != KErrNotFound )
       
  1015             {            
       
  1016             wildchar = IsAdaptiveFindMatchClassic( aItemString, aSearchText );
       
  1017             if ( wildchar == EFalse )
       
  1018                 {
       
  1019                 delete searchText;
       
  1020                 return wildchar;
       
  1021                 }
       
  1022             else 
       
  1023                 {  
       
  1024                 TInt val;      
       
  1025                 searchText->Des().Append( KLitStar );
       
  1026                 for( TInt i = 0; i < itemStringLength; i++ )
       
  1027                     {
       
  1028                     if ( i == 0 || IsFindWordSeparator( aItemString[i-1] ) )
       
  1029                         {
       
  1030                         val = MyFindC(  aItemString, aSearchText );                    
       
  1031                         if( (val == i) && (i < (itemStringLength-searchTextLength))) 
       
  1032                             {
       
  1033                             if( !(IsThaiSpecialCharacter(aItemString[i+searchTextLength])) && !(IsVietnameseSpecialCharacter( aItemString[i+searchTextLength]) ))
       
  1034                                 {
       
  1035                                 TRAP_IGNORE( UpdateNextCharsL( aNextChars, aItemString[i+searchTextLength]) );   
       
  1036                                 }                                
       
  1037                             }
       
  1038                         }         
       
  1039               	    } // for
       
  1040               	delete searchText;
       
  1041                 return wildchar;	 
       
  1042                 }
       
  1043             }
       
  1044       	     	
       
  1045         searchText->Des().Append( KLitStar );
       
  1046         searchText->Des().UpperCase();
       
  1047 
       
  1048         TBool isCommonChars = EFalse;
       
  1049         TInt all_result = KErrNotFound;
       
  1050         
       
  1051         TLanguage lang = User::Language();
       
  1052         
       
  1053         for( TInt i = 0; i < itemStringLength; i++ )
       
  1054             {
       
  1055             if ( i == 0 || IsFindWordSeparator( aItemString[i-1] ) )
       
  1056                 {
       
  1057                 TInt result = KErrNotFound;
       
  1058                 //Some vowels of Thai can not be searched with MatchC(). 
       
  1059                 if( aDigraphs.Length() != 0 || lang == ELangThai )
       
  1060                     {
       
  1061                     result = aItemString.Mid(i).Match( searchText->Des() );
       
  1062                     }
       
  1063                 else
       
  1064                     {
       
  1065                     result = aItemString.Mid(i).MatchC( searchText->Des() );
       
  1066                     }
       
  1067                 
       
  1068                 if( result != KErrNotFound ) 
       
  1069                     {
       
  1070                     all_result = result;
       
  1071                     if( i < (itemStringLength-searchTextLength) )                	   	       	   		
       
  1072                         {
       
  1073                         if( !(IsThaiSpecialCharacter( aItemString[i+searchTextLength])) && !(IsVietnameseSpecialCharacter( aItemString[i+searchTextLength]) ))
       
  1074                             {
       
  1075                             TRAP_IGNORE( UpdateNextCharsL( aNextChars, aItemString[i+searchTextLength]) );
       
  1076 
       
  1077                             if ( aDigraphs.Length() != 0 )
       
  1078                                 {
       
  1079                                 TBuf<2> digraph;
       
  1080                                 digraph.Append( aItemString[i+searchTextLength-1] );
       
  1081                                 digraph.Append( aItemString[i+searchTextLength] );
       
  1082 
       
  1083                                 if( searchTextLength == 1 )
       
  1084                                     {
       
  1085                                     if( aDigraphs.Find( digraph ) == KErrNotFound )
       
  1086                                         {
       
  1087                                         isCommonChars = ETrue;
       
  1088                                         }
       
  1089                                     }
       
  1090                                 else
       
  1091                                     {
       
  1092                                     TBuf<3> trigraph;
       
  1093                                     trigraph.Append( aItemString.Mid(i+searchTextLength-2,3) );
       
  1094                                     if( digraph[0] == KLitSpace 
       
  1095                                         || ( aDigraphs.Find( digraph ) == KErrNotFound
       
  1096                                         && aDigraphs.Find( trigraph ) == KErrNotFound ) )
       
  1097                                         {
       
  1098                                         isCommonChars = ETrue;
       
  1099                                         }
       
  1100                                     }
       
  1101                                 }
       
  1102                             }            	   
       
  1103                         }
       
  1104                     else
       
  1105                         {
       
  1106                         isCommonChars = ETrue;
       
  1107                         }
       
  1108                     }                                                                  	   	
       
  1109                 } // if (i==0 ..)  
       
  1110       	    } // for	 
       
  1111         
       
  1112         if(aDigraphs.Length() != 0 && !isCommonChars )   
       
  1113             {
       
  1114             all_result = KErrNotFound;
       
  1115             }
       
  1116 	    
       
  1117   	    if( all_result != KErrNotFound )
       
  1118             {
       
  1119             delete searchText;
       
  1120             return ETrue;
       
  1121            	}    
       
  1122         else 
       
  1123             {
       
  1124             delete searchText;
       
  1125             return EFalse;
       
  1126             }
       
  1127         	            		
       
  1128          } // if (error == KErrNone)   
       
  1129     delete searchText;                 
       
  1130     return EFalse;
       
  1131 	}
       
  1132 
       
  1133 // -----------------------------------------------------------------------------
       
  1134 // For Devanagari AS
       
  1135 // Checks if @c aItemText matches @c aSearchText.
       
  1136 // @param aItemText list box item text.
       
  1137 // @param aSearchText search text.
       
  1138 // @param aNextChars reference to the next characters for the adaptive search grid
       
  1139 // @return @c ETrue if list box item text matches EFalse otherwise.
       
  1140 // -----------------------------------------------------------------------------
       
  1141 //  
       
  1142 inline TBool IsIndicAdaptiveFindMatch( const TDesC& aItemString, 
       
  1143 	const TDesC& aSearchText, HBufC*& aNextChars, TInt /*aInputLang*/ )
       
  1144 	{	    	
       
  1145 	HBufC16* searchText(NULL);
       
  1146 	TRAPD( error, searchText = HBufC16::NewL( KMatchingBufferLength ) );
       
  1147 	if ( error == KErrNone )
       
  1148 	    {
       
  1149 	    TInt itemStringLength = aItemString.Length();
       
  1150         TInt searchTextLength = aSearchText.Length();    
       
  1151         
       
  1152         if ( searchTextLength < KMatchingBufferLength )
       
  1153         	{
       
  1154         	searchText->Des().Append( aSearchText );
       
  1155         	}
       
  1156         else
       
  1157         	{
       
  1158         	searchText->Des().Append( aSearchText.Left(KMatchingBufferLength-1) );
       
  1159         	}    
       
  1160     	
       
  1161     	TInt indicSyllableCount = -1;
       
  1162         if( aSearchText.Length()>0 )
       
  1163     		{
       
  1164     		//This will replace all placeholder '-' symbols with '*'
       
  1165      		indicSyllableCount = IndicSyllableCount( searchText, searchTextLength );
       
  1166     		}
       
  1167     	    	
       
  1168     	//Append '*' to the end if not already present.
       
  1169         if ( (*searchText)[searchText->Length() - 1] != KLitStar)
       
  1170     		{
       
  1171     		searchText->Des().Append( KLitStar );
       
  1172     		}   
       
  1173     	
       
  1174     	TInt result = KErrNotFound;
       
  1175         
       
  1176         //check if the search string is found in the item string
       
  1177         for( TInt index = 0; index < itemStringLength; index++ )
       
  1178             {
       
  1179             if ( index==0 || IsFindWordSeparator( aItemString[index-1] ) )
       
  1180                 {
       
  1181                 TUint flag = ( TCollationMethod::EFoldCase | TCollationMethod::EIgnoreNone | TCollationMethod::EIgnoreCombining);//TCollationMethod::EIgnoreNone |
       
  1182         		TCollationMethod collationMethod = *Mem::GetDefaultMatchingTable();
       
  1183         		collationMethod.iFlags |= flag;
       
  1184             
       
  1185            		result = aItemString.Mid(index).MatchC( (*searchText), &collationMethod );
       
  1186                 
       
  1187                 if( result != KErrNotFound ) 
       
  1188                     {
       
  1189                     if( index <= (itemStringLength-searchTextLength) )
       
  1190         	   			{
       
  1191         	   			//search for the last character in the string
       
  1192         	   			//We use a TBuf instead of TChar since a special ligature is 
       
  1193         	   			//represented by 3 characters. Last char would be the '*' wildchar.
       
  1194 	        	   		TBuf<4> lastChar;
       
  1195 	        	   		TInt modifiedStrLength = searchText->Length();
       
  1196 	        	   		if( (*searchText)[modifiedStrLength-1] == KLitStar )
       
  1197 	        	   			{
       
  1198 	        	   			//is this a special ligature?
       
  1199 	        	   			if ( modifiedStrLength > 3 &&
       
  1200 	        	   			        IsSpecialIndicLigature( (*searchText).Mid(modifiedStrLength-4) ) )
       
  1201 	        	   			    {
       
  1202 	        	   			    lastChar = (*searchText).Mid(modifiedStrLength-4);
       
  1203 	        	   			    }
       
  1204 	        	   			else
       
  1205 	        	   			    {
       
  1206 	        	   			    lastChar = (*searchText).Mid(modifiedStrLength-2);
       
  1207 	        	   			    }
       
  1208 	        	   			}
       
  1209 	        	   		else
       
  1210 	        	   			{
       
  1211 	        	   			//No wildchar here
       
  1212 	        	   			lastChar = (*searchText).Mid(modifiedStrLength-1);
       
  1213 	        	   			}
       
  1214 	        	   		
       
  1215 	        	   		lastChar.UpperCase(); //For latin characters as adaptive grid is always in upper case
       
  1216         	   			TInt charPos = result; //aItemString.Mid(index).MatchC( searchText->Des(), &collationMethod );
       
  1217         	   			//if found position is not within the substring to be searched, return EFalse.
       
  1218                         if( charPos == KErrNotFound)
       
  1219                             {
       
  1220                             delete searchText;
       
  1221                             return EFalse;
       
  1222                             }
       
  1223                         
       
  1224         	   			TInt tempPos = charPos;
       
  1225 	        	   		
       
  1226 	        	   		TInt startCount = -1 , endCount = -1;
       
  1227 	        	   		
       
  1228     	   				//TInt tempIndex(0);
       
  1229     	   				//Get the position of the next syllable to be checked
       
  1230     	   				IndicSyllableBoundary(startCount, endCount, indicSyllableCount, aItemString.Mid(index));
       
  1231     	   				tempPos = aItemString.Mid(index+startCount).MatchC( lastChar, &collationMethod ); 
       
  1232     	   				
       
  1233     	   				if (
       
  1234     	   				//if found position is not within the next syllable to be searched, 
       
  1235     	   				//return EFalse.
       
  1236     	   				    ( tempPos != 0 )  
       
  1237     	   				//Also check if character to be searched is a single unicode while
       
  1238     	   				//the match is at the start of a special ligature
       
  1239     	   				   	|| ( !IsSpecialIndicLigature( lastChar ) && 
       
  1240     	   				            IsSpecialIndicLigature( aItemString.Mid(index+startCount) ) )
       
  1241     	   				    )
       
  1242     	   				    {
       
  1243     	   				    delete searchText;
       
  1244     	   				    return EFalse;
       
  1245     	   				    }
       
  1246 	        	   		
       
  1247 	        	   		//else, continue - find the next characters to be displayed on the grid	
       
  1248 	        	   		tempPos = index + endCount + 1;
       
  1249 	        	   		
       
  1250 	        	   		do	{
       
  1251 	        	   		    if(charPos!=KErrNotFound && (tempPos) < itemStringLength )
       
  1252         	   					{
       
  1253         	   						TRAP_IGNORE( UpdateNextCharsL( aNextChars, aItemString.Mid(tempPos) ) );
       
  1254         	   					}
       
  1255         	   				
       
  1256         	   				//Is the found next character a consonent/independent-vowel/non-Indic character?
       
  1257         	   				if ( IsValidNextChars( *aNextChars ) )
       
  1258         	   					{
       
  1259         	   					//found a valid character for displaying on the grid - return from here
       
  1260         	   					delete searchText;
       
  1261             					return ETrue;
       
  1262         	   					}
       
  1263         	   				else //we found an invalid valid character - keep searching
       
  1264         	   					{
       
  1265         	   					TPtr ptr = aNextChars->Des();
       
  1266         	   					ptr.Delete(aNextChars->Length()-1,1);
       
  1267         	   					//Is this a fallback rendered character?
       
  1268         	   					if ( IsFallbackRenderedCharacter(aItemString, tempPos) )
       
  1269         	   					    {
       
  1270         	   					    //Keep the entry but don't show any more characters from this word
       
  1271         	   					    delete searchText;
       
  1272         	   					    return ETrue;
       
  1273         	   					    }
       
  1274         	   					}
       
  1275         	   				}
       
  1276         	   			//keep looping till we find a valid nextChar or we reach the end of the string
       
  1277         	   			while(tempPos < itemStringLength ); 
       
  1278         	   			
       
  1279         	   			}
       
  1280         	   			
       
  1281         	   		} // if( result != KErrNotFound )                                                                  	   	
       
  1282                 } // if (index==0 ..)        
       
  1283       	    } // for loop	 
       
  1284 	    
       
  1285   	    if( result != KErrNotFound )
       
  1286             {
       
  1287             delete searchText;
       
  1288             return ETrue;
       
  1289            	}    
       
  1290         else 
       
  1291             {
       
  1292             delete searchText;
       
  1293             return EFalse;
       
  1294             }
       
  1295         	            		
       
  1296          } // if (error == KErrNone)   
       
  1297     delete searchText;                 
       
  1298     return EFalse;
       
  1299 	}
       
  1300 	
       
  1301 // -----------------------------------------------------------------------------
       
  1302 // CFindUtilWestern::MatchAdaptiveRefineL
       
  1303 // (other items were commented in a header).
       
  1304 // -----------------------------------------------------------------------------
       
  1305 //  
       
  1306 TBool CFindUtilWestern::MatchAdaptiveRefineL( const TDesC& aItemString, 
       
  1307 	const TDesC& aSearchText, HBufC*& aNextChars )
       
  1308 	{
       
  1309     if ( aItemString.Length() == 0 )
       
  1310         {
       
  1311         return EFalse;
       
  1312         }
       
  1313     if ( aSearchText.Length() == 0 )
       
  1314         {        
       
  1315         UpdateNextCharsFromString( aNextChars, aItemString );
       
  1316         return ETrue;
       
  1317         }
       
  1318         
       
  1319     if( iDigraphChars == NULL )
       
  1320         {
       
  1321         iDigraphChars = StringLoader::LoadL( R_QTN_ADS_DIGRAPH );
       
  1322         TPtr digraph = iDigraphChars->Des();
       
  1323         digraph.UpperCase();
       
  1324 
       
  1325         _LIT( KMissing,"#MISSING" );
       
  1326         if( digraph.CompareC(KMissing()) == 0 )
       
  1327             {
       
  1328             digraph = KNullDesC;
       
  1329             }
       
  1330         }
       
  1331         
       
  1332     TBuf<KAknStringBufferSize> itemString(aItemString);
       
  1333     itemString.UpperCase();
       
  1334 
       
  1335     //AS does not show tone marks and diacritics when language is Thai.
       
  1336     TLanguage lang = User::Language();  
       
  1337     if ( lang == ELangThai )
       
  1338         {
       
  1339         for(TInt i=0; i < itemString.Length(); i++)
       
  1340             {
       
  1341             if(IsThaiSpecialCharacter( itemString[i] ))
       
  1342                 {
       
  1343                 itemString.Delete(i,1);
       
  1344                 }
       
  1345             }
       
  1346         }
       
  1347 
       
  1348     if ( IsIndicWord(aItemString) )
       
  1349     	{
       
  1350     	// itemString contains Devanagari letters
       
  1351     	return IsIndicAdaptiveFindMatch( itemString, aSearchText, aNextChars, iInputLanguage );		
       
  1352     	}
       
  1353     else 
       
  1354     	{
       
  1355     	return IsAdaptiveFindMatch( itemString, aSearchText, aNextChars, iInputLanguage, iDigraphChars->Des() );				
       
  1356     	}    
       
  1357 	}
       
  1358 	
       
  1359 // ---------------------------------------------------------
       
  1360 // Match arithmetic for accurate search, special conversion 
       
  1361 // for aItemString is implemented with MFindStringConverter
       
  1362 // before the final match
       
  1363 // ---------------------------------------------------------
       
  1364 //
       
  1365 TBool CFindUtilWestern::MatchRefineL( const TDesC& /*aItemString*/, const TDesC& /*aSearchText*/, 
       
  1366                                       TMatchPolicy /*aPolicy*/, MFindStringConverter* /*aConverter*/)
       
  1367     {
       
  1368     return EFalse;
       
  1369     }	
       
  1370 
       
  1371 // ========================== OTHER EXPORTED FUNCTIONS =========================
       
  1372 
       
  1373 // -----------------------------------------------------------------------------
       
  1374 // FindUtilFactoryFunctionL
       
  1375 // Factory function at first ordinal
       
  1376 // Returns: MFindUtil: It returns MFindUtil I/F.
       
  1377 // -----------------------------------------------------------------------------
       
  1378 //
       
  1379 // Factory function at first ordinal
       
  1380 EXPORT_C MFindUtil* FindUtilFactoryFunctionL()
       
  1381     {
       
  1382     return new( ELeave ) CFindUtilWestern();
       
  1383     }
       
  1384 
       
  1385 // end of file