/*
* 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:            Provides the TAknFepInputStateInitialIndicPhoneticMultitap methods.
*
*/











#include "aknfepuiinputstateinitialindicphoneticmultitap.h"
#include "AknFepUIManagerStateInterface.h"      //MAknFepUIManagerStateInterface
#include "AknFepUIManagerWestern.h"
#include "AknFepUiIndicEnums.h"
#include "AknFepCaseManager.h"
#include "AknFepUiIndicInputManager.h"

#include <uikon.hrh>
#include <PtiEngine.h>
#include <PtiDefs.h>
#include <aknsctdialog.h>
#include <avkon.rsg>
#include <aknfep.rsg>
#include <EikEnv.h>
#include <Aknutils.h>
#define PHONETIC_SEPARATOR 0x2e

const TUint KSpaceChar = 0x0020;
const TUint KQuestionMark = 0x003F;

#define PTI_CLEAR_CURRENTWORD( A, B ) \
		( A )->ClearCurrentWord(); \
		( B ) = ETrue; \

const TText KAknFEPLineFeedSymbol = 0x21B2;
const TText KAknFEPMirroredLineFeedSymbol = 0x21B3;
	
// -----------------------------------------------------------------------------
// TAknFepInputStateInitialIndicPhoneticMultitap::TAknFepInputStateInitialIndicPhoneticMultitap

// C++ default constructor can NOT contain any code, that
// might leave or if it is absolutely necessary then MUST be trapped.
// -----------------------------------------------------------------------------

TAknFepInputStateInitialIndicPhoneticMultitap::
TAknFepInputStateInitialIndicPhoneticMultitap( MAknFepUIManagerStateInterface* aOwner,
																			TInt aLanguage )
																			:TAknFepInputStateInitialMultitapBase( aOwner )
    {
    CPtiEngine* ptiengine = iOwner->PtiEngine();
    iIsStarKeyPressed = EFalse;
    iIndicLanguage = TLanguage(aLanguage);
    iIndicPhoneticBuffer.Zero();
    TRAP_IGNORE( ptiengine->ActivateLanguageL(KLangHindiPhonetic,
                 EPtiEngineInputModeIndicPhoneticMultitap))
    ptiengine->SetCase( EPtiCaseLower );
    iPreviousCommittedChar = NULL;
    }

// -----------------------------------------------------------------------------
// TAknFepInputStateInitialIndicPhoneticMultitap::HandleKeyL

// Handles the logic of Indic multitap input. This function first checks the validity
// of the inputed text and then enters it.
// -----------------------------------------------------------------------------

