email/mail/ViewerSrc/MsgMailViewerAppUi.cpp
changeset 0 72b543305e3a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/email/mail/ViewerSrc/MsgMailViewerAppUi.cpp	Thu Dec 17 08:44:11 2009 +0200
@@ -0,0 +1,2555 @@
+/*
+* 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:  Implements UI class for mail viewer application.
+*
+*/
+
+#include "MailLog.h"
+#include "MsgMailDocument.h"
+#include <MsgMailViewer.rsg>
+#include "MsgMailViewerAppUi.h"
+#include "msgmailviewer.hrh"
+#include "MsgMailViewerDocument.h"
+#include <MsgMailUIDs.h>                // Application UIDs
+#include "MsgMailViewerAttachmentsDlg.h"
+#include "MsgMailPreferences.h"
+#include "MsgMailViewerCharConv.h"
+#include "MailUtils.h"
+#include "Msgmailcharactersethandler.h"
+#include "MsgMailDRMHandler.h"
+#include "CMailCRHandler.h"
+#include "CMailViewManager.h"
+#include "CMailMessage.h"
+#include "mailmessageutils.h"
+#include "CMailMessageView.h"
+#include "cmailoperation.h"
+#include "cmsgmailviewerfinditemhandler.h"
+#include "cmsgmailviewerreplytomatcher.h"
+#include "cmsgmailviewercontactmatcher.h"
+#include "cmsgmailviewercontactcaller.h"
+#include <muiu.mbg>
+#include <avkon.mbg>
+#include <bautils.h>
+#include <CMessageData.h>
+#include <AknsUtils.h>
+#include <eikrted.h>
+#include <aknnotewrappers.h>
+#include <akncontext.h>
+#include <eikmop.h>                     // for SupplyMopObject
+#include <MsgEditorView.h>
+#include <MsgAddressControl.h>
+#include <msvuids.h>                    // KUidMsvFolderEntry
+#include <MsgFolderSelectionDialog.h>   // CMsgFolderSelectionDialog
+#include <AknWaitDialog.h>
+#include <miutpars.h>                   // TImMessageField
+#include <mmsvattachmentmanager.h>
+#include <muiumsvuiserviceutilitiesinternal.h>
+#include <AiwServiceHandler.h>          // aiw
+#include <MuiuMsvProgressReporterOperation.h> // progress note
+#include <MsgEditorCommon.h>
+#include <msgeditor.mbg>
+#include <MsgEditorAppUi.rsg>           // resource identifiers
+#include <MsgAttachmentModel.h>
+#include <MsgEditorCommon.h>
+#include <MsgAttachmentInfo.h>
+#include <MsgEditorAppUi.hrh>
+#include <messagingvariant.hrh>
+#include <MsgAttachmentControl.h>
+#include <StringLoader.h>
+#include <akntitle.h>
+#include <akntoolbar.h>
+#include <hlplch.h>
+#include <csxhelp/mail.hlp.hrh>
+#include <SenduiMtmUids.h>
+#include <sendui.h>
+#include <data_caging_path_literals.hrh>
+#include <featmgr.h>
+#include <msgvoipextension.h>
+#include <CommonUiInternalCRKeys.h>
+#include <MsgEditorAppUiExtension.h>// for iMsgEditorAppUiExtension
+#include <MsgEditorSettingCacheUpdatePlugin.h>
+#include <akninputblock.h>              // CAknInputBlock
+
+
+// LOCAL CONSTANTS
+const TInt KMSKControlID(3);
+
+enum TInternalFlags
+	{
+    EAttachments = KBit0,
+    EUseBaseBodyControl = KBit1
+    };
+
+
+// ================= MEMBER FUNCTIONS =======================
+//
+CMsgMailViewerAppUi::CMsgMailViewerAppUi()
+    : iState(0), iCount(0),
+    iResourceLoader(*iCoeEnv),
+    iMsgVoIPExtension(NULL),
+    iParams(EMailUseDefaultNaviPane),
+    iFlags(0),
+    iAttachmentLoadingOn(EFalse),
+    iDefaultDialerState( EFalse )   // Dialer is disabled by default
+    {
+    }
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::~CMsgMailViewerAppUi()
+// Destructor
+// Frees reserved resources
+// ------------------------------------------------------------------------------
+//
+CMsgMailViewerAppUi::~CMsgMailViewerAppUi()
+    {
+    LOG("~CMsgMailViewerAppUi destructor");
+    delete iContactCaller;
+    delete iContactMatcher;
+    delete iReplyToMatcher;
+    delete iFindItemHandler;
+    delete iServiceHandler;
+    delete iText;
+    delete iCharSetHandler;
+    iResourceLoader.Close();
+    delete iViewManager;
+    delete iMsgVoIPExtension;
+    delete iTitle;
+    // iOperationWatcher can not be deleted if dialog is visible
+    if ( iProgressReporter )
+    	{
+    	TRAP_IGNORE( iProgressReporter->MakeProgressVisibleL( EFalse ) );
+    	}
+    delete iOperationWatcher;
+
+    if(iOpeningWaitDialog)
+	    {
+	    TRAP_IGNORE(iOpeningWaitDialog->ProcessFinishedL());
+	    }
+
+    LOG("~CMsgMailViewerAppUi destructor end");
+    }
+
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::ConstructL()
+// Symbian OS constructor
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::ConstructL()
+    {
+    LOGHEAP();
+    LOG("CMsgMailViewerAppUi::ConstructL");
+    
+    // the implementation of this virtual function must call
+    // CEikAppUi::ConstructL or CEikAppUi::BaseConstructL
+    // before calling any other leaving function
+    CMsgMailAppUi::ConstructL();
+
+    //Set us as an observer for the toolbar
+    if ( PopupToolbar() )
+        {
+        PopupToolbar()->SetToolbarObserver( this );
+        PopupToolbar()->SetToolbarVisibility( ETrue, EFalse );
+        }
+    //Create inpu blocker to prevent unwanted exit event when constructing viewer.
+    CAknInputBlock::NewLC();
+    
+    iViewManager = CMailViewManager::NewL();
+    iView = CMsgEditorView::NewL(*this, CMsgEditorView::EMsgReadOnly);
+
+    //Open wait dialog
+    iOpeningWaitDialog = new(ELeave)CAknWaitDialog(
+    		(reinterpret_cast<CEikDialog**>(&iOpeningWaitDialog)), ETrue);
+
+    // safe to call LD even as a member variable, since sets itself to NULL when deleting
+    iOpeningWaitDialog->ExecuteLD(R_VIEWER_WAIT_OPEN_NOTE); // CSI: 50 # see comment above
+
+    iMsgVoIPExtension = CMsgVoIPExtension::NewL();
+
+	MenuBar()->SetContextMenuTitleResourceId(R_MSGMAILVIEWER_CONTEXT_MENUBAR);
+
+    iFindItemHandler = CMsgMailViewerFindItemHandler::NewL(
+        iView->ItemFinder() );
+
+	iServiceHandler = CAiwServiceHandler::NewL();
+
+    iContactMatcher = CMsgMailViewerContactMatcher::NewL( *iServiceHandler );
+    iContactCaller = CMsgMailViewerContactCaller::NewL( *iServiceHandler,
+                                                        *iContactMatcher );
+    iReplyToMatcher = CMsgMailViewerReplyToMatcher::NewL(*this, *iContactMatcher);
+
+#ifdef RD_MSG_NAVIPANE_IMPROVEMENT
+    iNaviPane = static_cast<CAknNavigationControlContainer*>
+        ( StatusPane( )->ControlL(  TUid::Uid( EEikStatusPaneUidNavi ) ) );
+#endif //RD_MSG_NAVIPANE_IMPROVEMENT
+
+    // Reset Dialer's state
+    SetDialerEnabled( iDefaultDialerState );
+
+    CleanupStack::PopAndDestroy(); // CAknInputBlock
+	LOG("CMsgMailViewerAppUi::ConstructL -> End");
+	LOGHEAP();
+    }
+
+// ------------------------------------------------------------------------------
+// void CMsgMailViewerAppUi::LaunchViewL
+// Opens received mail.
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::LaunchViewL()
+    {
+    LOGHEAP();
+    LOG("CMsgMailViewerAppUi::LaunchViewL");
+    Document()->MailMessage().LoadMessageL(*this);
+
+    // If mail is in sent folder, then Dialer is enabled
+    iDefaultDialerState =
+        MailMessageUtils::IsOutgoingL( Document()->MailMessage() );
+    SetDialerEnabled( iDefaultDialerState );
+    
+    // Dims a delete button from the toolbar if the mail is an attachment mail.
+    if( IsAttachment() )
+    	{
+    	if( PopupToolbar() )
+    		{
+    		PopupToolbar()->SetItemDimmed( EMsgMailViewerCmdDelete, ETrue, ETrue );
+    		}
+    	}
+
+	LOG("CMsgMailViewerAppUi::LaunchViewL -> End");
+	LOGHEAP();
+    }
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::::DynInitMenuPaneL()
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::DynInitMenuPaneL(
+    TInt aResourceId,
+    CEikMenuPane* aMenuPane )
+    {
+    SetContextBackToMessageL();
+
+	CMsgAddressControl* addrCtrl = FocusedOrFirstAddressControl();
+    iFindItemHandler->DynInitMenuPaneL( aResourceId,
+                                        aMenuPane,
+                                        FirstRecipientAddressL( addrCtrl ),
+                                        FirstRecipientNameL( addrCtrl ),
+                                        FocusedControlId() );
+
+    iContactCaller->DynInitMenuPaneL( aResourceId,
+                                      aMenuPane,
+                                      CanMakeCallToContactL() );
+
+    switch ( aResourceId )
+        {
+        case R_MSGMAILVIEWER_OPTIONS_MENU1:
+            {
+            DynInitOptionsMenu1L( *aMenuPane );
+            break;
+            }
+        case R_MSGMAILVIEWER_OPTIONS_MENU2:
+            {
+            DynInitOptionsMenu2L( *aMenuPane );
+            break;
+            }
+
+        case R_MSGMAILVIEWER_REPLY_MENU:
+            {
+			// Hide reply to all if only one recipient
+			aMenuPane->SetItemDimmed(
+				EMsgMailViewerCmdReplyAll,
+				DoHideReplyToAll() );
+
+			// Hide reply to sender if from field is empty
+			aMenuPane->SetItemDimmed(
+				EMsgMailViewerCmdReplySender,
+				DoHideReplyToSender() );
+
+			// received mail
+            if ( !MailMessageUtils::IsOutgoingL( Document()->MailMessage() ) )
+            	{
+	             // unieditor
+	             aMenuPane->SetItemDimmed(
+	                EMsgMailViewerCmdReplyViaUnified,
+	                !ValidateServiceL( KSenduiMtmUniMessageUid ) );
+
+	            // Reply via Audio msg
+                aMenuPane->SetItemDimmed(
+	                EMsgMailViewerCmdReplyViaAudio,
+	                !ValidateServiceL( KSenduiMtmAudioMessageUid ) );
+            	}
+            else
+            	{
+            	// reply to all is visible in sent items
+            	aMenuPane->SetItemDimmed(EMsgMailViewerCmdReplyAll,
+            		!HasAnyAddressFieldText());
+            	aMenuPane->SetItemDimmed(EMsgMailViewerCmdReplySender, ETrue);
+            	}
+
+            break;
+            }
+        case  R_MSGMAILVIEWER_CHARSET_MENU:
+            {
+            iCharSetHandler->SetCharacterSetSubMenuItemsL(
+                *aMenuPane,
+                Document()->Charset());
+
+            break;
+            }
+        case R_MSGMAILVIEWER_ZOOM_SUBMENU:
+            {
+            TInt zoomLevel = KErrGeneral;
+            iMsgEditorAppUiExtension->
+                iSettingCachePlugin.GetValue( KAknLocalZoomLayoutSwitch, zoomLevel );
+            switch ( zoomLevel )
+                {
+                case EAknUiZoomAutomatic:
+                    aMenuPane->SetItemButtonState( EMsgDispSizeAutomatic,
+                                     EEikMenuItemSymbolOn );
+                    break;
+                case EAknUiZoomNormal:
+                    aMenuPane->SetItemButtonState( EMsgDispSizeNormal,
+                                     EEikMenuItemSymbolOn );
+                    break;
+                case EAknUiZoomSmall:
+                    aMenuPane->SetItemButtonState( EMsgDispSizeSmall,
+                                     EEikMenuItemSymbolOn );
+                    break;
+                case EAknUiZoomLarge:
+                    aMenuPane->SetItemButtonState( EMsgDispSizeLarge,
+                                     EEikMenuItemSymbolOn );
+                    break;
+                default:
+                	ASSERT(0);
+                    break;
+                }
+            }
+            break;
+
+        default:
+            {
+            break;
+            }
+        }
+
+    // forwart to Plugin
+    MMailMessageView* messageView = iViewManager->ViewPlugin();
+    if ( messageView )
+    	{
+    	messageView->DynInitMenuPaneL(aResourceId, aMenuPane);
+    	}
+    }
+
+
+// --------------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::HandleKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
+// Handles key press events
+// --------------------------------------------------------------------------------------
+//
+TKeyResponse CMsgMailViewerAppUi::HandleKeyEventL(const TKeyEvent& aKeyEvent,
+                                                  TEventCode aType)
+    {
+    // still launching application
+    if ( !Document()->IsLaunched() )
+        {
+        return EKeyWasConsumed;
+        }
+
+    if (iView)
+        {
+        switch (aKeyEvent.iCode)
+            {
+            case EKeyLeftArrow:
+                {
+                if ( (iParams & EMailUseDefaultNaviPane) &&
+                	IsNextMessageAvailableL(EFalse) )
+                    {
+                    NextMessageL(EFalse);
+                    }
+                break;
+                }
+            case EKeyRightArrow:
+                {
+                if ( (iParams & EMailUseDefaultNaviPane) &&
+                	IsNextMessageAvailableL(ETrue) )
+                    {
+                    NextMessageL(ETrue);
+                    }
+                break;
+                }
+            case EKeyBackspace:
+                {
+                // Checks if this mail is an attachment mail.
+                if( !IsAttachment() )
+                	{
+                	HandleCommandL(EMsgMailViewerCmdDelete);
+                	}
+                break;
+                }
+            case EKeyEnter:
+                {
+                HandleEnterKeyL();
+                break;
+                }
+            case EKeyYes:
+				{
+                HandleEKeyYesL();
+                // FALLTROUGH
+                }
+            default:
+                {
+            	TKeyResponse consumed = SpecialScrolling( aKeyEvent.iCode ) ?
+            	    EKeyWasConsumed : iView->OfferKeyEventL(aKeyEvent, aType);
+			    if (consumed == EKeyWasNotConsumed)
+			    	{
+			    	// forwart to Plugin
+				    MMailMessageView* plugin = iViewManager->ViewPlugin();
+			    	if (plugin && plugin->HandleKeyEventL(
+			    		aKeyEvent, aType) == EKeyWasConsumed)
+			    		{
+			    		consumed = EKeyWasConsumed;
+			    		}
+
+			    	}
+                return consumed;
+                }
+
+            }
+
+
+        return EKeyWasConsumed;
+        }
+    else
+        {
+        // Just in case base class wants to do something
+        return CMsgMailAppUi::HandleKeyEventL(aKeyEvent, aType);
+        }
+    }
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::HandleCommandL(TInt aCommand)
+// Command handler
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::HandleCommandL(TInt aCommand)
+    {
+    // still launching application
+    if ( aCommand != EEikCmdExit && !Document()->IsLaunched() )
+        {
+        return;
+        }
+    TBool isExternalCmd( EFalse );
+    MAIL_ALLOC_TEST( isExternalCmd = HandleExternalCmdL( aCommand ) );
+    if ( !isExternalCmd )
+        {
+        MAIL_ALLOC_TEST( HandleInternalCmdL( aCommand ) );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMsgMailViewerAppUi::HandleNaviDecoratorEventL( TInt aEventID )
+// Handles the touch-ui related control events for next/previous arrows
+// -----------------------------------------------------------------------------
+//
+#ifdef RD_SCALABLE_UI_V2
+void CMsgMailViewerAppUi::HandleNaviDecoratorEventL( TInt aEventID )
+	{
+	if ( AknLayoutUtils::PenEnabled() &&
+		 IsNextMessageAvailableL( aEventID == EAknNaviDecoratorEventRightTabArrow ) )
+	    {
+		NextMessageL( aEventID == EAknNaviDecoratorEventRightTabArrow );
+	    }
+	}
+
+#endif // RD_SCALABLE_UI_V2
+
+// ----------------------------------------------------------------------------
+// CMsgMailViewerAppUi::DynInitToolbarL
+// ----------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::DynInitToolbarL( TInt /*aResourceId*/, CAknToolbar* /*aToolbar*/ )
+	{
+	}
+
+// ----------------------------------------------------------------------------
+// CMsgMailViewerAppUi::OfferToolbarEventL
+// ----------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::OfferToolbarEventL( TInt aCommand )
+	{
+    HandleCommandL( aCommand );
+    }
+
+// ------------------------------------------------------------------------------
+// void CMsgMailViewerAppUi::DoMsgSaveExitL.
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::DoMsgSaveExitL()
+    {
+    Exit();
+    }
+
+// ------------------------------------------------------------------------------
+// void CMsgMailViewerAppUi::DoDeleteL
+// Asks confirmation from user and calls DeleteAndExitL
+// in MsgEditorAppUi which deletes the message and closes mail viewer.
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::DoDeleteL()
+    {
+    CMsgMailViewerDocument* doc = Document();
+
+    const TMsvId owningService( doc->CurrentEntry().OwningService() );
+
+    if ( owningService == KMsvLocalServiceIndexEntryIdValue )
+        { // local entry
+        if ( MailUtils::ConfirmationQueryL( R_MAIL_QUEST_DELETE_MSG ) )
+            {
+            DeleteAndExitL();
+            }
+        return;
+        }
+	// check if operation was canceled
+    if ( !doc->DeleteMessageL() )
+        {
+		Exit( EAknSoftkeyBack );
+		}
+    }
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::HelpContextL
+// ------------------------------------------------------------------------------
+//
+CArrayFix<TCoeHelpContext>* CMsgMailViewerAppUi::HelpContextL( ) const
+    {
+    CArrayFix<TCoeHelpContext>* helpArray =
+                    new( ELeave ) CArrayFixFlat<TCoeHelpContext>( 1 );
+    CleanupStack::PushL( helpArray );
+    // This uses the editor's UID, because there's only one help file
+    helpArray->AppendL( TCoeHelpContext( TUid::Uid( KUidMsgMailEditor ),
+        KMAIL_HLP_MAIL_VIEWER() ) );
+    CleanupStack::Pop( helpArray );
+    return helpArray;
+    }
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::AddAttachmentL()
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::AddAttachmentL(
+	CMsvAttachment& aAttachmentInfo,
+	TBool aCanBeRemoved )
+	{
+	if( !iMessageReload )
+		{
+		CMsgMailViewerDocument* doc = Document();
+	    
+        // Check if attachment is already added. 
+		CMsgAttachmentModel& model = doc->AttachmentModel();
+		TBool duplicate = model.IsIdAttached( aAttachmentInfo.Id() );
+	    if( duplicate )
+	        {
+	        // Remove the previous inline attachment. In IMAP email the inline 
+	        // image does not always have size information included. So it's
+	        // replaced with more informative attachment. Inline attachments are
+	        // added first so the duplicate is always a regular attachment.
+	        for( TInt i = model.NumberOfItems() - 1; i >= 0; --i )
+	            {
+	            CMsgAttachmentInfo& info = model.AttachmentInfoAt( i );
+	            if( info.AttachmentId() == aAttachmentInfo.Id() )
+	                {
+	                model.DeleteAttachment( i );
+	                break;
+	                }
+	            }
+	        }
+
+	    doc->AddAttachmentL( aAttachmentInfo, aCanBeRemoved );
+        if ( doc->MailCRHandler()->MailAttachmentField() && !duplicate )
+            {
+            DoCreateAttachmentControlL();
+
+	        TParsePtrC fileParser( aAttachmentInfo.AttachmentName() );
+	        AttachmentControl()->AppendAttachmentL(
+	            fileParser.NameAndExt() );
+	        }
+	    iFlags |= EAttachments;
+	    DoUpdateNaviPaneL();
+
+	    // If attatchment dialog is already opened
+	    // update its list also
+	    if (iAttachmentdlg)
+	    	{
+	    	iAttachmentdlg->UpdateAttatchmentListL();
+	    	}
+		}
+	}
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::AddControlL()
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::AddControlL(TInt aControlType)
+	{
+    if(! iView->ControlById( aControlType ) )
+    	{
+	    TInt resourceId(0);
+	    TInt controlType(0);
+
+	    switch (aControlType)
+	        {
+	        case EMsgComponentIdTo:
+	            {
+	            resourceId = R_MAIL_VIEWER_TO;
+	            controlType = EMsgAddressControl;
+	            break;
+	            }
+	        case EMsgComponentIdFrom:
+	            {
+	            resourceId = R_MAIL_VIEWER_FROM;
+	            controlType = EMsgAddressControl;
+	            break;
+	            }
+	        case EMsgComponentIdCc:
+	            {
+	            resourceId = R_MAIL_VIEWER_CC;
+	            controlType = EMsgAddressControl;
+	            break;
+	            }
+	        case EMsgComponentIdBcc:
+	            {
+	            resourceId = R_MAIL_VIEWER_BCC;
+	            controlType = EMsgAddressControl;
+	            break;
+	            }
+	        case EMsgComponentIdSubject:
+	            {
+	            resourceId = R_MAIL_VIEWER_SUBJECT;
+	            controlType = EMsgExpandableControl;
+	            break;
+	            }
+	        default:
+	        	User::Leave(KErrNotSupported);
+	            break;
+	        }
+	    iView->AddControlFromResourceL(
+	        resourceId, controlType,
+	        iState, EMsgHeader);
+
+	    iState = EMsgAppendControl;
+    	}
+	}
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::AddControlL()
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::AddControlL(CCoeControl& aControl)
+	{
+	iViewManager->AddBodyControlL( iView, aControl );
+    iState = EMsgAppendControl;
+    iFlags &= ~EUseBaseBodyControl;
+	}
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::AddControlL()
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::AddControlL(MMailMsgBaseControl& aControl)
+	{
+	iViewManager->AddBodyControlL( iView, aControl );
+    iState = EMsgAppendControl;
+    iFlags &= ~EUseBaseBodyControl;
+	}
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::ParentControl()
+// ------------------------------------------------------------------------------
+//
+CCoeControl& CMsgMailViewerAppUi::ParentControl()
+	{
+	return *iView;
+	}
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::StatusPane()
+// ------------------------------------------------------------------------------
+//
+CEikStatusPane* CMsgMailViewerAppUi::StatusPane()
+	{
+	return CAknAppUi::StatusPane();
+	}
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::ShowWaitNoteL()
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::ShowWaitNoteL( TBool aCanCancel )
+	{
+    if (!iWaitDialog)
+        {
+        // safe to call LD even as a member variable,
+        // since sets itself to NULL when deleting
+        iWaitDialog = new(ELeave)CAknWaitDialog(
+        		(reinterpret_cast<CEikDialog**>( &iWaitDialog )), ETrue);
+
+        // safe to call LD even as a member variable, since sets itself to NULL when deleting
+        iWaitDialog->ExecuteLD(R_VIEWER_WAIT_OPEN_DIALOG_NOTE); // CSI: 50 # see comment above
+        iWaitDialog->MakePanelButtonVisible( EAknSoftkeyCancel, aCanCancel );
+        }
+	}
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::CloseWaitNote()
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::CloseWaitNote()
+	{
+     if (iWaitDialog)
+        {
+        LOG("CloseWaitNote 1");
+        TRAP_IGNORE(iWaitDialog->ProcessFinishedL());
+        iWaitDialog = NULL;
+
+        //If attachment dialog exists notify it
+        if(iAttachmentdlg)
+            {
+            iAttachmentdlg->NotifySizeChanged();
+            }
+
+        LOG("CloseWaitNote 2");
+        }
+	}
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::ForwardOperationLL()
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::ForwardOperationL()
+    {
+    CMsvSingleOpWatcher* opwatcher = CMsvSingleOpWatcher::NewLC( *this );
+
+    CMsvProgressReporterOperation* reporter =
+        CMsvProgressReporterOperation::NewL(
+            ( (iFlags & EAttachments) || iAttachmentLoadingOn ), // no delay
+            ETrue, // Show wait animation no progress
+            Document()->Session(),
+            opwatcher->iStatus,
+            EMbmAvkonQgn_note_progress );
+    opwatcher->SetOperation( reporter ); // Takes ownership
+    iProgressReporter = reporter;
+    reporter->SetCanCancelL( EFalse ); // there is nothing to cancel
+    reporter->SetTitleL( ( (iFlags & EAttachments) || iAttachmentLoadingOn ) ?
+        R_QTN_MAIL_WAIT_FETCH_ATT :
+        R_VIEWER_WAIT_OPENING );
+
+    iOperation = Document()->ForwardMailMessageL(
+        *reporter, reporter->RequestStatus(), iAttachmentLoadingOn );
+    reporter->SetOperationL( iOperation ); // Takes ownership
+    // don't allow cancel before there is something to cancel
+    reporter->SetCanCancelL( ETrue );
+
+    CleanupStack::Pop( opwatcher );
+    iOperationWatcher = opwatcher;
+    }
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::StartWaitNoteL()
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::StartWaitNoteL(/*const TDesC& aText*/)
+	{
+    iAttachmentLoadingOn = ETrue;
+    }
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::StopWaitNote()
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::StopWaitNote()
+	{
+    iAttachmentLoadingOn = EFalse;
+
+    if (iOperation )
+        {
+        TRAP_IGNORE( iOperation->SuspendL( EFalse ) );
+        }
+    CloseWaitNote();
+	}
+
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::SetTitleTextL()
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::SetTitleTextL(TInt aResourceId)
+	{
+	CAknTitlePane* titlePane = static_cast<CAknTitlePane *> (
+		StatusPane()->ControlL(TUid::Uid(EEikStatusPaneUidTitle)) );
+
+	TResourceReader reader;
+	iCoeEnv->CreateResourceReaderLC( reader, aResourceId );
+	titlePane->SetFromResourceL(reader);
+	CleanupStack::PopAndDestroy(); // CSI: 12 # CreateResourceReaderLC
+	}
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::SetAddressFieldTextL()
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::SetAddressFieldTextL(
+	TInt aControlType, CDesCArray& aText)
+	{
+	LOG("CMsgMailViewerAppUi::SetAddressFieldTextL");
+	CMsgAddressControl* addressControl = AddressControl(aControlType);
+	if (addressControl)
+		{
+	    TImMessageField msgField;
+	    TInt error = KErrNone;
+	    const TInt count(aText.Count());
+	    CMsgRecipientList* recips = CMsgRecipientList::NewL();
+	    CleanupStack::PushL(recips);
+	    for (TInt i=0; i < count; i++)
+	        {
+	        HBufC* address = msgField.GetValidInternetEmailAddressFromString(
+	            aText[i]).AllocLC();
+	        HBufC* alias = msgField.GetValidAlias(
+	            aText[i], error ).AllocLC();
+	        CMsgRecipientItem* reci = CMsgRecipientItem::NewLC(
+	            ( error==KErrNone ) ? *alias : KNullDesC(), *address);
+	        reci->SetVerified(ETrue);
+	        recips->AppendL(reci);
+	        CleanupStack::Pop( reci ); // reci, now owned by the array
+	        CleanupStack::PopAndDestroy(2,address);	// CSI: 47,12 # alias, address
+	        }
+	    addressControl->Reset();
+	    if (recips->Count())
+	        {
+	        addressControl->AddRecipientsL(*recips);
+	        }
+	    CleanupStack::PopAndDestroy( recips );
+		}
+	}
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::SetAddressFieldTextL()
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::SetAddressFieldTextL(
+	TInt aControlType, const TDesC& aText)
+	{
+	CMsgAddressControl* addressControl = AddressControl(aControlType);
+	if (addressControl)
+		{
+	    TImMessageField msgField;
+	    TInt error = KErrNone;
+	    HBufC* address = msgField.GetValidInternetEmailAddressFromString(
+	        aText).AllocLC();
+	    HBufC* alias = msgField.GetValidAlias(
+	        aText, error).AllocLC();
+	    addressControl->Reset();
+
+        // restored recipients don't have contact link, so NULL
+        MVPbkContactLink* link( NULL );
+	    addressControl->AddRecipientL(
+	        ( error==KErrNone ) ? *alias : KNullDesC(), *address, ETrue, link );
+
+	    CleanupStack::PopAndDestroy( 2, address );	// CSI: 47,12 # alias, address
+		}
+	}
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::SetBodyTextL()
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::SetBodyTextL(CRichText& aText)
+	{
+	BodyControl()->Reset();
+	BodyControl()->SetTextContentL(aText);
+	iFlags |= EUseBaseBodyControl;
+	DoSetAutomaticHighlightL();
+	BodyControl()->Editor().NotifyNewDocumentL();
+	}
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::SetSubjectL
+// Sets subject text into the subject control.
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::SetSubjectL(const TDesC& aText)
+    {
+    CMsgExpandableControl* subjectControl = SubjectControl();
+    if (subjectControl)
+        {
+        subjectControl->Reset();
+        subjectControl->SetTextContentL(aText);
+        }
+    }
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::SetContextBackToMessageL
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::SetContextBackToMessageL()
+    {
+    CMsgMailViewerDocument& doc = *Document();
+    CMailMessage* message = &doc.MailMessage();
+
+    //Check that message is created.
+    //It might be null if we are just opening the viewer.
+    if ( !message )
+        {
+        User::Leave( KErrNotReady);
+        }
+
+    doc.SetEntryWithoutNotificationL(doc.MailMessage().MessageEntry().Id() );
+
+    }
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::MsgViewRect
+// ------------------------------------------------------------------------------
+//
+TRect CMsgMailViewerAppUi::MsgViewRect(TInt aPane)
+	{
+	TRect rect(0,0,0,0);
+
+	switch (aPane)
+		{
+		case 0:
+			rect = MsgEditorCommons::MsgBodyPane();
+			break;
+		case 1:
+			rect = MsgEditorCommons::MsgDataPane();
+			break;
+		case 2:											// CSI: 47 # switch case
+			rect = MsgEditorCommons::MsgMainPane();
+			break;
+		case 3:											// CSI: 47 # switch case
+			rect = MsgEditorCommons::MsgHeaderPane();
+			break;
+		default:
+			{
+			// return zero size rect
+			}
+		}
+	return rect;
+	}
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::AppUiHandleCommandL
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::AppUiHandleCommandL(TInt aCommand)
+	{
+	HandleCommandL(aCommand);
+	}
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::IsNextMessageAvailableL
+// ------------------------------------------------------------------------------
+//
+TBool CMsgMailViewerAppUi::IsNextMessageAvailableL( TBool aForward )
+    {
+    return CMsgEditorAppUi::IsNextMessageAvailableL( aForward );
+    }
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::NextMessageL
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::NextMessageL( TBool aForward )
+    {
+    CMsgEditorAppUi::NextMessageL( aForward );
+    }
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::ViewMessageComplete
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::ViewMessageComplete()
+    {
+    // Dismiss "opening" waitnote
+    if( iOpeningWaitDialog )
+        {
+        TRAP_IGNORE( iOpeningWaitDialog->ProcessFinishedL() );
+        }
+    }
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::MessageLoadingL()
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::MessageLoadingL(TInt aStatus, CMailMessage& aMessage)
+	{
+	LOG1("CMsgMailViewerAppUi::MessageLoadingL: aStatus:%d", aStatus);
+	iViewManager->MessageLoadL(aStatus, aMessage);
+
+	if(aStatus == CMailMessage::ELoadEnd)
+		{
+		for(TInt index=0; index<iViewManager->PluginCount(); ++index)
+			{
+			MMailMessageView* viewPlugin = iViewManager->ViewPlugin();
+			if (viewPlugin)
+				{
+				// Load plugin Resource
+				LoadResourceFileL( viewPlugin->ResourceFile() );
+
+				TRAPD(error, viewPlugin->ViewMessageL(
+					aMessage, *this, iParams));
+				if (error == KErrNone)
+					{
+					break; // success, so break out
+					}
+				else
+					{
+					// Try to open with next plugin
+					iResourceLoader.Close();
+					iViewManager->RemovePlugin();
+					if ( !iViewManager->PluginCount() )
+					    {
+					    ViewMessageComplete();
+					    User::LeaveIfError( error );
+					    }
+					}
+				}
+			}
+        // Context might be somewhere else that in message itself
+        SetContextBackToMessageL();
+
+		iView->ExecuteL(ClientRect(),
+		        GetFirstAddressControl() != NULL
+                ? GetFirstAddressControl()->ControlId() :
+                iView->ControlById(EMsgComponentIdSubject) != NULL
+                ? EMsgComponentIdSubject : EMsgComponentIdNull);
+
+		if ((iParams & EMailUseDefaultNaviPane))
+			{
+			DoUpdateNaviPaneL();
+			}
+
+	    // observer for Automatic highlight key
+	    Document()->MailCRHandler()->SetNotifyHandlerL(this,
+				CMailCRHandler::ECommonUiRepository,
+				CCenRepNotifyHandler::EIntKey,
+	    		KCuiAutomaticHighlight);
+
+		DoSetAutomaticHighlightL();
+
+	    LOGHEAP();
+	    }
+	}
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::OpCompleted()
+// This method is tailor-made for handling completion of forward operation.
+// Other CMsvOperations are taken care by the document class.
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::OpCompleted(
+    CMsvSingleOpWatcher& aOpWatcher,
+	TInt aCompletionCode )
+    {
+	LOG1("CMsgMailViewerAppUi::OpCompleted:%d", aCompletionCode);
+    CMsvOperation* op=&aOpWatcher.Operation();
+	const TInt status( op->iStatus.Int() );
+
+    if ( aCompletionCode == EEikCmdExit || aCompletionCode == EAknSoftkeyBack )
+        {
+        // Exit causes leave with KLeaveExit
+        // Leave is trapped in active sheduler thus iOperationWatcher
+        // can not be deleted before this call.
+
+        if ( !( iEditorBaseFeatures & EStayInViewerAfterReply ) )
+            {
+            Exit(aCompletionCode);
+            }
+        }
+
+    // iOperationWatcher can not be deleted if dialog is visible
+    if ( iProgressReporter )
+    	{
+    	TRAP_IGNORE( iProgressReporter->MakeProgressVisibleL( EFalse ) );
+    	iProgressReporter = NULL;
+    	}
+
+    if ( iOperationWatcher &&
+        iOperationWatcher->Operation().Id()==op->Id() )
+        {
+        LOG("CMsgMailViewerAppUi::OpCompleted: delete iOperationWatcher");
+        delete iOperationWatcher;
+        iOperationWatcher = NULL;
+
+        iOperation = NULL;
+        }
+      }
+
+
+// ------------------------------------------------------------------------------
+// From MProgressDialogCallback called when wait note dismissed
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::DialogDismissedL( TInt aButtonId )
+   {
+   LOG1( "CMsgMailViewerAppUi::DialogDismissedL %d",
+       aButtonId );
+
+    if ( aButtonId == EAknSoftkeyCancel )
+        {
+        delete iAttachmentdlg;
+        iAttachmentdlg = NULL;
+        iWaitDialog = NULL;
+        }
+    }
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::BodyTextL()
+// ------------------------------------------------------------------------------
+//
+CRichText* CMsgMailViewerAppUi::BodyTextL()
+	{
+	return Document()->MailMessage().MessageBody();
+	}
+
+// ------------------------------------------------------------------------------
+// void CMsgMailViewerAppUi::DoReplyOrForwardLL()
+// Replies or forwards a message a message.
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::DoReplyOrForwardL(const TInt aOperation)
+    {
+    CMsgMailViewerDocument& doc = *Document();
+
+    if ( !CheckFFSL( doc.Entry().iSize ) )
+        {
+        return;
+        }
+    switch (aOperation)
+        {
+        case EMsgMailViewerCmdReplySender:
+            ReplyL(doc.DefaultMsgFolder(), ETrue);
+            break;
+        case EMsgMailViewerCmdReplyAll:
+            ReplyToAllL(doc.DefaultMsgFolder(), ETrue);
+            break;
+        case EMsgMailViewerCmdForward:
+            {
+            ForwardOperationL();
+            // calls opcompleted when done
+            return;
+            }
+        default:
+            break;
+        }
+
+    // check exit setting maintained by base editor (common to all types)
+    if ( !( iEditorBaseFeatures & EStayInViewerAfterReply ) )
+        {
+        Exit(EAknSoftkeyBack);
+        }
+    }
+
+// ------------------------------------------------------------------------------
+// void CMsgMailViewerAppUi::DoAttachmentL()
+// Opens an attachment dialog.
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::DoAttachmentL()
+    {
+    //Check if iTitle allready exists
+    if(!iTitle)
+        {
+        iTitle = iCoeEnv->AllocReadResourceLC(
+        R_VIEWER_TITLE_ATTACHMENTS);
+
+        CleanupStack::Pop(iTitle);
+        }
+
+    CMsgAttachmentModel& attmodel = Document()->AttachmentModel();
+
+    iAttachmentdlg = CMsgMailViewerAttachmentsDlg::NewL(*iTitle,
+        attmodel, *Document(), *this );
+
+    iAttachmentdlg->SetMopParent(this);
+
+#ifdef RD_SCALABLE_UI_V2
+    //Hide toolbar
+    if ( PopupToolbar() )
+        {
+        DoHideToolbar( ETrue );
+        }
+#endif // RD_SCALABLE_UI_V2
+
+    // safe to call LD even as a member variable, since sets itself to NULL when deleting
+    iAttachmentdlg->ExecuteLD(R_MAIL_VIEWER_ATTACHMENT_DIALOG); // CSI: 50 # see comment above
+
+    LOG("Attachement dialog launchded");
+
+    if(iAttachmentLoadingOn)
+        {
+        ShowWaitNoteL( ETrue );
+        if ( iWaitDialog )
+            {
+            iWaitDialog->SetCallback( this );
+            }
+        }
+    else
+        {
+        //Update attachment models fetched-flags
+        //if we are not currently loading attachments.
+        if(iAttachmentdlg)
+            {
+            iAttachmentdlg->UpdateAttachmentsFetchFlags();
+            }
+
+        }
+
+    // Dialer is always enabled in attachment dialog
+    SetDialerEnabled( ETrue );
+    }
+
+// ------------------------------------------------------------------------------
+// void CMsgMailViewerAppUi::DoMoveL()
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::DoMoveL()
+    {
+    // Context might be somewhere else that in message itself
+    SetContextBackToMessageL();
+    CMsgMailViewerDocument& doc = *Document();
+
+    TBool moveMessage(doc.CurrentEntry().OwningService() ==
+        KMsvLocalServiceIndexEntryIdValue);
+
+    // Check that file system has enough free space
+    TInt size(0);
+    if ( !moveMessage )
+        {
+        size = doc.Entry().iSize;
+        }
+
+    if (!CheckFFSL(size))
+        {
+        return;
+        }
+
+    HBufC* title = moveMessage ?
+        StringLoader::LoadLC(R_MCE_MOVE_MESSAGES, iCoeEnv) :
+        StringLoader::LoadLC(R_MCE_COPY_MESSAGES, iCoeEnv);
+
+    TMsvId selFolder(doc.Entry().Parent());
+    const TBool select( CMsgFolderSelectionDialog::SelectFolderL(
+        selFolder, *title) );
+    CleanupStack::PopAndDestroy( title );
+
+    if (select)
+        {
+        TMsvId serviceId;
+        TMsvEntry destEntry;
+        User::LeaveIfError(doc.Session().GetEntry(
+            selFolder, serviceId, destEntry));
+        const TBool destinationIsRemote(
+            KMsvLocalServiceIndexEntryIdValue != serviceId);
+        TMsvEntry srcEntry;
+        User::LeaveIfError(doc.Session().GetEntry(
+            doc.Entry().Parent(), serviceId, srcEntry));
+        const TBool sourceIsRemote(
+            KMsvLocalServiceIndexEntryIdValue != serviceId);
+
+        if ( !destinationIsRemote && !sourceIsRemote )
+            {
+            MoveMessageEntryL(selFolder);
+            }
+        else
+            {
+            // Handle remote entries
+			doc.MoveRemoteEntryL(
+			    selFolder, srcEntry.Id(), destinationIsRemote );
+            }
+
+        Exit(EAknSoftkeyBack);
+        }
+    }
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::DoCreateAttachmentControlL()
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::DoCreateAttachmentControlL()
+    {
+    // first attachment to be added?
+    if ( !(iFlags & EAttachments) )
+        {
+        CMsgAttachmentControl* control =
+            CMsgAttachmentControl::NewL( *iView, *iView );
+        CleanupStack::PushL( control );
+        iView->AddControlL( control,
+            EMsgComponentIdAttachment,
+            EMsgAppendControl,
+            EMsgHeader );
+        CleanupStack::Pop( control );
+        }
+    }
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::DoMessageInfoL()
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::DoMessageInfoL() const
+    {
+    Document()->ShowMessageInfoL();
+    }
+
+// ----------------------------------------------------------------------------
+// CMsgMailViewerAppUi::DoHideToolbar()
+// ----------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::DoHideToolbar( const TBool aHide )
+	{
+#ifdef RD_SCALABLE_UI_V2
+	if ( PopupToolbar() )
+        {
+        PopupToolbar()->HideItemsAndDrawOnlyBackground( aHide );
+        }
+#endif // RD_SCALABLE_UI_V
+	}
+
+// ----------------------------------------------------------------------------
+// CMsgMailViewerAppUi::AttachmentDialogExit()
+// ----------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::AttachmentDialogExit()
+	{
+#ifdef RD_SCALABLE_UI_V2
+	if ( PopupToolbar() )
+        {
+        PopupToolbar()->SetToolbarObserver( this );
+        DoHideToolbar( EFalse );
+        }
+#endif // RD_SCALABLE_UI_V
+
+	// Reset Dialer back to default when Attachment dialog exits
+	SetDialerEnabled( iDefaultDialerState );
+	// The NaviDecorator has to be moved to a top of NaviPane's stack so that 
+	// the navigation arrows refresh correctly. CMsgViewAttachmentsDialog
+	// puts an empty NaviDecorator to the top of the stack in constructor and 
+	// pops it in destructor so the empty NaviDecorator is moved back to the 
+	// top of the NaviPane's stack (PushDefaultL).
+	// If the methods leave there is not much possible to do any post-handling 
+	// so only TRAP_IGNORE is used to trap the methods if they leave.
+	TRAP_IGNORE(
+		iNaviPane->PushL( *iNaviDecorator );
+		iNaviPane->PushDefaultL());
+	}
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::HasAddressFieldText()
+// ------------------------------------------------------------------------------
+//
+TBool CMsgMailViewerAppUi::HasAddressFieldText(
+    CMsgAddressControl* aAddressControl) const
+    {
+    if (aAddressControl)
+        {
+        CEikRichTextEditor& fromEditor = aAddressControl->Editor();
+        if (fromEditor.TextLength() > 0)
+            {
+            return ETrue;
+            }
+        }
+    return EFalse;
+    }
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::HasAnyAddressFieldText()
+// ------------------------------------------------------------------------------
+//
+TBool CMsgMailViewerAppUi::HasAnyAddressFieldText() const
+	{
+    CMsgAddressControl* addressField = AddressControl(EMsgComponentIdTo);
+
+    TBool hasText(HasAddressFieldText(addressField));
+    addressField = AddressControl(EMsgComponentIdFrom);
+    hasText = hasText || HasAddressFieldText(addressField);
+    addressField = AddressControl(EMsgComponentIdCc);
+    hasText = hasText || HasAddressFieldText(addressField);
+    addressField = AddressControl(EMsgComponentIdBcc);
+    hasText = hasText || HasAddressFieldText(addressField);
+
+    return hasText;
+	}
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::HasValidFromAddress()
+// ------------------------------------------------------------------------------
+//
+TBool CMsgMailViewerAppUi::HasValidFromAddress() const
+    {
+    CImHeader* header = Document()->MailMessage().MessageHeader();
+    TImMessageField address;
+    return address.ValidInternetEmailAddress( header->From() );
+    }
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::FromOrToAddressL()
+// Returns KNullDesC if address not found
+// ------------------------------------------------------------------------------
+//
+const TDesC& CMsgMailViewerAppUi::FromOrToAddressL() const
+    {
+    CMsgAddressControl* addressField( NULL );
+    if ( !MailMessageUtils::IsOutgoingL( Document()->MailMessage() ) )
+        {
+        addressField = AddressControl( EMsgComponentIdFrom );
+        }
+    else
+        {
+        addressField = AddressControl( EMsgComponentIdTo );
+        }
+    return FirstRecipientAddressL( addressField );
+    }
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::HandleEKeyYesL()
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::HandleEKeyYesL()
+    {
+    const TDesC& address( FromOrToAddressL() );
+
+
+    //Check if call based on email address matching should be done.
+    //If VoIP is installed the email address shouldn't be matched.
+    if(CanMakeCallToContactL() && !VoipProfileExistL())
+        {
+        HandleCommandL(EMsgMailViewerCmdCall);
+        }
+    else
+        {
+        TBool isBodyFocused( FocusedControlId() == EMsgComponentIdBody );
+        CItemFinder::TItemType selectionType(
+            iFindItemHandler->SelectionType( isBodyFocused ) );
+        // will contain selection text or KNullDesC if nothing selected
+        const TDesC& selectionText(
+            iFindItemHandler->SelectionText( isBodyFocused ) );
+
+    	if ( selectionType == CItemFinder::EPhoneNumber )
+    		{
+
+            //Create VoIP call if pref send key is PS and
+            // atleast one VoIP profile.
+            if ( IsDefaultSendKeyValueVoIPL() &&
+                 VoipProfileExistL() )
+                {
+                MsvUiServiceUtilitiesInternal::InternetCallToSenderQueryL(
+					iView->ItemFinder()->
+					CurrentItemExt().iItemDescriptor->Des(),
+					KNullDesC, ETrue );
+                }
+            //otherwise create CS call
+            else
+                {
+                MsvUiServiceUtilitiesInternal::CallToSenderQueryL(
+                    iView->ItemFinder()->
+                    CurrentItemExt().iItemDescriptor->Des(),
+                    KNullDesC,
+                    ETrue );
+                }
+            }
+        else if ( VoipProfileExistL() )
+            {
+            if ( selectionType == CItemFinder::EEmailAddress )
+                {
+                MsvUiServiceUtilitiesInternal::InternetCallServiceL(
+                    address,
+                    Document()->MailMessage().MessageHeader()->From(),
+                    selectionText,
+                    iEikonEnv );
+                }
+            else if ( address.Length() > 0 )
+                { //call to sender
+                MsvUiServiceUtilitiesInternal::InternetCallToSenderQueryL(
+                    address,
+                    KNullDesC,
+                    ETrue );
+                }
+            }
+        }
+
+
+    }
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::GetRecipientArrayL()
+// ------------------------------------------------------------------------------
+//
+CMsgRecipientArray* CMsgMailViewerAppUi::GetRecipientArrayL(
+    CMsgAddressControl* aAddressControl ) const
+    {
+    CMsgRecipientArray* array(NULL); // prevent compiler warning
+    if ( aAddressControl )
+        {
+        array = aAddressControl->GetRecipientsL();
+        }
+    return array;
+    }
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::DoConvertToCharsetL()
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::DoConvertToCharsetL( TUint aCharset )
+    {
+    CMsgMailViewerDocument& doc = *Document();
+    CMailMessage& message = doc.MailMessage();
+    message.Cancel();
+
+	// set override characterset for html message
+	message.OverrideHtmlMessageCharset( aCharset );
+
+	// set the wanted character set for plain text message
+	message.ConvertToCharsetL( aCharset );
+
+	//Conversion complete, update document character set to current one
+    doc.SetCharSet( aCharset );
+
+    //Open wait dialog
+    delete iOpeningWaitDialog;
+    iOpeningWaitDialog = NULL;
+    iOpeningWaitDialog = new(ELeave)CAknWaitDialog(
+    		(reinterpret_cast<CEikDialog**>(&iOpeningWaitDialog)), ETrue );
+    // safe to call LD even as a member variable,
+    // since sets itself to NULL when deleting
+    iOpeningWaitDialog->ExecuteLD(R_VIEWER_WAIT_OPEN_NOTE); // CSI: 50 # see comment above
+
+    // HTML mail does not need to add temporary attachment when the mail is
+    // being reloaded (hence we have a flag for it).
+    // This also prevents the appearance of attachment duplicates when changing
+    // characte encoding
+    iMessageReload = ETrue;
+
+    message.LoadMessageL(*this);
+    }
+
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::DoUpdateNaviPaneL()
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::DoUpdateNaviPaneL()
+    {
+#ifdef RD_MSG_NAVIPANE_IMPROVEMENT
+    if ( !iNaviDecorator )
+        {
+        TMsgEditorMsgPriority priority = EMsgEditorMsgPriorityNormal;
+
+        if ( Document()->MailMessage().MessageEntry().Priority() == EMsvHighPriority )
+            {
+            priority = EMsgEditorMsgPriorityHigh;
+            }
+        else if ( Document()->MailMessage().MessageEntry().Priority() == EMsvLowPriority )
+            {
+            priority = EMsgEditorMsgPriorityLow;
+            }
+
+        CreateViewerNaviPaneL( Document()->Entry().iDate, priority, ETrue );
+        }
+
+    // if attachment dialog is visible don't update navi pane.
+    if( !iAttachmentdlg )
+        {
+        iNaviPane->PushL( *iNaviDecorator );  // <- This has nothing to do with cleanup-stack!
+        }
+
+#else
+
+
+
+	CFbsBitmap* bitmap(NULL);
+	CFbsBitmap* bitmapMask(NULL);
+
+    // if attachment dialog is visible don't update navi pane.
+    if(!iAttachmentdlg)
+        {
+        if ((iFlags & EAttachments) &&
+            !Document()->MailCRHandler()->MailAttachmentField())
+            {
+    	    TAknsItemID skinID (KAknsIIDQgnPropFolderMessageTab1);
+    	    TInt bitmapID(EMbmMsgeditorQgn_prop_folder_message_tab1);
+    	    TInt bitmapMaskID(EMbmMsgeditorQgn_prop_folder_message_tab1_mask);
+
+    	    AknsUtils::CreateIconLC( AknsUtils::SkinInstance(),
+    	        skinID,
+    	        bitmap,
+    	        bitmapMask,
+    	        KMsgEditorMbm,
+    	        bitmapID,
+    	        bitmapMaskID );
+
+    	    // navipane takes ownership of the bitmaps
+    	    UpdateNaviPaneL(bitmap, bitmapMask);
+    	    CleanupStack::Pop( 2, bitmapMask );			// CSI: 47,12 # bitmap, bitmapMask
+            }
+        else
+        	{
+       	    TInt bitmapID( 0 );
+    	    TInt bitmapMaskID( 0 );
+    	    const TMsvPriority messagePriority =
+    	        Document()->MailMessage().MessageEntry().Priority();
+
+    	    if ( messagePriority==EMsvHighPriority )
+    	        {
+      	        bitmapID = EMbmMuiuQgn_indi_mce_priority_high;
+                bitmapMaskID = EMbmMuiuQgn_indi_mce_priority_high_mask;
+    	        }
+            else if ( messagePriority==EMsvLowPriority )
+                {
+      	        bitmapID = EMbmMuiuQgn_indi_mce_priority_low;
+                bitmapMaskID = EMbmMuiuQgn_indi_mce_priority_low_mask;
+                }
+
+            if ( bitmapID )
+                {
+                _LIT(KDirAndMuiuMbmFile,"z:muiu.mbm");
+                TParse fileParse;
+                fileParse.Set( KDirAndMuiuMbmFile, &KDC_APP_BITMAP_DIR, NULL );
+        	    AknsUtils::CreateIconLC( AknsUtils::SkinInstance(),
+        	        KAknsIIDQgnPropFolderMessageTab1,
+        	        bitmap,
+        	        bitmapMask,
+        	        fileParse.FullName(),
+        	        bitmapID,
+        	        bitmapMaskID );
+
+        	    // navipane takes ownership of the bitmaps
+        	    UpdateNaviPaneL(bitmap, bitmapMask);
+        	    CleanupStack::Pop( 2 bitmapMask );				// CSI: 47,12 # bitmap, bitmapMask
+                }
+            else
+                {
+                UpdateNaviPaneL(bitmap, bitmapMask);
+                }
+        	}
+        }
+
+
+
+#ifdef RD_SCALABLE_UI_V2
+	//Register as observer for decorator events
+	if( iNaviDecorator )
+		{
+		iNaviDecorator->SetNaviDecoratorObserver( this );
+		}
+#endif
+
+
+#endif //RD_MSG_NAVIPANE_IMPROVEMENT
+    }
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::HandleExternalCmdL()
+// Command is offered to external handlers one by one until one of
+// them consumes it or no handlers are left.
+// ------------------------------------------------------------------------------
+//
+TBool CMsgMailViewerAppUi::HandleExternalCmdL( TInt aCommand )
+    {
+    // forwart to Plugin
+    MMailMessageView* plugin = iViewManager->ViewPlugin();
+    if ( plugin )
+    	{
+    	if (plugin->HandleCommandL(aCommand))
+    		{
+    		return ETrue;
+    		}
+    	}
+
+    if ( iCharSetHandler )
+        {
+        TUint charSetId;
+        if ( iCharSetHandler->GetCharacterSetId( aCommand, charSetId ) )
+            {
+            DoConvertToCharsetL( charSetId );
+            return ETrue;
+            }
+        }
+
+    if ( iFindItemHandler->CanHandleCommand( aCommand ) )
+        {
+        iFindItemHandler->HandleFinderCommandL( aCommand );
+        return ETrue;
+        }
+
+    if ( iContactCaller->CanHandleCommand( aCommand ) )
+        {
+        iContactCaller->CallToContactL( aCommand, FromOrToAddressL() );
+        return ETrue;
+        }
+
+    return EFalse;
+    }
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::HandleInternalCmdL()
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::HandleInternalCmdL( TInt aCommand )
+    {
+    switch ( aCommand )
+        {
+        case EEikCmdExit:
+            DoMsgSaveExitL();
+            break;
+        case EAknSoftkeyClear:
+                //FALLTHROGH
+        case EMsgMailViewerCmdDelete:
+            DoDeleteL();
+            break;
+        case EAknSoftkeyBack:
+            Exit(EAknSoftkeyBack);
+            break;
+        case EMsgMailViewerCmdReplySender:
+            // FALLTHROUGH
+        case EMsgMailViewerCmdReplyAll:
+            // FALLTHROUGH
+        case EMsgMailViewerCmdForward:
+            DoReplyOrForwardL(aCommand);
+            break;
+        case EMsgMailViewerCmdReplyViaUnified:
+            iReplyToMatcher->CheckMatchesL(KSenduiMtmUniMessageUid,
+            		GetRecipientArrayL(AddressControl( EMsgComponentIdFrom )));
+            break;
+        case EMsgMailViewerCmdReplyViaAudio:
+           iReplyToMatcher->CheckMatchesL(KSenduiMtmAudioMessageUid,
+        		   GetRecipientArrayL(AddressControl( EMsgComponentIdFrom )));
+            break;
+        case EMsgMailViewerCmdAttachments:
+            DoAttachmentL();
+            break;
+        case EMsgMailViewerCmdMove:
+            // FALLTHROUGH
+        case EMsgMailViewerCmdCopy:
+            DoMoveL();
+            break;
+        case EMsgMailViewerCmdMessageInfo:
+            DoMessageInfoL();
+            break;
+        case EAknCmdHelp:
+            // Launch help
+            HlpLauncher::LaunchHelpApplicationL( iEikonEnv->WsSession(),
+                iEikonEnv->EikAppUi()->AppHelpContextL() );
+            break;
+		case EMsgMailViewerCmdRetrieve:
+			DoRetrieveMessageL();
+			break;
+        case EMsgDispSizeAutomatic:
+        // FALLTROUGH
+        case EMsgDispSizeLarge:
+        // FALLTROUGH
+        case EMsgDispSizeNormal:
+        // FALLTROUGH
+        case EMsgDispSizeSmall:
+            HandleLocalZoomChangeL( (TMsgCommonCommands)aCommand );
+            break;
+        default:
+            CMsgMailAppUi::HandleCommandL( aCommand );
+            break;
+        }
+    }
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::DoHideReplyToAll()
+// ------------------------------------------------------------------------------
+//
+TBool CMsgMailViewerAppUi::DoHideReplyToAll() const
+	{
+    return !MessageAddresseeCount();
+	}
+
+// -----------------------------------------------------------------------------
+// CMsgMailViewerAppUi::DoHideReplyToSender()
+// -----------------------------------------------------------------------------
+//
+TBool CMsgMailViewerAppUi::DoHideReplyToSender() const
+	{
+    // From has text
+	CMsgAddressControl* addressField = AddressControl(EMsgComponentIdFrom);
+	if ( addressField && HasAddressFieldText( addressField ) )
+		{
+		return EFalse;
+	    }
+    return ETrue;
+	}
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::MopSupplyObject(TTypeUid aId)
+// Returns a pointer to popup menu.
+// ------------------------------------------------------------------------------
+//
+TTypeUid::Ptr CMsgMailViewerAppUi::MopSupplyObject(TTypeUid aId)
+    {
+    return SupplyMopObject(aId);
+    }
+
+// -----------------------------------------------------------------------------
+// CMsgMailViewerAppUi::HandleNotifyInt
+// -----------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::HandleNotifyInt(
+    TUint32  aId,
+    TInt aNewValue )
+    {
+    // Notifies changes on KCuiAutomaticHighlight
+    if (aId == KCuiAutomaticHighlight)
+    	{
+    	TRAP_IGNORE(SetAutomaticHighlightL( aNewValue ));
+    	}
+    }
+
+// -----------------------------------------------------------------------------
+// CMsgMailViewerAppUi::HandleNotifyError
+// -----------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::HandleNotifyError(
+    TUint32 /* aId */,
+    TInt /* aError */,
+    CCenRepNotifyHandler* /* aHandler */ )
+    {
+    // Do nothing
+    LOG("CMsgMailViewerAppUi::HandleNotifyError");
+    }
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::GetCharsetIdL()
+// ------------------------------------------------------------------------------
+//
+TUint CMsgMailViewerAppUi::GetCharsetIdL() const
+    {
+    //If this is a HTML mail then return the charset in html part
+    if ( Document()->MailMessage().MhtmlPartId() != 0)
+    	{
+    	return Document()->MailMessage().HtmlCharsetIdL();
+    	}
+    //else the regular
+    else
+    	{
+    	return Document()->MailMessage().CharsetIdL();
+    	}
+    }
+
+// -----------------------------------------------------------------------------
+// CMsgMailViewerAppUi::GetFirstAddressControl
+// -----------------------------------------------------------------------------
+//
+CMsgAddressControl* CMsgMailViewerAppUi::GetFirstAddressControl(
+    TBool aDirection ) const
+	{
+	CMsgAddressControl* addressField( NULL );
+	TInt controlId( aDirection ? EMsgComponentIdTo : EMsgComponentIdBcc );
+	TInt count( 1 + ( EMsgComponentIdBcc - EMsgComponentIdTo ) );
+	for ( TInt i( 0 ); i < count; i++ )
+	    {
+	    addressField = AddressControl( controlId );
+	    if ( addressField )
+	        { // found the first address, stop looping
+	        break;
+	        }
+	    aDirection ? ++controlId : --controlId;
+	    }
+	return addressField;
+	}
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::FirstRecipientAddressL()
+// Returns KNullDesC if addresscontrol is NULL or contains no addresses
+// ------------------------------------------------------------------------------
+//
+const TDesC& CMsgMailViewerAppUi::FirstRecipientAddressL(
+    CMsgAddressControl* aAddressControl ) const
+    {
+    CMsgRecipientArray* array = GetRecipientArrayL( aAddressControl );
+    if ( array && array->Count() > 0 )
+        {
+	    return ( *( *array )[0]->Address() ); // first address
+        }
+    else
+    	{
+    	return KNullDesC();
+    	}
+    }
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::FirstRecipientNameL()
+// Returns KNullDesC if addresscontrol is NULL or contains no addresses
+// ------------------------------------------------------------------------------
+//
+const TDesC& CMsgMailViewerAppUi::FirstRecipientNameL(
+    CMsgAddressControl* aAddressControl ) const
+    {
+    CMsgRecipientArray* array = GetRecipientArrayL( aAddressControl );
+    if ( array && array->Count() > 0 )
+        {
+	    return ( *( *array )[0]->Name() ); // first name
+        }
+    else
+    	{
+    	return KNullDesC();
+    	}
+    }
+
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::DoReplyOptionsMenuL()
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::DoReplyOptionsMenuL(CEikMenuPane& aMenuPane)
+    {
+	if ( HasValidFromAddress() )
+	    {
+	    if ( MessageAddresseeCount() ||
+	        ValidateServiceL( KSenduiMtmMmsUid ) ||
+	        ValidateServiceL( KSenduiMtmAudioMessageUid ) ||
+	        ValidateServiceL( KSenduiMtmUniMessageUid ) ||
+	        MailMessageUtils::IsOutgoingL( Document()->MailMessage() ) )
+	        {
+	        // Reply with submenu
+            aMenuPane.SetItemDimmed(
+    	        EMsgMailViewerCmdReply, EFalse );
+	        }
+	    else
+	        {
+	        // Reply to sender
+	        aMenuPane.SetItemDimmed(
+    	            EMsgMailViewerCmdReplySender, EFalse );
+	        }
+	    }
+    }
+
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::DoReplyViaL()
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::DoReplyViaL( TUid aMtmUid, const HBufC* aMatch, const HBufC* aName)
+    {
+    CMsgAddressControl* from = AddressControl( EMsgComponentIdFrom );
+    CMsgRecipientArray* recs = GetRecipientArrayL( from );
+    if ( recs )
+        {
+        CMessageData* messageData = CMessageData::NewL();
+	    CleanupStack::PushL(messageData);
+
+        if( aMatch )
+            {
+            //We have found matching sender address and that should be used
+
+            if( !aName )
+                {
+                //No alias name found. Just matching address added to messageData.
+                messageData->AppendToAddressL(*aMatch);
+                }
+            else
+                {
+                //Both address and alias added to messageData.
+                messageData->AppendToAddressL(*aMatch, *aName);
+                }
+            }
+        else
+            {
+            TInt count( recs->Count() );
+
+            for (TInt index = 0; index < count; index++)
+                {
+                messageData->AppendToAddressL(
+                	*recs->At(index)->Address(),
+                	*recs->At(index)->Name());
+                }
+            }
+        HBufC* subjectText(NULL);
+        CMsgExpandableControl* subjectControl = SubjectControl();
+        if ( subjectControl )
+            {
+            HBufC* buf = subjectControl->Editor().GetTextInHBufL();
+            // editor returns null pointer if subject line is empty,
+            // we must handle that
+            if ( !buf )
+                {
+                buf = HBufC::NewL( 0 );
+                }
+            CleanupStack::PushL( buf );
+            // base editor provides a service which removes unneeded prefixes
+            subjectText = CreateSubjectPrefixStringL( *buf, ETrue );
+            CleanupStack::PopAndDestroy( buf );
+            CleanupStack::PushL( subjectText );
+            }
+    	messageData->SetSubjectL( subjectText );
+    	CleanupStack::PopAndDestroy( subjectText );
+
+		Document()->SendUiL().CreateAndSendMessageL(
+		    aMtmUid, messageData );
+    	CleanupStack::PopAndDestroy(messageData); // messageData
+
+        // check exit setting maintained by base editor (common to all types)
+        if ( !( iEditorBaseFeatures & EStayInViewerAfterReply ) )
+            {
+            Exit(EAknSoftkeyBack);
+            }
+        }
+    }
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::DoRetrieveMessageL()
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::DoRetrieveMessageL()
+    {
+    CMsgMailViewerDocument* doc = Document();
+	doc->RetrieveMessageL();
+
+    // Refresh body text. HTML or plain text
+    doc->MailMessage().LoadMessageL(*this);
+    }
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::SetAutomaticHighlightL()
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::SetAutomaticHighlightL( TInt aValue )
+    {
+    if ( iFlags & EUseBaseBodyControl )
+        {
+        // content highlight
+        if ( aValue )
+            { // switch ON
+            iFindItemHandler->SetFindModeL( CItemFinder::EPhoneNumber |
+                                            CItemFinder::EUrlAddress |
+                                            CItemFinder::EEmailAddress );
+            }
+        else
+            { // switch OFF
+            iFindItemHandler->SetFindModeL( CItemFinder::ENoneSelected );
+            }
+        // header highlight
+        SetAddressControlHighlight(
+            AddressControl(EMsgComponentIdBcc), aValue );
+        SetAddressControlHighlight(
+            AddressControl(EMsgComponentIdCc), aValue );
+        SetAddressControlHighlight(
+            AddressControl(EMsgComponentIdFrom), aValue );
+        SetAddressControlHighlight(
+            AddressControl(EMsgComponentIdTo), aValue );
+        }
+    }
+
+// ------------------------------------------------------------------------------
+// CMsgMailViewerAppUi::DoSetAutomaticHighlightL()
+// ------------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::DoSetAutomaticHighlightL()
+    {
+	TInt value(0);
+	TInt crError = Document()->MailCRHandler()->GetCRInt(
+			KCRUidCommonUi,
+			KCuiAutomaticHighlight,
+			value );
+	SetAutomaticHighlightL(value);
+    }
+
+// -----------------------------------------------------------------------------
+// CMsgMailViewerAppUi::SetAddressControlHighlight
+// -----------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::SetAddressControlHighlight(
+            CMsgAddressControl* aControl, TInt aValue )
+    {
+    if ( aControl )
+        {
+        aControl->SetAddressFieldAutoHighlight( aValue );
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMsgMailViewerAppUi::DynInitOptionsMenu1L
+// -----------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::DynInitOptionsMenu1L(CEikMenuPane& aMenuPane)
+    {
+	// Reply option
+    DoReplyOptionsMenuL( aMenuPane );
+    
+    // Hides a Delete option from options menu if opened mail
+    // is an attachment mail.
+    if( IsAttachment() )
+    	{
+    	aMenuPane.SetItemDimmed( EMsgMailViewerCmdDelete, ETrue );
+    	}
+    }
+
+// -----------------------------------------------------------------------------
+// CMsgMailViewerAppUi::DynInitOptionsMenu2L
+// -----------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::DynInitOptionsMenu2L(CEikMenuPane& aMenuPane)
+    {
+    CMsgMailViewerDocument* doc = Document();
+
+    if ( !(iCommonFlags & EWestern) )
+        {
+        if ( !iCharSetHandler )
+            {
+            //Character set handler is now created, it is possible
+            //that character set changes if the user selects to do so
+            //Current character set must now be checked
+		    if( Document()->Charset() == 0 )
+			    {
+			    Document()->SetCharSet( GetCharsetIdL() );
+			    }
+
+            //Create the character set handler
+            iCharSetHandler = CMsgMailCharacterSetHandler::NewL(
+                EMsgMailViewerFirstCharacterSetCmd);
+            }
+        iCharSetHandler->SetCharacterSetMenuItemL( aMenuPane );
+        }
+
+    // check whether the mail is filtered
+    if (!Document()->MailMessage().MessageEntry().PartialDownloaded())
+        {
+        aMenuPane.DeleteMenuItem( EMsgMailViewerCmdRetrieve );
+        }
+
+    // hide Attachments, if message does not have any
+    aMenuPane.SetItemDimmed(
+    	EMsgMailViewerCmdAttachments,
+    	!( (iFlags & EAttachments) || iAttachmentLoadingOn ) );
+
+    if ( doc->MailCRHandler()->MailCopyMoveSupport() )
+        {
+        // show copy or move depending on if message is local or not
+        if ( doc->CurrentEntry().OwningService() ==
+            KMsvLocalServiceIndexEntryIdValue )
+            {
+            aMenuPane.SetItemDimmed( EMsgMailViewerCmdMove, EFalse );
+            }
+        else
+            {
+            aMenuPane.SetItemDimmed( EMsgMailViewerCmdCopy, EFalse );
+            }
+        }
+    if ( !FeatureManager::FeatureSupported( KFeatureIdHelp ))
+        {
+        aMenuPane.SetItemDimmed( EAknCmdHelp, ETrue );
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMsgMailViewerAppUi::IsDefaultSendKeyValueVoIPL
+// -----------------------------------------------------------------------------
+//
+TBool CMsgMailViewerAppUi::IsDefaultSendKeyValueVoIPL() const
+    {
+    return iMsgVoIPExtension->IsPreferredTelephonyVoIP();
+    }
+
+// -----------------------------------------------------------------------------
+// CMsgMailViewerAppUi::LoadResourceFileL
+// -----------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::LoadResourceFileL(const TDesC& aResourceName)
+	{
+	if ( aResourceName.Length() )
+		{
+		TParse* fp = new(ELeave) TParse();
+    	fp->Set(aResourceName, &KDC_RESOURCE_FILES_DIR, NULL);
+    	TFileName fileName(fp->FullName());
+    	BaflUtils::NearestLanguageFile(
+    		iEikonEnv->FsSession() ,fileName);
+    	LOG1("CMsgMailViewerAppUi iResourceLoader.Open:%S",
+    		&fileName);
+    	delete fp;
+    	// only one resource can be opened, so close previous
+    	iResourceLoader.Close();
+		TInt err = iResourceLoader.Open(fileName);
+		LOG1("iResourceLoader.Open:%d", err);
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CMsgMailViewerAppUi::FocusedControlId
+// returns EMsgComponentIdNull if nothing focused
+// -----------------------------------------------------------------------------
+//
+TMsgControlId CMsgMailViewerAppUi::FocusedControlId() const
+    {
+    TMsgControlId retVal = EMsgComponentIdNull;
+    CMsgBaseControl* ctrl = iView->FocusedControl();
+    if ( ctrl )
+        {
+        retVal = static_cast<TMsgControlId>( ctrl->ControlId() );
+        }
+	return retVal;
+    }
+
+// -----------------------------------------------------------------------------
+// CMsgMailViewerAppUi::ValidateServiceL
+// -----------------------------------------------------------------------------
+//
+TBool CMsgMailViewerAppUi::ValidateServiceL( TUid aUid )
+    {
+    // return ETrue also when service settings are not set
+    TSendingCapabilities dummy;
+    TInt error = Document()->SendUiL().ServiceCapabilitiesL( aUid, dummy );
+    return ( error == KErrNone );
+    }
+
+// -----------------------------------------------------------------------------
+// CMsgMailViewerAppUi::VoipProfileExistL
+// -----------------------------------------------------------------------------
+//
+TBool CMsgMailViewerAppUi::VoipProfileExistL() const
+    {
+    return iMsgVoIPExtension->VoIPProfilesExistL();
+    }
+
+// -----------------------------------------------------------------------------
+// CMsgMailViewerAppUi::MessageAddresseeCount
+// -----------------------------------------------------------------------------
+//
+TInt CMsgMailViewerAppUi::MessageAddresseeCount() const
+    {
+    TInt count(0);
+    CImHeader* header = Document()->MailMessage().MessageHeader();
+	ASSERT( header );
+    count = header->CcRecipients().Count();
+    // Add count only if several to recipients.
+    count += header->ToRecipients().Count() > 1 ?
+        header->ToRecipients().Count() : 0;
+    return count;
+    }
+
+// ---------------------------------------------------------------------------
+// CMsgMailViewerAppUi::SetMiddleSoftKeyLabelL
+// ---------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::SetMiddleSoftKeyLabelL(
+    const TInt aResourceId, const TInt aCommandId )
+    {
+    CEikButtonGroupContainer* cbaGroup = Cba();
+    if ( cbaGroup )
+        {
+        HBufC* middleSKText = StringLoader::LoadLC( aResourceId );
+        TPtr mskPtr = middleSKText->Des();
+        cbaGroup->AddCommandToStackL(
+            KMSKControlID,
+            aCommandId,
+            mskPtr );
+        CleanupStack::PopAndDestroy( middleSKText );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMsgMailViewerAppUi::RemoveMSKCommands
+// -----------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::RemoveMSKCommands()
+    {
+    if ( Cba() )
+        {
+        Cba()->RemoveCommandFromStack( KMSKControlID, EMsgMailViewerCmdAttachments );
+        Cba()->RemoveCommandFromStack( KMSKControlID, EAknSoftkeyContextOptions );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMsgMailViewerAppUi::SpecialScrolling
+// -----------------------------------------------------------------------------
+//
+TBool CMsgMailViewerAppUi::SpecialScrolling( TUint aKeyCode )
+    {
+    TBool keyConsumed( EFalse );
+    // last address is the first when direction is EFalse, may also be NULL
+    CMsgAddressControl* lastAddressControl( GetFirstAddressControl( EFalse ) );
+    if ( aKeyCode == EKeyDownArrow || aKeyCode == EKeyUpArrow )
+        {
+        CMsgBaseControl* focusedControl = iView->FocusedControl();
+        if ( focusedControl )
+            {
+            TInt focused( focusedControl->ControlId() );
+            if ( aKeyCode == EKeyDownArrow )
+                {
+                // Focus in on last address field??
+                if (  lastAddressControl &&
+                      focused == lastAddressControl->ControlId() )
+                    {
+                    // jump directly to atta control
+                    if ( iView->ControlById( EMsgComponentIdAttachment ) )
+                        {
+                        iView->SetFocus( EMsgComponentIdAttachment );
+                        keyConsumed = ETrue;
+                        }
+                    // or directly to body
+                    else if ( BodyControl() )
+                        {
+                        iView->SetFocus( BodyControl()->ControlId() );
+                        keyConsumed = ETrue;
+                        }
+                    }
+                }
+            else
+                {
+                // scroll up, and focus is top of the body part
+                if ( focused == EMsgComponentIdBody &&
+                        BodyControl()->IsFocusChangePossible( EMsgFocusUp ) )
+                        {
+                        // Move focus to atta control
+                        if ( iView->ControlById( EMsgComponentIdAttachment ) )
+                            {
+                            iView->SetFocus( EMsgComponentIdAttachment );
+                            keyConsumed = ETrue;
+                            }
+                        // or move to the last address field if one exists
+                        else if ( lastAddressControl )
+                            {
+                            iView->SetFocus( lastAddressControl->ControlId() );
+                            keyConsumed = ETrue;
+                            }
+                        }
+                // scroll up when focus is on the attachment control and
+                // one address control exists
+                else if ( focused == EMsgComponentIdAttachment &&
+                          lastAddressControl )
+                    {
+                    // Move focus to last address control
+                    iView->SetFocus( lastAddressControl->ControlId() );
+                    keyConsumed = ETrue;
+                    }
+                }
+            }
+        }
+
+    return keyConsumed;
+    }
+// ----------------------------------------------------------------------------
+// void CMsgMailViewerAppUi::EditorObserver()
+// ----------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::EditorObserver( TMsgEditorObserverFunc aFunc,
+                                            TAny* aArg1,
+                                            TAny* aArg2,
+                                            TAny* aArg3)
+    {
+	if ( aFunc == MMsgEditorObserver::EMsgHandleFocusChange )
+		{
+    	ASSERT( aArg1 );
+        TMsgControlId controlId = FocusedControlId();
+    	CMsgBaseControl* focusedControl = iView->FocusedControl();
+
+        TInt err(0);
+
+        if ( Document()->MailCRHandler()->MailAttachmentField() &&
+             controlId == EMsgComponentIdAttachment &&
+             iLastControlId != EMsgComponentIdAttachment )
+            {
+            RemoveMSKCommands();
+
+            //Change msk label to "attachments"
+            TRAP(err, SetMiddleSoftKeyLabelL(R_QTN_MSK_ATTACHMENT, EMsgMailViewerCmdAttachments));
+            }
+         //If last control was atta we must change back to context options menu.
+         else if( iLastControlId == EMsgComponentIdAttachment &&
+                  controlId != EMsgComponentIdAttachment )
+            {
+            RemoveMSKCommands();
+
+            //Change msk label back to normal (context sensitive menu icon)
+            TRAP(err, SetMiddleSoftKeyLabelL(R_TEXT_SOFTKEY_OPTION, EAknSoftkeyContextOptions));
+            }
+
+
+		if(err == KErrNone)
+		    {
+		    //Collect current id, may be EMsgComponentIdNull
+		    iLastControlId = controlId;
+		    }
+
+		}
+#ifdef RD_SCALABLE_UI_V2
+	else if( aFunc == MMsgEditorObserver::EMsgControlPointerEvent )
+		{
+		if( aArg1 && aArg2 )
+			{
+            TPointerEvent* event = static_cast<TPointerEvent*>( aArg2 );
+            CMsgBaseControl* control = static_cast<CMsgBaseControl*>( aArg1 );
+
+            if ( event->iType == TPointerEvent::EButton1Down )
+                {
+                iFocusedControl = control;
+                }
+            else if ( event->iType == TPointerEvent::EButton1Up )
+                {
+				if( control && iFocusedControl == control &&
+					control->ControlId() == EMsgComponentIdAttachment )
+					{
+					//Summon touch functionality
+					TRAP_IGNORE( DoAttachmentL() );
+					}
+                iFocusedControl = NULL;
+                }
+			}
+		}
+#endif
+    CMsgEditorAppUi::EditorObserver(aFunc, aArg1, aArg2, aArg3);
+    }
+
+// --------------------------------------------------------------------------
+// CMsgMailViewerAppUi::CanMakeCallToContactL
+// --------------------------------------------------------------------------
+//
+TBool CMsgMailViewerAppUi::CanMakeCallToContactL() const
+    {
+    TBool retVal( EFalse );
+    // We can show call option in following situations.
+    //From Mail Ui Specification:
+    //Send key initiates a voice call
+    //creation functionality for the sender in case
+    //the focus is in From field, when focus is not in
+    //a phonenumber or in case the auto-highlight
+    //functionality is set off.
+    //Send key is inactive is inactive,
+    //when message is opened from Sent items
+    //folder .
+
+    TBool isBodyFocused( FocusedControlId() == EMsgComponentIdBody );
+    TBool isFromFocused( FocusedControlId() == EMsgComponentIdFrom );
+
+#if defined(__VOIP) && defined(RD_VOIP_REL_2_2)
+    if ( !MailMessageUtils::IsOutgoingL( Document()->MailMessage() ) &&
+         ( !isBodyFocused ) )
+        {
+        retVal = ETrue;
+        }
+#else
+    CItemFinder::TItemType selectionType(
+            iFindItemHandler->SelectionType( isBodyFocused ) );
+
+    if ( !MailMessageUtils::IsOutgoingL( Document()->MailMessage() ) &&
+         ( isFromFocused || selectionType != CItemFinder::EPhoneNumber ) )
+        {
+        retVal = ETrue;
+        }
+#endif // __VOIP && RD_VOIP_REL_2_2
+
+    return retVal;
+    }
+
+// --------------------------------------------------------------------------
+// CMsgMailViewerAppUi::FocusedOrFirstAddressControl
+// This method returns empty string if GetFirstAddressControl() returns NULL
+// --------------------------------------------------------------------------
+//
+CMsgAddressControl* CMsgMailViewerAppUi::FocusedOrFirstAddressControl() const
+    {
+    CMsgAddressControl* addressControl( NULL );
+    TInt controlId( FocusedControlId() );
+	if ( controlId == EMsgComponentIdTo ||
+		 controlId ==  EMsgComponentIdFrom ||
+		 controlId ==  EMsgComponentIdCc ||
+		 controlId ==  EMsgComponentIdBcc )
+	    {
+        addressControl = AddressControl( controlId );
+        }
+    else
+        {
+        addressControl = GetFirstAddressControl();
+        }
+    return addressControl;
+    }
+
+// --------------------------------------------------------------------------
+// CMsgMailViewerAppUi::IsAttachment
+// --------------------------------------------------------------------------
+//
+TBool CMsgMailViewerAppUi::IsAttachment() const
+	{
+	CMsgMailViewerDocument* doc = Document();
+	
+	TMsvId parentId = doc->Entry().Parent();
+    TMsvId serviceId;
+    TMsvEntry entry;
+    
+    // Have to get parent's parent.
+    doc->Session().GetEntry(parentId, serviceId, entry);
+    parentId = entry.Parent();
+    doc->Session().GetEntry(parentId, serviceId, entry);
+    
+    if( entry.Attachment() )
+    	{
+    	return ETrue;
+    	}
+    else
+    	{
+    	return EFalse;
+    	}
+	}
+
+// --------------------------------------------------------------------------
+// CMsgMailViewerAppUi::HandleEnterKeyL
+// Handles enter key events.
+// --------------------------------------------------------------------------
+//
+void CMsgMailViewerAppUi::HandleEnterKeyL()
+    {
+    if( iView )
+        {
+        CMsgBaseControl* focusedCtrl = iView->FocusedControl();
+        if( focusedCtrl )
+            {
+            switch( focusedCtrl->ControlId() )
+                {
+                case EMsgComponentIdAttachment:
+                    {
+                    // Open attachment view
+                    DoAttachmentL();
+                    break;
+                    }
+                default:
+                    {
+                    // Display context menu
+                    CEikMenuBar* menu = MenuBar();
+                    if( menu )
+                        {
+                        menu->TryDisplayContextMenuBarL();
+                        }
+                    break;
+                    }
+                }
+            }
+        }
+    }
+
+// ---------------------------------------------------------
+// CMsgMailViewerAppUi::HandleEntryDeletedL
+//
+// HandleEntryDeletedL is called when the currently open message
+// has been deleted by some other messaging client.
+// ---------------------------------------------------------
+//
+void CMsgMailViewerAppUi::HandleEntryDeletedL()
+    {
+    //If message has been deleted while same entry is open on viewer
+    //we need to close viewer and go back to mce.
+    Exit(EAknSoftkeyBack);
+    }
+
+// End of File