uiutils/Findutil/src/FindUtilThai.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 01:00:49 +0200
changeset 0 2f259fa3e83a
permissions -rw-r--r--
Revision: 201003 Kit: 201005

/*
* Copyright (c) 2002-2004 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:         Thai Find Utilities implementation file.
*
*/









#include "FindUtilThai.h"
const TInt KLitTab('\t');
const TInt KLitSpace(' ');
const TInt KLitHyphen('-');
const TInt KLitLineFeed(8233);
const TInt KLitStar('*');
const TInt KMatchingBufferLength(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 IsFindMatch(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;
    }

}

// ============================ MEMBER FUNCTIONS ===============================

// -----------------------------------------------------------------------------
// CFindUtilThai::CFindUtilThai
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
CFindUtilThai::CFindUtilThai()
    {
    }

// Destructor
CFindUtilThai::~CFindUtilThai()
    {
    }

// -----------------------------------------------------------------------------
// CFindUtilThai::Match
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//

TBool CFindUtilThai::Match(const TDesC& aContactsField, const TDesC& aWord)
    {
    if (!aContactsField.Length())
        {
        return EFalse;
        }
    
    if (aContactsField.MatchC(aWord) != KErrNotFound)
        {
        return ETrue;
        }
    else if (aContactsField.MatchF(aWord) != KErrNotFound)
        {
        return ETrue;
        }
    return EFalse;
    }

// -----------------------------------------------------------------------------
// CFindUtilThai::MatchRefineL
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
TBool CFindUtilThai::MatchRefineL( const TDesC& aItemString, const TDesC& aSearchText)
    {
    if ( aItemString.Length() == 0 )
        {
        return EFalse;
        }

    if ( aSearchText.Length() == 0 )
        {
        return ETrue;
        }

    return IsFindMatch(aItemString, aSearchText);
    }

// -----------------------------------------------------------------------------
// CFindUtilThai::IsWordValidForMatching
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
TBool CFindUtilThai::IsWordValidForMatching(const TDesC& /*aWord*/)
    {
    return ETrue;
    }


// ========================= FOR ADAPTIVE FIND ================================

/**
 * 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 )
	{
	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 );			
		}
	}

/**
 * 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] ) )
            {            
            TRAP_IGNORE( UpdateNextCharsL( aNextChars, aItemString[i] ) );   	   		
            }
		}
	}

/**
 * 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
 * 
 * @return @c ETrue if list box item text @c aItemText matches @c 
 *         aSearchText otherwise @c EFalse.
 */
inline TBool IsAdaptiveFindMatch( const TDesC& aItemString, 
	const TDesC& aSearchText, HBufC*& aNextChars )
	{	    	
	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) );
        	}    
    	
        searchText->Des().Append( KLitStar );
       
        TInt all_result = KErrNotFound;
        for( TInt i = 0; i < itemStringLength; i++ )
            {
            if ( i==0 || IsFindWordSeparator( aItemString[i-1] ) )
                {
                TInt result = aItemString.Mid(i).MatchF( searchText->Des() );
                
                if( result != KErrNotFound ) 
                    {
                    all_result = result;
                    if( i < (itemStringLength-searchTextLength) )                	   	       	   		
                        {
                        if( !(IsThaiSpecialCharacter( aItemString[i+searchTextLength])) )
                            {
                            TRAP_IGNORE( UpdateNextCharsL( aNextChars, aItemString[i+searchTextLength]) );
                            }            	   
                        }
                    }                                                                  	   	
                } // if (i==0 ..)        
      	    } // for	 
	    
  	    if( all_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 CFindUtilThai::MatchAdaptiveRefineL( const TDesC& aItemString, 
	const TDesC& aSearchText, HBufC*& aNextChars )
	{
    if ( aItemString.Length() == 0 )
        {
        return EFalse;
        }
    if ( aSearchText.Length() == 0 )
        {        
        UpdateNextCharsFromString( aNextChars, aItemString );
        return ETrue;
        }        
    return IsAdaptiveFindMatch( aItemString, aSearchText, aNextChars );		
	}
	
// ---------------------------------------------------------
// Match arithmetic for accurate search, special conversion 
// for aItemString is implemented with MFindStringConverter
// before the final match
// ---------------------------------------------------------
//
TBool CFindUtilThai::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 ) CFindUtilThai();
    }

// end of file