fep/aknfep/src/AknFepUiInputStateEntryPinyinPhrase.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 11 Jun 2010 14:00:11 +0300
changeset 23 f043c81198e3
parent 0 eb1f2e154e89
permissions -rw-r--r--
Revision: 201021 Kit: 2010123

/*
* Copyright (c) 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 CAknFepUIInputStatePinyinPhrase methods.
*
*/












#include "AknFepPanic.h"
#include "AknFepUiInputStateEntryPinyinPhrase.h"
#include "AknFepUIManagerStateInterface.h"      //MAknFepUIManagerStateInterface
#include "AknFepManagerUIInterface.h"           //MAknFepManagerUIInterface
#include "AknFepUiCtrlContainerChinese.h"
#include "AknFepUICtrlInputPane.h"
#include "AknFepUICtrlCandidatePane.h"
#include "AknFepUICtrlPinyinPopup.h"		//Pinyin phrase
#include "AknFepManager.h"

#include <PtiEngine.h>                          //CPtiEngine
#include <PtiDefs.h>                            //keys
#include <avkon.rsg>
#include <aknfep.rsg>
#include <aknnotewrappers.h>

const TText KPinyinTone0Valid = 0x02C9;
const TText KPinyinTone1Valid = 0x02CA;
const TText KPinyinTone2Valid = 0x02C7;
const TText KPinyinTone3Valid = 0x02CB;
const TText KPinyinTone4Valid = 0x02D9;
const TText KPinyinTone4Invalid = 0x0020;

const TInt KMaxPhraseCount = 100;
const TInt KMaxKeystrokeCount = 100;
const TInt KMaxShowKeystrokeCount = 31;

const TInt KMaxPinyinLength = 60;

const TInt KMaxStarCount = 5;

const TInt KKey0Code = 48;
const TInt KKey1Code = 49;
const TInt KKey2Code = 50;
const TInt KKey3Code = 51;
const TInt KKey4Code = 52;
const TInt KKey5Code = 53;
const TInt KKey6Code = 54;
const TInt KKey7Code = 55;
const TInt KKey8Code = 56;
const TInt KKey9Code = 57;

_LIT( KPinyinListSeparator, "'" );
_LIT( KPinyinStar, "*" );
_LIT( KPinyinNote,"\x9020\x65B0\x8BCD" );
_LIT( KPinyinManualSeparator, "\x002E");

TAknFepInputStateEntryPinyinPhrase::TAknFepInputStateEntryPinyinPhrase(
                                MAknFepUIManagerStateInterface* aOwner,
                                MAknFepUICtrlContainerChinese* aUIContainer)
    :TAknFepInputStateChineseBase(aOwner, aUIContainer)
    {
    iState = EEntry;

    MAknFepUICtrlContainerChinese* uiContainer = UIContainer();
    uiContainer->FocusCandidatePane(EFalse);
    uiContainer->CandidatePane()->ShowCandidateOrdinals(EFalse);
    uiContainer->SetLayout(MAknFepUICtrlContainerChinese::ELayoutInput);
    uiContainer->CandidatePane()->SelectFirstPhrase(); 
    uiContainer->ShowVerticalScrollArrows(ETrue);
    uiContainer->ShowHorizontalScrollArrows(EFalse);
    uiContainer->InputPane()->SetOverrideFontId(0);

    iOwner->PtiEngine()->SetInputMode(EPtiEnginePinyinByPhrase);
    iOwner->PtiEngine()->SetCandidatePageLength(KMaxPhraseCount);
    uiContainer->PinyinPopupWindow()->SetTonemarkState( ETrue );
    // set the state is in input state,
    // so that it could handle EKeyCBA1
    iOwner->FepMan()->EntryPhrase( ETrue );
    uiContainer->SetFepMan( iOwner->FepMan() );
    
    ClearKeystrokeBuf();
    // in the case that we are coming back to the input pane from the candidate pane, 
    // we need to ensure that the current selection is selected correctly
    ImplicitlyUpdateSelection();
    // however we also need to clear the deliberate selection, in case we are not
    // coming back to the input pane from the candidate pane
    if ( uiContainer->PinyinPopupWindow()->GetFromCandidateChangeStateFlag() )
        {
        uiContainer->PinyinPopupWindow()->SetFromCandidateChangeStateFlag( EFalse );
        }
    else
        {
        ClearDeliberateSelection();
        }
    
    UpdateIndicator();
    TRAP_IGNORE( ChangeCbaL() );
    }

void TAknFepInputStateEntryPinyinPhrase::HandleCommandL( TInt aCommandId)
    {
    CPtiEngine* ptiengine = iOwner->PtiEngine( );
    MAknFepUICtrlContainerChinese* uiContainer = UIContainer( );
    MAknFepUICtrlPinyinPopup* popup = uiContainer->PinyinPopupWindow( );
    CDesCArrayFlat* keystrokeArray = popup->KeystrokeArray( );
    CDesCArrayFlat* inEffectKeystrokeArray = popup->InEffectKeystrokeArray( );
    CDesCArrayFlat* showKeystrokeArray = popup->ShowKeystrokeArray( );
    TInt currentSelect = popup->CurrentSelection( );
    TInt inEffectSpellingCount = ptiengine->PhoneticSpellingCount( );
    TBuf<KMaxKeystrokeCount> keystrokeBuf;
    switch ( aCommandId )
        {
        // Handle the event frome command.
        case EAknSoftkeyCancel:
            //  case (TUint16)EAknSoftkeyCancel: //the Cancle in soft CBA
            TAknFepInputStateChineseBase::HandleCommandL( aCommandId );
            break;
        case EAknSoftkeySelect:
            //case (TUint16)EAknSoftkeySelect: //the Selected in soft CBA
            if ( (currentSelect < inEffectSpellingCount)
                && (keystrokeArray->Count( )
                    == inEffectKeystrokeArray->Count( ) )
                && (popup->GetTonemarkState( ) ) )
                {
                if ( popup->IsEnabled( ) )
                    {
                    popup->Enable( EFalse );
                    }
                iOwner->FepMan()->PinyinPhraseCreation( EFalse );
                popup->SetChangeState( ETrue );
                iOwner->ChangeState( ECandidate );
                }
            else
                {
                GetKeystrokeBuf( *keystrokeArray, keystrokeBuf );
                iOwner->FepMan()->PinyinPhraseCreation( ETrue );
                popup->SetChangeState( ETrue );
                popup->SetPhraseCreationState( ETrue );
                if ( GetChangeState( ) )
                    {
                    ClearDeliberateSelection( );
                    popup->Enable( EFalse );
                    iOwner->ChangeState( ESpellingSelection );
                    }
                else
                    {
                    ClearDeliberateSelection( );
                    popup->Enable( EFalse );
                    iOwner->ChangeState( EKeySequenceEdit );
                    }
                }
            break;
        default:
            DeliberatelyUpdateSelection( );
            break;
        }

    }