TBool TAknFepInputStateInitialIndicPhoneticMultitap::HandleKeyL( TInt aKey, 
                                                                 TKeyPressLength aLength )
	{
	TBool                      result       	= ETrue;
	MAknFepManagerUIInterface* fepMan       	= iOwner->FepMan();
	CPtiEngine* 			   ptiengine 		= iOwner->PtiEngine();
	
	if(aKey == EKeyBackspace)
		{
		iIndicPhoneticBuffer.Zero();
		iPhoneticLatinChar = 0;	
    	iPreviousCommittedChar = 0;						
		}
	else if(fepMan->IsFlagSet(CAknFepManager::EFlagNoMatches) 
           && aKey != EPtiKey0 && aLength != ELongKeyPress)
		{
		//no matches, so just play tone
        fepMan->PlaySound(EAvkonSIDConfirmationTone);
		}
	else
		{
		if ( iData && ( iData != aKey ) && (!iIsStarKeyPressed ))
	    	{
	    	//iPrevCharacter = 
	    	TransliterateFromLatinL();
		    PTI_CLEAR_CURRENTWORD( ptiengine, iIsKeyTimerExpired )
		    // = ;
	   		}
		iIsStarKeyPressed = EFalse;
		if ( aLength == EShortKeyPress )
			{
		    if ( aKey == EPtiKeyStar ) // Overriding Key
	            {
		    	ptiengine->HandleCommandL(EPtiCommandBreakSyllable, NULL );	
		    	iIsStarKeyPressed = ETrue;
	    		}
			else
				{
				TPtrC ptiText = ptiengine->AppendKeyPress( ( TPtiKey )aKey );
				iPhoneticLatinChar = ptiText[0];
				
				if (IsToTransliterate(iPhoneticLatinChar) 
				&& (!fepMan->IsFlagSet(CAknFepManager::EFlagNoMatches)))
			    	{
			    	TBuf<CAknFepManager::EMaximumFepWordLength> buf;
		            buf.Copy(iIndicPhoneticBuffer);
		            buf.Append(ptiText);
					fepMan->NewCharacterSequenceL(buf,EIndicInputResponsePhoneticMultitapText);
			    	}
				else if(!IsToTransliterate(iPhoneticLatinChar))
					{
					TChar prevcharacter(fepMan->PreviousChar());
					
					if((fepMan->IsFlagSet(CAknFepManager::EFlagNoMatches)) && (KQuestionMark == prevcharacter))
						{
						fepMan->RemovePreviousCharacterL();		
						fepMan->ClearFlag(CAknFepManager::EFlagNoMatches);	
						ptiengine->HandleCommandL(EPtiCommandBreakSyllable, NULL );
						}
					iIndicPhoneticBuffer.Zero();
					if(IsToTransliterate(prevcharacter) && prevcharacter != '0')
						fepMan->CommitInlineEditL();	
					fepMan->NewCharacterSequenceL(ptiText,EIndicInputResponseNone);
					}
				}
			}
	   	else
	    	{
	    	if(fepMan->PreviousChar() == KQuestionMark)
				{
				fepMan->RemovePreviousCharacterL();		
				}
			fepMan->ClearFlag(CAknFepManager::EFlagNoMatches);

	        /* Long press of a Key */
	        if ( aKey == EPtiKeyStar)
		        {
	        	
	            /* Launch the SCT For Indic */
	   			if( fepMan->EditorHasFreeSpace() )
					{
					if (fepMan->IsAbleToLaunchSCT() && !fepMan->EditSubmenuInUse())
	        			{        			
		            	fepMan->LaunchSpecialCharacterTableL();	
		            	}
					}
			    }
	        else
		        {
		        //commit the inline text
		        fepMan->CommitInlineEditL();
		        //Remove one character, to remove the Latin character
		        //appended because of the short key press. This is 
		        //because long key press results  in short key press 
		        //and then long key press.
		        fepMan->RemovePreviousCharacterL();
		        //Reset the phonetic state in FEP. So, that any further 
		        //phonetic conversion will start from fresh.
		        iIndicPhoneticBuffer.SetLength(0);
		        iPhoneticLatinChar = 0;	
    	        iPreviousCommittedChar = 0;
    	        
		        ptiengine->HandleCommandL(EPtiCommandBreakSyllable, NULL );
		        TUint prevchar = fepMan->PreviousChar(ETrue);
	            if(!((aKey == EPtiKey1) && ((0x0031 == prevchar) || (0x0967 == prevchar)) ))
			        {
					TChar ch( aKey );
			        TBuf<1> buf;
			        buf.Append( ch );
			        fepMan->NewCharacterSequenceL( buf, EIndicInputResponseNumber );
					fepMan->CommitInlineEditL();			
					PTI_CLEAR_CURRENTWORD( ptiengine, iIsKeyTimerExpired )				
					}
		        }
	    	}
	    iData = aKey;
		}
   //hindi phonetic changes
   if(iPhoneticLatinChar.IsUpper())
	{
		fepMan->HandleIndicCaseL();
	}
    return( result );
	}

// -----------------------------------------------------------------------------
// TAknFepInputStateInitialIndicPhoneticMultitap::KeyTimerExpired

// Handles the logic of post keytimerexpired event. This function commits 
// the inline editing text to the editor.
// -----------------------------------------------------------------------------

void TAknFepInputStateInitialIndicPhoneticMultitap::KeyTimerExpired()
	{
	TRAP_IGNORE(HandleKeyTimerExpiryL())
	iData = 0;	
	iOwner->PtiEngine()->ClearCurrentWord();
	if((iPreviousCommittedChar = iOwner->FepMan()->PreviousChar()) == 0x002E)
		iPreviousCommittedChar = iOwner->FepMan()->PreviousToPreviousChar(ETrue);
	iIsKeyTimerExpired = ETrue;
	}
	
void TAknFepInputStateInitialIndicPhoneticMultitap::HandleKeyTimerExpiryL()
	{
	CPtiEngine* ptiengine = iOwner->PtiEngine();
	MAknFepManagerUIInterface* fepMan = iOwner->FepMan();	
	if ( !(fepMan->EditorHasFreeSpace() 
       || fepMan->IsFlagSet(CAknFepManager::EFlagInsideMultitapInlineEditingTransaction)))
	    {
	    return;
	    }
	if(iData && ( IsToTransliterate(iPhoneticLatinChar) &&  iData != EPtiKeyStar) 
     && !fepMan->IsFlagSet(CAknFepManager::EFlagNoMatches))
		{
		TransliterateFromLatinL();
		}
	else if ( !IsToTransliterate (iPhoneticLatinChar))
        {
		MPtiLanguage* ptilang = ptiengine->CurrentLanguage();
	    TInt languageCode = (ptilang)? ptilang->LanguageCode() : 0;
		// Space clears Explicite halant for North Indian Languages.
		if(IsToRemoveHalantForLanguage(languageCode))
			{
			RemoveHalantL(TLanguage(languageCode));
			}	
		ptiengine->HandleCommandL(EPtiCommandBreakSyllable, NULL );
		fepMan->CommitInlineEditL();
		iIndicPhoneticBuffer.Zero();
        }	
	else
		{
		iOwner->FepMan()->CommitInlineEditL();
    	iIndicPhoneticBuffer.Zero();
		}	
	}

