textinput/peninputvkbcn/ctrlsrc/peninputvkbcompositionfield.cpp
changeset 0 eb1f2e154e89
child 19 5e18d8c489d6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/textinput/peninputvkbcn/ctrlsrc/peninputvkbcompositionfield.cpp	Tue Feb 02 01:02:04 2010 +0200
@@ -0,0 +1,1479 @@
+/*
+* 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:  vkb conposition field implementation
+*
+*/
+
+
+#include <peninputlayoutbasecontrol.h>
+
+#include <AknsDrawUtils.h> 
+#include <barsread.h>
+
+#include "peninputvkbcompositionfield.h"
+
+#include "peninputvkbevent.h"
+
+#include "peninputvkb.hrh"
+
+#include "peninputvkbdataprovider.h"
+
+#include "AknFepVkbPinyinAnalyser.h"
+
+#include "AknFepVkbPinyinAnalyserDb.h"
+#include "peninputvkbdatamgr.h"
+
+//Tone make
+const TUint16 KCharToneMarkZhuyin1 = 0x0020;
+const TUint16 KCharToneMarkPinyin1 = 0x02C9;
+const TUint16 KCharToneMark2 = 0x02CA;
+const TUint16 KCharToneMark3 = 0x02C7;
+const TUint16 KCharToneMark4 = 0x02CB;
+const TUint16 KCharToneMark5 = 0x02D9;
+
+const TInt32 KInvalidResId = -1;
+
+const TInt KInvalidImg = -1 ;
+
+//Manual stroke separator char
+const TUint16 KStrokeManuSeparator = 0x2022;
+//Manul separator char       
+const TUint KManulSeparator = 0x0027; // "'"
+//Manul separator char       
+const TUint KAutoSeparator = 0x002e;   //"."
+
+
+_LIT(KWildChar, "\xFF1F");
+
+_LIT(KInternalWildChar, "\x002B");
+
+// ---------------------------------------------------------
+// Helper function
+// ---------------------------------------------------------
+//
+//Don't test aKey's length, treat as programming error!
+inline TBool IsKeyToneMark(const TDesC& aKey)
+    {
+    return   (aKey[0] == KCharToneMarkZhuyin1 ||
+              aKey[0] == KCharToneMarkPinyin1 ||
+              aKey[0] == KCharToneMark2 ||
+              aKey[0] == KCharToneMark3 ||
+              aKey[0] == KCharToneMark4 ||
+              aKey[0] == KCharToneMark5 );
+    }
+    
+inline TBool IsKeyAutoSeparator(const TDesC& aKey)
+    {
+    return (aKey[0] == KAutoSeparator );
+    }
+
+inline TBool IsKeyManualSeparator(const TDesC& aKey)
+    {
+    return (aKey[0] == KManulSeparator || aKey[0] == KStrokeManuSeparator);
+    }
+    
+inline TBool IsKeyInternalWildChar(const TDesC& aKey)
+    {
+    return (aKey[0] == KInternalWildChar()[0] );
+    }
+
+
+    
+// ---------------------------------------------------------
+// Constructor
+// ---------------------------------------------------------
+//
+CCompositionElement* CCompositionElement::NewLC(const TDesC& aKey)
+    {
+    TInt keyType = EElementTypeCompositionChar;   
+    if( IsKeyAutoSeparator(aKey) )
+        {
+        keyType = EElementTypeAutoSeparator;
+        }
+    else if( IsKeyManualSeparator(aKey) )
+        {
+        keyType = EElementTypeManualSeparator;
+        }
+    else if( IsKeyToneMark(aKey) )
+        {
+        keyType = EElementTypeTonemark;
+        }
+
+    CCompositionElement* self = new (ELeave) CCompositionElement(keyType);
+    
+    CleanupStack::PushL(self);
+
+    if( IsKeyInternalWildChar(aKey) )
+        {
+        self->BaseConstructL(KWildChar);
+        }
+    else
+        {
+        self->BaseConstructL(aKey);
+        }
+    
+    
+    return self;
+    }
+
+// ---------------------------------------------------------
+// Constructor
+// ---------------------------------------------------------
+//
+CCompositionElement::CCompositionElement(TInt aKeyType)
+:iKeyType(aKeyType)
+    {
+    }
+    
+// ---------------------------------------------------------
+// Constructor
+// ---------------------------------------------------------
+//
+void CCompositionElement::BaseConstructL(const TDesC& aKey)
+    {
+    iKey = aKey.AllocL();
+    }
+    
+// ---------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------
+//
+CCompositionElement::~CCompositionElement()
+    {
+    delete iKey;
+    }
+
+// ---------------------------------------------------------
+// Get original input length
+// ---------------------------------------------------------
+//
+TInt CCompositionElement::OriginalCount() const
+    {
+    TInt result = (IsAutoSeparator() || !iKey)? 0 : iKey->Length();
+    
+    return result;
+    }
+    
+// ---------------------------------------------------------
+// UnConvert and insert the original elements back
+// ---------------------------------------------------------
+//
+TInt CCompositionElement::UndoConvertL(CAknFepVkbCompositionField* /*aField*/, TInt /*aStartPos*/)
+    {
+    return 0;
+    }
+
+// ---------------------------------------------------------
+// Get the content  of original input
+// ---------------------------------------------------------
+//
+const CCompositionElement* CCompositionElement::OriginalContent( TInt /*aIndex*/ ) const
+    {
+    return NULL;
+    }
+
+// ---------------------------------------------------------
+// Constructor
+// ---------------------------------------------------------
+//
+CCompositionConvertedElement* CCompositionConvertedElement::NewLC(const TDesC& aKey)
+    {
+    CCompositionConvertedElement* self = new (ELeave) CCompositionConvertedElement();
+    
+    CleanupStack::PushL(self);
+    self->ConstructL(aKey);
+    
+    return self;
+    }
+
+// ---------------------------------------------------------
+// Constructor
+// ---------------------------------------------------------
+//
+CCompositionConvertedElement::CCompositionConvertedElement()
+:CCompositionElement(EElementTypeConvertedChar)
+    {
+    }
+    
+// ---------------------------------------------------------
+// Constructor
+// ---------------------------------------------------------
+//
+void CCompositionConvertedElement::ConstructL(const TDesC& aKey)
+    {
+    BaseConstructL(aKey);
+    }
+
+// ---------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------
+//
+CCompositionConvertedElement::~CCompositionConvertedElement()
+    {
+    iOriginalElements.ResetAndDestroy();
+    iOriginalElements.Close();
+    }
+
+// ---------------------------------------------------------
+// UnConvert and insert the original elements back
+// ---------------------------------------------------------
+//
+TInt CCompositionConvertedElement::UndoConvertL(CAknFepVkbCompositionField* aField, 
+                                               TInt aStartPos)
+    {
+    ASSERT(aStartPos >=0 && aStartPos < aField->Length());
+    
+    TInt length = iOriginalElements.Count();
+    
+    for (TInt i = length -1 ; i >= 0 ; i --)
+        {
+        aField->InsertL(aStartPos, iOriginalElements[i] );
+        
+        //ownership transfer to CAknFepVkbCompositionField
+        iOriginalElements.Remove(i);
+        }
+        
+    return length;
+    }
+
+// ---------------------------------------------------------
+// Append an original element
+// ---------------------------------------------------------
+//
+void CCompositionConvertedElement::AppendOriginal(const CCompositionElement* aElements)
+    {
+    iOriginalElements.Append(aElements);
+    }
+
+// ---------------------------------------------------------
+// Get original input length
+// ---------------------------------------------------------
+//
+TInt CCompositionConvertedElement::OriginalCount() const
+    {
+    return iOriginalElements.Count();
+    }
+    
+// ---------------------------------------------------------
+// Get the content  of original input
+// ---------------------------------------------------------
+//
+const CCompositionElement* CCompositionConvertedElement::OriginalContent( TInt aIndex ) const
+    {
+    if( aIndex < 0 || aIndex > iOriginalElements.Count() - 1 )
+        {
+        return NULL;
+        }
+    return iOriginalElements[aIndex];
+    }
+    
+// ---------------------------------------------------------
+// Constructor
+// ---------------------------------------------------------
+//
+CAknFepVkbCompositionField* CAknFepVkbCompositionField::NewL(TInt aMaxLength,
+                                                            TRect aRect,
+                                                            CFepUiLayout* aUiLayout,
+                                                            TInt aControlId,
+                                                            MAknFepVkbDataProvider* aDataProvider )
+    {
+    CAknFepVkbCompositionField* self = new (ELeave) CAknFepVkbCompositionField(aMaxLength,
+                                                                              aRect,
+                                                                              aUiLayout,
+                                                                              aControlId,
+                                                                              aDataProvider );
+    
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    
+    return self;
+    }
+
+// ---------------------------------------------------------
+// C++ Constructor
+// ---------------------------------------------------------
+//
+CAknFepVkbCompositionField::CAknFepVkbCompositionField(TInt aMaxLength,
+                                                      TRect aRect,
+                                                      CFepUiLayout* aUiLayout,
+                                                      TInt aControlId,
+                                                      MAknFepVkbDataProvider* aDataProvider)
+: CFepLayoutEditAreaBase(aRect,aUiLayout,aControlId)
+    {
+    //iMaxLength <=0 means no max length limited
+    iMaxLength = aMaxLength;
+    iCurrentPos = 0;
+    iFirstSegment = NULL;
+    iDataProvider = aDataProvider;
+    
+    iIsValidSpells = EFalse;
+
+    }
+
+// ---------------------------------------------------------
+// 2nd Constructor
+// ---------------------------------------------------------
+//
+void CAknFepVkbCompositionField::ConstructL()
+    {
+    //No cursor in construction
+    BaseConstructL();
+    //iBufferForCommit = HBufC::NewL(KDefaultLen);
+ 
+    
+    CPinyinAnalyserDbFeed* pZhuyinDb = CPinyinAnalyserDbFeed::NewL( EPinyinAnalyserTypeZhuyin );
+    CleanupStack::PushL( pZhuyinDb );
+    iZhuyinAnalyser = CAknFepVkbPinyinAnalyser::NewL( pZhuyinDb );
+    CleanupStack::Pop( pZhuyinDb );
+    
+    CPinyinAnalyserDbFeed* pPinyinDb = CPinyinAnalyserDbFeed::NewL( EPinyinAnalyserTypePinyin );
+    CleanupStack::PushL( pPinyinDb );
+    iPinyinAnalyser = CAknFepVkbPinyinAnalyser::NewL( pPinyinDb );
+    CleanupStack::Pop( pPinyinDb );
+    
+    
+    }
+
+// ---------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------
+//
+CAknFepVkbCompositionField::~CAknFepVkbCompositionField()
+    {
+    iElements.ResetAndDestroy();
+    iElements.Close();
+    //delete iBufferForCommit;
+    delete iFirstSegment;
+    delete iZhuyinAnalyser;
+    delete iPinyinAnalyser;
+    }
+
+// ---------------------------------------------------------
+// Handle events in
+// ---------------------------------------------------------
+//
+void CAknFepVkbCompositionField::HandleControlEvent(TInt aEventType, 
+                                                             CFepUiBaseCtrl* /*aCtrl*/, 
+                                                             const TDesC& aEventData)
+    {
+    TBuf<4> buf;    
+    switch (aEventType)
+        {
+        case EEventVirtualKeyUp:
+            {
+            TKeyEvent* event = (TKeyEvent*) aEventData.Ptr();
+            buf.Append(TChar(event->iScanCode));	
+            //assume keys are insertable
+            TRAP_IGNORE(HandleInsertL(buf));
+            break;
+            }
+        case EVkbEventKeySpace:
+            {
+            TInt imLayout = iDataProvider->RequestData(EAknFepDataTypeIMLayout);
+            if (imLayout == EAknFepVkbImCnCangjie)
+                {
+                if(!IsValidSpell())
+                    {
+                    break;
+                    }
+                
+                RBuf firstCandidate(static_cast<CAknFepVkbDataMgr*>(iDataProvider)->Candidates()[0]); 
+                firstCandidate.AppendNum( 0 );
+                TRAP_IGNORE(HandleConvertedResultL(firstCandidate));
+                }
+            else
+                {
+                TKeyEvent* event = (TKeyEvent*) aEventData.Ptr();
+                buf.Append(TChar(event->iCode));	
+                //assume keys are insertable
+                TRAP_IGNORE(HandleInsertL(buf));
+                }
+            break;
+            }        
+        case EVkbEventKeyEnter:
+            TRAP_IGNORE(HandleFlushL());        
+            break;
+        case EPeninputLayoutEventBack:
+            TRAP_IGNORE(HandleBackL());
+            break;
+		case EVkbEventLeftArrow:
+			{
+		    TCursorSelection currentCursorSelection;
+		    currentCursorSelection = Selection();
+		    
+		    if (ETrue)
+		        {
+	            if (currentCursorSelection.iCursorPos == 0)
+	                {
+	                currentCursorSelection.iCursorPos = TextLength();
+	                }
+	            else 
+	                {
+	                currentCursorSelection.iCursorPos--;
+	                if(currentCursorSelection.iCursorPos > 0 &&
+						iElements[currentCursorSelection.iCursorPos - 1]->IsAutoSeparator())
+	                    {
+	                    currentCursorSelection.iCursorPos--;		                
+		                }
+	                }
+		        }
+		        
+		    TCursorSelection movedCursor(currentCursorSelection.iCursorPos, 
+                                     currentCursorSelection.iCursorPos);
+		    UpdateCursorSelection(movedCursor);
+		    break;
+			}
+		case EVkbEventRightArrow:
+			{
+			TCursorSelection currentCursorSelection;
+			currentCursorSelection = Selection();
+
+		    if (currentCursorSelection.iCursorPos == TextLength())
+		        {
+		        currentCursorSelection.iCursorPos = 0;
+		        }
+		    else 
+		        {
+		        currentCursorSelection.iCursorPos++;
+				if(currentCursorSelection.iCursorPos < TextLength() &&
+					iElements[currentCursorSelection.iCursorPos - 1]->IsAutoSeparator())
+                  {
+                  currentCursorSelection.iCursorPos++;
+                  }
+		        
+		        }	        
+
+			TCursorSelection movedCursor(currentCursorSelection.iCursorPos, 
+                                   currentCursorSelection.iCursorPos);
+			UpdateCursorSelection(movedCursor);
+			break;
+			}
+        case EEventControlFocusLost:
+            SetFocus(EFalse);
+            break;
+        case EEventControlFocusGained:
+            SetFocus();
+            break;
+        case EVkbEventCompFieldAnalysisResponse:
+            TRAP_IGNORE(HandleAnalysisResponseL(aEventData));
+            break;
+        case EVkbEventCandidateSelected:
+            TRAP_IGNORE(HandleConvertedResultL(aEventData));
+            break;
+        case EVkbEventWindowClose:
+        case EVkbEventClearContent:
+            TRAP_IGNORE(ClearTextL());
+            break;
+        default:
+            break;
+        }
+    }
+
+// ---------------------------------------------------------
+// Count of elements
+// ---------------------------------------------------------
+//
+TInt CAknFepVkbCompositionField::Length() const
+    {
+    return iElements.Count();
+    }
+
+// ---------------------------------------------------------
+// Set warning color
+// ---------------------------------------------------------
+//
+void CAknFepVkbCompositionField::SetWarningColor(const TRgb& aColor) 
+    {
+    iWarningColor = aColor;
+    }
+    
+// ---------------------------------------------------------
+// Set normal color
+// ---------------------------------------------------------
+//
+void CAknFepVkbCompositionField::SetNormalColor(const TRgb& aColor) 
+    {
+    iNormalColor = aColor;
+    }    
+
+// ---------------------------------------------------------
+// Insert a key
+// ---------------------------------------------------------
+//
+void CAknFepVkbCompositionField::HandleInsertL(const TDesC& aKey)
+    {
+    CCompositionElement *element = CCompositionElement::NewLC(aKey);
+    
+    iCurrentPos = DisplayPosToInternaPos( iSelectedCompositionText.iCursorPos );              
+    
+    TBool updateText = EFalse;  
+    //remove selection first
+    if( iSelectedCompositionText.Length() > 0)
+        {
+        RemoveSelection();
+        updateText = ETrue;
+        }
+        
+    if (IsAllowedInsert(element))
+        {
+        InsertElementL(element);
+        CleanupStack::Pop(element);
+        SendAnalysisRequestL();
+        updateText = EFalse;
+        }
+    else
+        {
+        // If select all the chars in composition and input an invalid char,
+        // go to standby status.
+        if(Length() == 0)
+            {
+            ReportEvent(EVkbEventCompFieldNoChars);
+            ClearTextL();
+            }
+        else
+            {
+            SendAnalysisRequestL();
+            }
+            
+        CleanupStack::PopAndDestroy(element);
+        }
+        
+    if( updateText )
+        {
+        UpdateTextL();
+        }
+    }
+
+// ---------------------------------------------------------
+// Insert an element
+// ---------------------------------------------------------
+//
+//insert is only insert 
+void CAknFepVkbCompositionField::InsertElementL(const CCompositionElement* aElement)
+    {
+    if( IsReplaceFront(aElement) )
+        {
+        Remove(iCurrentPos - 1, 1);        
+        }
+    else if( IsReplaceBack(aElement) )
+        {
+        Remove(iCurrentPos, 1);        
+        }      
+
+    InsertL(iCurrentPos, aElement);  
+    }
+    
+// ---------------------------------------------------------
+// Clear text
+// ---------------------------------------------------------
+//
+void CAknFepVkbCompositionField::ClearTextL()
+    {
+    Clear();
+    
+    UpdateTextL();
+    
+    iNeedCreateWord = EFalse;
+    iConvertedElement = 0;
+    iIsValidSpells = ETrue;
+    }
+
+// ---------------------------------------------------------
+// Submit all text
+// ---------------------------------------------------------
+//
+void CAknFepVkbCompositionField::HandleFlushL()
+    {
+    // Don't response when CangJieVkb state
+    if ( iDataProvider->RequestData( EAknFepDataTypeIMLayout )  == EAknFepVkbImCnCangjie )
+        {
+        return;
+        }
+    
+    HBufC* temp = HBufC::NewLC(iElements.Count());
+    TPtr ptr = temp->Des();
+    
+    for (TInt i = 0; i < iElements.Count(); i++)
+        {
+        if (!iElements[i]->IsTypeOf(EElementTypeAutoSeparator))
+            {
+            ptr.Append(*iElements[i]->Key());
+            }
+        }
+        
+    if (ptr.Length() > 0)
+        {
+        ReportEvent(EVkbEventCompFieldDataFlush, *temp);
+        ClearTextL();
+        }
+        
+    CleanupStack::PopAndDestroy(temp);
+    }
+    
+// ---------------------------------------------------------
+// Handle back key
+// ---------------------------------------------------------
+//
+void CAknFepVkbCompositionField::HandleBackL()
+    {
+    if (Length() == 0)
+        {
+        return;
+        }
+    
+    iCurrentPos = DisplayPosToInternaPos( iSelectedCompositionText.iCursorPos );
+    
+    if(iSelectedCompositionText.Length() > 0)
+        {
+        // update cursor position
+        RemoveSelection();
+        }
+    else
+        {
+        TInt pos = iCurrentPos - 1;
+        if ( iCurrentPos == 0 )
+            {//nothing to delete
+            return;
+            }
+            
+        //assure the element before cursor is not an auto separator
+        //cursor can not be put right after an auto separator
+        ASSERT(!iElements[pos]->IsAutoSeparator());
+
+        if (!iElements[pos]->IsTypeOf(EElementTypeConvertedChar))
+            {
+            Remove(pos, 1, ETrue);
+            ReFomatAfterDelete();
+            }
+        else
+            {
+            //current element is converted element, undo convert 
+            TInt len = iElements[pos]->UndoConvertL(this, pos);
+            iCurrentPos -= ( len + 1 );
+            if ( iCurrentPos < 0 )
+                {
+                iCurrentPos = 0;
+                }
+            //remove the converted element
+            Remove(pos + len, 1);
+            iConvertedElement--;
+            if( iConvertedElement == 0 && iNeedCreateWord)
+                {
+                iNeedCreateWord = EFalse;
+                }
+            }
+        }
+
+    if (Length() == 0)
+        {
+        ReportEvent(EVkbEventCompFieldNoChars);
+        ClearTextL();
+        }
+    else
+        {
+        //no composition to analysis
+        if (IsFinishComposition())
+            {
+            UpdateTextL();
+            ReportEvent(EVkbEventCompFieldSubmit, iDisplayText);
+            ClearTextL();
+            }
+        else
+            {
+            SendAnalysisRequestL();
+            }
+        }
+    }
+    
+// ---------------------------------------------------------
+// Handle analysis response
+// ---------------------------------------------------------
+//
+void CAknFepVkbCompositionField::HandleAnalysisResponseL(const TDesC& aCompText)
+    {
+    
+    if ( ( iDataProvider->RequestData( EAknFepDataTypeIMLayout )  == EAknFepVkbImCnZhuyin
+        || iDataProvider->RequestData( EAknFepDataTypeIMLayout )  == EAknFepVkbImCnPinyin ) )
+    {
+    if( iIsValidSpells )
+        {
+        SetTextColor(iNormalColor);
+        }
+    else
+        {
+        SetTextColor(iWarningColor);    
+        }
+    }
+            
+    if ( iDataProvider->RequestData( EAknFepDataTypeIMLayout )  == EAknFepVkbImCnCangjie
+        || iDataProvider->RequestData( EAknFepDataTypeIMLayout )  == EAknFepVkbImCnStroke )
+    {
+    if ( aCompText.Length() == 0 )
+        {
+        iIsValidSpells  = EFalse;
+        SetTextColor(iWarningColor);
+        }
+    else
+        {
+        iIsValidSpells  = ETrue;
+        SetTextColor(iNormalColor);
+        }
+
+    }
+            
+    if (aCompText.Length() > 0)
+        {
+        //merge the original elements with engine returned strings
+        //remove auto separator in orignal elements and insert auto separator
+        //add by engine 
+        TInt origin = iFirstSegmentOffset;
+        TInt engine = 0;
+        while( engine < aCompText.Length() && origin < iElements.Count() )
+            {
+            if( *(iElements[origin]) == aCompText[engine] )
+                {
+                origin++;
+                engine++;
+                }
+            else if( iElements[origin]->IsAutoSeparator() )
+                {
+                Remove(origin, 1);
+                iFirstSegmentLength--;
+                }
+            else if( IsKeyAutoSeparator(aCompText.Mid(engine,1)) )
+                {
+                if( !iElements[origin]->IsManualSeparator() )
+                    {
+                	CCompositionElement* element = 
+                                             CCompositionElement::NewLC(aCompText.Mid(engine, 1));
+                    InsertL(origin, element);
+                    CleanupStack::Pop(element);
+                    iFirstSegmentLength++;
+                    }
+                origin++;
+                engine++;
+                }
+            else
+                {
+                ASSERT(0);                
+                }
+            }
+        //judge if invalid tone mark exist in iElements
+        if(aCompText.Length() < iElements.Count() - iFirstSegmentOffset)
+            {
+            if(origin <= iElements.Count() - 1 && iElements[origin]->IsTonemark())
+                {
+                iIsValidSpells  = EFalse;
+                SetTextColor(iWarningColor);                
+                }
+            }
+        }
+
+    UpdateTextL();
+    Draw();
+    UpdateArea(Rect(),EFalse);
+    }
+    
+// ---------------------------------------------------------
+// Handle converted result
+// ---------------------------------------------------------
+//
+void CAknFepVkbCompositionField::HandleConvertedResultL(const TDesC& aConvertedText)
+    {
+    TInt index = iFirstSegmentOffset;
+    
+    //the last aConvertedText is the cell No of candidate list
+    for (TInt i = 0; i < aConvertedText.Length() - 1; i ++)
+        {
+        CCompositionConvertedElement* element = 
+                                     CCompositionConvertedElement::NewLC(aConvertedText.Mid(i, 1));
+        
+        TBool goOn = ETrue;
+                
+        while (index < Length() && !iElements[index]->IsTypeOf(EElementTypeConvertedChar) && goOn)
+            {
+            goOn = !iElements[index]->IsAuxilian();
+            
+            if( iElements[index]->IsAutoSeparator() )
+                {
+                Remove(index, 1); //remove automatic separator
+                }
+            else
+                {
+                element->AppendOriginal(iElements[index]); //transfer ownership to converted element                    
+                Remove(index, 1, EFalse); //remove the original element
+                }
+            }
+
+        //insert the converted element
+        InsertL(index, element);
+        iCurrentPos = index + 1;
+        iConvertedElement++;
+        
+        CleanupStack::Pop(element);
+        index ++;
+        }
+
+    if( IsFinishComposition() )
+        {
+        UpdateTextL();
+        ReportEvent(EVkbEventCompFieldSubmit, *iBuffer);
+        ClearTextL();
+        }
+    else
+        {
+        //user takes part in composition
+        iNeedCreateWord = ETrue;
+        SendAnalysisRequestL();
+        }
+    }
+    
+// ---------------------------------------------------------
+// Is there need to create new word
+// ---------------------------------------------------------
+//
+TBool CAknFepVkbCompositionField::NeedCreateWord()
+	{
+	return iNeedCreateWord && iElements.Count() <= KCpiMaxInputPhraseLen;
+	}
+    
+// ---------------------------------------------------------
+// Remove elements
+// ---------------------------------------------------------
+//
+void CAknFepVkbCompositionField::Remove(TInt aStartPos, TInt aLength, TBool aDestroy)
+    {
+    ASSERT (aStartPos >= 0 && aStartPos < Length());
+        
+    TInt index = Min(aStartPos + aLength - 1, Length() -1);
+
+    //adjust cursor position if necessary
+    if( iCurrentPos > aStartPos)
+        {
+        iCurrentPos -= index - aStartPos + 1;    
+        }
+            
+    for (TInt i = index; i >= aStartPos; i --)    
+        {
+        if (aDestroy)
+            {
+            delete iElements[i];
+            }
+            
+        iElements.Remove(i);
+        }          
+    }
+
+// ---------------------------------------------------------
+// Insert an element
+// ---------------------------------------------------------
+//
+void CAknFepVkbCompositionField::InsertL(TInt aPos, const CCompositionElement* aElement)
+    {
+    ASSERT (aPos >=0 && aPos <= Length());
+    iElements.Insert(aElement, aPos);    
+    if( iCurrentPos >= aPos )
+        {
+        iCurrentPos ++;
+        }
+    }
+
+// ---------------------------------------------------------
+// Clear element
+// ---------------------------------------------------------
+//
+void CAknFepVkbCompositionField::Clear()
+    {
+    if (Length() == 0)
+        {
+        return;
+        }
+    
+    iCurrentPos = 0;
+    iElements.ResetAndDestroy();
+    }
+        
+// ---------------------------------------------------------
+// Generate first segment
+// ---------------------------------------------------------
+//
+void CAknFepVkbCompositionField::GetFirstSegmentL()
+    {    
+    delete iFirstSegment;
+    iFirstSegment = NULL;
+    iFirstSegment = HBufC::NewL(Length());
+    TPtr ptr = iFirstSegment->Des();
+
+    iFirstSegmentOffset = 0;
+    iFirstSegmentLength = 0;
+    
+    TInt i = 0;
+    for (i = 0; i < Length(); i++)
+        {
+        //start from the first unconverted element
+        if (!iElements[i]->IsTypeOf(EElementTypeConvertedChar) &&
+            !iElements[i]->IsSeparator() )
+            {
+            iFirstSegmentOffset = i;
+            ptr.Append((*iElements[i++]->Key()));
+            iFirstSegmentLength++;
+            while( i < Length() && !iElements[i]->IsTypeOf(EElementTypeConvertedChar)  )
+                {
+                if( !iElements[i]->IsAutoSeparator() )
+                    {
+                    ptr.Append(*(iElements[i]->Key()));
+                    }
+                    
+                i++;
+                }
+            
+            break;
+            }
+        }
+    
+    iFirstSegmentLength = i - iFirstSegmentOffset;
+    if( ptr.Length() > 0 && 
+        IsKeyManualSeparator(ptr.Right(1)) )
+        {
+        ptr.SetLength(ptr.Length() - 1);
+        iFirstSegmentLength--;
+        }
+    }
+
+// ---------------------------------------------------------
+// Update editbase cursor and text
+// ---------------------------------------------------------
+// assume the current all elements are valid
+void CAknFepVkbCompositionField::UpdateTextL()
+    {
+    HBufC* displayText = HBufC::NewLC(iElements.Count());
+    //adjust cursor to avoid autosepartor
+    if( iCurrentPos > 0 && iElements[iCurrentPos - 1]->IsAutoSeparator() )
+        {
+        iCurrentPos--;
+        }
+        
+    TInt pos = iCurrentPos;
+    for( TInt i = 0; i < iElements.Count(); ++i )
+        {
+        //deal with manual separator 
+        if( iElements[i]->IsManualSeparator() )
+            {
+            //valid format ensure i > 0
+            if( iElements[i - 1]->IsTypeOf(EElementTypeConvertedChar))
+                {
+                iElements[i]->Hide(ETrue);
+                }
+            else if( i + 1 < iElements.Count() && 
+                     iElements[i + 1]->IsTypeOf(EElementTypeConvertedChar) )
+                {
+                iElements[i]->Hide(ETrue);
+                }
+            else
+                {
+                iElements[i]->Hide(EFalse);
+                }
+            }
+        //maybe other things
+        if(iElements[i]->IsVisible())
+            {
+                {
+                displayText->Des().Append(iElements[i]->Key()->Left(1));
+                }
+            }
+        else if( i < iCurrentPos)
+            {
+            pos--;
+            }
+        }
+    
+    TFepInputContextFieldData data;
+    data.iCmd = EPeninputICFInitial;
+    data.iStartPos = 0;
+    data.iLength = displayText->Length();
+    data.iMidPos = -1;
+    data.iText.Set( *displayText );
+    data.iCurSel = TCursorSelection(pos, pos);
+    data.iCursorVisibility = ETrue;
+    data.iCursorSelVisible = ETrue;
+    SetTextL( data );
+    
+    CleanupStack::PopAndDestroy(displayText);
+    }
+
+// ---------------------------------------------------------
+// Adjust cursor when pen down
+// ---------------------------------------------------------
+//
+void CAknFepVkbCompositionField::AdjustSelectedCompositionText(
+                                              TInt& aPositionOfInsertionPointInBuffer)
+    {
+    TInt pos = DisplayPosToInternaPos(aPositionOfInsertionPointInBuffer);
+    pos--;
+    if (pos >=0 && pos < Length() && iElements[pos]->IsAutoSeparator())
+        {
+        aPositionOfInsertionPointInBuffer --;
+        }
+
+    if (aPositionOfInsertionPointInBuffer < 0)
+        {
+        aPositionOfInsertionPointInBuffer = 0;
+        }
+    }
+    
+// ---------------------------------------------------------
+// Update edit base content when scrolling
+// ---------------------------------------------------------
+//
+void CAknFepVkbCompositionField::UpdateContent(const TCursorSelection& aCursorSel)
+    {
+    TInt cursorPos = aCursorSel.iCursorPos;
+    if (cursorPos < 0 )
+        {
+        cursorPos = 0;
+        }
+    else if (cursorPos > iBuffer->Length())
+        {
+        cursorPos = iBuffer->Length();
+        }
+        
+    UpdateCursorSelection(TCursorSelection(cursorPos, aCursorSel.iAnchorPos));
+    }
+    
+// ---------------------------------------------------------
+// Is allowed insert
+// ---------------------------------------------------------
+//
+TBool CAknFepVkbCompositionField::IsAllowedInsert(const CCompositionElement* aElement)
+    {
+    if( (iCurrentPos == 0 ||
+         iElements[iCurrentPos - 1]->IsTypeOf(EElementTypeConvertedChar)) &&
+        aElement->IsAuxilian() )
+        {
+        return EFalse;
+        }
+    
+    if (aElement->IsManualSeparator())
+    	{
+    	//cursor must be larger than zero
+    	if (iElements[iCurrentPos - 1]->IsTonemark() ||
+    	    iElements[iCurrentPos - 1]->IsManualSeparator())
+    		{
+    		return EFalse;
+    		}    	
+    	if ( (iElements.Count() >= iCurrentPos + 1) && 
+    	     (iElements[iCurrentPos]->IsTonemark() ||
+    	      iElements[iCurrentPos]->IsTypeOf(EElementTypeConvertedChar) ||
+    	      iElements[iCurrentPos]->IsManualSeparator()) )
+    		{
+    		return EFalse;
+    		}
+    	}
+
+    if ( IsReplaceFront(aElement) || 
+         IsReplaceBack(aElement))
+        {
+        return ETrue;
+        }
+        
+    TInt count = 0;    
+    for (TInt i = 0; i <Length(); i++)
+        {
+        count += iElements[i]->OriginalCount();
+        }
+        
+    return (count < iMaxLength);
+    }
+
+// ---------------------------------------------------------
+// Send analysis request
+// ---------------------------------------------------------
+//
+void CAknFepVkbCompositionField::SendAnalysisRequestL()
+    {
+    GetFirstSegmentL();
+    CAknFepVkbPinyinAnalyser* pAnalyser = NULL;
+    
+    if( iDataProvider->RequestData( EAknFepDataTypeIMLayout )  == EAknFepVkbImCnZhuyin )
+        {
+        pAnalyser = iZhuyinAnalyser;
+        }
+    else if ( iDataProvider->RequestData( EAknFepDataTypeIMLayout ) == EAknFepVkbImCnPinyin )
+        {
+        pAnalyser = iPinyinAnalyser;
+        }
+    
+    if ( pAnalyser )
+        {
+        iIsValidSpells = pAnalyser->AnalyzeL( *iFirstSegment );
+    
+        TPtrC compText( *pAnalyser->LastAnalysisResult() );
+        TInt origin = iFirstSegmentOffset;
+        TInt engine = 0;
+        while( engine < compText.Length() && origin < iElements.Count() )
+            {
+            if( *(iElements[origin]) == compText[engine] )
+                {
+                origin++;
+                engine++;
+                }
+            else if( iElements[origin]->IsAutoSeparator() )
+                {
+                Remove(origin, 1);
+                iFirstSegmentLength--;
+                }
+            else if( IsKeyAutoSeparator(compText.Mid(engine,1)) )
+                {
+                if( !iElements[origin]->IsManualSeparator() )
+                    {
+                	CCompositionElement* element = CCompositionElement::NewLC(compText.Mid(engine, 1));
+                    InsertL(origin, element);
+                    CleanupStack::Pop(element);
+                    iFirstSegmentLength++;
+                    }
+                origin++;
+                engine++;
+                }
+            else
+                {
+                ASSERT(0);                
+                }
+        }
+        
+        ReportEvent(EVkbEventCompFieldAnalysisReq, *pAnalyser->LastAnalysisResult() );
+        }
+    else
+        {
+        ReportEvent(EVkbEventCompFieldAnalysisReq, *iFirstSegment);
+        }
+    }
+
+// ---------------------------------------------------------
+// To test whether the all input keys are converted
+// ---------------------------------------------------------
+//
+TBool CAknFepVkbCompositionField::IsFinishComposition()
+    {
+    for (TInt i = 0; i < Length(); i++)
+        {
+        if (!iElements[i]->IsTypeOf(EElementTypeConvertedChar))
+            {
+            return EFalse;
+            }
+        }
+        
+    return ETrue;        
+    }
+
+// ---------------------------------------------------------
+// To test whether current pos element should be replaced by input one
+// ---------------------------------------------------------
+//
+TBool CAknFepVkbCompositionField::IsReplacePosition(const CCompositionElement* aElement,
+                                                   TInt aPos)
+    {
+    if( aElement->IsTonemark() )
+        {
+        return iElements[aPos]->IsTonemark() || 
+               iElements[aPos]->IsSeparator();
+        }
+    else if(aElement->IsManualSeparator() )
+        {
+        return iElements[aPos]->IsAutoSeparator();
+        }
+    else
+        {
+        return EFalse;
+        }
+    }
+
+// ---------------------------------------------------------
+// To test whether the one before current pos element should be replaced by input one
+// ---------------------------------------------------------
+//
+TBool CAknFepVkbCompositionField::IsReplaceFront(const CCompositionElement* aElement)
+    {
+    if( iCurrentPos > 0 )
+        {
+        return IsReplacePosition(aElement, iCurrentPos - 1);
+        }
+        
+    return EFalse;
+    }
+    
+// ---------------------------------------------------------
+// To test whether current pos element should be replaced by input one
+// ---------------------------------------------------------
+//
+TBool CAknFepVkbCompositionField::IsReplaceBack(const CCompositionElement* aElement)
+    {
+    if( iCurrentPos <= iElements.Count() - 1 )
+        {
+        return IsReplacePosition(aElement, iCurrentPos);
+        }
+        
+    return EFalse;
+    }
+
+// ---------------------------------------------------------
+// Redo the format after deletion
+// ---------------------------------------------------------
+//
+void CAknFepVkbCompositionField::ReFomatAfterDelete()
+    {
+//assumption
+//1. delete only happen in cursor position
+//2. before deletion, the format is OK
+    if( iElements.Count() == 0 )
+        {
+        return;
+        }
+        
+    if( iCurrentPos == 0 )
+        {
+        if( iElements[0]->IsSeparator() || 
+            iElements[0]->IsTonemark())
+            {
+            Remove(0, 1, ETrue);
+            }
+        }
+    else if( iCurrentPos <= iElements.Count() - 1)
+        {
+        if(iElements[iCurrentPos - 1]->IsAuxilian() &&
+           iElements[iCurrentPos]->IsAuxilian() )
+            { //one of two is need to be removed
+            if(iElements[iCurrentPos]->IsTonemark() ||
+               iElements[iCurrentPos]->IsManualSeparator() )
+                {//remove the one before cursor
+                Remove(iCurrentPos - 1, 1, ETrue);
+                //to simulate remove + insert opertion
+                iCurrentPos++;
+                }
+            else
+                {//remove the one on the cursor        
+                Remove(iCurrentPos, 1, ETrue);
+                }
+            }
+        else if( iElements[iCurrentPos - 1]->IsAutoSeparator() &&
+                 iElements[iCurrentPos]->IsTypeOf(EElementTypeConvertedChar) )
+            {
+            //remove auto separator before convert char
+            Remove(iCurrentPos - 1, 1, ETrue);
+            }
+        else if( iElements[iCurrentPos]->IsAutoSeparator() &&
+                 iElements[iCurrentPos - 1]->IsTypeOf(EElementTypeConvertedChar) )
+            {
+            //remove auto separator before convert char
+            Remove(iCurrentPos, 1, ETrue);
+            }
+        }
+    else //if( iCurrentPos == iElements.Count() )
+        {
+        if( iElements[iCurrentPos - 1]->IsAutoSeparator() )
+            {
+            Remove(iCurrentPos - 1, 1);
+            }
+        }
+    }
+
+// ---------------------------------------------------------
+// Get display cursor positon by internal cursor position
+// ---------------------------------------------------------
+//
+TInt CAknFepVkbCompositionField::InternalPosToDisplayPos(TInt aInternalPos)
+    {
+    for(TInt i = 0; i < aInternalPos; i++)
+        {
+        if( !iElements[i]->IsVisible() )
+            {
+            aInternalPos--;
+            }
+        }
+    
+    return aInternalPos;
+    }
+
+// ---------------------------------------------------------
+// Get internal cursor positon by display cursor position
+// ---------------------------------------------------------
+//
+TInt CAknFepVkbCompositionField::DisplayPosToInternaPos(TInt aDisplayPos)
+    {
+    TInt pos = 0;
+    TInt i = 0;
+    
+    for( i = 0; i < iElements.Count() && pos < aDisplayPos; i++ )
+        {
+        if( iElements[i]->IsVisible() )
+            {
+            pos++;
+            }        
+        }
+    for( i++; i < iElements.Count(); i++ )
+        {
+        if( iElements[i]->IsVisible() )
+            {
+            break;
+            }
+        }
+    
+    return --i;
+    }
+
+// ---------------------------------------------------------
+// Remove the selected text
+// ---------------------------------------------------------
+//
+void CAknFepVkbCompositionField::RemoveSelection()
+    {
+    TInt lower = DisplayPosToInternaPos( iSelectedCompositionText.LowerPos() );
+    TInt upper = DisplayPosToInternaPos( iSelectedCompositionText.HigherPos() ); 
+    Remove(lower, upper - lower);    
+    ReFomatAfterDelete();    
+    }
+
+// ---------------------------------------------------------------------------
+// CAknFepVkbCompositionField::GetCreatedWordSpell
+// (other items were commented in a header)
+// ---------------------------------------------------------------------------
+//
+const TInt KSpellSpace = 8; // private protocol for PtiCpiCore   
+TPtrC CAknFepVkbCompositionField::GetCreatedWordSpell()
+    {
+    iCreateWordSpellBuffer.SetLength( 0 );
+    //TUint16 bufText[10] = {0};
+    //TUint16 bufSpell[100] = {0};    
+    
+    if( iNeedCreateWord )
+        {
+        //for()
+        iCreateWordSpellBuffer.SetLength( KSpellSpace * iElements.Count() );
+        iCreateWordSpellBuffer.FillZ();
+        for ( int i = 0; i < iElements.Count(); i++ )
+            {
+            //bufText[i] = ( *( iElements[i]->Key() ) )[0];
+
+            TUint16 temp  = ( *( iElements[i]->Key() ) )[0];
+            iCreateWordSpellBuffer[KSpellSpace*i] = ( *( iElements[i]->Key() ) )[0];
+            for( int j=0; j < iElements[i]->OriginalCount(); j++ )
+                {
+                const CCompositionElement* element = iElements[i]->OriginalContent( j );
+                if( element && !element->IsSeparator() )
+                    {
+                    //bufSpell[ i*KSpellSpace + j] = ( *( element->Key() ) )[0];
+                    iCreateWordSpellBuffer[KSpellSpace*i + j + 1] = ( *( element->Key() ) )[0];;
+                    }
+                }
+            }
+        }
+    
+    return iCreateWordSpellBuffer;
+    }
+    
+// ---------------------------------------------------------------------------
+// CAknFepVkbCompositionField::IsValidSpell
+// (other items were commented in a header)
+// ---------------------------------------------------------------------------
+//
+TBool CAknFepVkbCompositionField::IsValidSpell()
+    {
+    // no just verify the Zhuyin & Pinyin spell, stoke&cangjie verify later
+    if (  iDataProvider->RequestData( EAknFepDataTypeIMLayout )  == EAknFepVkbImCnZhuyin
+        || iDataProvider->RequestData( EAknFepDataTypeIMLayout )  == EAknFepVkbImCnPinyin )
+            {
+            return iIsValidSpells;
+            }
+    if( ( iDataProvider->RequestData( EAknFepDataTypeIMLayout ) ==  EAknFepVkbImCnStroke
+        || iDataProvider->RequestData( EAknFepDataTypeIMLayout ) ==  EAknFepVkbImCnCangjie ) )
+        {
+        return iIsValidSpells;
+        }
+    return ETrue;
+    }
+    
+void CAknFepVkbCompositionField::ConstructFromResourceL()
+    {    
+    if (iResourceId == KInvalidResId)
+    	{
+        User::Leave(KErrArgument);
+    	}
+
+    TResourceReader reader;
+    CCoeEnv::Static()->CreateResourceReaderLC(reader, iResourceId);
+
+
+    TPtrC bmpFileName = reader.ReadTPtrC();  
+    TInt32 imgMajorSkinId = reader.ReadInt32();
+
+    TAknsItemID id;
+    TInt skinitemid;
+    
+    MAknsSkinInstance* skininstance = AknsUtils::SkinInstance();
+
+    const TInt16 compositionbgId = reader.ReadInt16();
+    const TInt16 compositionbgIdmaskId = reader.ReadInt16();
+    skinitemid = reader.ReadInt16();
+
+    id.Set( TInt( imgMajorSkinId ), skinitemid );
+    
+    if ( compositionbgId != KInvalidImg )
+    	{
+        CFbsBitmap* compositionImg = NULL;
+
+        if (compositionbgIdmaskId != KInvalidImg)
+            {
+            CFbsBitmap* compositionmaskImg = NULL;
+            
+            AknsUtils::CreateIconL(skininstance,
+                                   id,
+                                   compositionImg,
+                                   compositionmaskImg,
+                                   bmpFileName,
+                                   compositionbgId,
+                                   compositionbgIdmaskId);
+            
+            AknIconUtils::SetSize(compositionmaskImg, TSize(1,1), EAspectRatioNotPreserved);
+            SetBackgroundMaskBitmapL(compositionmaskImg);
+            }
+        else
+            {
+            AknsUtils::CreateIconL(skininstance,
+                                   id,
+                                   compositionImg,
+                                   bmpFileName,
+                                   compositionbgId);
+            }
+    	
+    	AknIconUtils::SetSize(compositionImg, TSize(1,1), EAspectRatioNotPreserved);
+    	SetBackgroundBitmapL(compositionImg);
+    	}
+
+    CleanupStack::PopAndDestroy(); // reader
+    
+    }
+    
+void CAknFepVkbCompositionField::SizeChanged(TRect aRect)
+	{
+	CFepLayoutEditAreaBase::SetRect(aRect);
+    if( BackgroundBmp() )
+        {
+        CFbsBitmap* bmp = BackgroundBmp();
+        if( aRect.Size() != bmp->SizeInPixels() )
+            {
+            AknIconUtils::SetSize(bmp, aRect.Size(), EAspectRatioNotPreserved);            
+            }
+        }
+	}
+// End Of File