TBool TAknFepInputStateEntryPinyinPhrase::HandleKeyL( TInt aKey, TKeyPressLength aLength )
    {
    CPtiEngine* ptiengine = iOwner->PtiEngine();
    MAknFepUICtrlContainerChinese* uiContainer = UIContainer();
    MAknFepUICtrlPinyinPopup* popup = uiContainer->PinyinPopupWindow();
    CDesCArrayFlat* keystrokeArray = popup->KeystrokeArray();
    CDesCArrayFlat* inEffectKeystrokeArray = popup->InEffectKeystrokeArray();
    CDesCArrayFlat* showKeystrokeArray = popup->ShowKeystrokeArray();
    TInt currentSelect = popup->CurrentSelection();
    TInt inEffectSpellingCount = ptiengine->PhoneticSpellingCount();
    TInt offset = 0;
    
    TBuf<1> keyBuf;
    TBuf<1> keyShow;
    TBuf<KMaxKeystrokeCount> keystrokeBuf;
    
    if(aKey == EKeyBackspace)
        {
        TBool state = ETrue;
        if ( popup->IsChangeStatet() && aLength == ELongKeyPress )
            {
            state = EFalse;
            }
        else
            {
            popup->SetChangeState( EFalse );
            }
        if ( state )
            {
            DeleteCurrentKeystroke();
            showKeystrokeArray->Delete( showKeystrokeArray->Count() - 1 );
            showKeystrokeArray->Compress();
            if ( inEffectKeystrokeArray->Count()> 0 )
                {
                ImplicitlyUpdateSelection();
                }
            else
                {
                ClearDeliberateSelection();
                iOwner->FepMan()->TryCloseUiL(); //no more keys, close the UI.
                if (aLength == ELongKeyPress)
                    {
                    iOwner->FepMan()->SetLongClearAfterCloseUI(ETrue);
                    }
                }
            }
        }
    else if(aKey == EKeyRightArrow)
        {
        if(popup->IsEnabled())
            {
            if(popup->SelectNextPhrase())
                {
                DeliberatelyUpdateSelection();
                }
            }
        }
    else if(aKey == EKeyLeftArrow)
        {
        if(popup->IsEnabled())
            {
            if(popup->SelectPrevPhrase())
                {
                DeliberatelyUpdateSelection();
                }
            }
        }
    else if( ( aKey == EKeyOK || aKey == EKeyDownArrow || aKey == EKeyCBA1)
        && aLength == EShortKeyPress)
        {
        if ( ( currentSelect < inEffectSpellingCount) && 
            ( keystrokeArray->Count() == inEffectKeystrokeArray->Count() ) &&
            ( popup->GetTonemarkState() ) )
            {
            if(popup->IsEnabled())
                {
                popup->Enable(EFalse);
                }
            iOwner->FepMan()->PinyinPhraseCreation( EFalse );
            popup->SetChangeState( ETrue );
            iOwner->ChangeState(ECandidate);              
            }
        else
            {
            GetKeystrokeBuf( *keystrokeArray, keystrokeBuf );
            iOwner->FepMan()->PinyinPhraseCreation( ETrue );
            popup->SetChangeState( ETrue );
            popup->SetPhraseCreationState( ETrue );
            if ( GetChangeState() )
                {
                ClearDeliberateSelection();
                popup->Enable( EFalse );
                iOwner->ChangeState(ESpellingSelection);
                }
            else
                {
                ClearDeliberateSelection();
                popup->Enable( EFalse );
                iOwner->ChangeState(EKeySequenceEdit);
                }
            }
        }
    else if (aLength == EShortKeyPress) // don't want repeats on these keys
        {
    	iOwner->FepMan()->SetCcpuFlag(CAknFepManager::ECcpuStateIgnoreStarUp);            
        
        if ( ( iOwner->IsValidChineseInputKey(aKey) ) &&
             ( CheckKeystroke( aKey, *keystrokeArray ) ) )
            {
            TInt stringBeforeLength(0);
            TInt stringAfterLength(0);
            GetKeystrokeNum( aKey, keyBuf );
            keystrokeArray->AppendL( keyBuf );
            showKeystrokeArray->AppendL( keyBuf );
            
            if ( popup->GetTonemarkState() )
                {
            stringBeforeLength = ptiengine->GetPhoneticSpelling(1).Length();
            stringAfterLength = ptiengine->AppendKeyPress((TPtiKey)aKey).Length();
                if (stringBeforeLength != stringAfterLength)
                    {
                    if (ptiengine->GetPhoneticSpelling(1).Length() == 1)
                        {
                        iOwner->FepMan()->UpdateCbaL(R_AKNFEP_SOFTKEYS_PHRASE_CREATION_SELECT_CANCEL_SELECT);
                        }
                    inEffectKeystrokeArray->AppendL(keyBuf);
                    ImplicitlyUpdateSelection();
                    }
                else
                    {
                    ptiengine->EnableToneMarks(ETrue);
                    UIContainer()->PinyinPopupWindow()->SetFlag(MAknFepUICtrlPinyinPopup::ESpellingChanged);
                    RefreshUI(0);
                    } 
                }
            else
                {
                ImplicitlyUpdateSelection();
                }
            }
        else if ( ( aKey == EPtiKeyStar ) &&  
                  ( CheckKeystroke( aKey, *keystrokeArray ) ) ) // we increment the tone mark.
            {
            keyBuf.Append( EPtiKeyStar );
            
            if ( keystrokeArray->Count() == inEffectKeystrokeArray->Count() )
                {
                inEffectKeystrokeArray->AppendL(keyBuf);
                keystrokeArray->AppendL( keyBuf );
                GetPinyinToneMark( *keystrokeArray, keyShow );
                ShowKeystrokeAppendL( *showKeystrokeArray, *keystrokeArray, keyShow );
                CheckTonemarkL();
                }
            else
                {
                keystrokeArray->AppendL( keyBuf );
                GetPinyinToneMark( *keystrokeArray, keyShow );
                ShowKeystrokeAppendL( *showKeystrokeArray, *keystrokeArray, keyShow );
                for ( TInt i = keystrokeArray->Count() - 1; i >= 0; i-- )
                    {
                    if ( 0 == keystrokeArray->MdcaPoint( i ).
                            Compare( KPinyinStar ) )
                        {
                        offset = offset + 1;
                        }
                    else
                        {
                        break;
                        }
                    }
                if ( offset > KMaxStarCount )
                    {
                    for ( TInt j = 0; j < KMaxStarCount; ++j )
                        {
                        keystrokeArray->Delete( keystrokeArray->Count() - 1 );
                        }
                    keystrokeArray->Compress();
                    }
                }
            ImplicitlyUpdateSelection();
            }
        else
            {
            iOwner->FepMan()->PlaySound(EAvkonSIDErrorTone);
            }
        }
    return ETrue;
    }

