messagingappbase/msgeditor/viewsrc/MsgAddressControlEditor.cpp
changeset 0 72b543305e3a
child 14 c6838af47512
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingappbase/msgeditor/viewsrc/MsgAddressControlEditor.cpp	Thu Dec 17 08:44:11 2009 +0200
@@ -0,0 +1,1980 @@
+/*
+* Copyright (c) 2002 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:  MsgAddressControlEditor implementation
+*
+*/
+
+
+
+// ========== INCLUDE FILES ================================
+
+#include <barsread.h>                      // for TResourceReader
+#include <eikenv.h>                        // for CEikonEnv
+#include <txtrich.h>                       // for CRichText
+#include <AknUtils.h>                      // for AknUtils
+#include <AknSettingCache.h>               // for SettingCache().InputLanguage()
+#include <AknsUtils.h>                     // for AknsUtils::GetCachedColor()
+#include <AknsConstants.h>                 // for KAknsIIDQsnHighlightColors and EAknsCIQsnHighlightColorsCG1
+
+#include <aknlayout.cdl.h> // LAF
+#include <txtetext.h>
+#include <fldinfo.h>
+
+#ifdef RD_TACTILE_FEEDBACK
+#include <touchfeedback.h>
+#endif 
+
+
+#include "MsgEditorCommon.h"               //
+#include "MsgAddressControlEditor.h"       // for CMsgAddressControlEditor
+#include "MsgAddressControlEditorField.h"  // for CMsgAddressControlEditorField and TMsgAddressControlEditorFieldFactory
+#include "MsgBaseControl.h"                // for TMsgEditPermissionFlags
+#include "MsgBaseControlObserver.h"        // for MMsgBaseControlObserver
+#include "MsgAddressControl.h"             // for permission flags
+#include "MsgEditorPanic.h"                // for MsgEditor panics
+#include "MsgEditor.hrh"                   // for EditPermission flags
+#include "MsgEditorKeyCatcher.h"           // for CMsgEditorKeyCatcher
+
+// ========== EXTERNAL DATA STRUCTURES =====================
+
+// ========== EXTERNAL FUNCTION PROTOTYPES =================
+
+// ========== CONSTANTS ====================================
+
+// ========== MACROS =======================================
+
+// ========== LOCAL CONSTANTS AND MACROS ===================
+
+// Highlighted field does not exist.
+const TInt KMsgHighlightedFieldPosNone = -1;
+// Current entry not defined.
+const TInt KMsgCurrentEntryNone        = -1;
+
+const TText KZeroWidthJoiner = 0x200D;
+const TText KLRMarker = 0x200E;
+const TText KRLMarker = 0x200F;
+
+// ========== MODULE DATA STRUCTURES =======================
+
+// ========== LOCAL FUNCTION PROTOTYPES ====================
+
+// ========== LOCAL FUNCTIONS ==============================
+
+// ========== MEMBER FUNCTIONS =============================
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::CMsgAddressControlEditor
+//
+// Constructor.
+// ---------------------------------------------------------
+//
+CMsgAddressControlEditor::CMsgAddressControlEditor(
+    const CCoeControl* aParent,
+    TUint32& aFlags,
+    MMsgBaseControlObserver* aBaseControlObserver )
+    : CMsgExpandableControlEditor( aParent, aFlags, aBaseControlObserver ),
+      iHighLightedFieldPos( KMsgHighlightedFieldPosNone ),
+      iCurrentEntry( KMsgCurrentEntryNone )
+    {
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::~CMsgAddressControlEditor
+//
+// Destructor.
+// ---------------------------------------------------------
+//
+CMsgAddressControlEditor::~CMsgAddressControlEditor()
+    {
+    delete iKeyCatcher;
+    delete iAddressControlEditorFieldFactory;
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::ConstructL
+//
+// 2nd phase constructor.
+// ---------------------------------------------------------
+//
+void CMsgAddressControlEditor::ConstructL()
+    {
+    CMsgExpandableControlEditor::ConstructL();
+    
+    //To Dis-able Smiley support for address fields
+    RemoveFlagFromUserFlags(EAvkonEnableSmileySupport);
+    
+    iFlags |= EMsgControlModeDoNotDrawFrameBgContext; 
+    iKeyCatcher = new ( ELeave ) CMsgEditorKeyCatcher();
+    iKeyCatcher->ConstructL( this );
+
+    SetAllowUndo( EFalse );
+    // Variation is done inside edwin
+    SetPhoneNumberGrouping( ETrue );
+    iCusPos = 0;
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::ExtractEntry
+//
+// Extracts an entry according to aEntryNumber and returns it in aEntryString.
+// ---------------------------------------------------------
+//
+void CMsgAddressControlEditor::ExtractEntry(
+    TDes& aEntryString, TInt aEntryNumber )
+    {
+    __ASSERT_DEBUG( ( aEntryNumber >= 0 ) &&
+        ( aEntryNumber < iRichText->ParagraphCount() ),
+        Panic( EMsgInvalidEntryNumber ) );
+
+    TInt entryLength = 0;
+    TInt entryStart = iRichText->CharPosOfParagraph( entryLength, aEntryNumber );
+    iRichText->Extract( aEntryString, entryStart, entryLength - 1 );
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::ReadEntry
+//
+// Reads an entry aEntryNumber and returns pointer to it.
+// ---------------------------------------------------------
+//
+TPtrC CMsgAddressControlEditor::ReadEntry( TInt aEntryNumber ) const
+    {
+    __ASSERT_DEBUG( ( aEntryNumber >= 0 ) &&
+        ( aEntryNumber < iRichText->ParagraphCount() ),
+        Panic( EMsgInvalidEntryNumber ) );
+
+    TInt entryLength = 0;
+    TInt entryStart = iRichText->CharPosOfParagraph( entryLength, aEntryNumber );
+    return iRichText->Read( entryStart, entryLength - 1 );
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::EntryCount
+//
+// Returns number of entries.
+// ---------------------------------------------------------
+//
+TInt CMsgAddressControlEditor::EntryCount() const
+    {
+    return iRichText->ParagraphCount();
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::DeleteEntryL
+//
+// Deletes an entry aEntryNumber.
+// ---------------------------------------------------------
+//
+void CMsgAddressControlEditor::DeleteEntryL( TInt aEntryNumber )
+    {
+    __ASSERT_DEBUG( ( aEntryNumber >= 0 ) &&
+        ( aEntryNumber < iRichText->ParagraphCount() ),
+        Panic( EMsgInvalidEntryNumber ) );
+
+    CancelFepTransaction();
+    TBool setcursorpos(EFalse);
+    TInt numOfEntries = iRichText->ParagraphCount();
+    TInt entryLength = 0;
+    TInt entryStart = iRichText->CharPosOfParagraph( entryLength, aEntryNumber );
+    if ( numOfEntries == aEntryNumber + 1 ) //entry to be deleted is the lowest one
+        {
+        if ( aEntryNumber != 0 ) // but not the only one
+            {
+            entryStart--;
+            }
+        else
+            {
+            entryLength--;
+            }
+        }
+    
+    if ( TextView() )
+        {
+        // Cursor position must not go beyond text end. Otherwise
+        // panic will happen on text formatting.
+        TInt newTextLength = TextLength() - entryLength;
+        
+        if ( CursorPos() > newTextLength )
+            {
+            SetCursorPosL( newTextLength, EFalse );
+            iCusPos = newTextLength;
+            setcursorpos = ETrue;
+            }
+        }
+    
+    iRichText->CancelInsertCharFormat();
+    iRichText->DelSetInsertCharFormatL( entryStart, entryLength );
+    if ( iTextView )
+       {
+        iTextView->HandleInsertDeleteL(
+            TCursorSelection( entryStart, entryStart + entryLength ), entryLength, EFalse );
+       }
+     numOfEntries = iRichText->ParagraphCount();
+     if( numOfEntries > 0 && numOfEntries != aEntryNumber && !setcursorpos)
+        {
+         TInt  txtlen = TextLength();
+         TInt  curpos = CursorPos();                
+         entryStart = iRichText->CharPosOfParagraph( entryLength, aEntryNumber );
+         curpos+= --entryLength;
+         if ( TextView() )
+            {
+                if(curpos < txtlen)
+                {
+                    iCusPos = curpos;
+                    SetCursorPosL( curpos, EFalse );   
+                }
+              else
+                {
+                    iCusPos =entryStart ;
+                    SetCursorPosL( iCusPos, EFalse );   
+                    ReportEdwinEventL( MEikEdwinObserver::EEventTextUpdate );
+                }        
+            }
+        }
+ }
+ // ---------------------------------------------------------
+// CMsgAddressControlEditor::GetCursorpos
+//
+// returns the current cursor position.
+// ---------------------------------------------------------
+//
+
+TInt CMsgAddressControlEditor::GetCursorpos() const
+    {
+        return iCusPos;
+    }
+    
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::ClearEntryL
+//
+// Clears all the text of an entry aEntryNumber but not the paragraph delimiter.
+// ---------------------------------------------------------
+//
+void CMsgAddressControlEditor::ClearEntryL( TInt aEntryNumber, TBool aUpdate )
+    {
+    __ASSERT_DEBUG( ( aEntryNumber >= 0 ) &&
+        ( aEntryNumber < iRichText->ParagraphCount() ),
+        Panic( EMsgInvalidEntryNumber ) );
+
+    TInt entryLength = 0;
+    TInt entryStart = iRichText->CharPosOfParagraph( entryLength, aEntryNumber );
+    DeleteEntryCharsL( aEntryNumber, 0, entryLength );
+    if ( iTextView && aUpdate )
+        {
+        iTextView->HandleInsertDeleteL(
+            TCursorSelection( entryStart, entryStart ), --entryLength, EFalse );
+        SetCursorPosAndCancelSelectionL( entryStart );
+        }
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::DeleteAllL
+//
+// Clears the content of the editor. Updates also the scroll bars.
+// ---------------------------------------------------------
+//
+void CMsgAddressControlEditor::DeleteAllL()
+    {
+    CancelFepTransaction();
+    iRichText->CancelInsertCharFormat();
+    iRichText->Reset();
+    if (iTextView)
+        {
+        SetAmountToFormatL( ETrue );
+        SetCursorPosAndCancelSelectionL( 0 );
+        }
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::DeleteEntryCharsL
+//
+// Deletes characters from aStartPos to aEndPos at entry aEntryNumber. Never
+// removes the paragraph delimiter.
+// ---------------------------------------------------------
+//
+void CMsgAddressControlEditor::DeleteEntryCharsL(
+    TInt aEntryNumber, TInt aStartPos, TInt aEndPos)
+    {
+    __ASSERT_DEBUG( ( aEntryNumber >= 0 ) &&
+        ( aEntryNumber < iRichText->ParagraphCount() ),
+        Panic( EMsgInvalidEntryNumber ) );
+    __ASSERT_DEBUG( ( aStartPos >= 0 ) && ( aStartPos <= aEndPos ),
+        Panic( EMsgInvalidStartPos ) );
+
+    CancelFepTransaction();
+    TInt entryLength = 0;
+    TInt entryStart = iRichText->CharPosOfParagraph( entryLength, aEntryNumber );
+    entryLength--;
+    entryLength = ( aEndPos < entryLength )
+        ? aEndPos - aStartPos
+        : entryLength - aStartPos;
+    entryStart += aStartPos;
+    
+    if ( TextView() )
+        {
+        // Cursor position must not go beyond text end. Otherwise
+        // panic will happen on text formatting.
+        TInt newTextLength = TextLength() - entryLength;
+        
+        if ( CursorPos() > newTextLength )
+            {
+            SetCursorPosL( newTextLength, EFalse );
+            }
+        }
+    
+    iRichText->CancelInsertCharFormat();
+    iRichText->DelSetInsertCharFormatL( entryStart, entryLength );
+    //clear the iTextView cache too
+    if ( iTextView )
+        {
+        iTextView->HandleInsertDeleteL(
+            TCursorSelection( entryStart, entryStart + entryLength ), entryLength, EFalse );
+        SetCursorPosAndCancelSelectionL( entryStart );
+        }
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::SetCursorPosAndCancelSelectionL
+//
+// Sets cursor position to aPos and cancels selection.
+// This is needed because Edwin/TextView does not do it as expected.
+// ---------------------------------------------------------
+//
+void CMsgAddressControlEditor::SetCursorPosAndCancelSelectionL( TInt aPos )
+    {
+    if ( iTextView )
+        {
+        CancelFepTransaction();
+
+        iTextView->SetDocPosL( aPos, EFalse );
+        ForceScrollBarUpdateL();
+        }
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::InsertEntryL
+//
+// Inserts an entry to the location aEntryNumber with strings a text aName
+// and aAddress. Makes an entry as verified if aVerified = ETrue and validated
+// if aValidated = ETrue.
+// ---------------------------------------------------------
+//
+void CMsgAddressControlEditor::InsertEntryL(
+    TInt aEntryNumber,
+    const TDesC& aName,
+    const TDesC& aAddress,
+    TBool aVerified,
+    TBool aValidated,
+    const MVPbkContactLink* aContactLink )
+    {
+    __ASSERT_DEBUG( aEntryNumber >= 0 && 
+                    aEntryNumber <= iRichText->ParagraphCount(),
+                    Panic( EMsgInvalidEntryNumber ) );
+
+    TChar semicolon = KSemicolon;
+    TInt entryLength = 0;
+    TInt numOfEntries = iRichText->ParagraphCount();
+
+    TInt pos = TextLength();
+    TChar ch = CharAtPos( pos - 1 );
+
+    if ( ch == CEditableText::EParagraphDelimiter )
+        {
+        // last character is parag.delim. => decrease entry num.
+        aEntryNumber--;
+        }
+    
+    /*
+     * Fix the split contact name issue::ECYU-7FPC93.
+     * Replace any enter-key characters with space characters.
+     */
+
+    TBufC<KMaxContactLength> parsedName(aName.Left(KMaxContactLength));
+    
+    TInt enterKeyPos;
+    TChar enterChar( CEditableText::EParagraphDelimiter );
+    TChar spaceChar( CEditableText::ESpace );
+    TPtr namePtr = parsedName.Des();
+    TInt nameLength = parsedName.Length();
+    
+    enterKeyPos = namePtr.Locate(enterChar);
+    while( enterKeyPos != KErrNotFound && enterKeyPos < nameLength )
+        {
+        namePtr[enterKeyPos] = spaceChar;
+        enterKeyPos = namePtr.Locate(enterChar);
+        }
+
+    if ( aEntryNumber >= numOfEntries )
+        {
+        // entry appended to the end.
+        iRichText->CancelInsertCharFormat();
+        iRichText->InsertL( pos, CEditableText::EParagraphDelimiter );
+        }
+    else
+        {
+        // entry appended to the middle or beginning.
+        iRichText->CharPosOfParagraph( entryLength, aEntryNumber );
+        
+        if ( entryLength - 1 )
+            {
+            InsertEntryBreakL( aEntryNumber, 0 );
+            }
+        }
+
+    TInt entryStart = iRichText->CharPosOfParagraph( entryLength, aEntryNumber );
+    
+    //ECYU-7FPC93:: Fix
+    HBufC* string = CreateEntryStringLC( parsedName, aAddress, aVerified );
+    //HBufC* string = CreateEntryStringLC( aName, aAddress, aVerified );
+
+    if ( aVerified || aValidated )
+        {
+        // Setting up the field factory.
+        iRichText->SetFieldFactory( iAddressControlEditorFieldFactory );
+        
+        CMsgAddressControlEditorField* field = 
+            static_cast<CMsgAddressControlEditorField*>( 
+                                        iRichText->NewTextFieldL( KMsgAddressControlEditorFieldUid ) );
+
+        if ( field )
+            {
+            field->SetEntryStringL( *string );
+            
+            //ECYU-7FPC93:: Fix
+            field->SetNameL( parsedName );
+            //field->SetNameL( aName );
+           
+            field->SetAddressL( aAddress );
+            field->SetVerified( aVerified );
+            field->SetValidated( aValidated );
+            field->SetContactLink( aContactLink );
+
+            iRichText->InsertFieldL( entryStart, 
+                                     field, 
+                                     KMsgAddressControlEditorFieldUid );
+                                     
+            iRichText->UpdateFieldL( entryStart );
+            }
+        }
+    else
+        {
+        if ( string->Length() > 0 )
+            {
+            iRichText->InsertL( entryStart, *string );
+            }
+        else
+            {
+            // This should not happen. Zero lenght contact name is being added. 
+            // Insert semicolon only.
+            if ( iAvkonEnv->SettingCache().InputLanguage() == ELangArabic )
+                {
+                semicolon = KArabicSemicolon;
+                }
+                
+            iRichText->InsertL( entryStart, semicolon );
+            }
+        }
+
+    if ( aEntryNumber >= numOfEntries )
+        {
+        if ( ch != semicolon &&
+             ch != CEditableText::EParagraphDelimiter &&
+             ch != KArabicSemicolon )
+            {
+            if ( iAvkonEnv->SettingCache().InputLanguage() == ELangArabic )
+                {
+                semicolon = KArabicSemicolon;
+                }
+                
+            iRichText->InsertL( pos, semicolon );
+            }
+        }
+        
+    CleanupStack::PopAndDestroy();  // string
+    }
+    
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::InsertEntryBreakL
+//
+// Inserts the paragraph delimiter at aPos on entry aEntryNumber.
+// ---------------------------------------------------------
+//
+void CMsgAddressControlEditor::InsertEntryBreakL( TInt aEntryNumber, TInt aPos )
+    {
+    __ASSERT_DEBUG( aEntryNumber >= 0 &&
+                    aEntryNumber < iRichText->ParagraphCount(),
+                    Panic( EMsgInvalidEntryNumber ) );
+
+    TInt entryLength = 0;
+    TInt insertPos = iRichText->CharPosOfParagraph( entryLength, aEntryNumber );
+    insertPos += aPos;
+    iRichText->CancelInsertCharFormat();
+    iRichText->InsertL( insertPos, CEditableText::EParagraphDelimiter );
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::EntryNumber
+//
+// Returs an entry number where aPos is on.
+// ---------------------------------------------------------
+//
+TInt CMsgAddressControlEditor::EntryNumber( TInt aPos ) const
+    {
+    __ASSERT_DEBUG( ( aPos >= 0 ) && ( aPos <= TextLength() ),
+        Panic( EMsgDocPosOutOfRange ) );
+
+    // first paragraph==0
+    TInt paragraphNumber = iRichText->ParagraphNumberForPos( aPos );
+    return paragraphNumber;
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::EntryLength
+//
+// Returns length of the entry aEntryNumber. Does not count paragraph delimiter.
+// ---------------------------------------------------------
+//
+TInt CMsgAddressControlEditor::EntryLength( TInt aEntryNumber ) const
+    {
+    __ASSERT_DEBUG( ( aEntryNumber >= 0 ) &&
+        ( aEntryNumber < iRichText->ParagraphCount() ),
+        Panic( EMsgInvalidEntryNumber ) );
+
+    TInt entryLength = 0;
+    iRichText->CharPosOfParagraph( entryLength, aEntryNumber );
+    return entryLength - 1;
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::EntryStartPos
+//
+// Returns first character position on the entry aEntryNumber.
+// ---------------------------------------------------------
+//
+TInt CMsgAddressControlEditor::EntryStartPos( TInt aEntryNumber ) const
+    {
+    __ASSERT_DEBUG( ( aEntryNumber >= 0 ) &&
+        ( aEntryNumber < iRichText->ParagraphCount() ),
+        Panic( EMsgInvalidEntryNumber ) );
+
+    TInt entryLength = 0;
+    return iRichText->CharPosOfParagraph( entryLength, aEntryNumber );
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::FirstFieldPos
+//
+//
+// ---------------------------------------------------------
+//
+TInt CMsgAddressControlEditor::FirstFieldPos( TInt aCursorPos ) const
+    {
+    TFindFieldInfo fieldInfo;
+
+    /*TBool ret =*/ iRichText->FindFields( fieldInfo, aCursorPos, 0 );
+
+    return fieldInfo.iFirstFieldPos;
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::MoveCursorToEntryPosL
+//
+// Moves the cursor on an entry aEntryNumber to a position aPos. 0 == entry start.
+// ---------------------------------------------------------
+//
+void CMsgAddressControlEditor::MoveCursorToEntryPosL( TInt aEntryNumber, TInt aPos )
+    {
+    __ASSERT_DEBUG( ( aEntryNumber >= 0 ) &&
+        ( aEntryNumber < iRichText->ParagraphCount() ),
+        Panic( EMsgInvalidEntryNumber ) );
+
+    TInt entryLength = 0;
+    TInt entryStart = iRichText->CharPosOfParagraph( entryLength, aEntryNumber );
+    if ( entryLength - 1 < aPos )
+        {
+        aPos = entryLength - 1; // adjust the aPos if it happens to be too big
+        }
+    SetCursorPosAndCancelSelectionL( entryStart + aPos );
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::IsPosAtEntryBeginning
+//
+// Checks whether the cursor is at the beginning of the entry and returns ETrue
+// if it is, otherwise EFalse.
+// ---------------------------------------------------------
+//
+TBool CMsgAddressControlEditor::IsPosAtEntryBeginning( TInt aPos ) const
+    {
+    __ASSERT_DEBUG( ( aPos >= 0 ) && ( aPos <= TextLength() ),
+        Panic( EMsgDocPosOutOfRange ) );
+
+    TInt entryLength = 0;
+    return ( iRichText->CharPosOfParagraph(
+        entryLength, EntryNumber( aPos ) ) == aPos );
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::IsEntryVerified
+//
+// Check whether an entry aEntryNumber is verified or not and returns ETrue
+// if it is, otherwise EFalse.
+// ---------------------------------------------------------
+//
+TBool CMsgAddressControlEditor::IsEntryVerified( TInt aEntryNumber ) const
+    {
+    const CMsgAddressControlEditorField* field = Field( aEntryNumber );
+
+    return ( field ? field->IsVerified() : EFalse );
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::IsPriorEntryVerified
+//
+// Checks whether an entry aEntryNumber-1 is verified and returns ETrue if
+// it is, otherwise EFalse.
+// ---------------------------------------------------------
+//
+TBool CMsgAddressControlEditor::IsPriorEntryVerified( TInt aEntryNumber ) const
+    {
+    __ASSERT_DEBUG( ( aEntryNumber >= 0 ) &&
+        ( aEntryNumber < iRichText->ParagraphCount() ),
+        Panic( EMsgInvalidEntryNumber ) );
+
+    if ( aEntryNumber > 0 )
+        {
+        return IsEntryVerified( aEntryNumber - 1 );
+        }
+
+    return EFalse;
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::IsEntryValidated
+//
+// Check whether an entry aEntryNumber is validated or not and returns ETrue
+// if it is, otherwise EFalse.
+// ---------------------------------------------------------
+//
+TBool CMsgAddressControlEditor::IsEntryValidated( TInt aEntryNumber ) const
+    {
+    const CMsgAddressControlEditorField* field = Field( aEntryNumber );
+
+    return ( field ? field->IsValidated() : EFalse );
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::IsFieldOnLeft
+//
+// Checks if there is a text field on the left hand side of the cursor at
+// position aPos and returns ETrue if it is, otherwise EFalse.
+// ---------------------------------------------------------
+//
+TBool CMsgAddressControlEditor::IsFieldOnLeft( TInt aPos ) const
+    {
+    if ( aPos > 0 && aPos <= TextLength() )
+        {
+        const CMsgAddressControlEditorField* field = FieldFromPos( aPos - 1 );
+
+        return ( field ? field->IsVerified() : EFalse );
+        }
+    return EFalse;
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::IsFieldOnRight
+//
+// Checks if there is a text field on the right hand side of the cursor at position
+// aPos and returns ETrue if it is, otherwise EFalse.
+// ---------------------------------------------------------
+//
+TBool CMsgAddressControlEditor::IsFieldOnRight( TInt aPos ) const
+    {
+    if ( aPos >= 0 && aPos < TextLength() )
+        {
+        // Fixing Fixing "ESPI-63C45M - Messags: The contact named with one
+        // characteronly cannot be deleted from ‘To’ field by ‘Clear’ key."
+
+        const CMsgAddressControlEditorField* field = FieldFromPos( aPos );
+
+        return ( field ? field->IsVerified() : EFalse );
+        }
+    return EFalse;
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::IsFieldOnPos
+//
+// Checks if there is a text field under the cursor at position
+// aPos and returns ETrue if it is, otherwise EFalse.
+// ---------------------------------------------------------
+//
+TBool CMsgAddressControlEditor::IsFieldOnPos( TInt aPos ) const
+    {
+    if ( aPos >= 0 && aPos < TextLength() )
+        {
+        const CMsgAddressControlEditorField* field = FieldFromPos( aPos );
+
+        return ( field ? field->IsVerified() : EFalse );
+        }
+    return EFalse;
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::IsEntryEmpty
+//
+// Checks whether an entry aEntryNumber is empty.
+// ---------------------------------------------------------
+//
+TBool CMsgAddressControlEditor::IsEntryEmpty( TInt aEntryNumber ) const
+    {
+    __ASSERT_DEBUG( ( aEntryNumber >= 0 ) &&
+        ( aEntryNumber < iRichText->ParagraphCount() ),
+        Panic( EMsgInvalidEntryNumber ) );
+
+    TInt entryLength = 0;
+    iRichText->CharPosOfParagraph( entryLength, aEntryNumber );
+
+    return ( entryLength == 1 );
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::IsEntryRightToLeft
+//
+// ---------------------------------------------------------
+//
+TBool CMsgAddressControlEditor::IsEntryRightToLeft( TInt aEntryNumber ) const
+    {
+    TBool isRightToLeft( EFalse );
+
+    const CMsgAddressControlEditorField* field = Field( aEntryNumber );
+    if ( field )
+        {
+        TPtrC entryText = ReadEntry( aEntryNumber );
+        if ( entryText.Length() > 0 )
+            {
+            if ( TBidiText::TextDirectionality( entryText ) ==
+                TBidiText::ERightToLeft ) 
+                {
+                isRightToLeft = ETrue;
+                }
+            }
+        } 
+    return isRightToLeft;
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::CheckHighlightingL
+//
+// Turns entry as highlighted if the cursor is on the top of the verified
+// entry, otherwise turns highlighting off if there were any somewhere else.
+// ---------------------------------------------------------
+//
+void CMsgAddressControlEditor::CheckHighlightingL( TBool aCancelFep /*= ETrue*/ )
+    {
+    if ( !iTextView )
+        {
+        return ;
+        }
+
+    if ( aCancelFep && IsFocused())
+        {
+        CancelFepTransaction();
+        }
+
+    TInt cursorPos = CursorPos();
+
+    if ( !IsReadOnly() && IsFieldOnPos( cursorPos ) )
+        {
+        TFindFieldInfo fieldInfo;
+
+        if ( iRichText->FindFields( fieldInfo, cursorPos, 0 ) )
+            {
+            TCharFormat charFormat;
+            TCharFormatMask applyMask;
+            
+            if ( iHighLightedFieldPos != fieldInfo.iFirstFieldPos )
+                {
+                if ( !( iFlags & EMsgControlModeShiftPressed ) )
+                    {
+                    TRgb highlightColor;
+                    
+                    AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), 
+                            highlightColor, 
+                            KAknsIIDQsnHighlightColors,
+                            EAknsCIQsnHighlightColorsCG1 );
+
+                    charFormat.iFontPresentation.iHighlightColor = highlightColor;
+                    applyMask.SetAttrib( EAttFontHighlightColor );
+
+                    charFormat.iFontPresentation.iHighlightStyle =
+                        TFontPresentation::EFontHighlightNormal;
+                    applyMask.SetAttrib( EAttFontHighlightStyle );
+                    
+                    // Sets only the attributes specified to be set on mask.
+                    iRichText->ApplyCharFormatL(
+                        charFormat,
+                        applyMask,
+                        fieldInfo.iFirstFieldPos,
+                        fieldInfo.iFirstFieldLen );
+                    }
+
+                if ( iTextView )
+                    { 
+                    iTextView->HandleRangeFormatChangeL(
+                        TCursorSelection(
+                            fieldInfo.iFirstFieldPos,
+                            fieldInfo.iFirstFieldPos + fieldInfo.iFirstFieldLen ),
+                        EFalse );
+                    }
+
+                if ( cursorPos != fieldInfo.iFirstFieldPos && 
+                     !iHandlingPointerEvent )
+                    {
+                    MoveCursorToEntryPosL(EntryNumber( cursorPos ), 0 );
+                    }
+
+                TurnHighlightingOffL( aCancelFep );
+                iHighLightedFieldPos = fieldInfo.iFirstFieldPos;
+                }
+            }
+        }
+    else
+        {
+        if ( IsReadOnly() && iValidHighlightable )
+			{
+            // Use "link highlight"
+			SetHighlightStyleL( EEikEdwinHighlightLink );
+            SelectAllL();
+            }
+		else
+            {
+            TurnHighlightingOffL( aCancelFep );
+            if ( IsReadOnly() )
+                {
+                iTextView->SetDocPosL( cursorPos, ETrue );                    
+                }
+            }
+        }
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::TurnHighlightingOffL
+//
+// Turns highlighting off if it happens to be on aSelection.
+// ---------------------------------------------------------
+//
+void CMsgAddressControlEditor::TurnHighlightingOffL( TCursorSelection aSelection )
+    {
+    if ( !Selection().Length() ||
+        ( iHighLightedFieldPos == KMsgHighlightedFieldPosNone ) )
+        {
+        return;
+        }
+
+    if ( IsFieldOnPos( iHighLightedFieldPos ) )
+        {
+        CancelFepTransaction();
+
+        TInt selLowerPos = aSelection.LowerPos();
+        // The higherPos is more close to the end of the text
+        TInt selHigherPos = aSelection.HigherPos();
+
+        TFindFieldInfo fieldInfo;
+        iRichText->FindFields( fieldInfo, iHighLightedFieldPos, 0 );
+
+        if ( ( selLowerPos >= iHighLightedFieldPos ) &&
+            ( iHighLightedFieldPos + fieldInfo.iFirstFieldLen <= selHigherPos ) )
+            {
+            TurnHighlightingOffL();
+            }
+        }
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::TurnHighlightingOffL
+//
+// Turns highlighting off if such a highlighted text field is somewhere.
+// ---------------------------------------------------------
+//
+void CMsgAddressControlEditor::TurnHighlightingOffL( TBool aCancelFep /*= ETrue*/ )
+    {
+    TInt textLength = TextLength();
+
+    if ( ( iHighLightedFieldPos == KMsgHighlightedFieldPosNone ) ||
+        ( iHighLightedFieldPos > textLength ) )
+        {
+        return;
+        }
+
+    if ( aCancelFep )
+        {
+        CancelFepTransaction();
+        }
+
+    TInt cursorPos = CursorPos();
+
+    if ( cursorPos == textLength )
+        {
+        if ( IsFieldOnPos( cursorPos - 1 ) )
+            {
+            // Remove the highlight from last cursor position only if
+            // there is highlightable field. 
+            TurnHighlightingOffFromPosL( cursorPos - 1 );
+            }
+        }
+
+    TurnHighlightingOffFromPosL( iHighLightedFieldPos );
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::TurnHighlightingOffFromPosL
+//
+// Turns highlighting off from position aPos.
+// ---------------------------------------------------------
+//
+void CMsgAddressControlEditor::TurnHighlightingOffFromPosL( TInt aPos )
+    {
+    TInt textLength = TextLength();
+
+    if ( iHighLightedFieldPos == KMsgHighlightedFieldPosNone ||
+         aPos < 0 ||        
+         aPos > textLength )
+        {
+        return;
+        }
+
+    TFindFieldInfo fieldInfo;
+
+    if ( !iRichText->FindFields( fieldInfo, aPos, 0 ) )
+        {
+        // iHighLightedFieldPos is not updated correctly and hence, clear whole text
+        fieldInfo.iFirstFieldPos = 0;
+        fieldInfo.iFirstFieldLen = textLength;
+        __ASSERT_DEBUG( EFalse, Panic( EMsgInvalidStartPos ) );
+        }
+    
+    TCharFormat charFormat;
+    TCharFormatMask applyMask;    
+
+    // background color.
+    charFormat.iFontPresentation.iHighlightColor = AKN_LAF_COLOR( 0 );
+    applyMask.SetAttrib( EAttFontHighlightColor );
+    
+    charFormat.iFontPresentation.iHighlightStyle = TFontPresentation::EFontHighlightNone;
+    applyMask.SetAttrib( EAttFontHighlightStyle );
+    
+    // Sets only the attributes specified to be set on mask.
+    iRichText->ApplyCharFormatL( charFormat,
+                                 applyMask,
+                                 fieldInfo.iFirstFieldPos,
+                                 fieldInfo.iFirstFieldLen );
+
+    if ( iTextView )
+        {
+        TCursorSelection selection( fieldInfo.iFirstFieldPos,
+                                    fieldInfo.iFirstFieldPos + fieldInfo.iFirstFieldLen );
+        iTextView->HandleRangeFormatChangeL( selection, EFalse );
+        }
+    
+    if ( iHighLightedFieldPos == aPos )
+        {
+        // If highlight was removed from currently highlighted position 
+        // reset highlighted field position.
+        iHighLightedFieldPos = KMsgHighlightedFieldPosNone;
+        }
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::CreateEntryStringLC
+//
+// Creates a suitable text string for the text field using strings aName and
+// aAddress and return pointer to it. If aFormat == EFalse, this function does
+// not format the string but takes only aAddess. If text string does not fit to
+// view it clips it and adds ... to end of it. If text layout does not exist
+// this function does not attempt to clip text string.
+// ---------------------------------------------------------
+//
+
+HBufC* CMsgAddressControlEditor::CreateEntryStringLC(
+    const TDesC& aName,
+    const TDesC& aAddress,
+    TBool aVerified /*= ETrue*/ )
+    {
+    HBufC* addressCopy = aAddress.AllocLC();
+    TPtr addrTPtr = addressCopy->Des();
+    AknTextUtils::DisplayTextLanguageSpecificNumberConversion( addrTPtr );
+    
+    if ( aVerified || IsReadOnly() )
+        {
+        TInt len = aName.Length();
+        if ( len == 0 )
+            {
+            len = addrTPtr.Length();
+            }
+
+        // +2 for KZeroWidthJoiner and direction marker
+        HBufC* string = HBufC::NewLC( len + 2 );
+        TPtr strPtr = string->Des();
+
+        if ( aName.Length() == 0 )
+            {
+            strPtr.Append( addrTPtr );
+            }
+        else
+            {
+            strPtr.Append( aName );
+            }
+
+        TInt maxWidth = 0;
+
+        if ( iTextView )
+            {
+            // We must have iTextView because LayoutWidth calls CursorPos.
+            maxWidth = LayoutWidth();
+            }
+
+        if ( maxWidth > 0 )
+            {
+            const CFont* font = TextFont();
+
+            if ( strPtr.Length() )
+                {
+                // Clip a little bit more than maxWidth to prevent wrapping.
+                TInt clipWidth = Max( 0, maxWidth - 4 );
+                TInt ellipsisWidth = font->CharWidthInPixels( KEllipsis );
+
+                TInt fits = font->TextCount( strPtr, clipWidth );
+
+                if ( fits < strPtr.Length() )
+                    {
+                    fits = font->TextCount( strPtr, clipWidth - ellipsisWidth );
+                    
+                    // Work out the text directionality before the truncation point.
+                    // First put the text in reverse order and then call
+                    // TBidiText::TextDirectionality. This effectively tells the
+                    // directionality of the last strongly directional character
+                    // in the text.
+                    HBufC* temp = strPtr.Left( fits ).AllocL();
+                    TPtr tempPtr = temp->Des();
+
+                    TInt i = 0;
+                    TInt j = tempPtr.Length() - 1;
+                    while ( i < j )
+                        {
+                        TText t = tempPtr[i];
+                        tempPtr[i++] = tempPtr[j];
+                        tempPtr[j--] = t;
+                        }
+
+                    TBidiText::TDirectionality dir = 
+                        TBidiText::TextDirectionality( tempPtr );
+
+                    delete temp;
+
+                    TText dirMarker = ( dir == TBidiText::ERightToLeft )
+                        ? KRLMarker
+                        : KLRMarker;
+
+                    // Insert zero width joiner if necessary to get the correct glyph form
+                    // before truncation.
+
+                    TText lastChar = strPtr[fits - 1];
+                    TText next = strPtr[fits];
+                    
+                    TInt ellipsisPos = fits;
+                    
+                    if ( CFont::CharactersJoin( lastChar, KZeroWidthJoiner ) &&
+                         CFont::CharactersJoin( lastChar, next ) )
+                        {
+                        strPtr[fits] = KZeroWidthJoiner;
+                        ellipsisPos++;
+                        }
+                    strPtr.SetMax();
+                    strPtr[ellipsisPos] = KEllipsis;
+                    // Inserting direction marker after the ellipsis ensures that
+                    // the ellipsis is shown on the correct side of the text
+                    // before it.
+                    strPtr[ellipsisPos + 1] = dirMarker;
+
+                    strPtr.SetLength( ellipsisPos + 2 );
+                    }
+                }
+            }
+
+        HBufC* newString = strPtr.AllocL();
+        CleanupStack::PopAndDestroy( 2 );  // string, addressCopy
+
+        CleanupStack::PushL(newString);
+        return newString;
+        }
+    else
+        {
+        HBufC* string = addrTPtr.AllocL();
+        CleanupStack::PopAndDestroy();  // addressCopy
+        CleanupStack::PushL( string );
+        return string;
+        }
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::ReBuildEntryStringsL
+//
+// Re-builds all the text strings. Goes through all the fields in the
+// text and assigns a new string into them. After this we call UpdateAllFieldsL 
+// to update all the fields and after this restores to cursor position
+// to old position if it is valid or to the end of the text.
+// ---------------------------------------------------------
+//
+void CMsgAddressControlEditor::ReBuildEntryStringsL()
+    {
+    const TInt textLength = TextLength();
+    TInt length = textLength;
+    TInt docPos = 0;
+    TFindFieldInfo fieldInfo;
+
+    iCurrentEntry = EntryNumber( CursorPos() );
+
+    while ( length > 0 &&
+            docPos < textLength &&
+            iRichText->FindFields( fieldInfo, docPos, length ) )
+        {
+        CMsgAddressControlEditorField* field =
+            const_cast<CMsgAddressControlEditorField*>( FieldFromPos( fieldInfo.iFirstFieldPos ) );
+
+        HBufC* string = CreateEntryStringLC( *field->Name(), 
+                                             *field->Address(), 
+                                             field->IsVerified() );
+
+        field->SetEntryStringL( *string );
+
+        CleanupStack::PopAndDestroy( string );
+
+        if ( fieldInfo.iFieldCountInRange == 0 ) // no more fields left within a range
+            {
+            break;
+            }
+
+        docPos = fieldInfo.iFirstFieldPos + fieldInfo.iFirstFieldLen;
+        length = textLength - docPos;
+        }
+    
+    if ( IsFocused() )
+        {
+        CancelFepTransaction();
+        }
+    
+    TInt oldCursorPos( CursorPos() );
+
+    // Sets cursor pos always to beginning
+    UpdateAllFieldsL();
+    
+    oldCursorPos = Min( oldCursorPos, TextLength() );
+    
+    // Restore the original cursor position if it was
+    // not out of the limit.
+    SetCursorPosL( oldCursorPos, EFalse );
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::Field
+//
+// Returns a field of the entry aEntryNumber. If there is no field on that entry,
+// returns NULL.
+// ---------------------------------------------------------
+//
+const CMsgAddressControlEditorField* CMsgAddressControlEditor::Field(
+    TInt aEntryNumber ) const
+    {
+    __ASSERT_DEBUG( ( aEntryNumber >= 0 ) &&
+        ( aEntryNumber < iRichText->ParagraphCount() ),
+        Panic( EMsgInvalidEntryNumber ) );
+
+    TInt entryLength = 0;
+    TInt entryStart = iRichText->CharPosOfParagraph( entryLength, aEntryNumber );
+
+    return FieldFromPos( entryStart );
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::CharAtPos
+//
+//
+// ---------------------------------------------------------
+//
+TChar CMsgAddressControlEditor::CharAtPos( TInt aPos ) const
+    {
+    if ( aPos >= 0 && aPos < TextLength() )
+        {
+        TBuf<1> buf;
+        iText->Extract( buf, aPos, 1 );
+        return buf[0];
+        }
+    else
+        {
+        return 0;
+        }
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::PrepareForViewing
+//
+// Prepares control for viewing.
+// ---------------------------------------------------------
+//
+void CMsgAddressControlEditor::PrepareForViewing()
+    {
+    if ( iCurrentEntry >= 0 )
+        {
+        TRAP_IGNORE( MoveCursorToEntryPosL(
+            iCurrentEntry, EntryLength( iCurrentEntry ) ) );
+
+        iCurrentEntry = KMsgCurrentEntryNone;
+        }
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::PreInsertEditorFormattingL
+//
+//
+// ---------------------------------------------------------
+//
+void CMsgAddressControlEditor::PreInsertEditorFormattingL( const TKeyEvent& aKeyEvent )
+    {
+    if ( IsFocused() && !IsReadOnly() )
+        {    
+        TBool modified = EFalse;
+        TInt editPos = CursorPos();
+        
+        // No preinserting is done in a case edit position is over
+        // text length (should not be possible) or if delete key is pressed.
+        if ( editPos > TextLength() ||
+             aKeyEvent.iCode == EKeyDelete )
+            {
+            return;
+            }
+        
+        TInt entryNumber = EntryNumber( editPos );
+        TInt startPos = FirstFieldPos( editPos );
+        TInt endPos = startPos + EntryLength( entryNumber );
+        
+        if ( startPos < editPos && editPos < endPos && 
+             IsEntryVerified( entryNumber ) )
+            {
+            // Cursor is in the middle of verified entry, se inserting not possible.
+            return;
+            }
+            
+        TChar currentChar = CharAtPos( editPos );
+        TChar previousChar = CharAtPos( editPos - 1 );
+        
+        if ( IsFieldOnLeft( editPos + 1 ) ) // looking on the right, but before the key is inserted
+            {
+            // user is trying to add character to left of field:
+            // insert paragraph delimiter in front of the field,
+            // and in front of that a semicolon.
+            iTextView->SetDocPosL( editPos, EFalse );
+            iRichText->CancelInsertCharFormat();
+            InsertParagraphL( editPos );
+            InsertSemicolonL( editPos );
+            modified = ETrue;
+            }
+        else if ( IsFieldOnLeft( editPos ) )
+            {
+            // user is trying to add character to right of field:
+            // insert semicolon after the field if there isn't one already,
+            // and after that a paragraph delimiter.
+            iTextView->SetDocPosL( editPos, EFalse );
+            iRichText->CancelInsertCharFormat();
+            if ( currentChar != KSemicolon && currentChar != KArabicSemicolon )
+                {
+                InsertSemicolonL( editPos );
+                }
+            InsertParagraphL( ++editPos );
+            editPos++;
+            modified = ETrue;
+            }
+        else if ( ( previousChar == KSemicolon || 
+                    previousChar == KArabicSemicolon  ) &&
+                  IsFieldOnLeft( editPos - 1 ) )
+            {
+            // user is trying to add character to right of semicolon
+            // and there is field right next to it:
+            // insert a paragraph delimiter after semicolon.
+            iTextView->SetDocPosL( editPos, EFalse );
+            iRichText->CancelInsertCharFormat();
+            InsertParagraphL( editPos );
+            editPos++;
+            modified = ETrue;
+            }
+            
+        if ( modified )
+            {
+            CheckHighlightingL( EFalse );
+
+            TInt len = TextLength();
+            if ( editPos > len )
+                {
+                editPos = len;
+                }
+
+            iTextView->SetDocPosL( editPos, EFalse );
+
+            TViewYPosQualifier yPosQualifier;
+            yPosQualifier.SetFillScreen();
+            yPosQualifier.SetMakeLineFullyVisible();
+            iTextView->HandleGlobalChangeL( yPosQualifier );
+
+            iHighLightedFieldPos = KMsgHighlightedFieldPosNone;
+            }
+        }
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::PostInsertEditorFormattingL
+//
+//
+// ---------------------------------------------------------
+//
+void CMsgAddressControlEditor::PostInsertEditorFormattingL( TBool aDuplicateEvent )
+    {
+    if ( IsFocused() && !IsReadOnly() )
+        {
+        TInt editPos = CursorPos();
+        if ( editPos > TextLength() )
+            {
+            return;
+            }
+        TChar prevChar = CharAtPos( editPos - 1 );
+
+        if ( !aDuplicateEvent && 
+             ( prevChar == KSemicolon || prevChar == KArabicSemicolon  ) )
+            {
+            // user is at the end of a line, after a semicolon:
+            // paragraph delimiter after semicolon.
+            iTextView->SetDocPosL( editPos, EFalse );
+            iRichText->CancelInsertCharFormat();
+            InsertParagraphL( editPos++ );
+                
+            TInt len = TextLength();
+            if ( editPos > len )
+                {
+                editPos = len;
+                }
+
+            iTextView->SetDocPosL( editPos, EFalse );
+
+            TViewYPosQualifier yPosQualifier;
+            yPosQualifier.SetFillScreen();
+            yPosQualifier.SetMakeLineFullyVisible();
+            iTextView->HandleGlobalChangeL( yPosQualifier );
+
+            iHighLightedFieldPos = KMsgHighlightedFieldPosNone;
+            }
+        }
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::CheckEditPermission
+//
+// Does edit permission check and returns its result.
+// ---------------------------------------------------------
+//
+TUint32 CMsgAddressControlEditor::CheckEditPermission() const
+    {
+    TUint32 editPermission = CMsgBaseControl::EMsgEditNone;
+    TInt textLength = TextLength();
+    TCursorSelection selection = iTextView->Selection();
+
+    if ( selection.Length() )
+        {
+        TInt selLowerPos = selection.LowerPos();
+        // The higherPos is more close to the end of the text
+        TInt selHigherPos = selection.HigherPos();
+        TFindFieldInfo fieldInfoLower;
+        TFindFieldInfo fieldInfoHigher;
+        TBool lowerPosOnField(
+            iRichText->FindFields( fieldInfoLower, selLowerPos, 0 ) );
+        TBool higherPosOnField(
+            iRichText->FindFields( fieldInfoHigher, selHigherPos, 0 ) );
+
+        if ( lowerPosOnField && higherPosOnField )
+            {
+            // Both the lowerPos and the higherPos are on a field
+            if ( IsPosAtEntryBeginning( selLowerPos ) &&
+                IsPosAtEntryBeginning( selHigherPos ) )
+                {
+                // Both positions are at the beginning of the fields
+                editPermission |= CMsgAddressControl::EMsgEditParagraphDelimiter
+                    | CMsgAddressControl::EMsgEditBackspace
+                    | CMsgAddressControl::EMsgEditDelete
+                    | CMsgBaseControl::EMsgEditCut;
+                }
+            }
+        else if ( lowerPosOnField )
+            {
+            if ( IsPosAtEntryBeginning( selLowerPos ) )
+                {
+                editPermission |= CMsgAddressControl::EMsgEditParagraphDelimiter
+                    | CMsgAddressControl::EMsgEditBackspace
+                    | CMsgAddressControl::EMsgEditCharInsert
+                    | CMsgAddressControl::EMsgEditDelete
+                    | CMsgBaseControl::EMsgEditCut
+                    | CMsgBaseControl::EMsgEditPaste;
+                }
+            }
+        else if ( higherPosOnField )
+            {
+            if ( IsPosAtEntryBeginning( selHigherPos ) )
+                {
+                editPermission |= CMsgAddressControl::EMsgEditParagraphDelimiter;
+                }
+            }
+        else if ( IsFieldOnLeft( selLowerPos ) )
+            {
+            // Neither position are on a field but the lower pos is
+            // just next to a field on the right side
+            editPermission |= CMsgAddressControl::EMsgEditParagraphDelimiter;
+            }
+        else
+            {
+            // Neither position are on a field
+            editPermission |= CMsgAddressControl::EMsgEditCharInsert
+                | CMsgAddressControl::EMsgEditParagraphDelimiter
+                | CMsgAddressControl::EMsgEditBackspace
+                | CMsgAddressControl::EMsgEditDelete
+                | CMsgBaseControl::EMsgEditCut
+                | CMsgBaseControl::EMsgEditPaste;
+            }
+
+        // Copy is always possible
+        editPermission |= CMsgBaseControl::EMsgEditCopy;
+
+        // BackspaceMove and RemoveEntry are never possible when selection is on
+        editPermission &= ~CMsgAddressControl::EMsgEditBackspaceMove;
+        editPermission &= ~CMsgAddressControl::EMsgEditRemoveEntry;
+
+        editPermission |=
+            (selHigherPos - selLowerPos) == textLength ?
+            CMsgBaseControl::EMsgEditUnSelectAll : 0;
+        }
+    else
+        {
+        // Selection is off
+        TInt cursorPos = CursorPos();
+        TBool posAtEntryBeginning = IsPosAtEntryBeginning( cursorPos );
+        TChar ch = CharAtPos( cursorPos - 1 );
+        TChar nextCh = CharAtPos( cursorPos );
+
+        if ( ch == CEditableText::EParagraphDelimiter )
+            {
+            ch = CharAtPos( cursorPos - 2 );
+            }
+
+        TInt entryAtPos = EntryNumber( cursorPos );
+
+        if ( IsFieldOnPos( cursorPos ) && !posAtEntryBeginning )
+            {
+            // The cursor is in a field. No edit actions are allowed.
+            editPermission = (TUint32) CMsgBaseControl::EMsgEditNone;
+            }
+        else if ( IsFieldOnLeft( cursorPos ) && !posAtEntryBeginning )
+            {
+            // The cursor is not on a field but just next to it on the right
+            // side. Only the paragraph delimiter can be inserted or the field
+            // can be removed by the backspace.
+            editPermission |= CMsgAddressControl::EMsgEditParagraphDelimiter;
+            editPermission |= CMsgAddressControl::EMsgEditRemoveEntry;
+            editPermission |= CMsgAddressControl::EMsgEditCharInsert;
+            // This should check also a situation when next entry is empty
+            // and when delete is also possible.
+            }
+        else if ( ( ch == KSemicolon || ch == KArabicSemicolon 
+                || IsPriorEntryVerified( entryAtPos ) ) && posAtEntryBeginning )
+            {
+            // The cursor is not in a field but just below it at the
+            // beginning of the line.
+            if ( IsEntryEmpty( entryAtPos ) )
+                {
+                // Current entry is empty. RemoveEntry and BackspaceMove
+                // the edit actions are not allowed.
+                editPermission = (TUint32) CMsgBaseControl::EMsgEditAll;
+                editPermission &= ~CMsgAddressControl::EMsgEditBackspaceMove;
+                editPermission &= ~CMsgAddressControl::EMsgEditRemoveEntry;
+                }
+            else
+                {
+                // Pressing the backspace button is allowed but no char
+                // removal i.e the BackspaceMove is allowed.
+                editPermission = (TUint32) CMsgBaseControl::EMsgEditAll;
+                editPermission &= ~CMsgAddressControl::EMsgEditBackspace;
+                editPermission &= ~CMsgAddressControl::EMsgEditRemoveEntry;
+                }
+            }
+        else
+            {
+            // The cursor is somewhere else but in a field or next to it on
+            // the right side. All but the RemoveEntry and BackspaceMove the
+            // edit actions are allowed.
+            editPermission = (TUint32) CMsgBaseControl::EMsgEditAll;
+            editPermission &= ~CMsgAddressControl::EMsgEditBackspaceMove;
+            editPermission &= ~CMsgAddressControl::EMsgEditRemoveEntry;
+            }
+
+        if ( IsFieldOnRight( cursorPos ) )
+            {
+            // Field immediatelly on right side of curser. Delete and RemoveEntry
+            // are allowed.
+            editPermission |= CMsgAddressControl::EMsgEditDelete;
+            editPermission |= CMsgAddressControl::EMsgEditRemoveEntry;
+            }
+        else if ( IsFieldOnRight( cursorPos + 1) && 
+                  nextCh == CEditableText::EParagraphDelimiter )
+            {
+            // The cursor is not in a field but just above it at the
+            // end of the line.
+            if ( IsEntryEmpty( entryAtPos ) )
+                {
+                // Current entry is empty. RemoveEntry are not allowed.
+                editPermission |= CMsgAddressControl::EMsgEditDelete;
+                editPermission &= ~CMsgAddressControl::EMsgEditRemoveEntry;
+                }
+            else
+                {
+                // Current entry is not empty. Delete is not allowed.
+                editPermission &= ~CMsgAddressControl::EMsgEditDelete;
+                }
+            }
+
+        // Copy is never allowed when selection is off.
+        editPermission &= ~CMsgBaseControl::EMsgEditCopy;
+        // Cut is never allowed when selection is off.
+        editPermission &= ~CMsgBaseControl::EMsgEditCut;
+        // UnSelectAll is never allowed when selection is off.
+        editPermission &= ~CMsgBaseControl::EMsgEditUnSelectAll;
+        }
+
+    editPermission &= ~CMsgBaseControl::EMsgEditUndo; // Undo is never allowed.
+
+    if ( textLength )
+        {
+        editPermission |= CMsgBaseControl::EMsgEditSelectAll;
+        }
+    else
+        {
+        editPermission &= ~CMsgBaseControl::EMsgEditSelectAll;
+        }
+
+    if ( IsReadOnly() )
+        {
+        editPermission &= ~CMsgBaseControl::EMsgEditPaste;
+        editPermission &= ~CMsgBaseControl::EMsgEditCut;
+        editPermission &= ~CMsgAddressControl::EMsgEditRemoveEntry;
+        editPermission &= ~CMsgAddressControl::EMsgEditParagraphDelimiter;
+        editPermission &= ~CMsgAddressControl::EMsgEditCharInsert;
+        }
+
+    return editPermission;
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::ConstructFromResourceL
+//
+// Creates this control from resource.
+// ---------------------------------------------------------
+//
+void CMsgAddressControlEditor::ConstructFromResourceL( TResourceReader& aReader )
+    {
+    // This used to be font id. Not used anymore. Have to read it, though.
+    /*TInt fontId =*/ aReader.ReadInt32();
+
+    ConstructL();
+
+    iAddressControlEditorFieldFactory =
+        new ( ELeave ) TMsgAddressControlEditorFieldFactory();
+
+    if ( !IsReadOnly() )
+        {
+        ReadAknResourceL( aReader );
+        }
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::SetAndGetSizeL
+//
+// Calculates and sets the size of the control and returns new size as
+// reference aSize. Sets maximum height for editor to be maximum
+// body height. If our height has already been set then uses the current
+// one since edwin will decide internally what is the correct height and
+// report this through HandleEdwinSizeEventL observer interface. 
+// After all this finally set the size to 
+// edwin. This might cause reformatting so after this we need to check
+// whether we are band formatting and set the size to maximum body height
+// if we are since edwin will not report height change through HandleEdwinSizeEventL
+// when band formatting is enabled.
+// ---------------------------------------------------------
+//
+void CMsgAddressControlEditor::SetAndGetSizeL( TSize& aSize )
+    {
+    TSize controlSize( aSize );
+    
+    if ( iSize.iHeight > 0 )
+        {
+        controlSize.iHeight = iSize.iHeight;
+        }
+
+    CMsgExpandableControlEditor::SetAndGetSizeL( aSize );
+    
+    // Make sure that if we are band formatting editor size is set
+    // to maximum body height. Will not do any harm resetting this
+    // even if we already are at maximum body height.
+    if ( TextLayout() && TextLayout()->IsFormattingBand() )
+        {
+        controlSize.iHeight = MaximumHeight();
+        SetSizeWithoutNotification( controlSize );
+        }
+    
+    aSize = iSize;
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::OfferKeyEventL
+//
+// Handles key event.
+// ---------------------------------------------------------
+//
+TKeyResponse CMsgAddressControlEditor::OfferKeyEventL(
+    const TKeyEvent& aKeyEvent, TEventCode aType )
+    {
+    if ( IsReadOnly() && 
+        aKeyEvent.iCode == EKeyUpArrow &&
+        iValidHighlightable )
+        {
+        return EKeyWasConsumed;
+        }
+    return CMsgExpandableControlEditor::OfferKeyEventL( aKeyEvent, aType );
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::HandlePointerEventL
+//
+// Handles pointer events. Sets handling pointer event flag on during
+// edwin pointer event handling so that callbacks from edwin can
+// use this information. 
+// In readonly mode:
+// On button down event when automatic find is
+// activated stores the previously focused field if there is one. 
+// On button up event checks whether same field is still focused. 
+// If user has tapped already focused field again selection key menu
+// is launched by simulating key event into it.
+// In non-readonly mode:
+// If user taps in the middle of validated recipient field cursor
+// is moved to the beginning of that field if it is not already located
+// there. Also highlight is checked.
+// ---------------------------------------------------------
+//
+#ifdef RD_SCALABLE_UI_V2
+void CMsgAddressControlEditor::HandlePointerEventL( const TPointerEvent& aPointerEvent )
+    {
+    iHandlingPointerEvent = ETrue;
+    
+    TBool forwardRequest( ETrue );
+    
+    if ( IsReadOnly() )
+        {
+        if ( iValidHighlightable && 
+             ( aPointerEvent.iType == TPointerEvent::EButton1Down ||
+               aPointerEvent.iType == TPointerEvent::EButton1Up ) )
+            {
+            TPoint tapPoint( aPointerEvent.iPosition );
+            TInt docPos( TextView()->XyPosToDocPosL( tapPoint ) );
+            
+            const CMsgAddressControlEditorField* currentField = FieldFromPos( docPos );
+                
+            if ( aPointerEvent.iType == TPointerEvent::EButton1Down )
+                {
+                iPreviousField = currentField;
+                            
+                if ( iPreviousField &&
+                     !iPreviousField->IsVerified() )
+                    {
+                    iPreviousField = NULL;
+                    }
+                else
+                    {
+                    forwardRequest = EFalse;
+                    }
+                }
+            else if ( aPointerEvent.iType == TPointerEvent::EButton1Up )
+                {
+                if ( currentField &&
+                     iPreviousField == currentField )
+                    {
+                    TKeyEvent event;
+                    event.iCode = EKeyDevice3;
+                    event.iScanCode = EStdKeyDevice3;
+                    event.iModifiers = 0;
+                    event.iRepeats = 0;
+                    
+                    iCoeEnv->WsSession().SimulateKeyEvent( event );
+                    
+                    forwardRequest = EFalse;
+                    }
+                }
+            }
+        }
+    else
+        {
+        if ( aPointerEvent.iType == TPointerEvent::EButton1Down ||
+             aPointerEvent.iType == TPointerEvent::EButton1Up )
+            {
+            TPoint tapPoint( aPointerEvent.iPosition );
+            TInt docPos( TextView()->XyPosToDocPosL( tapPoint ) );
+            
+            const CMsgAddressControlEditorField* currentField = FieldFromPos( docPos );
+            
+            if ( currentField &&
+                 currentField->IsVerified() )
+                {
+              //  forwardRequest = EFalse;
+                TInt entryStartPos = EntryStartPos( EntryNumber( docPos ) );
+                if ( entryStartPos != CursorPos() )
+                    {
+                    SetCursorPosL( entryStartPos, EFalse );
+                    CheckHighlightingL();
+                    }                    
+                }
+            }
+        }
+        
+    if ( forwardRequest )
+        {
+        CMsgExpandableControlEditor::HandlePointerEventL( aPointerEvent );
+        }
+#ifdef RD_TACTILE_FEEDBACK         
+    else if(aPointerEvent.iType == TPointerEvent::EButton1Down)
+        {                                
+        MTouchFeedback* feedback = MTouchFeedback::Instance();
+        if ( feedback )
+            {
+            feedback->InstantFeedback( this, ETouchFeedbackBasic );
+            }
+        }
+#endif        
+            
+    iHandlingPointerEvent = EFalse;
+    }
+#else
+void CMsgAddressControlEditor::HandlePointerEventL( const TPointerEvent& /*aPointerEvent*/ )
+    {
+    }
+#endif // RD_SCALABLE_UI_V2
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::HandleResourceChange
+//
+// During layout switching if editor contains text highlight is
+// turned off and entry string are rebuild as width of the editor
+// might have changed. Also underlining is checked.
+// ---------------------------------------------------------
+//
+void CMsgAddressControlEditor::HandleResourceChange( TInt aType )
+    {
+    if ( aType == KEikDynamicLayoutVariantSwitch )
+        {
+        CMsgExpandableControlEditor::HandleResourceChange( aType );
+    
+	    //SKIM-7NKC4B
+        /*if ( TextLength() > 0 )
+            {
+            TRAP_IGNORE( 
+                {
+                TurnHighlightingOffL();
+                ReBuildEntryStringsL();
+            
+                CheckUnderliningL();
+                
+                if ( IsFocused() )
+                    {
+                    CheckHighlightingL( EFalse );
+                    }
+                } );
+            }
+	    */
+        }
+    else
+        {
+        CMsgExpandableControlEditor::HandleResourceChange( aType );
+        }
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::InsertParagraphL
+//
+//
+// ---------------------------------------------------------
+//
+void CMsgAddressControlEditor::InsertParagraphL( TInt aPos )
+    {
+    iRichText->InsertL( aPos, CEditableText::EParagraphDelimiter );
+    iTextView->HandleCharEditL( CTextLayout::EFParagraphDelimiter );
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::InsertSemicolonL
+//
+//
+// ---------------------------------------------------------
+//
+void CMsgAddressControlEditor::InsertSemicolonL( TInt aPos )
+    {
+    TInt langcode = CAknEnv::Static()->SettingCache().InputLanguage();
+    TChar semicolon = ( langcode == ELangArabic )
+        ? KArabicSemicolon
+        : KSemicolon; 
+
+    iRichText->InsertL( aPos, semicolon );
+    iTextView->HandleCharEditL( CTextLayout::EFCharacterInsert );
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::CcpuPasteL
+//
+//
+// ---------------------------------------------------------
+//
+void CMsgAddressControlEditor::CcpuPasteL()
+    {
+    TInt cursorPos = CursorPos();
+    TChar ch = CharAtPos ( cursorPos );
+
+    if ( ch == KSemicolon || ch == KArabicSemicolon )
+        {
+        iRichText->CancelInsertCharFormat();
+        iRichText->InsertL(cursorPos, CEditableText::EParagraphDelimiter);
+        iTextView->HandleCharEditL( CTextLayout::EFParagraphDelimiter );
+        }
+
+    CMsgExpandableControlEditor::CcpuPasteL();
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::SetAddressFieldAutoHighlight
+//
+//
+// ---------------------------------------------------------
+//
+void CMsgAddressControlEditor::SetAddressFieldAutoHighlight( TBool aValidHighlightable )
+    {
+    if ( iValidHighlightable != aValidHighlightable && !aValidHighlightable )
+        {
+        // Automatic find turned off -> cancel selection
+        TRAP_IGNORE( ClearSelectionL() );
+        }
+    iValidHighlightable = aValidHighlightable;
+    
+    TRAP_IGNORE( CheckUnderliningL() );
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::CheckUnderliningL
+//
+//
+// ---------------------------------------------------------
+//
+void CMsgAddressControlEditor::CheckUnderliningL()
+    {
+    TInt textLength = TextLength();
+    TInt length = textLength;
+    TInt docPos = 0;
+    TFindFieldInfo fieldInfo;
+        
+    while ( length > 0 &&
+            docPos < textLength &&
+            iRichText->FindFields( fieldInfo, docPos, length ) )
+        {
+        TCharFormat currentCharFormat;
+        TCharFormatMask currentCharMask;
+        
+        TCharFormat newCharFormat;
+        TCharFormatMask newCharMask;
+        
+        iRichText->GetCharFormat( currentCharFormat,
+                                  currentCharMask,
+                                  fieldInfo.iFirstFieldPos,
+                                  fieldInfo.iFirstFieldLen );
+        
+        if ( iValidHighlightable )
+            {
+            if ( currentCharFormat.iFontPresentation.iUnderline != EUnderlineOn )
+                {
+                newCharFormat.iFontPresentation.iUnderline = EUnderlineOn;
+                newCharMask.SetAttrib( EAttFontUnderline );
+                }
+            }
+        else
+            {
+            if ( currentCharFormat.iFontPresentation.iUnderline != EUnderlineOff )
+                {
+                newCharFormat.iFontPresentation.iUnderline = EUnderlineOff;
+                newCharMask.SetAttrib( EAttFontUnderline );
+                }
+            }
+        
+        if ( newCharMask.AttribIsSet( EAttFontUnderline ) )
+            {
+            iRichText->ApplyCharFormatL( newCharFormat,
+                                         newCharMask,
+                                         fieldInfo.iFirstFieldPos,
+                                         fieldInfo.iFirstFieldLen );
+            }
+        
+        if ( fieldInfo.iFieldCountInRange == 0 ) // no more fields left within a range
+            {
+            break;
+            }
+        
+        docPos = fieldInfo.iFirstFieldPos + fieldInfo.iFirstFieldLen;
+        length = textLength - docPos;
+        }
+    }
+
+// ---------------------------------------------------------
+// CMsgAddressControlEditor::PrepareForReadOnlyL
+// ---------------------------------------------------------
+//
+void CMsgAddressControlEditor::PrepareForReadOnlyL( TBool aReadOnly )
+    {
+    if ( IsReadOnly() == aReadOnly )
+        {
+        return;
+        }
+
+    if ( aReadOnly )
+        {
+#ifdef RD_SCALABLE_UI_V2
+        SetHighlightStyleL( EEikEdwinHighlightLink );
+#endif   
+        
+        SetWordWrapL( EFalse );
+        if ( AddressFieldAutoHighlight() )
+            {
+            SelectAllL(); // for automatic highlight
+            }
+        }
+    
+    CMsgExpandableControlEditor::PrepareForReadOnlyL( aReadOnly );
+    }
+
+//  End of File