void TAknFepInputStateInitialIndicPhoneticMultitap :: TransliterateFromLatinL() 
	{
	TPhoneticArg arg;
    TBuf<CAknFepManager::EMaximumFepWordLength> destinationbuf;
    destinationbuf.Zero();               
	TInt errorcode = 0; 
	CPtiEngine* ptiengine = iOwner->PtiEngine();
	MAknFepManagerUIInterface* fepMan = iOwner->FepMan();
	MPtiLanguage* ptilang = iOwner->PtiEngine()->CurrentLanguage();
    TInt languageCode = (ptilang)? ptilang->LanguageCode() : 0;
	    
	arg.iChar = iPhoneticLatinChar;
	arg.iDest = & destinationbuf;
	errorcode = ptiengine->HandleCommandL(EPtiCommandGetPhoneticText,REINTERPRET_CAST( TAny*, &arg));
	AknTextUtils::LanguageSpecificNumberConversion(destinationbuf);
	switch(errorcode)
    	{
    	case KErrNone:
    		{
    		if(arg.iState == EIndicSyllableStateSyllableBroken)
    			{
				if(iIndicPhoneticBuffer.Length())
					{
					fepMan->CommitInlineEditL(iIndicPhoneticBuffer, iIndicPhoneticBuffer.Length());
					iPreviousCommittedChar = fepMan->PreviousChar(ETrue);
					iIndicPhoneticBuffer.Zero();
					}
      			}

			if (destinationbuf.Length())
	            {
	            	if(! ValidatePhoneticInputL(destinationbuf, TLanguage(languageCode)))
	            		{
	            		break;	
	            		}
	            	
	            fepMan->NewCharacterSequenceL(destinationbuf,
	                                          EIndicInputResponsePhoneticMultitapText);

        		if(TAknFepUiIndicInputManager::IsCharOther(destinationbuf[0],
        		     TLanguage(languageCode)) && 0x002E != destinationbuf[0])
        			{
        			fepMan->CommitInlineEditL();
        			iIndicPhoneticBuffer.Zero();
        			}
				else
					{
        			iIndicPhoneticBuffer.Copy(destinationbuf);
					}
	            }
    		}
    	break;
    	case KErrOverflow:
    		{
			fepMan->NewCharacterSequenceL(destinationbuf,EIndicInputResponsePhoneticMultitapText);    		
    		fepMan->CommitInlineEditL();
        	ptiengine->HandleCommandL(EPtiCommandClearPhoneticBuffer,NULL);
    		}
    	break;
    	default:
    	break;
    	}
    iPhoneticLatinChar = 0;	
	}

TBool TAknFepInputStateInitialIndicPhoneticMultitap::IsToRemoveHalantForLanguage(TInt aLanguage)
	{
	TBool ret = EFalse;
	switch(aLanguage)
		{
		case KLangHindiPhonetic:
			ret = ETrue;
		break;
		}
	return ret;	
	}
	
inline TBool TAknFepInputStateInitialIndicPhoneticMultitap::IsToTransliterate(TChar& aChar)
	{
	return !(KAknFEPLineFeedSymbol == aChar || KSpaceChar == aChar);
	}
	