// ---------------------------------------------------------
// Optimize spelling
// ---------------------------------------------------------
//
void TAknFepInputStateEntryPinyinPhrase::OptimizeSpellingL( CDesCArrayFlat& aOptimizeBefore, CDesCArrayFlat& aOptimizeAfter )
    {
    MAknFepUICtrlContainerChinese* uiContainer = UIContainer();
    MAknFepUICtrlPinyinPopup* popup = uiContainer->PinyinPopupWindow();
    CDesCArrayFlat* inEffectKeystrokeArray = popup->InEffectKeystrokeArray();
    TBool checkSeparator = EFalse;
    TBuf<KMaxPinyinLength> spellingBuf;
    TInt bufLength = 0;
    TInt countSeparator = 0;

    TInt countBuf[KMaxPhraseCount];
    memset( countBuf, 0, sizeof( countBuf ) );
    
    TInt position = 0;
    TInt i = 0;
    TInt j = 0;
    
    if ( 0 == inEffectKeystrokeArray->Count() )
        {
        return;
        }
    
    for ( i = 0 ; i < inEffectKeystrokeArray->Count(); ++i )
        {
        if ( 0 == inEffectKeystrokeArray->MdcaPoint( i ).Compare( KPinyinListSeparator ) )
            {
            checkSeparator = ETrue;
            countBuf[countSeparator] = j;
            countSeparator = countSeparator + 1;
            }
        else
            {
            if (  0 == i  )
                {
                j = j + 1;
                }
            else
                {
                if ( ( 0 == inEffectKeystrokeArray->MdcaPoint( i ).Compare( KPinyinStar ) ) &&
                    ( 0 != inEffectKeystrokeArray->MdcaPoint( i - 1 ).Compare( KPinyinStar ) ))
                    {
                    j = j + 1;
                    }
                else if ( 0 != inEffectKeystrokeArray->MdcaPoint( i ).Compare( KPinyinStar ) )
                    {
                    j = j + 1;
                    }
                }
            }
        }
  
    j = 0;
    for ( i = 0; i < aOptimizeBefore.Count(); ++i )
        {
        j = 0;
        bufLength = 0;
        position = 0;
        spellingBuf.Size();
        spellingBuf.Copy( aOptimizeBefore.MdcaPoint( i ) );
        bufLength = spellingBuf.Length();
        while( j < bufLength )
            {
            position = spellingBuf.Find( KPinyinListSeparator );
            if ( position != KErrNotFound )
                {
                spellingBuf.Replace( position, 1, KPinyinManualSeparator );
                j = position + 1;
                }
            else
                {
                break;
                }
            }
        aOptimizeAfter.AppendL( spellingBuf );
        }    
    
    if ( !checkSeparator )
        {
        return;
        }
    
    aOptimizeBefore.Reset();
    aOptimizeBefore.Compress();
    
    for ( i = 0; i < aOptimizeAfter.Count(); ++i )
        {
        aOptimizeBefore.AppendL( aOptimizeAfter.MdcaPoint( i ) );
        }
    
    aOptimizeAfter.Reset();
    aOptimizeAfter.Compress();
    

    for ( TInt k = 0; k < aOptimizeBefore.Count(); ++k )
        {
        j = 0;
        bufLength = 0;
        position = 0;
        spellingBuf.Size();
        spellingBuf.Copy( aOptimizeBefore.MdcaPoint( k ) );
        bufLength = spellingBuf.Length();
        for ( TInt kk = 0; kk < bufLength; ++kk )
            {
            if ( 0 == spellingBuf.Mid( kk, 1 ).Compare( KPinyinManualSeparator ) )
                {
                for ( TInt kkk = 0; kkk < countSeparator; ++kkk)
                    {
                    if ( j == countBuf[kkk] )
                        {
                        spellingBuf.Replace( kk, 1, KPinyinListSeparator );
                        }
                    }
                }
            else
                {
                j = j + 1;
                }
            }
        aOptimizeAfter.AppendL( spellingBuf );
        }
    }
void TAknFepInputStateEntryPinyinPhrase::DeliberatelyUpdateSelection()
    {
    TPtr deliberateSelection = iOwner->GetLatestDeliberateSelection();
    CPtiEngine* ptiengine = iOwner->PtiEngine();
    MAknFepUICtrlContainerChinese* uiContainer = UIContainer();
    MAknFepUICtrlPinyinPopup* popup = uiContainer->PinyinPopupWindow();

    TInt selected = popup->CurrentSelection();
    ptiengine->EnableToneMarks(EFalse);
    TPtrC spelling = ptiengine->GetPhoneticSpelling(selected + 1); // our index is zero based, engine index is one based
    deliberateSelection = spelling.Left(
                        MAknFepUICtrlInputPane::EMaxInputCharsPinyinPopupNotIncludingToneMark);
    ptiengine->EnableToneMarks(ETrue);
    UIContainer()->PinyinPopupWindow()->SetFlag(MAknFepUICtrlPinyinPopup::ESpellingNavigation);    
    RefreshUI(popup->CurrentVisibleSelection());
    }

void TAknFepInputStateEntryPinyinPhrase::ImplicitlyUpdateSelection()
    {
    TPtr oldDeliberateSelection = iOwner->GetLatestDeliberateSelection();
    TInt oldDeliberateSelectionLength = oldDeliberateSelection.Length();
    CPtiEngine* ptiengine = iOwner->PtiEngine();

    // previously selected is compared in turn to each of the new candidates
    ptiengine->EnableToneMarks(EFalse);
    TInt pinyinCount = ptiengine->PhoneticSpellingCount();
    TInt newSelection = 0;
    for(TInt i = 0; i < pinyinCount; i++)
        {
        TPtrC spelling = ptiengine->GetPhoneticSpelling(i + 1);  // our index is zero based, engine index is one based
        TInt spellingLength = spelling.Length();

        // figure out how many characters we are comparing, this depends on the 
        // direction of the edit
        TInt compareLength = oldDeliberateSelectionLength <= spellingLength ? 
            oldDeliberateSelectionLength : spellingLength;

        if(oldDeliberateSelection.Left(compareLength) == spelling.Left(compareLength))
            {
            // as soon as a substring match is found, the 
            // highlight position is set to that candidate in the new list. 
            // note that in the case of the first character entered, the
            // oldBuf will be empty so it will always match... which is 
            // fine as we want to select the top one anyway, so we will
            // quit the loop early.
            newSelection = i;
            break;
            }
        }
    
        ptiengine->EnableToneMarks(ETrue);
        UIContainer()->PinyinPopupWindow()->SetFlag(MAknFepUICtrlPinyinPopup::ESpellingChanged);
    	RefreshUI(newSelection);
    }

