uiutils/Findutil/src/FindUtilWestern.cpp
changeset 0 2f259fa3e83a
child 3 8ca85d2f0db7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uiutils/Findutil/src/FindUtilWestern.cpp	Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,1385 @@
+/*
+* Copyright (c) 2002-2005 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:         Western Find Utilities implementation file.
+*
+*/
+
+
+
+
+
+
+
+
+
+#include "FindUtilWestern.h"
+#include <collate.h>
+#include <PtiIndicDefs.h>
+#include "FindUtilKorean.h"
+#include <avkon.rsg>
+#include <stringloader.h>
+const TInt KLitTab('\t');
+const TInt KLitSpace(' ');
+const TInt KLitHyphen('-');
+const TInt KLitLineFeed(8233);
+const TInt KLitStar('*');
+const TInt KLitQuestion('?');
+
+const TInt KMatchingBufferLength(256);
+const TInt KAknStringBufferSize = 256;
+
+namespace {
+
+// ---------------------------------------------------------------------------
+// IsFindWordSeparator
+// ---------------------------------------------------------------------------
+//
+inline TBool IsFindWordSeparator(TChar aCh)
+    {
+    return aCh == KLitSpace || aCh == KLitHyphen || aCh == KLitTab || aCh == KLitLineFeed;
+    }
+
+
+
+void ReplaceCharacters(TDes &aDes, const TDesC &aChars, TChar aReplacement)
+    //
+    // Running time O(aDes.Length() * aChars.Length())
+    // Does not change length of the string.
+    // 
+    {
+    TInt src = 0;
+    TInt srclength = aDes.Length();
+    while(src < srclength)
+        {
+        TChar c = aDes[src];
+        if (aChars.LocateF(c) != KErrNotFound)
+            aDes[src] = TUint16(aReplacement);
+        ++src;
+        }
+    }
+
+inline TInt MyFindC(const TDesC &aItemString, const TDesC &aSearchText)
+    {
+    TBuf<200> searchText;
+    TBuf<200> itemString;
+    searchText.Append(aSearchText);
+    // The replacecharacters are to disable regexp matching provided
+    // by MatchC().
+	_LIT(KQuestion,"?");
+	_LIT(KStar,"*");
+    ReplaceCharacters(searchText, KQuestion, TChar('\t'));
+    ReplaceCharacters(searchText, KStar, TChar('\r'));
+    searchText.Append(KStar);
+    if (aItemString.Length() < 200)
+        itemString.Append(aItemString);
+    else
+        itemString.Append(aItemString.Left(200));
+    ReplaceCharacters(itemString, KQuestion, TChar('\t'));
+    ReplaceCharacters(itemString, KStar, TChar('\r'));
+
+
+    TInt length = itemString.Length();
+    for(int i=0;i<length;i++)
+        {
+        if (i==0 || IsFindWordSeparator(aItemString[i-1]))
+            {
+            if (itemString.Mid(i).MatchC(searchText) != KErrNotFound)
+                {
+                return i;
+                }
+            }
+        }
+    return KErrNotFound;
+    }
+inline TBool IsFindMatchClassic(const TDesC& aItemString, const TDesC& aSearchText, TInt /*aInputLang = 0*/)
+    {
+    TPtrC itemptr = aItemString;
+    TPtrC searchptr = aSearchText;
+
+    TBool match = EFalse;
+    
+    for(;;) 
+        {
+        // Loop invariant: itemptr is next character from ' ' or '-'
+        // Loop invariant: seachptr is at beginning of searched item
+    
+        TInt val = MyFindC(itemptr,searchptr);
+        if (val == 0)
+            {
+            match = ETrue;
+            break;
+            }
+        if (val != KErrNotFound && IsFindWordSeparator(itemptr[val-1]))
+            {
+            match = ETrue;
+            break;
+            }
+
+        // find the word separator characters from list item
+        TInt spacepos = itemptr.LocateF(TChar(' '));
+        TInt minuspos = itemptr.LocateF(TChar('-'));
+        TInt tabpos = itemptr.LocateF(TChar('\t'));
+        if (spacepos != KErrNotFound)
+            {
+            itemptr.Set(itemptr.Mid(spacepos+1));
+            }
+        else if (minuspos != KErrNotFound)
+            {
+            itemptr.Set(itemptr.Mid(minuspos+1));
+            }
+        else if (tabpos != KErrNotFound)
+            {
+            itemptr.Set(itemptr.Mid(tabpos+1));
+            }
+        else
+            {
+            match = EFalse;
+            break;
+            }
+        if (itemptr.Length() == 0)
+            {
+            match = EFalse;
+            break;
+            }
+
+        }
+    return match;
+    }
+
+// ---------------------------------------------------------------------------
+// IsFindMatch
+// ---------------------------------------------------------------------------
+//
+inline TBool IsFindMatch(const TDesC& aItemString, const TDesC& aSearchText, TInt aInputLang = 0)
+    {
+    TBuf<200> searchText;
+    TInt itemStringLength = aItemString.Length();
+    
+    if ( aSearchText.Length() < 200 )
+        {
+        searchText.Append( aSearchText );
+        }
+    else
+        {
+        searchText.Append( aSearchText.Left(199) );
+        }
+    
+    // To disable the wildchar matching provided by MatchC
+    if (aSearchText.Locate( KLitQuestion ) != KErrNotFound)
+        {
+        return IsFindMatchClassic(aItemString, aSearchText, aInputLang);
+        }
+    if (aSearchText.Locate( KLitStar ) != KErrNotFound)
+        {
+        return IsFindMatchClassic(aItemString, aSearchText, aInputLang);
+        }
+
+    searchText.Append( KLitStar );
+        
+    TInt result = KErrNone;
+   
+    for( TInt i = 0; i < itemStringLength; i++ )
+        {
+        if ( i==0 || IsFindWordSeparator( aItemString[i-1] ) )
+            {
+            
+            if(aInputLang == ELangHindi
+#ifdef RD_MARATHI
+                || aInputLang == ELangMarathi
+#endif
+
+#ifdef RD_HINDI_PHONETIC_INPUT
+                || aInputLang == KLangHindiPhonetic
+#endif            
+            )
+            {
+            TUint flag = ( TCollationMethod::EIgnoreNone | TCollationMethod::EFoldCase | TCollationMethod::EIgnoreCombining );
+        	TCollationMethod m = *Mem::GetDefaultMatchingTable();
+  			m.iFlags |= flag;
+        	result = aItemString.Mid(i).MatchC( searchText, &m, 3);
+            }
+            else
+            {
+            	result = aItemString.Mid(i).MatchC( searchText );
+            }
+                        	
+            if(result != KErrNotFound)
+            	{
+            		return ETrue;
+            	}
+            }
+        }
+        
+    return EFalse;
+	}	
+}
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CFindUtilWestern::CFindUtilWestern
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CFindUtilWestern::CFindUtilWestern()
+    {
+    iRepository = NULL;
+    iNotifyHandler = NULL;
+    }
+
+// Destructor
+CFindUtilWestern::~CFindUtilWestern()
+    {
+    if ( iNotifyHandler )
+        {
+        iNotifyHandler->StopListening();
+        delete iNotifyHandler;
+        iNotifyHandler=NULL;
+        }
+    if(iRepository)
+        {
+        delete iRepository;
+        iRepository = NULL;    
+        }    	
+    if ( iFindUtilKorean )
+        {
+    	delete iFindUtilKorean;
+    	iFindUtilKorean = NULL;
+        }
+    if( iDigraphChars )       
+        {
+        delete iDigraphChars;
+        }
+    }
+
+
+void CFindUtilWestern::OpenL()
+	{
+	CFindUtilBase::OpenL();
+    
+    if(!iRepository)
+    	{
+		iRepository = CRepository::NewL(KCRUidAknFep);
+		iRepository->Get(KAknFepInputTxtLang, iInputLanguage);
+	    }
+	if(!iNotifyHandler)
+	    {
+		iNotifyHandler = CCenRepNotifyHandler::NewL( *this, 
+                                              *iRepository,
+                                              CCenRepNotifyHandler::EIntKey,
+                                              KAknFepInputTxtLang );
+		iNotifyHandler->StartListeningL();
+	    }	
+//TSW: LYEE-7Q2GRV  
+	if(!iFindUtilKorean)
+	    {
+        iFindUtilKorean = CFindUtilKorean::NewL();
+	    }
+	}
+	
+void CFindUtilWestern::HandleNotifyInt( TUint32 aId, TInt aNewValue )
+	{
+	if(aId == KAknFepInputTxtLang)
+	    iInputLanguage = aNewValue;
+	}
+	
+// -----------------------------------------------------------------------------
+// CFindUtilWestern::Match
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+
+TBool CFindUtilWestern::Match(const TDesC& aContactsField, const TDesC& aWord)
+    {
+    if ( iFindUtilKorean->IsKoreanLanguage( aContactsField ) || iFindUtilKorean->IsKoreanLanguage( aWord ) )
+        {
+        return iFindUtilKorean->Match( aContactsField, aWord );	
+        }
+    else
+    	{
+    TInt numChar = 1;
+    	if (!aContactsField.Length())
+        	{
+                _LIT( KNone, "*" );
+    	        if( aWord.CompareC(KNone()) == 0 )
+                    {
+    	            return ETrue;
+                    }
+                else
+                    {
+        	    return EFalse;
+                    }
+        	}        
+    	if((aWord.Length() > 1) && aWord[aWord.Length()-2] == 0x200B)
+    		{
+    		numChar = 2;
+    		}    	
+    	if ( IsFindMatch(aContactsField, aWord.Left(aWord.Length()-numChar), iInputLanguage) )
+        	{
+        	return ETrue;
+        	}
+  		return EFalse;
+   		}
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFindUtilWestern::MatchRefineL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TBool CFindUtilWestern::MatchRefineL( const TDesC& aItemString, const TDesC& aSearchText )
+    {
+    if ( iFindUtilKorean->IsKoreanLanguage( aItemString ) || iFindUtilKorean->IsKoreanLanguage( aSearchText ) )
+        {
+        return iFindUtilKorean->MatchRefineL( aItemString, aSearchText );	
+        }
+    else
+    {
+    if ( aItemString.Length() == 0 )
+        {
+        return EFalse;
+        }
+
+    if ( aSearchText.Length() == 0 )
+        {
+        return ETrue;
+        }
+    return IsFindMatch( aItemString, aSearchText, iInputLanguage );
+    	}
+    }
+
+// -----------------------------------------------------------------------------
+// CFindUtilWestern::IsWordValidForMatching
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TBool CFindUtilWestern::IsWordValidForMatching(const TDesC& /*aWord*/)
+    {
+    return ETrue;
+    }
+
+
+// ========================= FOR ADAPTIVE FIND ================================
+
+// -----------------------------------------------------------------------------
+// For Vietnamese AS
+// 
+// -----------------------------------------------------------------------------
+//
+inline TChar ReplaceVietnameseChar( const TChar aCh )   
+    {
+    TChar Char = aCh.GetUpperCase();
+    if ( (Char >= 0x00C0 && Char <= 0x00C3) || Char == 0x102  ||
+         ((Char >= 0x1EA0 && Char <= 0x1EB6) && Char%2 == 0) )  
+        {
+        Char = 0x0041; // A
+        return Char; 
+        }        
+    if ( (Char >= 0x00C8 && Char <= 0x00CA) || 
+        ((Char >= 0x1EB8 && Char <= 0x1EC6) && Char%2 == 0) )
+        {
+        Char = 0x0045; // E
+        return Char; 
+        }               
+    if ( Char == 0x00CC || Char == 0x00CD || Char == 0x0128 || 
+         Char == 0x1EC8 || Char == 0x1ECA  )
+        {
+        Char = 0x0049; // I
+        return Char; 
+        }    
+    if ( (Char >= 0x00D2 && Char <= 0x00D5 ) || Char == 0x1ECE || Char == 0x1ECC ||
+        ((Char >= 0x1ED0 && Char <= 0x1ED8) && Char%2 == 0)) 
+        {
+        Char = 0x004F; // O
+        return Char; 
+        }            
+    if ( Char == 0x1EDA || Char == 0x1EDC || Char == 0x1EDE || 
+         Char == 0x1EE0 || Char == 0x1EE2  )
+        {
+        Char = 0x01A0; // O-horn
+        return Char; 
+        }          
+    if ( Char == 0x00DA || Char == 0x00D9 || Char == 0x0168 || 
+         Char == 0x1EE4 || Char == 0x1EE6  )
+        {
+        Char = 0x0055; // U
+        return Char; 
+        }         
+     if ( (Char >= 0x1EE8 && Char <= 0x1EF0) && Char%2 == 0 )
+        {
+        Char = 0x01AF; // U-horn        
+        return Char; 
+        }         
+     if ( ((Char >= 0x1EF2 && Char <= 0x1EF8) && Char%2 == 0) || Char == 0x00DD ) 
+        {
+        Char = 0x0059; // Y
+        return Char; 
+        }              
+    return Char;
+    } 
+    
+ /**
+ * Checks current character is it special character from Vietnamese language . 
+ *
+ * @since 5.0
+ * @return @c ETrue If it is accent from Vietnamese language, otherwise EFalse. 
+ */	
+inline TBool IsVietnameseSpecialCharacter( TChar aCh )
+    {   
+    if ( ( aCh >= 0x0300 && aCh <= 0x0303 ) ||       
+        aCh == 0x0306 || aCh == 0x0309 || aCh == 0x0323 || aCh == 0x031B )
+        {
+        return ETrue;            
+        }  
+    return EFalse;
+    }
+       
+/**
+ * Update next characters if find pane state was changed.
+ *
+ * @since 5.0
+ * @param aNextChars reference to the next characters for the adaptive search grid
+ * @param aCh Criteria from the search field.    
+ */
+inline void UpdateNextCharsL( HBufC*& aNextChars, TChar aCh )
+    {
+        TChar ch_temp = aCh;          
+    
+    TLanguage lang = User::Language();  
+    if ( lang == ELangVietnamese )
+	   {
+	   aCh = ReplaceVietnameseChar ( ch_temp );
+	   }
+    
+    if( ( aNextChars->Locate(aCh.GetLowerCase() ) == KErrNotFound ) &&
+        ( aNextChars->Locate(aCh.GetUpperCase() ) == KErrNotFound ) )
+        {               
+        if( aNextChars->Des().Length() == aNextChars->Des().MaxLength() )
+            {
+            aNextChars = aNextChars->ReAllocL( aNextChars->Des().MaxLength()+10 );
+            TInt length1 = aNextChars->Des().Length();
+            TInt maxlength1 = aNextChars->Des().MaxLength();
+            }       
+        aNextChars->Des().Append( aCh );            
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// For Devanagari AS
+// Checks if aCh denotes a consonant with nukta. 
+// @return ETrue if aCh is a consonant with nukta EFalse otherwise.
+// -----------------------------------------------------------------------------
+//
+inline TBool IsIndicCombinedChar( const TChar aCh )
+    {   
+    if ( aCh < 0x0900 || aCh > 0x0980 )
+        {
+        return EFalse;
+        }
+    else
+        {
+        return ( aCh == 0x0929 || aCh == 0x0931 || aCh == 0x0934 || 
+                (aCh >= 0x0958 && aCh <= 0x095F) );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// For Devanagari AS
+// Returns the correcponding character without nukta
+// @param aCh - character to be stripped of nukta
+// @return corresponding character with nukta
+// -----------------------------------------------------------------------------
+//
+inline TChar RemoveIndicNukta( const TChar aCh )
+    {
+    switch (aCh)
+        {
+        case 0x0929 : return 0x0928; //vocallic 'nna' to 'na'
+        case 0x0931 : return 0x0930; //vocallic 'rra' to 'ra'
+        case 0x0934 : return 0x0933; //vocallic 'lllla' to 'lla'
+        case 0x0958 : return 0x0915; //vocallic 'qa' to 'ka'
+        case 0x0959 : return 0x0916; //vocallic 'khha' to 'kha'
+        case 0x095A : return 0x0917; //vocallic 'ghha' to 'ga'
+        case 0x095B : return 0x091C; //letter 'za' to 'ja'
+        case 0x095C : return 0x0921; //vocallic 'dddha' to 'da'
+        case 0x095D : return 0x0922; //vocallic 'rha' to 'ddha'
+        case 0x095E : return 0x092B; //letter 'fa' to 'pha'
+        case 0x095F : return 0x092F; //letter 'yya' to 'ya'        
+        default : return aCh;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// For Devanagari AS
+// Checks if the given character is a Indic consonant.
+// @param aSearchChar - character to be checked.  
+// @return ETrue if this is an independent character EFalse otherwise       
+// -----------------------------------------------------------------------------
+//  
+inline TBool IsIndicConsonant( const TChar aSearchChar )
+    {    
+	if  (
+	    ( aSearchChar >= 0x0915 && aSearchChar <= 0x0939 ) ||
+	    ( aSearchChar >= 0x0958 && aSearchChar <= 0x0961 )
+	    )
+        {
+        return ETrue;
+        }
+    else 
+        {
+        return EFalse;
+        }
+    }
+    
+// -----------------------------------------------------------------------------
+// For Devanagari AS
+// Checks if the given character is a Indic matra.
+// @param aSearchChar - character to be checked.  
+// @return ETrue if this is an matra EFalse otherwise  
+// -----------------------------------------------------------------------------
+//  
+inline TBool IsIndicMatra( const TChar aSearchChar )
+    {   
+    if ( aSearchChar >= 0x093E && aSearchChar <= 0x094C )
+        {
+        return ETrue;
+        }
+    else 
+        {
+        return EFalse;
+        }
+    }
+    
+// -----------------------------------------------------------------------------
+// For Devanagari AS
+// Checks if the given character is a Devanagari independent character.
+// @param aSearchChar - character to be checked.  
+// @return ETrue if this is an independent character EFalse otherwise  
+// -----------------------------------------------------------------------------
+//
+inline TBool IsIndicIndependentChar( const TChar aSearchChar )
+    {    
+	if (( aSearchChar >= 0x0905 && aSearchChar <= 0x0939 ) ||
+	    ( aSearchChar >= 0x0958 && aSearchChar <= 0x0961 ))
+        {
+        return ETrue;
+        }
+    else 
+        {
+        return EFalse;
+        }
+    }    
+    
+// -----------------------------------------------------------------------------
+// For Devanagari AS
+// Checks if the passed string denotes one of the four special
+// Devanagari ligatures - refer UI specs for the description of special ligatures
+// @param aCharString - The string containing set of characters to be checked
+// @return ETrue if a special ligature is found EFalse otherwise   
+// -----------------------------------------------------------------------------
+//  
+inline TBool IsSpecialIndicLigature( const TDesC& aCharString )
+    {
+    TBool ret = EFalse;
+    if( aCharString.Length() >= 3 )
+        {      
+        if( (((aCharString[0] == 0x915) && (aCharString[1] == 0x94D)&& (aCharString[2] == 0x937)) ||
+             ((aCharString[0] == 0x91C) && (aCharString[1] == 0x94D)&& (aCharString[2] == 0x91E)) ||
+             ((aCharString[0] == 0x936) && (aCharString[1] == 0x94D)&& (aCharString[2] == 0x930)) ||
+             ((aCharString[0] == 0x924) && (aCharString[1] == 0x94D)&& (aCharString[2] == 0x930))) )
+            {
+            ret = ETrue;
+            }
+         }
+    return ret;
+    }    
+   
+// -----------------------------------------------------------------------------
+// For Devanagari AS
+// Counts the number of Indic syllables in the search string
+// For the purpose of supporting mixed language entries, we count each
+// non-Devanagari charcter as a single syllable. 
+// Also replaces the place holder '-' with '*' for searching 
+// @param aSearchText - The search string entered so far
+// @param aSearchTextLength - Number of characters in string excluding '*'
+// @return the number of Devanagari syllables in aCriteria   
+// -----------------------------------------------------------------------------
+//  
+inline TInt IndicSyllableCount( HBufC* aSearchText, TInt& aSearchTextLength )
+	{
+	TInt syllableCount = 0;
+	TPtr ptrSearchText = aSearchText->Des();
+	TInt strLength = ptrSearchText.Length();
+	for(TInt index=0 ; index < strLength ; index++)
+		{
+		if( (index) && ptrSearchText[index] == KLitHyphen && 
+		        IsIndicIndependentChar(ptrSearchText[index-1]) )
+			{
+			syllableCount++;
+			ptrSearchText[index] = KLitStar;
+			--aSearchTextLength;
+			}
+		else if ( !IsIndicIndependentChar(ptrSearchText[index]) && ptrSearchText[index]!=0x094D )
+			{
+			//For any other non Indic-independent-character that was entered 
+			//through adaptive grid, we consider it as a seperate syllable. 
+			++syllableCount;
+			}
+		}
+	return syllableCount;
+	}    
+	
+// -----------------------------------------------------------------------------
+// For Devanagari AS
+// Checks if aCriteria[aCurrentIndex] is a fallback rendered character.
+// @param aCriteria - string in which we need to check.
+// @param aCurrentIndex - position in string of character to be checked
+// @return ETrue if aCriteria is a rendered character EFalse otherwise.
+// -----------------------------------------------------------------------------
+//  
+inline TBool IsFallbackRenderedCharacter( const TDesC& aCriteria, TInt aCurrentIndex )
+    {    
+    if ( aCriteria[aCurrentIndex] >= 0x0900 && aCriteria[aCurrentIndex] <= 0x0980)
+        {
+        // Check for invalid Nuktas:
+        if ( aCriteria[aCurrentIndex] == 0x093C )
+            {
+            // A Nukta is valid only if placed after a consonant 
+            if ( !IsIndicConsonant(aCriteria[(aCurrentIndex-1)]) )
+                {
+                return ETrue;
+                }
+            }
+        // Check for invalid Matras: 
+        else if ( IsIndicMatra(aCriteria[aCurrentIndex]) )
+            {
+            // These can only be placed after a consonant or a valid nukta
+            TChar prevChar = aCriteria[(aCurrentIndex-1)];            
+            if ( !(IsIndicConsonant(prevChar) || prevChar == 0x093C) )
+                {
+                return ETrue;
+                }
+            }
+        // Check for invalid Modifiers:
+        else if ( aCriteria[aCurrentIndex] >= 0x0901 && aCriteria[aCurrentIndex] <= 0x0903)
+            {
+            //These are valid only if placed after an independent vowel or a 
+            //consonant or a valid nukta or a valid matra.
+            TChar prevChar = aCriteria[(aCurrentIndex-1)];
+            //if prev character is nukta or matra, it would have been already validated
+            if ( !(IsIndicIndependentChar(prevChar) || prevChar == 0x093C 
+                    || IsIndicMatra(prevChar) ) )
+                {
+                return ETrue;
+                }
+            }
+        // Check for invalid Halant/Virama:
+        else if ( aCriteria[aCurrentIndex] == 0x094D )
+            {
+            //This is valid only if placed immediately after a consonant or a valid nukta
+            TChar prevChar = aCriteria[(aCurrentIndex-1)];
+            //if prev character is nukta, it would have been already validated
+            if ( !(IsIndicConsonant(prevChar) || prevChar == 0x093C) )
+                {
+                return ETrue;
+                }
+            }
+        } //end of "if devanagari character range"    
+    return EFalse;
+    }
+    
+// -----------------------------------------------------------------------------
+// For Devanagari AS
+// Mark the end boundary of syllables in input string
+// @param aCriteria - The search/input string entered so far
+// @param aStart - The start boundary of syllable to be marked
+// @return the end boundary of the syllable  
+// -----------------------------------------------------------------------------
+//  
+inline TInt IndicSyllableEnd( TInt& aStart, const TDesC& aCriteria )
+	{
+	TInt maxLength = aCriteria.Length();
+	TInt endMarker(-1);
+	if(aStart >= (maxLength-1))
+		{		
+		aStart = endMarker = maxLength-1;
+		}
+	else 
+		{			
+		TInt nextCharIndex = aStart + 1 ;
+		TChar startingChar = aCriteria[aStart];
+		if ( IsIndicIndependentChar(startingChar) )
+			{
+			//Check if syllable contains a special ligature		
+			if(  aStart < (maxLength-2) && IsSpecialIndicLigature(aCriteria.Mid(aStart, 3)) ) 
+				{
+				//Move nextCharIndex till after the 3rd symbol of special ligature.
+				nextCharIndex+=2;
+				}					
+			//check for the next character that is a matra/halant/nukta/modifier
+			//Currently this check only for Devanagari characters. If other Indic language support
+			//is required, we will need to add to this list.
+			while( (nextCharIndex<maxLength) && 
+			      ( ( IsIndicMatra(aCriteria[nextCharIndex]) ) //matra
+		          ||( aCriteria[nextCharIndex] == 0x094D ) //Devanagari halant
+		          ||( aCriteria[nextCharIndex] == 0x093C ) //Devanagari nukta 
+			      ||( aCriteria[nextCharIndex] >= 0x0901 && aCriteria[nextCharIndex] <= 0x0903 ))) //Devanagari modifier			      
+			    {
+				//check if this is a fallback rendered character. Increment index only if it isn't:
+				if ( !IsFallbackRenderedCharacter(aCriteria, nextCharIndex) )
+				    {
+				    ++nextCharIndex;
+				    }
+				else
+				    {
+				    break;
+				    }
+				}
+			}		
+		//nextCharIndex should now be pointing to either the start of the next syllable
+		//or a non-Devanagari-letter. 
+		//End marker of current syllable should be placed just before the nextCharIndex
+		endMarker = nextCharIndex-1;		
+		}		
+	return endMarker;			
+	}
+
+// -----------------------------------------------------------------------------
+// For Devanagari AS
+// Parses through each Devanagari-syllable in the input string.
+// It will stop when we have gone through aInputSyllableCount number of syllables. 
+// @param aCriteria - The search string entered so far
+// @param aStart - The start boundary of the last parsed syllable 
+// @param aEnd - The end boundary of the last parsed syllable  
+// -----------------------------------------------------------------------------
+//  
+inline void IndicSyllableBoundary( TInt& aStart, TInt& aEnd, TInt aInputSyllableCount, 
+    const TDesC &aCriteria )
+	{
+	TInt boundaryCount = 0;
+	TInt tStart = aStart = 0;
+	while( boundaryCount != aInputSyllableCount )
+		{
+		aEnd = IndicSyllableEnd(tStart, aCriteria);	
+		boundaryCount++;
+		aStart = tStart;
+		tStart = aEnd+1;	
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// For Devanagari AS
+// Checks if aItemString contains atleast one Indic letter
+// @param aItemString - string to be checked
+// @return ETrue if aItemString contains Devanagari letter EFalse otherwise.
+// -----------------------------------------------------------------------------
+//  
+inline TBool IsIndicWord( const TDesC& aItemString )
+	{
+	TInt strLength = aItemString.Length();
+	for ( TInt index = 0; index < strLength; ++index )
+		{	
+		if ( (aItemString[index] >= 0x900) && (aItemString[index] <= 0x980) )
+			return ETrue;
+		}
+	return EFalse;
+	}
+
+// -----------------------------------------------------------------------------
+// For Devanagari AS
+// Checks if the last character from aNextChars can be displayed on 
+// the adaptive search grid or not. For now, this filters out the Devanagari 
+// vowels and other special symbol which are represented by the placeholder '-'.
+// @param aNextChars list of characters to be displayed on adaptive search grid
+// @return ETrue last character is valid for AS Grid, else EFalse.  
+// -----------------------------------------------------------------------------
+//  
+inline TBool IsValidNextChars( const TDesC &aNextChars )
+	{
+	TBool ret = ETrue;
+	if(aNextChars.Length()>0)
+		{
+		TChar ch = aNextChars[aNextChars.Length()-1];
+		if( (ch >= 0x0901 && ch <= 0x0903) || (ch >= 0x093C && ch <= 0x094D) )
+			{
+			ret = EFalse;
+			}	   
+        }
+	return ret;
+	}
+
+
+// -----------------------------------------------------------------------------
+// For Devanagari AS
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//  
+inline void UpdateNextCharsL( HBufC*& aNextChars, const TDesC& aItemString )
+	{
+	TChar searchChar = aItemString[0];
+    //Check if this is an Indic special ligature
+    if ( IsIndicConsonant(searchChar) && aItemString.Length() > 2
+            && IsSpecialIndicLigature(aItemString) 
+            && KErrNotFound == (*aNextChars).Find(aItemString.Mid(0,3)) )
+        {
+        //Check if we have enough space for 3 more characters
+        if( aNextChars->Des().Length() >= aNextChars->Des().MaxLength()-3 )
+            {
+            aNextChars = aNextChars->ReAllocL( aNextChars->Des().MaxLength()+10 );
+            }       
+        aNextChars->Des().Append( aItemString.Mid(0,3) );        
+        }
+    else
+        {
+        //check if this is an Indic combined Char
+        if ( IsIndicCombinedChar(searchChar) )
+            {
+            searchChar = RemoveIndicNukta( searchChar );
+            }
+        //Now update the nextChars string
+        TInt strLength = aNextChars->Length();
+        for ( TInt i(0); i < strLength ; ++i )
+            {
+            if ( IsSpecialIndicLigature( (*aNextChars).Mid( i ) ) )
+                {
+                //As aItemString is not a special ligature (checked above)
+                //we can move directly to the 3rd character from here
+                i+=2;
+                }
+            else if ( searchChar.GetUpperCase() == (*aNextChars)[i] ||
+                        searchChar.GetLowerCase() == (*aNextChars)[i] )
+                {
+                //already exists - do nothing
+                return;
+                }
+            //else continue the loop
+            }
+        //So this character is not yet in the list of nextChars.
+        if ( aNextChars->Des().Length() == aNextChars->Des().MaxLength() )
+            {
+            aNextChars = aNextChars->ReAllocL( aNextChars->Des().MaxLength()+10 );
+            }       
+        aNextChars->Des().Append( searchChar );   
+        }
+   	}
+
+/**
+ * Update next chars from the list box item text, when search field is empty.
+ * This need to be done for update next characters for adaptive grid
+ * works faster then calling IsAdaptiveFindMatch().   
+ *
+ * @since 5.0
+ * @param aNextChars reference to the next characters for the adaptive search grid
+ * @param aItemString List box item text.
+ */
+ 
+inline void UpdateNextCharsFromString( HBufC*& aNextChars, const TDesC& aItemString )
+	{   
+	 TInt itemStringLength = aItemString.Length();
+	 
+	 for( TInt i = 0; i < itemStringLength; i++ )
+        {
+        if ( i == 0 || IsFindWordSeparator( aItemString[i-1] ) )
+            {  
+            //If this is an Indic letter 
+            if ( aItemString[i] >= 0x0900 && aItemString[i] <= 0x0980 )
+                {
+                TRAP_IGNORE( UpdateNextCharsL( aNextChars, aItemString.Mid(i) ) );
+                }
+            else  if (!(IsVietnameseSpecialCharacter( aItemString[i])))
+                {
+                TRAP_IGNORE( UpdateNextCharsL( aNextChars, aItemString[i] ) );
+                }
+            }
+		}
+	}
+	
+inline TBool IsAdaptiveFindMatchClassic( const TDesC& aItemString, const TDesC& aSearchText )
+    {
+    TPtrC itemptr = aItemString;
+    TPtrC searchptr = aSearchText;
+
+    TBool match = EFalse;
+    
+    for(;;) 
+        {
+        // Loop invariant: itemptr is next character from ' ' or '-'
+        // Loop invariant: seachptr is at beginning of searched item
+    
+        TInt val = MyFindC(itemptr,searchptr);
+        if (val == 0)
+            {
+            match = ETrue;
+            break;
+            }
+        if (val != KErrNotFound && IsFindWordSeparator(itemptr[val-1]))
+            {
+            match = ETrue;
+            break;
+            }
+
+        // find the word separator characters from list item
+        TInt spacepos = itemptr.LocateF(TChar(' '));
+        TInt minuspos = itemptr.LocateF(TChar('-'));
+        TInt tabpos = itemptr.LocateF(TChar('\t'));
+        if (spacepos != KErrNotFound)
+            {
+            itemptr.Set(itemptr.Mid(spacepos+1));
+            }
+        else if (minuspos != KErrNotFound)
+            {
+            itemptr.Set(itemptr.Mid(minuspos+1));
+            }
+        else if (tabpos != KErrNotFound)
+            {
+            itemptr.Set(itemptr.Mid(tabpos+1));
+            }
+        else
+            {
+            match = EFalse;
+            break;
+            }
+        if (itemptr.Length() == 0)
+            {
+            match = EFalse;
+            break;
+            }
+
+        }
+    return match;
+    }	
+
+/**
+ * Checks the current character for special character from Thai language . 
+ *
+ * @since 5.0
+ * @return @c ETrue If tone mark or diatric from Thai language otherwise EFalse. 
+ */	
+inline TBool IsThaiSpecialCharacter( TChar aCh )
+    {    
+    if( ( aCh > 0xE46 && aCh < 0xE4F ) ||  aCh == 0xE3A )
+		{
+		return ETrue;
+		}       
+	return EFalse;
+    }
+
+/**
+ * Checks if @c aItemText matches @c aSearchText in the sense described in
+ * S60.  Calls UpdateNextCharsL() if findutil is not supported.
+ *
+ * @since 5.0
+ * @param aItemText list box item text.
+ * @param aSearchText search text.
+ * @param aNextChars reference to the next characters for the adaptive search grid
+ * @param aDigraphs digraphs and trigraph text.
+ * 
+ * @return @c ETrue if list box item text matches aSearchText EFalse otherwise.
+ */
+inline TBool IsAdaptiveFindMatch( const TDesC& aItemString, 
+	const TDesC& aSearchText, HBufC*& aNextChars, TInt /*aInputLang*/, const TDesC& aDigraphs )
+	{	    	
+	HBufC16* searchText = NULL;
+	TRAPD( error, searchText = HBufC16::NewL( KMatchingBufferLength ) );
+	TBool wildchar = EFalse;
+	if ( error == KErrNone )
+	    {
+	    TInt itemStringLength = aItemString.Length();
+        TInt searchTextLength = aSearchText.Length();    
+        
+        if ( searchTextLength < KMatchingBufferLength )
+        	{
+        	searchText->Des().Append( aSearchText );
+        	}
+        else
+        	{
+        	searchText->Des().Append( aSearchText.Left(KMatchingBufferLength-1) );
+        	}  
+        	 
+         // To disable the wildchar matching provided by MatchC
+        if ( aSearchText.Locate( KLitQuestion ) != KErrNotFound || 
+             aSearchText.Locate( KLitStar ) != KErrNotFound )
+            {            
+            wildchar = IsAdaptiveFindMatchClassic( aItemString, aSearchText );
+            if ( wildchar == EFalse )
+                {
+                delete searchText;
+                return wildchar;
+                }
+            else 
+                {  
+                TInt val;      
+                searchText->Des().Append( KLitStar );
+                for( TInt i = 0; i < itemStringLength; i++ )
+                    {
+                    if ( i == 0 || IsFindWordSeparator( aItemString[i-1] ) )
+                        {
+                        val = MyFindC(  aItemString, aSearchText );                    
+                        if( (val == i) && (i < (itemStringLength-searchTextLength))) 
+                            {
+                            if( !(IsThaiSpecialCharacter(aItemString[i+searchTextLength])) && !(IsVietnameseSpecialCharacter( aItemString[i+searchTextLength]) ))
+                                {
+                                TRAP_IGNORE( UpdateNextCharsL( aNextChars, aItemString[i+searchTextLength]) );   
+                                }                                
+                            }
+                        }         
+              	    } // for
+              	delete searchText;
+                return wildchar;	 
+                }
+            }
+      	     	
+        searchText->Des().Append( KLitStar );
+        searchText->Des().UpperCase();
+
+        TBool isCommonChars = EFalse;
+        TInt all_result = KErrNotFound;
+        
+        TLanguage lang = User::Language();
+        
+        for( TInt i = 0; i < itemStringLength; i++ )
+            {
+            if ( i == 0 || IsFindWordSeparator( aItemString[i-1] ) )
+                {
+                TInt result = KErrNotFound;
+                //Some vowels of Thai can not be searched with MatchC(). 
+                if( aDigraphs.Length() != 0 || lang == ELangThai )
+                    {
+                    result = aItemString.Mid(i).Match( searchText->Des() );
+                    }
+                else
+                    {
+                    result = aItemString.Mid(i).MatchC( searchText->Des() );
+                    }
+                
+                if( result != KErrNotFound ) 
+                    {
+                    all_result = result;
+                    if( i < (itemStringLength-searchTextLength) )                	   	       	   		
+                        {
+                        if( !(IsThaiSpecialCharacter( aItemString[i+searchTextLength])) && !(IsVietnameseSpecialCharacter( aItemString[i+searchTextLength]) ))
+                            {
+                            TRAP_IGNORE( UpdateNextCharsL( aNextChars, aItemString[i+searchTextLength]) );
+
+                            if ( aDigraphs.Length() != 0 )
+                                {
+                                TBuf<2> digraph;
+                                digraph.Append( aItemString[i+searchTextLength-1] );
+                                digraph.Append( aItemString[i+searchTextLength] );
+
+                                if( searchTextLength == 1 )
+                                    {
+                                    if( aDigraphs.Find( digraph ) == KErrNotFound )
+                                        {
+                                        isCommonChars = ETrue;
+                                        }
+                                    }
+                                else
+                                    {
+                                    TBuf<3> trigraph;
+                                    trigraph.Append( aItemString.Mid(i+searchTextLength-2,3) );
+                                    if( digraph[0] == KLitSpace 
+                                        || ( aDigraphs.Find( digraph ) == KErrNotFound
+                                        && aDigraphs.Find( trigraph ) == KErrNotFound ) )
+                                        {
+                                        isCommonChars = ETrue;
+                                        }
+                                    }
+                                }
+                            }            	   
+                        }
+                    else
+                        {
+                        isCommonChars = ETrue;
+                        }
+                    }                                                                  	   	
+                } // if (i==0 ..)  
+      	    } // for	 
+        
+        if(aDigraphs.Length() != 0 && !isCommonChars )   
+            {
+            all_result = KErrNotFound;
+            }
+	    
+  	    if( all_result != KErrNotFound )
+            {
+            delete searchText;
+            return ETrue;
+           	}    
+        else 
+            {
+            delete searchText;
+            return EFalse;
+            }
+        	            		
+         } // if (error == KErrNone)   
+    delete searchText;                 
+    return EFalse;
+	}
+
+// -----------------------------------------------------------------------------
+// For Devanagari AS
+// Checks if @c aItemText matches @c aSearchText.
+// @param aItemText list box item text.
+// @param aSearchText search text.
+// @param aNextChars reference to the next characters for the adaptive search grid
+// @return @c ETrue if list box item text matches EFalse otherwise.
+// -----------------------------------------------------------------------------
+//  
+inline TBool IsIndicAdaptiveFindMatch( const TDesC& aItemString, 
+	const TDesC& aSearchText, HBufC*& aNextChars, TInt /*aInputLang*/ )
+	{	    	
+	HBufC16* searchText(NULL);
+	TRAPD( error, searchText = HBufC16::NewL( KMatchingBufferLength ) );
+	if ( error == KErrNone )
+	    {
+	    TInt itemStringLength = aItemString.Length();
+        TInt searchTextLength = aSearchText.Length();    
+        
+        if ( searchTextLength < KMatchingBufferLength )
+        	{
+        	searchText->Des().Append( aSearchText );
+        	}
+        else
+        	{
+        	searchText->Des().Append( aSearchText.Left(KMatchingBufferLength-1) );
+        	}    
+    	
+    	TInt indicSyllableCount = -1;
+        if( aSearchText.Length()>0 )
+    		{
+    		//This will replace all placeholder '-' symbols with '*'
+     		indicSyllableCount = IndicSyllableCount( searchText, searchTextLength );
+    		}
+    	    	
+    	//Append '*' to the end if not already present.
+        if ( (*searchText)[searchText->Length() - 1] != KLitStar)
+    		{
+    		searchText->Des().Append( KLitStar );
+    		}   
+    	
+    	TInt result = KErrNotFound;
+        
+        //check if the search string is found in the item string
+        for( TInt index = 0; index < itemStringLength; index++ )
+            {
+            if ( index==0 || IsFindWordSeparator( aItemString[index-1] ) )
+                {
+                TUint flag = ( TCollationMethod::EFoldCase | TCollationMethod::EIgnoreNone | TCollationMethod::EIgnoreCombining);//TCollationMethod::EIgnoreNone |
+        		TCollationMethod collationMethod = *Mem::GetDefaultMatchingTable();
+        		collationMethod.iFlags |= flag;
+            
+           		result = aItemString.Mid(index).MatchC( (*searchText), &collationMethod );
+                
+                if( result != KErrNotFound ) 
+                    {
+                    if( index <= (itemStringLength-searchTextLength) )
+        	   			{
+        	   			//search for the last character in the string
+        	   			//We use a TBuf instead of TChar since a special ligature is 
+        	   			//represented by 3 characters. Last char would be the '*' wildchar.
+	        	   		TBuf<4> lastChar;
+	        	   		TInt modifiedStrLength = searchText->Length();
+	        	   		if( (*searchText)[modifiedStrLength-1] == KLitStar )
+	        	   			{
+	        	   			//is this a special ligature?
+	        	   			if ( modifiedStrLength > 3 &&
+	        	   			        IsSpecialIndicLigature( (*searchText).Mid(modifiedStrLength-4) ) )
+	        	   			    {
+	        	   			    lastChar = (*searchText).Mid(modifiedStrLength-4);
+	        	   			    }
+	        	   			else
+	        	   			    {
+	        	   			    lastChar = (*searchText).Mid(modifiedStrLength-2);
+	        	   			    }
+	        	   			}
+	        	   		else
+	        	   			{
+	        	   			//No wildchar here
+	        	   			lastChar = (*searchText).Mid(modifiedStrLength-1);
+	        	   			}
+	        	   		
+	        	   		lastChar.UpperCase(); //For latin characters as adaptive grid is always in upper case
+        	   			TInt charPos = result; //aItemString.Mid(index).MatchC( searchText->Des(), &collationMethod );
+        	   			//if found position is not within the substring to be searched, return EFalse.
+                        if( charPos == KErrNotFound)
+                            {
+                            delete searchText;
+                            return EFalse;
+                            }
+                        
+        	   			TInt tempPos = charPos;
+	        	   		
+	        	   		TInt startCount = -1 , endCount = -1;
+	        	   		
+    	   				//TInt tempIndex(0);
+    	   				//Get the position of the next syllable to be checked
+    	   				IndicSyllableBoundary(startCount, endCount, indicSyllableCount, aItemString.Mid(index));
+    	   				tempPos = aItemString.Mid(index+startCount).MatchC( lastChar, &collationMethod ); 
+    	   				
+    	   				if (
+    	   				//if found position is not within the next syllable to be searched, 
+    	   				//return EFalse.
+    	   				    ( tempPos != 0 )  
+    	   				//Also check if character to be searched is a single unicode while
+    	   				//the match is at the start of a special ligature
+    	   				   	|| ( !IsSpecialIndicLigature( lastChar ) && 
+    	   				            IsSpecialIndicLigature( aItemString.Mid(index+startCount) ) )
+    	   				    )
+    	   				    {
+    	   				    delete searchText;
+    	   				    return EFalse;
+    	   				    }
+	        	   		
+	        	   		//else, continue - find the next characters to be displayed on the grid	
+	        	   		tempPos = index + endCount + 1;
+	        	   		
+	        	   		do	{
+	        	   		    if(charPos!=KErrNotFound && (tempPos) < itemStringLength )
+        	   					{
+        	   						TRAP_IGNORE( UpdateNextCharsL( aNextChars, aItemString.Mid(tempPos) ) );
+        	   					}
+        	   				
+        	   				//Is the found next character a consonent/independent-vowel/non-Indic character?
+        	   				if ( IsValidNextChars( *aNextChars ) )
+        	   					{
+        	   					//found a valid character for displaying on the grid - return from here
+        	   					delete searchText;
+            					return ETrue;
+        	   					}
+        	   				else //we found an invalid valid character - keep searching
+        	   					{
+        	   					TPtr ptr = aNextChars->Des();
+        	   					ptr.Delete(aNextChars->Length()-1,1);
+        	   					//Is this a fallback rendered character?
+        	   					if ( IsFallbackRenderedCharacter(aItemString, tempPos) )
+        	   					    {
+        	   					    //Keep the entry but don't show any more characters from this word
+        	   					    delete searchText;
+        	   					    return ETrue;
+        	   					    }
+        	   					}
+        	   				}
+        	   			//keep looping till we find a valid nextChar or we reach the end of the string
+        	   			while(tempPos < itemStringLength ); 
+        	   			
+        	   			}
+        	   			
+        	   		} // if( result != KErrNotFound )                                                                  	   	
+                } // if (index==0 ..)        
+      	    } // for loop	 
+	    
+  	    if( result != KErrNotFound )
+            {
+            delete searchText;
+            return ETrue;
+           	}    
+        else 
+            {
+            delete searchText;
+            return EFalse;
+            }
+        	            		
+         } // if (error == KErrNone)   
+    delete searchText;                 
+    return EFalse;
+	}
+	
+// -----------------------------------------------------------------------------
+// CFindUtilWestern::MatchAdaptiveRefineL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//  
+TBool CFindUtilWestern::MatchAdaptiveRefineL( const TDesC& aItemString, 
+	const TDesC& aSearchText, HBufC*& aNextChars )
+	{
+    if ( aItemString.Length() == 0 )
+        {
+        return EFalse;
+        }
+    if ( aSearchText.Length() == 0 )
+        {        
+        UpdateNextCharsFromString( aNextChars, aItemString );
+        return ETrue;
+        }
+        
+    if( iDigraphChars == NULL )
+        {
+        iDigraphChars = StringLoader::LoadL( R_QTN_ADS_DIGRAPH );
+        TPtr digraph = iDigraphChars->Des();
+        digraph.UpperCase();
+
+        _LIT( KMissing,"#MISSING" );
+        if( digraph.CompareC(KMissing()) == 0 )
+            {
+            digraph = KNullDesC;
+            }
+        }
+        
+    TBuf<KAknStringBufferSize> itemString(aItemString);
+    itemString.UpperCase();
+
+    //AS does not show tone marks and diacritics when language is Thai.
+    TLanguage lang = User::Language();  
+    if ( lang == ELangThai )
+        {
+        for(TInt i=0; i < itemString.Length(); i++)
+            {
+            if(IsThaiSpecialCharacter( itemString[i] ))
+                {
+                itemString.Delete(i,1);
+                }
+            }
+        }
+
+    if ( IsIndicWord(aItemString) )
+    	{
+    	// itemString contains Devanagari letters
+    	return IsIndicAdaptiveFindMatch( itemString, aSearchText, aNextChars, iInputLanguage );		
+    	}
+    else 
+    	{
+    	return IsAdaptiveFindMatch( itemString, aSearchText, aNextChars, iInputLanguage, iDigraphChars->Des() );				
+    	}    
+	}
+	
+// ---------------------------------------------------------
+// Match arithmetic for accurate search, special conversion 
+// for aItemString is implemented with MFindStringConverter
+// before the final match
+// ---------------------------------------------------------
+//
+TBool CFindUtilWestern::MatchRefineL( const TDesC& /*aItemString*/, const TDesC& /*aSearchText*/, 
+                                      TMatchPolicy /*aPolicy*/, MFindStringConverter* /*aConverter*/)
+    {
+    return EFalse;
+    }	
+
+// ========================== OTHER EXPORTED FUNCTIONS =========================
+
+// -----------------------------------------------------------------------------
+// FindUtilFactoryFunctionL
+// Factory function at first ordinal
+// Returns: MFindUtil: It returns MFindUtil I/F.
+// -----------------------------------------------------------------------------
+//
+// Factory function at first ordinal
+EXPORT_C MFindUtil* FindUtilFactoryFunctionL()
+    {
+    return new( ELeave ) CFindUtilWestern();
+    }
+
+// end of file