TBool TAknFepInputStateInitialIndicPhoneticMultitap::ValidatePhoneticInputL(const TDes& aBuf, 
                                                                            TLanguage aLanguage)
	{
	TBool ret = ETrue;
    TUint curChar = 0;
    TUint prevChar=0;
    TUint len=aBuf.Length();
    TPtr buffer(const_cast<TText*>( aBuf.Ptr() ),len,len);
	MAknFepManagerUIInterface* fepMan = iOwner->FepMan();
	TPtiTextCase newCase = iOwner->PtiEngine()->Case();
	if(! iPreviousCommittedChar)
		{
		iPreviousCommittedChar = fepMan->PreviousChar(ETrue);	
		}
       while(len)
                {
                if(buffer[len-1] == 0x94d)
                    {
                    len--;
                    buffer.SetLength(len);
                    continue;
                    }
                else if(!curChar)
                    {
                    curChar = buffer[len-1] ;
                    len--;
                    }
                else if(!prevChar)
                    {
                    prevChar = buffer[len-1] ;
                    len--;
                    }
                else
                    break;
                }
       if(!prevChar)
            prevChar = iPreviousCommittedChar;
       /*
       Multitap does not allow any fall back characters. The phonetic engine does not
       check for the fallback characters and FEP has to do it.
       */
       //fallback character if Nukta is entered after Nukta
       if((TAknFepUiIndicInputManager::IsCharNukta(prevChar,aLanguage) && 
        TAknFepUiIndicInputManager::IsCharNukta(curChar,aLanguage)) ||
        
        //fallback character if Nukta is entered after Modifier or
        //Modifier is entered after Modifier
        (TAknFepUiIndicInputManager::IsCharModifier(prevChar,aLanguage) && 
        (TAknFepUiIndicInputManager::IsCharNukta(curChar,aLanguage) ||
        TAknFepUiIndicInputManager::IsCharModifier(curChar,aLanguage))) ||
        
        //fallback character if Nukta is entered after Vowel or
        //Nukta is entered after matra
       ((TAknFepUiIndicInputManager::IsCharAnVowel(prevChar,aLanguage) ||
       TAknFepUiIndicInputManager::IsCharMatra(prevChar,aLanguage)) && 
        TAknFepUiIndicInputManager::IsCharNukta(curChar,aLanguage))  ||
        //fallback character if Nukta is entered after Nukta Consonant
        (TAknFepUiIndicInputManager::IsCharNuktaConsonant(prevChar,aLanguage) &&
        TAknFepUiIndicInputManager::IsCharNukta(curChar,aLanguage)) ||
        
        //fallback character if Nukta entered in an empty editor
        (prevChar == PHONETIC_SEPARATOR &&
        TAknFepUiIndicInputManager::IsCharNukta(curChar,aLanguage))
        )
           {
            TBuf<1> buffer;
            fepMan->CommitInlineEditL(iIndicPhoneticBuffer, iIndicPhoneticBuffer.Length());
	        buffer.Append(KQuestionMark);
		if(!fepMan->IsFlagSet(CAknFepManager::EFlagInsideInlineEditingTransaction))
			{
			fepMan->StartInlineEditL();	
			}
        fepMan->UpdateInlineEditL(buffer,CAknFepManager::ESingleCharacter);
        fepMan->SetFlag(CAknFepManager::EFlagNoMatches);
		ret = EFalse;
		}
	return ret;
	}
	
TBool TAknFepInputStateInitialIndicPhoneticMultitap::IsInvalidPhoneticCharacter( 
                                              TUint aChar, TLanguage aLanguage )
	{
	TBool ret = EFalse;
	if(TAknFepUiIndicInputManager::IsCharNukta( aChar, aLanguage )
	   || TAknFepUiIndicInputManager::IsCharMatra( aChar,  aLanguage )
	   || TAknFepUiIndicInputManager::IsCharModifier( aChar,  aLanguage )
	   || TAknFepUiIndicInputManager::IsCharVirama( aChar,  aLanguage ))
		{	
		ret = ETrue;
		}
	return ret;	
	}

void TAknFepInputStateInitialIndicPhoneticMultitap::RemoveHalantL(TLanguage aLanguage)
	{
	MAknFepManagerUIInterface* fepMan = iOwner->FepMan();
	TBool isLineFeedEntered = fepMan->IsFlagSet(CAknFepManager::EFlagLineFeedCharacter);
	if (fepMan->IsFlagSet(CAknFepManager::EFlagInsideInlineEditingTransaction))
        {
        fepMan->CommitInlineEditL();
        }

	TInt position = 0;
	
    if(TAknFepUiIndicInputManager::IsCharVirama(fepMan->PreviousChar(ETrue), aLanguage))
    	{
    	position = 1;
    	}
    else if(!isLineFeedEntered && 
    TAknFepUiIndicInputManager::IsCharVirama(fepMan->PreviousToPreviousChar(ETrue), aLanguage))
    	{
    	position = 2;	
    	}
    if(position)	
    	fepMan->RemoveTextFromEditorL( 1, position-1, EFalse );
   	if(fepMan->NextChar() == KSpaceChar)
   		{
   		fepMan->AlignLogicalAndVisualCursorL(TTmDocPosSpec::ELeading, EFalse);	
   		}
	}

void TAknFepInputStateInitialIndicPhoneticMultitap::GetPhoneticLatinChar(TChar& aChar)const
	{
		aChar = iPhoneticLatinChar;
	}
//End of File