void TAknFepInputStateEntryPinyinPhrase::ClearDeliberateSelection()
    {
    // we must have just deleted the last character, 
    // or we are starting a new pinyin session, so wipe the last deliberate selection
    TPtr oldDeliberateSelection = iOwner->GetLatestDeliberateSelection();
    oldDeliberateSelection = KNullDesC;
    }

void TAknFepInputStateEntryPinyinPhrase::RefreshUI(TInt aSelection)
    {
    CPtiEngine* ptiengine = iOwner->PtiEngine();
    MAknFepUICtrlContainerChinese* uiContainer = UIContainer();
    MAknFepUICtrlPinyinPopup* popup = uiContainer->PinyinPopupWindow();
    MAknFepUICtrlInputPane* inputPane = uiContainer->InputPane();
    CDesCArrayFlat* keystrokeArray = popup->KeystrokeArray();
    CDesCArrayFlat* inEffectKeystrokeArray = popup->InEffectKeystrokeArray();
    CDesCArrayFlat* showKeystrokeArray = popup->ShowKeystrokeArray();
    CDesCArrayFlat* optimizeSpelling = popup->PhoneticSpellingArray();
    CDesCArrayFlat* spelling = popup->OptimizeSpelling();
        
    TBuf<KMaxKeystrokeCount> keystrokeBuf;
    
    // get cursor position
    TPoint baseLine = TPoint(0,0);
    TInt height = 0;
    TInt ascent = 0;

    TBool checkTonemark = popup->GetTonemarkState();
    TRAPD(ret,iOwner->FepMan()->GetScreenCoordinatesL(baseLine,height,ascent));
    if (ret == KErrNone)
        {
        uiContainer->SetContainerPosition(baseLine, height);    
        }

    TText toneMark;
    TBool toneMarkEntered = ptiengine->ToneMark(toneMark);
    TBuf<1> validToneMarkBuf;
    if(toneMarkEntered)
        {
        // override specific invalid tonemark character only, the others are the same character 
        // when both valid and invalid
        if(toneMark == KPinyinTone4Invalid)
            toneMark = KPinyinTone4Valid;
        validToneMarkBuf.Append(toneMark);
        }

    // to start with, disable the tone marks so we can get the list of all pinyin matches
    // later we will figure out which ones are invalid
    ptiengine->EnableToneMarks(EFalse);
    TInt pinyinCountWithoutToneMarks = ptiengine->PhoneticSpellingCount();
    if(pinyinCountWithoutToneMarks > 0)
        {
        if(popup->IsFlagSet(MAknFepUICtrlPinyinPopup::ESpellingChanged))
            {
            if ( ( inEffectKeystrokeArray->Count() < keystrokeArray->Count() ) ||
                ( !checkTonemark ) )
                {
                spelling->Reset();
                optimizeSpelling->Reset();
                spelling->Compress();
                optimizeSpelling->Compress();
                }
            else
                {
                spelling->Reset();
                optimizeSpelling->Reset();
                spelling->Compress();
                optimizeSpelling->Compress();
            TRAPD(ignore, ptiengine->GetPhoneticSpellingsL(*spelling));
            if (ignore != KErrNone)
                    {
                    return;
                    }
                
                TRAPD( iOptimize, OptimizeSpellingL( *spelling, *optimizeSpelling ) );
                if ( KErrNone != iOptimize )
                    {
                    return;
                    }
                }
            
            GetKeystrokeBuf( *showKeystrokeArray, keystrokeBuf );
            
            TRAPD( retOptimize, optimizeSpelling->AppendL( keystrokeBuf ) );
            if ( KErrNone != retOptimize )
                {
                return;
                }
            popup->SplitPhraseSpellingIntoPages(); 
            }

        // set display page for delibrate selection
        popup->SetDisplayPage(aSelection);
        popup->SetPhraseItemTexts();
 
        // fill in input pane although it's invisible
        if ( inEffectKeystrokeArray->Count() < keystrokeArray->Count() )
            {
            inputPane->SetText( keystrokeBuf );    
            }
        else
            {
            if ( optimizeSpelling->Count() > popup->CurrentSelection() )
                {
                inputPane->SetText( optimizeSpelling->MdcaPoint( popup->CurrentSelection() ) );
                }
            else
                {
                inputPane->SetText( KNullDesC );
                }
            }
        popup->PopupSizeChanged(); // phrase input
        }
    // turn tone marks back on so that we know where we are.
    ptiengine->EnableToneMarks(ETrue);

    // this is where we start to figure out whether the tonemarks are valid,
    // whether the selected tonemark is valid, and what is the index of the 
    // selected candidate in the list of candidates with tonemarks...
    TBool selectionToneMarkValid = EFalse;
    TInt selectionIndexAdjustedForToneMarkValidity = popup->CurrentSelection();
    
    // we only need to deal with tone marks if there is one
    if(toneMarkEntered)
        {
        if(pinyinCountWithoutToneMarks > 0)
            {
            for(TInt i = 0; i < pinyinCountWithoutToneMarks; i++)
                {
                TBool valid = EFalse;
                
                TBuf<MAknFepUICtrlInputPane::EMaxInputCharsPinyinPopupNotIncludingToneMark> nextCandidateWithoutToneMark;
                nextCandidateWithoutToneMark.Copy(ptiengine->GetPhoneticSpelling(i + 1).Left(
                      MAknFepUICtrlInputPane::EMaxInputCharsPinyinPopupNotIncludingToneMark));
                
                ptiengine->EnableToneMarks(EFalse); 
                ptiengine->SelectPhoneticSpelling(i + 1);

                valid = ptiengine->IsToneMarkValidForSpelling();
                if(valid)
                    {
                    ptiengine->EnableToneMarks(ETrue); 
                    TInt pinyinCountWithToneMarks = ptiengine->PhoneticSpellingCount();

                    for(TInt j = 0; j < pinyinCountWithToneMarks; j++)
                        {
                        // use j here not i as we are looking at the list with tonemarks
                        TPtrC nextCandidateWithToneMark = ptiengine->GetPhoneticSpelling(j + 1);  
                        if(nextCandidateWithToneMark == nextCandidateWithoutToneMark)
                            {
                            if(i == aSelection)
                                {
                                selectionToneMarkValid = ETrue;
                                
                                // fill in input pane even if it can't be seen, for when we have to hide popup window
                                inputPane->SetText(nextCandidateWithoutToneMark);
                                }
                            break;
                            }
                        }
                    }
                }
            }
        }
    ptiengine->EnableToneMarks(EFalse); 
    ptiengine->SelectPhoneticSpelling(popup->CurrentSelection() + 1); 
    // next two lines are for tonemark validity
    ptiengine->EnableToneMarks(selectionToneMarkValid); 
    ptiengine->SelectPhoneticSpelling(selectionIndexAdjustedForToneMarkValidity + 1); // our index is zero based, engine index is one based

    // update the candidate pane.
    if(popup->IsFlagSet(MAknFepUICtrlPinyinPopup::ESpellingChanged) 
        || popup->IsFlagSet(MAknFepUICtrlPinyinPopup::ESpellingNavigation))
        {
        CDesCArrayFlat* phraseCandidates = uiContainer->CandidatePane()->CandidateArray();
        if ( ( pinyinCountWithoutToneMarks > popup->CurrentSelection() ) && 
             ( inEffectKeystrokeArray->Count() == keystrokeArray->Count() ) && 
             checkTonemark )      
            {
            TRAPD(ignore, ptiengine->GetChinesePhraseCandidatesL(*phraseCandidates));
            if (ignore != KErrNone)
                {
                return;
                }            
            }        
        else if ( keystrokeArray->Count() != 0 )
            {
            phraseCandidates->Reset();
            TRAPD( retAddPinyinNote, phraseCandidates->AppendL( KPinyinNote ) );
            if ( KErrNone != retAddPinyinNote )
                {
                return;
                }
            }
        uiContainer->CandidatePane()->SplitPhraseCandidatesIntoPages(); 
        popup->ClearFlag(MAknFepUICtrlPinyinPopup::ESpellingChanged 
                        | MAknFepUICtrlPinyinPopup::ESpellingNavigation);
        }
    uiContainer->CandidatePane()->SetCandidateBuffer();
    uiContainer->Enable(ETrue);
    // need to enable the pinyin popup after the container so that it is raised to the front
    popup->Enable(pinyinCountWithoutToneMarks > 0);
    UpdateIndicator();
    }

void TAknFepInputStateEntryPinyinPhrase::InitializeStateL(void)
    {
    iOwner->FepMan()->UpdateCbaL(R_AKNFEP_SOFTKEYS_PHRASE_CREATION_SELECT_CANCEL_SELECT);
    }
    
void TAknFepInputStateEntryPinyinPhrase::UpdateIndicator()
    {
    CPtiEngine* ptiengine = iOwner->PtiEngine();
    MAknFepUICtrlContainerChinese* uiContainer = UIContainer();        
    TInt bufLength = iOwner->PtiEngine()->CandidatePage().Length();
    MAknFepUICtrlCandidatePane* candidatePane = uiContainer->CandidatePane();
        
    if (candidatePane->IsFirstPage())
        {
        uiContainer->CandidatePane()->ShowUpScrollArrows(EFalse);    
        }
    else
        {
        uiContainer->CandidatePane()->ShowUpScrollArrows(ETrue);    
        }
   
    if (candidatePane->IsLastPage())
        {
        uiContainer->CandidatePane()->ShowDownScrollArrows(EFalse);     
        }
    else
   	    {
   	    uiContainer->CandidatePane()->ShowDownScrollArrows(ETrue);      
   	    }
        
    if (candidatePane->SelectedIndex() == 0 && 
        candidatePane->IsFirstPage() )
        {
        uiContainer->CandidatePane()->ShowLeftScrollArrows(EFalse);
        }
    else
        {
        uiContainer->CandidatePane()->ShowLeftScrollArrows(ETrue);
        }
        
    if (candidatePane->IsLastPage() && 
        (candidatePane->SelectedIndex() == candidatePane->VisibleCandidateCount() - 1))
        {
        uiContainer->CandidatePane()->ShowRightScrollArrows(EFalse);        
        }
    else
        {
        uiContainer->CandidatePane()->ShowRightScrollArrows(ETrue);
        }
    } 
// ---------------------------------------------------------
// Delete current keystroke.
// ---------------------------------------------------------
//
void TAknFepInputStateEntryPinyinPhrase::DeleteCurrentKeystroke()
    {
    MAknFepUICtrlContainerChinese* uiContainer = UIContainer();
    MAknFepUICtrlPinyinPopup* popup = uiContainer->PinyinPopupWindow();
    CDesCArrayFlat* keystrokeArray = popup->KeystrokeArray();
    CDesCArrayFlat* inEffectKeystrokeArray = popup->InEffectKeystrokeArray();
    CPtiEngine* ptiengine = iOwner->PtiEngine();
    TInt i = keystrokeArray->Count() - 1;
    TInt count = keystrokeArray->Count() - 1;
    TInt inECTKeystrokeCount = inEffectKeystrokeArray->Count();
    TInt validCount = 0;
    
    if ( keystrokeArray->Count() > inEffectKeystrokeArray->Count() )
        {
        for ( i = keystrokeArray->Count() - 1; i >= 0; i-- )
            {
            if ( 0 == keystrokeArray->MdcaPoint( i ).Compare( KPinyinStar ) )
                {
                keystrokeArray->Delete( i );
                }
            else
                {
                if ( i == count )
                    {
                    keystrokeArray->Delete( i );
                    break;
                    }
                break;
                }
           }
        }
    else
        {
        for ( TInt j = 0; j < inECTKeystrokeCount; ++j )
            {            
            if ( 0 != inEffectKeystrokeArray->
                MdcaPoint( j ).Compare( KPinyinStar ) )
                 {
                 validCount = validCount + 1;
                 }
            if ( j > 1 )
                {
                if ( ( 0 != inEffectKeystrokeArray->MdcaPoint( j ).
                    Compare( KPinyinStar ) ) && 
                    ( 0 == inEffectKeystrokeArray->MdcaPoint( j - 1).
                        Compare( KPinyinStar ) ) )
                     {
                     validCount = validCount + 1;
                     }
                if  ( ( j == inECTKeystrokeCount - 1 ) && 
                    ( 0 == inEffectKeystrokeArray->MdcaPoint( j ).
                        Compare( KPinyinStar ) ) )
                    {
                    validCount = validCount + 1;
                    }
                }
            }
        
        if ( inEffectKeystrokeArray->Count() > 0 )
            {
            if ( 0 == inEffectKeystrokeArray->MdcaPoint( 
                inEffectKeystrokeArray->Count() - 1 ).Compare( KPinyinStar ) )
                {
                popup->SetTonemarkState( ETrue );
                }
            }
        
        if ( 0 == keystrokeArray->MdcaPoint( keystrokeArray->Count() - 1 ).
            Compare( KPinyinStar ) )
            {
            ptiengine->DeleteKeyPress();
            for ( i = keystrokeArray->Count() - 1; i >= 0; i-- )
                {
                if ( 0 == keystrokeArray->MdcaPoint( i ).Compare( KPinyinStar ) )
                    {
                    keystrokeArray->Delete( i );
                    inEffectKeystrokeArray->Delete(i);
                    }
                else
                    {
                    break;
                    }
                }
            }
        else
            {
            keystrokeArray->Delete( i );
            inEffectKeystrokeArray->Delete(i);
            ptiengine->DeleteKeyPress();
            }
        }
    keystrokeArray->Compress();
    inEffectKeystrokeArray->Compress();
    }

// ---------------------------------------------------------
// Add current keystroke.
// ---------------------------------------------------------
void TAknFepInputStateEntryPinyinPhrase::AddCurrentKeystrokeL( const TDesC& keystroke )
    {
    MAknFepUICtrlContainerChinese* uiContainer = UIContainer();
    MAknFepUICtrlPinyinPopup* popup = uiContainer->PinyinPopupWindow();
    CDesCArrayFlat* keystrokeArray = popup->KeystrokeArray();
    CDesCArrayFlat* inEffectKeystrokeArray = popup->InEffectKeystrokeArray();
    const TInt offsetSize = 4;
    TInt count = keystrokeArray->Count();
    TInt offset = 0;
    TInt i = count - 1;
    
    if ( 0 != keystroke.Compare( KPinyinStar ) )
        {
        if ( keystrokeArray->Count() > inEffectKeystrokeArray->Count() )
            {
            keystrokeArray->AppendL( keystroke );
            keystrokeArray->Compress();
            return;
            }
        else
            {
            keystrokeArray->AppendL( keystroke );
            keystrokeArray->Compress();
            inEffectKeystrokeArray->AppendL( keystroke );
            inEffectKeystrokeArray->Compress();
            return;
            }
        }
    
    for ( i = count - 1; i >= 0; i-- )
        {
        if ( 0 == keystrokeArray->MdcaPoint( i ).Compare( KPinyinStar ) )
            {
            offset = offset + 1;
            }
        else
            {
            break;
            }
        }     
    if ( ( 0 <= offset ) && ( offset <= offsetSize ) )
        {
        if ( keystrokeArray->Count() > inEffectKeystrokeArray->Count() )
            {
            keystrokeArray->AppendL( keystroke );
            keystrokeArray->Compress();
            }
        else
            {
            keystrokeArray->AppendL( keystroke );
            keystrokeArray->Compress();
            inEffectKeystrokeArray->AppendL( keystroke );
            inEffectKeystrokeArray->Compress();
            }
        }
    else
        {
        if ( keystrokeArray->Count() > inEffectKeystrokeArray->Count() )
            {
            for ( TInt ii = 0; ii < offsetSize; ++ii )
            {
                keystrokeArray->Delete( count - 1 -ii );
            }
            keystrokeArray->Compress();
            }
        else
            {
            for ( TInt ii = 0; ii < offsetSize; ++ii )
            {
                keystrokeArray->Delete( count - 1 -ii );
                inEffectKeystrokeArray->Delete( count - 1 -ii );
            }
            keystrokeArray->Compress();
            inEffectKeystrokeArray->Compress();
            }
        }    
    }


// ---------------------------------------------------------
// Get the keystroke.
// ---------------------------------------------------------
//
void TAknFepInputStateEntryPinyinPhrase::GetKeystrokeNum( TInt aKey, TDes& aKeystroke ) 
    {
    switch(aKey)
        {
        case KKey0Code:
            aKeystroke.Append( KPinyinListSeparator );
            break;
        case KKey1Code:
            aKeystroke.Append( KPinyinListSeparator );
            break;
        case KKey2Code:
            aKeystroke.Append(EPtiKey2);
            break;
        case KKey3Code:
            aKeystroke.Append(EPtiKey3);
            break;
        case KKey4Code:
            aKeystroke.Append(EPtiKey4);
            break;
        case KKey5Code:
            aKeystroke.Append(EPtiKey5);
            break;
        case KKey6Code:
            aKeystroke.Append(EPtiKey6);
            break;
        case KKey7Code:
            aKeystroke.Append(EPtiKey7);
            break;
        case KKey8Code:
            aKeystroke.Append(EPtiKey8);
            break;
        case KKey9Code:
            aKeystroke.Append(EPtiKey9);
            break;
        default:
            aKeystroke.Append(EPtiKeyStar);
            break;
        }
    }

// ---------------------------------------------------------
// Get the keystroke buf.
// ---------------------------------------------------------
//
void TAknFepInputStateEntryPinyinPhrase::GetKeystrokeBuf(const CDesCArrayFlat& aKeystrokeArray, TDes& aKeystrokeBuf )
    {
    for ( TInt i = 0; i < aKeystrokeArray.Count(); ++i )
        {
        aKeystrokeBuf.Append(aKeystrokeArray.MdcaPoint(i));
        }
    }

// ---------------------------------------------------------
// clear keystroke.
// ---------------------------------------------------------
//
void TAknFepInputStateEntryPinyinPhrase::ClearKeystrokeBuf()
    {
    MAknFepUICtrlContainerChinese* uiContainer = UIContainer();
    MAknFepUICtrlPinyinPopup* popup = uiContainer->PinyinPopupWindow();
    CDesCArrayFlat* keystrokeArray = popup->KeystrokeArray();
    CDesCArrayFlat* inEffectKeystrokeArray = popup->InEffectKeystrokeArray();
    CDesCArrayFlat* showKeystrokeArray = popup->ShowKeystrokeArray();
    CDesCArrayFlat* chooseChineseArray = popup->ChooseChineseCharacterArray();
    CDesCArrayFlat* chooseChienseKeystroke = popup->ChooseChineseCharacterArrayKeystroke();
    
    CPtiEngine* ptiengine = iOwner->PtiEngine();
    TInt pinyinCount = ptiengine->PhoneticSpellingCount();
    chooseChineseArray->Reset();
    chooseChienseKeystroke->Reset();
    
    if ( 0 == pinyinCount )
        {
        keystrokeArray->Reset();
        inEffectKeystrokeArray->Reset();
        showKeystrokeArray->Reset();
        }
    }

// ---------------------------------------------------------
// Get tome mark.
// ---------------------------------------------------------
//
void TAknFepInputStateEntryPinyinPhrase::GetPinyinToneMark( const CDesCArrayFlat& aKeystrokeArray, TDes& aPinyinToneMark )
    {
    TInt starCount = 0;
    TInt pinyinToneMark;
    TBuf<1> buf;
    TInt count = aKeystrokeArray.Count();
    const TInt toneMark0 = 0;
    const TInt toneMark1 = 1;
    const TInt toneMark2 = 2;
    const TInt toneMark3 = 3;
    const TInt toneMark4 = 4;
    
    if ( 0 == count )
        {
        aPinyinToneMark.Append( KPinyinTone0Valid );
        return;
        }
    
    for ( TInt i = count - 1; i >= 0; --i )
        {
        buf = aKeystrokeArray.MdcaPoint( i );
        if ( 0 == buf.Compare( KPinyinStar ) )
            {
            starCount = starCount + 1; 
            }
        else
            {
            break;
            }
        }
    
    if ( 0 == starCount )
        {
        aPinyinToneMark.Append( KPinyinTone0Valid );
        }
    else
        {
        pinyinToneMark = starCount % KMaxStarCount;
        switch ( pinyinToneMark )
            {
            case toneMark0:
                aPinyinToneMark.Append( KPinyinTone4Valid );
                break;
            case toneMark1:
                aPinyinToneMark.Append( KPinyinTone0Valid );
                break;
            case toneMark2:
                aPinyinToneMark.Append( KPinyinTone1Valid );
                break;
            case toneMark3:
                aPinyinToneMark.Append( KPinyinTone2Valid );
                break;
            case toneMark4:
                aPinyinToneMark.Append( KPinyinTone3Valid );
                break;
            default:
               break;
            }
        }
    }

// ---------------------------------------------------------
// Check keystroke.
// ---------------------------------------------------------
//
TBool TAknFepInputStateEntryPinyinPhrase::CheckKeystroke( TInt aKey, const CDesCArrayFlat& aKeystrokeArray )
    {
    CDesCArrayFlat* showKeystrokeArray = UIContainer()->
        PinyinPopupWindow()->ShowKeystrokeArray();
    
    TInt count = showKeystrokeArray->Count();
    TBuf<1> keyBuf;
    
    if ( count >= KMaxShowKeystrokeCount )
        {
        if ( ( 0 != aKeystrokeArray.MdcaPoint( aKeystrokeArray.Count() - 1 ).
            Compare( KPinyinStar ) ) || ( aKey != EPtiKeyStar )  )
            {
            return EFalse;
            }
        }
    
    GetKeystrokeNum( aKey, keyBuf );

    if ( 0 == aKeystrokeArray.Count() )
        {        
        if ( ( 0 == keyBuf.Compare ( KPinyinStar ) ) || ( 0 == keyBuf.Compare ( KPinyinListSeparator ) ) )
            {
            return EFalse;
            }        
        }
    else
        {
        if ( 0 == aKeystrokeArray.MdcaPoint( aKeystrokeArray.Count() - 1 ).Compare( KPinyinStar ) && 
            ( 0 == keyBuf.Compare ( KPinyinListSeparator ) ) )
            {
            return EFalse;
            }
        
        if ( 0 == aKeystrokeArray.MdcaPoint( aKeystrokeArray.Count() - 1 ).Compare( KPinyinListSeparator ) && 
            ( 0 == keyBuf.Compare ( KPinyinStar ) ) )
            {
            return EFalse;
            }
        }
    return ETrue;
    }

// ---------------------------------------------------------
// Check tome mark.
// ---------------------------------------------------------
//
void TAknFepInputStateEntryPinyinPhrase::CheckTonemarkL()
    {
    CPtiEngine* ptiengine = iOwner->PtiEngine();
    MAknFepUICtrlPinyinPopup* popup = UIContainer()->PinyinPopupWindow();
    CDesCArrayFlat* keystrokeArray = popup->KeystrokeArray();
    CDesCArrayFlat* inEffectKeystrokeArray = popup->InEffectKeystrokeArray();
    CDesCArrayFlat* showKeystrokeArray = popup->ShowKeystrokeArray();
    CDesCArrayFlat* spelling = popup->OptimizeSpelling();

    TInt tonemarkCount = 0;
    TInt spellTonemarkCount = 0;
    TInt keystrokeStarCount = 0;

    TInt offset = 0;
    TInt i = 0;
    TBool checkReturn = EFalse;
    
    TBuf<1> buf;
    TBuf<1> lastTonemark;
    TBuf<1> lastSpellTonemark;
    TBuf<1> tonmarkBuf0;
    TBuf<1> tonmarkBuf1;
    TBuf<1> tonmarkBuf2;
    TBuf<1> tonmarkBuf3;
    TBuf<1> tonmarkBuf4;
    TBuf<KMaxPinyinLength> spellBuf;
    
    tonmarkBuf0.Append( KPinyinTone0Valid );
    tonmarkBuf1.Append( KPinyinTone1Valid );
    tonmarkBuf2.Append( KPinyinTone2Valid );
    tonmarkBuf3.Append( KPinyinTone3Valid );
    tonmarkBuf4.Append( KPinyinTone4Valid );
    
    if ( 0 == inEffectKeystrokeArray->Count() )
        {
        popup->SetTonemarkState( EFalse );
        return;
        }
    
    if ( keystrokeArray->Count() > inEffectKeystrokeArray->Count() )
        {
        popup->SetTonemarkState( EFalse );
        return;
        }
    
    for ( i = 0; i < showKeystrokeArray->Count(); ++i )
        {
        buf.Copy( showKeystrokeArray->MdcaPoint( i ) );
        if ( 0 == buf.Compare( tonmarkBuf0 ) )
            {
            tonemarkCount = tonemarkCount + 1;
            lastTonemark.Copy( showKeystrokeArray->MdcaPoint( i ) );
            }
        else if ( 0 == buf.Compare( tonmarkBuf1 ) )
            {
            tonemarkCount = tonemarkCount + 1;
            lastTonemark.Copy( showKeystrokeArray->MdcaPoint( i ) );
            }
        else if ( 0 == buf.Compare( tonmarkBuf2 ) )
            {
            tonemarkCount = tonemarkCount + 1;
            lastTonemark.Copy( showKeystrokeArray->MdcaPoint( i ) );
            }
        else if ( 0 == buf.Compare( tonmarkBuf3 ) )
            {
            tonemarkCount = tonemarkCount + 1;
            lastTonemark.Copy( showKeystrokeArray->MdcaPoint( i ) );
            }
        else if ( 0 == buf.Compare( tonmarkBuf4 ) )
            {
            tonemarkCount = tonemarkCount + 1;
            lastTonemark.Copy( showKeystrokeArray->MdcaPoint( i ) );
            }
        }
    
    if ( 0 == tonemarkCount )
        {
        popup->SetTonemarkState( ETrue );
        return;
        }

    for( i = 0; i < inEffectKeystrokeArray->Count(); ++i )
        {
        if ( 0 == inEffectKeystrokeArray->MdcaPoint( 
            inEffectKeystrokeArray->Count() - 1 - i ).Compare( KPinyinStar ) )
            {
            keystrokeStarCount = keystrokeStarCount + 1;
            }
        else
            {
            break;
            }
        }
    if ( keystrokeStarCount > 1 )
        {
        ptiengine->DeleteKeyPress();
        }
    
    if ( keystrokeStarCount > KMaxStarCount )
        {
        offset = 1;
        for ( i = 0; i < KMaxStarCount; ++i )
            {
            keystrokeArray->Delete( keystrokeArray->Count() - 1 );
            inEffectKeystrokeArray->Delete( inEffectKeystrokeArray->Count() - 1 );
            }
        }
    else
        {
        offset = keystrokeStarCount;
        }
    
    if ( 0 == offset )
        {
        popup->SetTonemarkState( ETrue );
        return;
        }
    else
        {
        for( i = 0; i < offset; ++i )
            {
            ptiengine->IncrementToneMark( ETrue );
            spelling->Reset();
            spelling->Compress();
            ptiengine->GetPhoneticSpellingsL(*spelling);
            for ( TInt j = 0; j < spelling->Count(); ++j )
                {
                spellTonemarkCount = 0;
                spellBuf.Copy( spelling->MdcaPoint( j ) );
                for ( TInt jj = 0; jj < spellBuf.Length(); ++jj )
                    {
                    if ( 0 == spellBuf.Mid( jj, 1 ).Compare( tonmarkBuf0 ) )
                        {
                        spellTonemarkCount = spellTonemarkCount + 1;
                        lastSpellTonemark.Copy( tonmarkBuf0 );
                        }
                    else if ( 0 == spellBuf.Mid( jj, 1 ).Compare( tonmarkBuf1 ) )
                        {
                        spellTonemarkCount = spellTonemarkCount + 1;
                        lastSpellTonemark.Copy( tonmarkBuf1 );
                        }
                    else if ( 0 == spellBuf.Mid( jj, 1 ).Compare( tonmarkBuf2 ) )
                        {
                        spellTonemarkCount = spellTonemarkCount + 1;
                        lastSpellTonemark.Copy( tonmarkBuf2 );
                        }
                    else if ( 0 == spellBuf.Mid( jj, 1 ).Compare( tonmarkBuf3 ) )
                        {
                        spellTonemarkCount = spellTonemarkCount + 1;
                        lastSpellTonemark.Copy( tonmarkBuf3 );
                        }
                    else if ( 0 == spellBuf.Mid( jj, 1 ).Compare( tonmarkBuf4 ) )
                        {
                        spellTonemarkCount = spellTonemarkCount + 1;
                        lastSpellTonemark.Copy( tonmarkBuf4 );
                        }
                    }
                
                if ( ( tonemarkCount != spellTonemarkCount ) ||
                    ( 0 != lastSpellTonemark.Compare( lastTonemark ) ))
                    {
                    checkReturn = EFalse;
                    break;
                    }
                else
                    {
                    checkReturn = ETrue;
                    }
                }
            if ( checkReturn )
                {
                break;
                }
            }
        }
    
    spelling->Reset();
    spelling->Compress();
    
    if ( checkReturn )
        {
        popup->SetTonemarkState( ETrue );
        return;
        }
    else
        {
        popup->SetTonemarkState( EFalse );
        return;
        }
    
    }

// ---------------------------------------------------------
// Get change state.
// ---------------------------------------------------------
//
TBool TAknFepInputStateEntryPinyinPhrase::GetChangeState()
    {
    MAknFepUICtrlPinyinPopup* popup = UIContainer()->PinyinPopupWindow();
    CDesCArrayFlat* KeystrokeArray = popup->KeystrokeArray();
    CDesCArrayFlat* inEffectKeystrokeArray = popup->InEffectKeystrokeArray();
    TInt firstIndex = -1;
    TInt count = inEffectKeystrokeArray->Count() - 1;
    

    
    if ( 2 > inEffectKeystrokeArray->Count() )
        {
        return ETrue;
        }
    
    for ( TInt i = count; i >= 0; i-- )
        {
        if ( 0 != inEffectKeystrokeArray->MdcaPoint( i ).
            Compare( KPinyinStar ) )
            {
            firstIndex = i;
            break;
            }
        }
    
    if ( ( 0 == firstIndex ) && ( !popup->GetTonemarkState() ) )
        {
        return EFalse;
        }
    
    return ETrue;
    }

// ---------------------------------------------------------
// Append show keystroke.
// ---------------------------------------------------------
//
void TAknFepInputStateEntryPinyinPhrase::ShowKeystrokeAppendL( 
                                          CDesCArrayFlat& aShowKeystrokeArray, 
                                          const CDesCArrayFlat& aKeystrokeArray, 
                                          const TDesC& aPinyinToneMark )
    {
    TInt showCount = 0;
    TInt count = 0;
    TBuf<1> buf;
    count = aKeystrokeArray.Count();
    showCount = aShowKeystrokeArray.Count();
    
    if ( ( count > 2 ) && ( showCount > 1 ) )
        {
        if ( 0 == aKeystrokeArray.MdcaPoint( count - 2 ).Compare( KPinyinStar ) )
            {
            aShowKeystrokeArray.Delete( showCount - 1 );
            aShowKeystrokeArray.Compress();
            aShowKeystrokeArray.AppendL( aPinyinToneMark );
            }
        else
            {
            aShowKeystrokeArray.AppendL( aPinyinToneMark );
            }
        }
    else
        {
        aShowKeystrokeArray.AppendL( aPinyinToneMark );
        }
    }

// ---------------------------------------------------------
// change  CBA.
// ---------------------------------------------------------
//
void TAknFepInputStateEntryPinyinPhrase::ChangeCbaL()
    {
    MAknFepUICtrlPinyinPopup* popup = UIContainer()->PinyinPopupWindow();
    TInt lastRes = popup->GetLastResouce();
    if ( lastRes == R_AKNFEP_SOFTKEYS_PHRASE_CREATION_SELECT_CANCEL_SELECT )
        {
        return;
        }
    iOwner->FepMan()->UpdateCbaL( R_AKNFEP_SOFTKEYS_PHRASE_CREATION_SELECT_CANCEL_SELECT );
    popup->SetLastResouce( R_AKNFEP_SOFTKEYS_PHRASE_CREATION_SELECT_CANCEL_SELECT );
    }

// End of file