/*
* Copyright (c) 2007 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 : Compose view class
*
*/

// INCLUDE FILES
#include "emailtrace.h"
#include <aknnotewrappers.h>
#include <NpdApi.h>
#include <StringLoader.h>
#include <txtrich.h>
#include <AknWaitDialog.h>
#include <MsgAttachmentUtils.h>
#include <featmgr.h>
#include "cfsmailbox.h"
#include "cfsmailmessage.h"
#include "cfsmailaddress.h"
#include "cfsmailclient.h"
#include "cfsmailcommon.h"
#include <csxhelp/cmail.hlp.hrh>
#include <akntoolbar.h>
#include <akntoolbarextension.h>
#include <AknUtils.h>
#include <FreestyleEmailUi.rsg>
#include <freestyleemailui.mbg>
#include <aknstyluspopupmenu.h>

#include "ncscomposeview.h"
#include "ncscomposeviewcontainer.h"
#include "ncsconstants.h"
#include "ncsutility.h"
#include "ncsemailaddressobject.h"
#include "freestyleemailcenrephandler.h"
#include "FreestyleEmailUi.hrh"
#include "FreestyleEmailUiConstants.h"
#include "FreestyleEmailUiSendAttachmentsListControl.h"
#include "FreestyleEmailUiSendAttachmentsListVisualiser.h"
#include "FreestyleEmailUiSendAttachmentsListModel.h"
#include "FreestyleEmailUiUtilities.h"
#include "FreestyleEmailUiConstants.h"
#include "FSAutoSaver.h"
#include "FSEmail.pan"


// line separators that should not appear in Subject
_LIT(KLineSeparators, "\u2029");
const TChar KReplacementChar = ' ';


#pragma mark +++COMPOSE VIEW - CONSTRUCTORS AND DESTRUCTORS

// -----------------------------------------------------------------------------
// Safe pointer deletion
//
// -----------------------------------------------------------------------------
//
template <class T> void SafeDelete( T*& aPtr )
    {
    delete aPtr;
    aPtr = NULL;
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::CNcsComposeView()
// C++ default constructor can NOT contain any code, that might leave.
// -----------------------------------------------------------------------------
//
CNcsComposeView::CNcsComposeView( CFreestyleEmailUiAppUi& aAppUi,
    CAlfEnv& aEnv, CAlfControlGroup& aSendAttachmentControlGroup,
    CFSMailClient& aMailClient, CMsvSession& aMsvSession )
    : CFsEmailUiViewBase( aSendAttachmentControlGroup, aAppUi ),
     iMailClient( aMailClient ), iOrigMessage( NULL ), iNewMessage( NULL ),
     iMsvSession( aMsvSession ), iEnv( aEnv ),
     iFakeSyncGoingOn(EFalse), iFetchDialogCancelled(EFalse),
     iExecutingDoExitL( EFalse )
    {
    FUNC_LOG;

    iAttachmentListSaveDraft = EFalse;

    }

// -----------------------------------------------------------------------------
// CNcsComposeView::NewL()
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CNcsComposeView* CNcsComposeView::NewL( 
        CFSMailClient& aMailClient, CAlfEnv& aEnv,
        CFreestyleEmailUiAppUi* aAppUi, CAlfControlGroup& aControlGroup,
        CMsvSession& aMsvSession )
    {
    FUNC_LOG;

    CNcsComposeView* self = 
        CNcsComposeView::NewLC( aMailClient, aEnv, aAppUi,
                                aControlGroup, aMsvSession );
    CleanupStack::Pop( self );

    return self;
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::NewLC()
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CNcsComposeView* CNcsComposeView::NewLC(
    CFSMailClient& aMailClient,
    CAlfEnv& aEnv,
    CFreestyleEmailUiAppUi* aAppUi,
    CAlfControlGroup& aControlGroup,
    CMsvSession& aMsvSession )
    {
    FUNC_LOG;

    CNcsComposeView* self = new ( ELeave ) CNcsComposeView( 
            *aAppUi, aEnv, aControlGroup, aMailClient, aMsvSession );
    CleanupStack::PushL( self );
    self->ConstructL();

    return self;
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::ConstructL()
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CNcsComposeView::ConstructL()
    {
    FUNC_LOG;

    BaseConstructL( R_NCS_COMPOSE_VIEW );
    iFirstStartCompleted = EFalse;
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::DoFirstStartL()
// Purpose of this function is to do first start only when msg details is
// really needed to be shown. Implemented to make app startuo faster.
// -----------------------------------------------------------------------------
//
void CNcsComposeView::DoFirstStartL()
    {
    FUNC_LOG;
    // Attachment list for compose screen, owned by AlfEnv
    CAlfControlGroup& attListControlGroup = 
        iEnv.NewControlGroupL( KSendAttachmentManagerDisplayGroup );
    CFSEmailUiSendAttachmentsListVisualiser* sendAttachmentVisualiser =
        CFSEmailUiSendAttachmentsListVisualiser::NewLC(
            iEnv, &iAppUi, attListControlGroup );
    iAppUi.AddViewL( sendAttachmentVisualiser );
    CleanupStack::Pop( sendAttachmentVisualiser );

    iCrHandler = CFSEmailCRHandler::InstanceL(); // singleton, not owned

    iEnv.AddActionObserverL( this );

    iAutoSaver = CFsAutoSaver::NewL( iEnv, KAutoSaveTimeDelayMs );
    iAutoSaver->Enable( EFalse );
    iFirstStartCompleted = ETrue;
    iCheckQuery = EFalse;
    iAsyncCallback = new (ELeave) CAsyncCallBack( CActive::EPriorityLow );
    // msk context menu added into composer
    MenuBar()->SetContextMenuTitleResourceId( R_NCS_COMPOSE_BODY_MSK_MENUBAR );
    iActiveHelper = CActiveHelper::NewL( this );

    iAsyncAttachmentAdd = 
        new (ELeave) CAsyncCallBack( CActive::EPriorityStandard );
    
    // Initializing the default stylus long tap popup menu
	if( !iStylusPopUpMenu )
		{
		TPoint point( 0, 0 );
		iStylusPopUpMenu = CAknStylusPopUpMenu::NewL( this, point );
		TResourceReader reader;
		iCoeEnv->CreateResourceReaderLC( reader,
				R_STYLUS_POPUP_MENU_COMPOSE_VIEW_ATTACHMENT );
		iStylusPopUpMenu->ConstructFromResourceL( reader );
		CleanupStack::PopAndDestroy(); // reader
		}
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::~CNcsComposeView()
// Destructor.
// -----------------------------------------------------------------------------
//
CNcsComposeView::~CNcsComposeView()
    {
    FUNC_LOG;
	delete iAutoSaver;
	if ( iAsyncCallback )
	    {
	    iAsyncCallback->Cancel();
	    delete iAsyncCallback;
	    }
    delete iFetchLogic;
    if( iActiveHelper )
        {
        iActiveHelper->Cancel();
        delete iActiveHelper;
        }
    if ( iAsyncAttachmentAdd )
        {
        iAsyncAttachmentAdd->Cancel();
        delete iAsyncAttachmentAdd;
        }
    delete iStylusPopUpMenu;
    }

void CNcsComposeView::PrepareForExit()
    {
    FUNC_LOG;
    if ( iCheckQuery && iDlg )
        {
        TKeyEvent check = { EKeyEscape, EStdKeyNull, 0, 0 };
        TRAP_IGNORE( iDlg->OfferKeyEventL( check, EEventKey ) );
        iDlg = NULL;

        iAsyncCallback->Cancel(); // cancel any outstanding callback
        iAsyncCallback->Set( TCallBack( AsyncExit, this ) );
        iAsyncCallback->CallBack();
        }
    else if( iFakeSyncGoingOn || iExecutingDoExitL )
        {
        // low priority active obj so that iwait in plugins finish
        iActiveHelper->Cancel();
        iActiveHelper->Start();
        }
    else
        {
        DoSafeExit( ESaveDraft );
        }

    if( iFetchLogic )
        {
        iFetchLogic->CancelFetchings();
        }
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::Id()
// Returns View's ID.
// -----------------------------------------------------------------------------
//
TUid CNcsComposeView::Id() const
    {
    FUNC_LOG;
    return MailEditorId;
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::ChildDoActivateL()
// Activate the Compose view
// -----------------------------------------------------------------------------
//
void CNcsComposeView::ChildDoActivateL( const TVwsViewId& aPrevViewId,
    TUid aCustomMessageId, const TDesC8& aCustomMessage )
    {
    FUNC_LOG;
    if ( !iFirstStartCompleted )
        {
        DoFirstStartL();
        }
    Toolbar()->SetDimmed( ETrue );
    // Set status pane indicators
    iStatusPaneIndicators = iAppUi.GetStatusPaneIndicatorContainer();
    iStatusPaneIndicators->ShowStatusPaneIndicators();

    // Notify base class about view being entered unless 
    // returned from another view
    if ( aCustomMessageId.iUid != KEditorCmdReturnToPrevious )
        {
        ViewEntered( aPrevViewId );
        }

    // Cleanup the previous message before opening a new one
    SaveAndCleanPreviousMessage();

    // Get the launch parameters
    if ( aCustomMessageId.iUid == KEditorCmdReturnToPrevious )
        {
        // Use previous launch parameters when returning to previously 
        // opened message
        iMailBox = iMailClient.GetMailBoxByUidL( iLaunchParams.iMailboxId );
        }
    else if ( aCustomMessage.Length() > 0 )
        {

        TPckgBuf<TEditorLaunchParams> buf( iLaunchParams );
        buf.Copy( aCustomMessage );
        iLaunchParams = buf();
        iMailBox = iMailClient.GetMailBoxByUidL( iLaunchParams.iMailboxId );

        }
    else
        {
        iLaunchParams.iActivatedExternally = ETrue;
        }

    // Inform the AppUi about external view activation to fix the view stack.
    // Normally this happens based on the previous view AppUid in the BaseView
    // but in case contacts action menu was used within FsEmail, this doesn' 
    // work. It doesn't hurt to call this again even if it was already called
    // once from BaseView.
    if ( iLaunchParams.iActivatedExternally )
        {
        iAppUi.ViewActivatedExternallyL( Id() );
        }

    // Try to get the mailbox by other means if using launch parameters failed
    if ( !iMailBox )
        {
        TInt error( KErrNone );

        // can we get it from MSV Id
        // MSV id is passed to us when account is defined email key settings
        if ( aCustomMessageId != TUid::Null() )
            {
            TRAP( error, iMailBox = TFsEmailUiUtility::GetMailboxForMtmIdL( 
                    iMailClient, iMsvSession, aCustomMessageId.iUid ) );
            }

        error = KErrNone;

        // try to use mailbox set as default in MCE
        if ( !iMailBox )
            {
            TRAP( error, iMailBox = TFsEmailUiUtility::GetMceDefaultMailboxL(
                    iMailClient, iMsvSession ) );
            }

        // use first mail account from the list
        if ( !iMailBox )
            {
            TFSMailMsgId id;
            RPointerArray<CFSMailBox> mailboxes;
            CleanupResetAndDestroyClosePushL( mailboxes );
            iMailClient.ListMailBoxes( id, mailboxes );
            if ( mailboxes.Count() > 0 )
                {
                iMailBox = 
                    iMailClient.GetMailBoxByUidL( mailboxes[0]->GetId() );
                }
            CleanupStack::PopAndDestroy( &mailboxes );
            }

        // could not get mailbox so leave
        if ( !iMailBox )
            {
            User::Leave( KErrGeneral );
            }

        aCustomMessageId = TUid::Uid( KEditorCmdCreateNew );
        }


    iMailSent = EFalse;
    iMailSendFailed = EFalse;
    iCustomMessageId = aCustomMessageId;

    CreateContainerL();

    TRAPD( err, HandleActivationCommandL( aCustomMessageId ) );
    if ( !err )
        {
        err = iMailFetchingErrCode;
        }

    if ( err == KErrCancel || 
         err == KErrCouldNotConnect || 
         err == KErrConnectionTerminated )
        {
        // Just close composer without any notes if operation was cancelled.
        // For connection errors, DownloadInfoMediator already shows error 
        // message, so no need to show another one.
        ExitComposer();
        }
    else if ( err )
        {
        // some other error => show generic error note and close composer
        if( !iAppUi.AppUiExitOngoing() )
            TFsEmailUiUtility::ShowErrorNoteL( 
                R_FREESTYLE_EMAIL_ERROR_GENERAL_UNABLE_TO_COMPLETE, ETrue );
        ExitComposer();
        }
    else
        {
        // everything went fine => do rest of the generic initialization
        InitUiGeneralL();
        iAppUi.StartEndKeyCapture();
        iContainer->SetMskL();
        iViewReady = ETrue;
        Toolbar()->SetDimmed( EFalse );
        RefreshToolbar();
        }
        
    // if there is a embedded app in FSEmail.
    if( iAppUi.EmbeddedApp() )
        {
        // Set email editor started from embedded app flag to true 
        // so that we can switch view correct when sent email.
        iAppUi.SetEditorStartedFromEmbeddedApp( ETrue );
        
        RWsSession rwsSession;
        User::LeaveIfError( rwsSession.Connect() );
        CleanupClosePushL( rwsSession );
        
        // Simulate a back key to exit embedded app 
        // so that email editor could show on the top level.
        TKeyEvent KeyEvent = TKeyEvent();
        KeyEvent.iCode = EKeyCBA2;
        rwsSession.SimulateKeyEvent( KeyEvent );

        rwsSession.Close();
        CleanupStack::PopAndDestroy( &rwsSession );
        }
        
    TIMESTAMP( "Editor launched" );
    }

// -----------------------------------------------------------------------------
// Initialises toolbar items.
// -----------------------------------------------------------------------------
//
void CNcsComposeView::DynInitToolbarL( TInt aResourceId,
    CAknToolbar* aToolbar )
    {
    FUNC_LOG;
    if ( aResourceId == EFsEmailUiTbCmdExpandActions && aToolbar )
        {
        CAknToolbarExtension* ext = aToolbar->ToolbarExtension();
        if ( iContainer )
            {
            // Set correct state for show/hide cc field button.
            CAknButton* ccButton = Button( EFsEmailUiTbCmdCcField, ext );
            if ( ccButton )
                {
                TInt index = iContainer->IsCcFieldVisible() ? 1 : 0;
                ccButton->SetCurrentState( index, EFalse );

                // Command is dimmed, if there is content in the field.
                ccButton->SetDimmed( iContainer->GetCcFieldLength() > 0 );
                }

            // Set correct state for show/hide bcc field button.
            CAknButton* bccButton = Button( EFsEmailUiTbCmdBccField, ext );
            if ( bccButton )
                {
                TInt index = iContainer->IsBccFieldVisible() ? 1 : 0;
                bccButton->SetCurrentState( index, EFalse );

                // Command is dimmed, if there is content in the field.
                bccButton->SetDimmed( iContainer->GetBccFieldLength() > 0 );
                }
            }
        else
            {
            ext->HideItemL( EFsEmailUiTbCmdCcField, ETrue );
            ext->HideItemL( EFsEmailUiTbCmdBccField, ETrue );
            }

        if ( iNewMessage )
            {
            // Set correct state for low priority button.
            TBool lowPriority = iNewMessage->IsFlagSet( EFSMsgFlag_Low );
            CAknButton* lowPriorityButton = static_cast<CAknButton*>(
                ext->ControlOrNull( EFsEmailUiTbCmdLowPriority ) );
            if ( lowPriorityButton )
                {
                TInt index = lowPriority ? 1 : 0;
                lowPriorityButton->SetCurrentState( index, EFalse ); 
                }

            // Set correct state for high priority button.
            TBool highPriority = iNewMessage->IsFlagSet( EFSMsgFlag_Important );
            CAknButton* highPriorityButton = static_cast<CAknButton*>(
                ext->ControlOrNull( EFsEmailUiTbCmdHighPriority ) );
            if ( highPriorityButton )
                {
                TInt index = highPriority ? 1 : 0;
                highPriorityButton->SetCurrentState( index, EFalse );
                }

            // Set correct state for follow up button.
            TBool followUp = iNewMessage->IsFlagSet( EFSMsgFlag_FollowUp );
            CAknButton* followUpButton = static_cast<CAknButton*>(
                ext->ControlOrNull( EFsEmailUiTbCmdFollowUp ) );
            if ( followUpButton )
                {
                TInt index = followUp ? 1 : 0;
                followUpButton->SetCurrentState( index, EFalse );

                // Hide follow up button, if follow up is not supported.
                ext->HideItemL( EFsEmailUiTbCmdFollowUp,
                    !TFsEmailUiUtility::IsFollowUpSupported( *iMailBox ) );
                }
            }
        else
            {
            ext->HideItemL( EFsEmailUiTbCmdLowPriority, ETrue );
            ext->HideItemL( EFsEmailUiTbCmdHighPriority, ETrue );
            ext->HideItemL( EFsEmailUiTbCmdFollowUp, ETrue );
            }
        }
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::OfferToolbarEventL
// -----------------------------------------------------------------------------
void CNcsComposeView::OfferToolbarEventL( TInt aCommand )
    {
    FUNC_LOG;
    TBool attachmentAddition = EFalse;
    switch ( aCommand )
        {
        case EFsEmailUiTbCmdSend:
            if ( iContainer && iContainer->AreAddressFieldsEmpty() )
                {
                RefreshToolbar();
                }
            else
                {
                HandleCommandL( ENcsCmdSend );
                }
            break;
        case EFsEmailUiTbCmdCcField:
            {
            CAknButton* ccFieldButton = Button( EFsEmailUiTbCmdCcField );
            if ( ccFieldButton )
                {
                if ( ccFieldButton->StateIndex() )
                    {
                    HandleCommandL( ENcsCmdShowCc );
                    }
                else
                    {
                    HandleCommandL( ENcsCmdHideCc );
                    }
                }
            break;
            }
        case EFsEmailUiTbCmdBccField:
            {
            CAknButton* bccFieldButton = Button( EFsEmailUiTbCmdBccField );
            if ( bccFieldButton )
                {
                if ( bccFieldButton->StateIndex()  )
                    {
                    HandleCommandL( ENcsCmdShowBcc );
                    }
                else
                    {
                    HandleCommandL( ENcsCmdHideBcc );
                    }
                }
            break;
            }
        case EFsEmailUiTbCmdLowPriority:
            {
            CAknButton* lowPriorityButton = Button( EFsEmailUiTbCmdLowPriority );
            if ( lowPriorityButton )
                {
                if ( lowPriorityButton->StateIndex() )
                    {
                    CAknButton* highPriorityButton = Button( 
                        EFsEmailUiTbCmdHighPriority );
                    if ( highPriorityButton )
                        {
                        highPriorityButton->SetCurrentState( 0, ETrue );
                        }
                    HandleCommandL( ENcsCmdPriorityLow );
                    }
                else
                    {
                    HandleCommandL( ENcsCmdPriorityNormal );
                    }
                }
            break;
            }
        case EFsEmailUiTbCmdHighPriority:
            {
            CAknButton* highPriorityButton = Button( EFsEmailUiTbCmdHighPriority );
            if ( highPriorityButton )
                {
                if ( highPriorityButton->StateIndex() )
                    {
                    CAknButton* lowPriorityButton = Button( 
                        EFsEmailUiTbCmdLowPriority );
                    if ( lowPriorityButton )
                        {
                        lowPriorityButton->SetCurrentState( 0, ETrue );
                        }
                    HandleCommandL( ENcsCmdPriorityHigh );
                    }
                else
                    {
                    HandleCommandL( ENcsCmdPriorityNormal );
                    }
                }
            break;
            }
        case EFsEmailUiTbCmdFollowUp:
            {
            CAknButton* button = Button( EFsEmailUiTbCmdFollowUp );
            if ( button && iNewMessage )
                {
                if ( button->StateIndex() )
                    {
                    iNewMessage->SetFlag( EFSMsgFlag_FollowUp );
                    iNewMessage->ResetFlag( EFSMsgFlag_FollowUpComplete );
                    iStatusPaneIndicators->SetFollowUpFlag( 
                        CCustomStatuspaneIndicators::EFollowUp );
                    }
                else
                    {
                    iNewMessage->ResetFlag( EFSMsgFlag_FollowUp 
                        | EFSMsgFlag_FollowUpComplete );
                    iStatusPaneIndicators->SetFollowUpFlag( 
                        CCustomStatuspaneIndicators::EFollowUpNone );
                    }
                }
            break;
            }
        case EFsEmailUiTbCmdInsertAudio:
            iAttachmentAddType = MsgAttachmentUtils::EAudio;
            attachmentAddition = ETrue;
            break;
        case EFsEmailUiTbCmdInsertImage:
            iAttachmentAddType = MsgAttachmentUtils::EImage;
            attachmentAddition = ETrue;
            break;
        case EFsEmailUiTbCmdInsertVideo:
            iAttachmentAddType = MsgAttachmentUtils::EVideo;
            attachmentAddition = ETrue;
            break;
        case EFsEmailUiTbCmdInsertNote:
            iAttachmentAddType = MsgAttachmentUtils::ENote;
            attachmentAddition = ETrue;
            break;
        case EFsEmailUiTbCmdInsertPresentation:
            iAttachmentAddType = MsgAttachmentUtils::ESVG;
            attachmentAddition = ETrue;
            break;
        case EFsEmailUiTbCmdInsertOther:
            iAttachmentAddType = MsgAttachmentUtils::EUnknown;
            attachmentAddition = ETrue;
            break;
        default:
            break;
        }
    if ( attachmentAddition )
        {
        iAsyncAttachmentAdd->Cancel(); // cancel any outstanding callback
        iAsyncAttachmentAdd->Set( TCallBack( AsyncAddAttachment, this ) );
        iAsyncAttachmentAdd->CallBack();
        }
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::ToolbarResourceId()
// -----------------------------------------------------------------------------
//
TInt CNcsComposeView::ToolbarResourceId() const
    {
    FUNC_LOG;
    return R_FREESTYLE_EMAIL_UI_TOOLBAR_MESSAGE_EDITOR;
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::GetInitiallyDimmedItemsL()
// -----------------------------------------------------------------------------
//
void CNcsComposeView::GetInitiallyDimmedItemsL( const TInt aResourceId,
        RArray<TInt>& aDimmedItems ) const
    {
    FUNC_LOG;
    aDimmedItems.Reset();
    switch ( aResourceId )
        {
        case R_FREESTYLE_EMAIL_UI_TOOLBAR_MESSAGE_EDITOR:
            aDimmedItems.AppendL( EFsEmailUiTbCmdSend );
            break;
        default:
            break;
        }
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::RefreshToolbar()
// -----------------------------------------------------------------------------
//
void CNcsComposeView::RefreshToolbar()
    {
    FUNC_LOG;
    if ( iContainer )
        {
        // DimAllOptions if remotesearch is in progress, 
        // because it takes you into a different view
        TBool dimAllOptions = iContainer->IsRemoteSearchInprogress();
        SetToolbarItemDimmed( EFsEmailUiTbCmdExpandActions, dimAllOptions );
        SetToolbarItemDimmed( EFsEmailUiTbCmdExpandInsert, dimAllOptions );
        SetToolbarItemDimmed( EFsEmailUiTbCmdSend, dimAllOptions 
            || iContainer->AreAddressFieldsEmpty() );
        }
    }


// -----------------------------------------------------------------------------
// CNcsComposeView::ChildDoDeactivate()
// Deactivate the Compose view
// -----------------------------------------------------------------------------
//
void CNcsComposeView::ChildDoDeactivate()
    {
    FUNC_LOG;

    iAppUi.StopEndKeyCapture();

    SafeDelete( iFetchLogic );

    // Normally Comopser state has been already cleaned by now but in special
    // cases (like external view activation while in Composer) this may not be
    // the case. In those cases the message needs to be saved before the view
    // is deactivated.
    if ( !iAppUi.AppUiExitOngoing() )
        {
        SaveAndCleanPreviousMessage();
        }

    }

// -----------------------------------------------------------------------------
// CNcsComposeView::DynInitMenuPaneL()
// -----------------------------------------------------------------------------
//
void CNcsComposeView::DynInitMenuPaneL( TInt aResourceId,
                                        CEikMenuPane* aMenuPane )
    {
    FUNC_LOG;

    if ( !iViewReady )
        {
        User::Leave( KErrNcsComposeViewNotReady );
        }

    __ASSERT_DEBUG( iContainer, Panic( ENcsBasicUi ) );
    __ASSERT_DEBUG( iMailBox, Panic( ENcsBasicUi ) );
    __ASSERT_DEBUG( iNewMessage, Panic( ENcsBasicUi ) );

    //we are forbiding to change MSK label, because popup will be opened 
    iContainer->SwitchChangeMskOff( ETrue );
    
    if ( aResourceId == R_NCS_COMPOSE_MENU )
        {
	    if ( FeatureManager::FeatureSupported( 
	            KFeatureIdFfCmailIntegration ) )
		   {
		   // remove help support in pf5250
		   aMenuPane->SetItemDimmed( EAknCmdHelp, ETrue);      
		   }     
        
    	// Disable send if there are no addresses in any of the AIF fields,
    	if ( iContainer->AreAddressFieldsEmpty() )
		    {
	    	aMenuPane->DeleteMenuItem( ENcsCmdSend );
		    }

	    // If no attachments, delete the remove attachments menu item
		CFreestyleEmailUiSendAttachmentsListControl* attachmentControl;
		attachmentControl = AttachmentsListControl();
		TInt count = attachmentControl->Model()->Count();

        // if mail has remote attachments then attachments can't be 
		// removed via options menu
		if ( count <= 0 || 
		     AttachmentsListControl()->Model()->HasReadOnlyAttachments() )
	    	{
    		aMenuPane->DeleteMenuItem( ENcsCmdRemoveAttachment );
    		aMenuPane->DeleteMenuItem( ENcsCmdRemoveAllAttachments );
	    	}
        else if ( count == 1 )
	     	{
    		aMenuPane->DeleteMenuItem( ENcsCmdRemoveAllAttachments );
	     	}
        else
	     	{
    		aMenuPane->DeleteMenuItem( ENcsCmdRemoveAttachment );
	     	}

        if ( iContainer->GetCcFieldLength() > 0 &&
             iContainer->GetBccFieldLength() > 0 )
        	{
            aMenuPane->DeleteMenuItem( ENcsCmdMore );
        	}

        if ( !TFsEmailUiUtility::IsFollowUpSupported( *iMailBox ) )
        	{
    		aMenuPane->DeleteMenuItem( ENcsCmdFlag );
        	}
        }

    if ( aResourceId == R_NCS_EXTRA_RECEPIENT_FIELDS_MENU )
        {
		// Select which View->CC menu items to show
		if ( iContainer->IsCcFieldVisible() )
            {
            aMenuPane->DeleteMenuItem( ENcsCmdShowCc );
            // if there is text in Cc field do not show "hide Cc" menu item
            if ( iContainer->GetCcFieldLength() > 0 )
            	{
            	aMenuPane->DeleteMenuItem( ENcsCmdHideCc );
            	}
            }
        else
            {
        	aMenuPane->DeleteMenuItem( ENcsCmdHideCc );
            }

		// Select which View->BCC menu items to show
        if ( iContainer->IsBccFieldVisible() )
            {
            aMenuPane->DeleteMenuItem( ENcsCmdShowBcc );
            // if there is text in Bcc field do not show "hide Bcc" menu item
            if ( iContainer->GetBccFieldLength() > 0 )
            	{
            	aMenuPane->DeleteMenuItem( ENcsCmdHideBcc );
            	}
            }
        else
            {
            aMenuPane->DeleteMenuItem( ENcsCmdHideBcc );
            }
        }

	if ( aResourceId == R_NCS_PRIORITY_MENU )
    	{

        if ( iNewMessage->IsFlagSet( EFSMsgFlag_Important ) )
            {
            aMenuPane->DeleteMenuItem( ENcsCmdPriorityHigh );
            }
        else if ( iNewMessage->IsFlagSet( EFSMsgFlag_Low ) )
            {
            aMenuPane->DeleteMenuItem( ENcsCmdPriorityLow );
            }
        else
            {
            aMenuPane->DeleteMenuItem( ENcsCmdPriorityNormal );
            }
    	}

    }

// -----------------------------------------------------------------------------
// CNcsComposeView::HandleCommandL()
// Takes care of Command handling.
// -----------------------------------------------------------------------------
//
void CNcsComposeView::HandleCommandL( TInt aCommand )
    {
    FUNC_LOG;

    // Attempt to handle commands only after view is fully activated and exit
    // has not yet been initiated.
    if ( iViewReady && !iAppUi.ViewSwitchingOngoing() )
        {
        __ASSERT_DEBUG( iContainer, Panic( ENcsBasicUi ) );
        __ASSERT_DEBUG( iNewMessage, Panic( ENcsBasicUi ) );
        __ASSERT_DEBUG( iCrHandler, Panic( ENcsBasicUi ) );

        switch( aCommand )
            {
            case ENcsCmdSend:
                {
                // Show query if the Subject field is empty
                if ( iContainer->IsSubjectFieldEmpty() )
                    {
                    TInt answer = TFsEmailUiUtility::ShowConfirmationQueryL(
                            R_FREESTYLE_EMAIL_QUERY_NO_SUBJECT );
                    if ( !answer )
                        {
                        // user didn't want to send yet
                        // -> go back to the message
                        return;
                        }
                    }

                TRAPD( error, DoSendL() );
                if ( !error )
                    {
                    // Sending successful
                    HBufC* confMessage = NULL;
                    if ( !TFsEmailUiUtility::IsOfflineModeL() )
                        {
                        // when sync status is currently ONLINE
                        confMessage = StringLoader::LoadLC( 
                                R_FREESTYLE_EMAIL_CONFIRM_NOTE_SENDING_QUEUED );
                        }
                    else
                        {
                        // when sync status is currently OFFLINE
                        confMessage = StringLoader::LoadLC( 
                                R_FREESTYLE_EMAIL_CONFIRM_NOTE_QUEUED_UNTIL_ONLINE );
                        }
                    CAknConfirmationNote* note = 
                        new (ELeave) CAknConfirmationNote( ETrue ); //waiting
                    note->SetTimeout( CAknNoteDialog::ELongTimeout );
                    note->ExecuteLD( *confMessage );
                    CleanupStack::PopAndDestroy( confMessage );
                    DoSafeExit(); // Exit after successful sending
                    }
                else if ( error == KErrBadName )
                	{
                  	// sending failed because recipient address was invalid
                	TFsEmailUiUtility::ShowErrorNoteL( 
                        R_FREESTYLE_EMAIL_CONFIRM_NOTE_INVALID_EMAIL_ADDRESS,
                        ETrue );
                	}
                else
                	{
                	// sending failed for some other reason
                    TFsEmailUiUtility::ShowErrorNoteL( 
                        R_FREESTYLE_EMAIL_CONFIRM_NOTE_MESSAGE_NOT_SENT,
                        ETrue );
                    // Exit after sending failed for other reason for other
                    // reason than KErrBadName
                	DoSafeExit();
                	}
                }
                break;
            case ENcsCmdAddAttachment:
           	 	{
                if ( AknLayoutUtils::PenEnabled() )
                    {
                    // show the toolbar
                    UpdateToolbarL();
                    CAknToolbar* toolbar = Toolbar();
                    if ( toolbar )
                        {
                        CAknToolbarExtension* extension =
                            static_cast<CAknToolbarExtension*>(
                                toolbar->ControlOrNull( EFsEmailUiTbCmdExpandInsert ) );
                        if ( extension )
                            {
                            extension->SetShown( ETrue );
                            }
                        }
                    }
                else
                    {
                    iAttachmentAddType = MsgAttachmentUtils::EUnknown;
                    iAsyncAttachmentAdd->Cancel();
                    iAsyncAttachmentAdd->Set( 
                            TCallBack( AsyncAddAttachment, this ) );
                    iAsyncAttachmentAdd->CallBack();
                    iContainer->SetMskL();
                    }                
           	 	}
                break;
            case EFsEmailUiCmdOpenAttachment:
            case EFsEmailUiCmdOpenAttachmentList:
                {
                DoOpenAttachmentListL();
                }
                break;
            case ENcsCmdRemoveAttachment:
            case EFsEmailUiCmdRemoveAttachment:
                {
                TInt index( iContainer->FocusedAttachmentLabelIndex() );
                CFreestyleEmailUiSendAttachmentsListControl* ctrl =
                    AttachmentsListControl();
                if ( ctrl && KNoAttachmentLabelFocused != index )
                    {
                    ctrl->RemoveAttachmentFromListL( index );
                    }
                SetAttachmentLabelContentL();
                }
                break;
            case ENcsCmdRemoveAllAttachments:
           	 	{
           	 	CFreestyleEmailUiSendAttachmentsListControl* ctrl =
                    AttachmentsListControl();
           	 	if ( ctrl )
           	 	    {
           	 	    ctrl->RemoveAllAttachmentsL();
           	 	    }
           	 	SetAttachmentLabelContentL();
            	}
                break;
            case ENcsCmdPriorityHigh:
            	{
            	iNewMessage->ResetFlag( EFSMsgFlag_Low );
            	iNewMessage->SetFlag( EFSMsgFlag_Important );
            	iNewMessage->SaveMessageL();
            	iStatusPaneIndicators->SetPriorityFlag( EMsgPriorityHigh );
            	}
                break;
        	case ENcsCmdPriorityNormal:
    	    	{
            	iNewMessage->ResetFlag( EFSMsgFlag_Low );
            	iNewMessage->ResetFlag( EFSMsgFlag_Important );
            	iNewMessage->SaveMessageL();
            	iStatusPaneIndicators->SetPriorityFlag( EMsgPriorityNormal );
    	    	}
                break;
        	case ENcsCmdPriorityLow:
    	    	{
            	iNewMessage->ResetFlag( EFSMsgFlag_Important );
            	iNewMessage->SetFlag( EFSMsgFlag_Low );
            	iNewMessage->SaveMessageL();
            	iStatusPaneIndicators->SetPriorityFlag( EMsgPriorityLow );
    	    	}
                break;
            case ENcsCmdShowCc:
                {
                iContainer->SetCcFieldVisibleL( ETrue );
                iCrHandler->SetEditorCCVisible( 1 );
                }
                break;
            case ENcsCmdHideCc:
                {
                iContainer->SetCcFieldVisibleL( EFalse );
                iCrHandler->SetEditorCCVisible( 0 );
                }
                break;
            case ENcsCmdShowBcc:
                {
                iContainer->SetBccFieldVisibleL( ETrue );
                iCrHandler->SetEditorBCVisible( 1 );
                }
                break;
            case ENcsCmdHideBcc:
                {
                iContainer->SetBccFieldVisibleL( EFalse );
                iCrHandler->SetEditorBCVisible( 0 );
                }
                break;
            case ENcsCmdFlag:
    	        {
    	        RunFollowUpFlagDlgL();
    	        }
                break;
            case ENcsCmdQuickText:
    	        {
    	        DoQuickTextL();
    	        }
                break;
            case ENcsCmdInsertContact:
            case ENcsInsertContact:
            	{
            	iContainer->AppendAddressesL();
            	}
                break;
            case ENcsCmdSaveDraft:
            	{

                iContainer->FixSemicolonL();


            	TRAPD( saveDraftError, DoSaveDraftL( EFalse ) );
                if ( saveDraftError == KErrNone )
                	{
                    // Saving successful
                	if( !iAppUi.AppUiExitOngoing() )
                	TFsEmailUiUtility::ShowInfoNoteL( 
                        R_FREESTYLE_EMAIL_CONFIRM_NOTE_SAVED_TO_DRAFTS,
                        ETrue );
                    }
            	else
                    {
                    // error occured in saving -> show an error message
                    if( !iAppUi.AppUiExitOngoing() )
                        TFsEmailUiUtility::ShowErrorNoteL( 
                            R_FREESTYLE_EMAIL_ERROR_GENERAL_UNABLE_TO_COMPLETE,
                            ETrue );
                    }

            	DoSafeExit( ENoSave );
            	}
                break;
            case EAknCmdHelp:
            	{
            	TFsEmailUiUtility::LaunchHelpL( KFSE_HLP_LAUNCHER_GRID );
    	        }
            	break;
            case EAknSoftkeySelect:
                {
                iContainer->DoPopupSelectL();
                }
                break;
       	    case EAknSoftkeyCancel:
        	    {
    	 		iContainer->ClosePopupContactListL();
                }
                break;
            case EAknSoftkeyClose:
                {
                DoSafeExit();
                }
                break;
            case ENcsCmdExit:
                {
                TIMESTAMP( "Exit selected from editor" );
                iAppUi.Exit();
                }
                break;
            default:
                {
                // empty implementation
                // these commands are passed next to FEP for processing
                }
                break;
            }
        }

    }

// -----------------------------------------------------------------------------
// CNcsComposeView::DoSendL()
// Send message
// -----------------------------------------------------------------------------
//
void CNcsComposeView::DoSendL()
    {
    FUNC_LOG;

    // check that addresses exist
    if ( iContainer->AreAddressFieldsEmpty() )
        {
        User::Leave( KErrNotFound );
        }

	CommitL();

    TRAPD(r, iMailBox->SendMessageL( *iNewMessage ) );
    if ( KErrNone != r )
        {
        iMailSendFailed = ETrue;
        User::Leave( r );
        }

    // prevent sending failure if original message is
    // removed from server while replying/forwarding
	TRAPD( flagError, SetReplyForwardFlagL() );

    if ( KErrNone != flagError && KErrNotFound != flagError )
        {
        iMailSendFailed = ETrue;
        User::Leave( flagError );
        }

    iMailSent = ETrue;

    }


// -----------------------------------------------------------------------------
// CNcsComposeView::DoSaveDraftL()
// Saves message to Drafts
// Displays dialog asking user choice if preferred
// Pressing cancel in the query dialog causes Leave with code KErrCancel
// -----------------------------------------------------------------------------
//
TBool CNcsComposeView::DoSaveDraftL( TBool aAskUser )
    {
    FUNC_LOG;

    __ASSERT_DEBUG( iNewMessage, Panic( ENcsBasicUi ) );

    TBool result( ETrue );

    if ( aAskUser )
        {
    	TInt selectedOption( -1 );
    	CDesCArrayFlat* array = new (ELeave) CDesCArrayFlat( 2 );
    	CleanupStack::PushL( array );

    	HBufC* saveItem = StringLoader::LoadLC( R_NCS_DRAFT_SAVE );
        array->AppendL( *saveItem );
		CleanupStack::PopAndDestroy( saveItem );

    	HBufC* deleteItem = StringLoader::LoadLC( R_NCS_DRAFT_DELETE );
        array->AppendL( *deleteItem );
		CleanupStack::PopAndDestroy( deleteItem );

		iDlg = new (ELeave) CAknListQueryDialog( &selectedOption );
    	iDlg->PrepareLC( R_DRAFT_QUERY_DIALOG );
    	iDlg->SetItemTextArray( array );
    	iDlg->SetOwnershipType( ELbmDoesNotOwnItemArray );

        iCheckQuery = ETrue;
        //we are forbiding to change MSK label, cause popup will be opend 
        iContainer->SwitchChangeMskOff( ETrue );
        TInt ret = iDlg->RunLD();
        iDlg = NULL;

        iCheckQuery = EFalse; 
        iContainer->SwitchChangeMskOff( EFalse );

    	if ( !ret )
    	    {
    	    selectedOption = KErrCancel;
    	    }

    	switch ( selectedOption )
    		{
    		case 0:
    			{
				TRAPD( saveError, SaveToDraftsL( ETrue ) );

				if ( saveError == KErrNone )
				    {
				    // User wanted to save to Drafts and saving was successful
				    if( !iAppUi.AppUiExitOngoing() )
				        TFsEmailUiUtility::ShowInfoNoteL( 
                            R_FREESTYLE_EMAIL_CONFIRM_NOTE_SAVED_TO_DRAFTS, 
                            ETrue );
				    }
				else
				    {

				    // error occured in saving -> show an error message
				    if( !iAppUi.AppUiExitOngoing() )
				        TFsEmailUiUtility::ShowErrorNoteL( 
                            R_FREESTYLE_EMAIL_ERROR_GENERAL_UNABLE_TO_COMPLETE,
                            ETrue );

				    // let's return EFalse so after completing this query
				    // so the focus would stay in compose view (same behaviour
				    // as if Cancel was pressed )
				    result = EFalse;
				    }
				}
                break;
    		case 1:
    			{
    			TIMESTAMP( "Delete draft message selected in editor" ); 
				TRAPD( error, SaveToDraftsL( ETrue ) );
    			if ( KErrNone != error )
    			    {
    			    }
    			// for delete messages fake sync calls
    	        iFakeSyncGoingOn = ETrue;
                error = NcsUtility::DeleteMessage( iMailClient,
            		iMailBox->GetId(),
            		iNewMessage->GetFolderId(),
            		iNewMessage->GetMessageId() );

    			if ( KErrNone == error && 
    			     iMailBox->HasCapability( 
    			             EFSMBoxCapaSupportsDeletedItemsFolder ) )
    			    {
                    error = NcsUtility::DeleteMessage( iMailClient,
                		iMailBox->GetId(),
                		iMailBox->GetStandardFolderId( EFSDeleted ),
                		iNewMessage->GetMessageId() );
    			    }
    		     iFakeSyncGoingOn = EFalse;

                if( !iAppUi.AppUiExitOngoing() )
                    {
                    if ( KErrNone != error )
                        {
                        // error occured in saving -> show an error message
                        TFsEmailUiUtility::ShowErrorNoteL( 
                            R_FREESTYLE_EMAIL_ERROR_GENERAL_UNABLE_TO_COMPLETE,
                            ETrue );
                        }
                    else
                        {
                        // Simulate delete event so that drafts folder is
                        // updated correctly.
                        RArray<TFSMailMsgId> messageIds;
                        CleanupClosePushL( messageIds );
                        messageIds.AppendL( iNewMessage->GetMessageId() );
                        TFSMailMsgId folderId = iNewMessage->GetFolderId();
                        TFSMailMsgId mailboxId = iNewMessage->GetMailBoxId();
                        iAppUi.EventL( TFSEventMailDeleted,
                            mailboxId, &messageIds, &folderId, NULL );
                        CleanupStack::PopAndDestroy( &messageIds );
                        }
                    }
                }
                break;
    		default:
    			{
    			result = EFalse;
    			}
                break;
    		}
    	CleanupStack::PopAndDestroy( array );
        }
    else  // no question from user
        {
        SaveToDraftsL( ETrue );
        }

    return result;
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::NewMessage()
// Returns pointer to currently composed mail message
// -----------------------------------------------------------------------------
//
CFSMailMessage* CNcsComposeView::NewMessage()
    {
    FUNC_LOG;
	return iNewMessage;
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::AsyncAddAttachmentL()
// Open file dialog and add selected file as an attachment
// -----------------------------------------------------------------------------
//
TInt CNcsComposeView::AsyncAddAttachment( TAny* aSelfPtr )
    {
    FUNC_LOG;

    CNcsComposeView* self = static_cast<CNcsComposeView*>( aSelfPtr );

    // get pointer to attachment list view
	CFreestyleEmailUiSendAttachmentsListControl* attachmentControl;
	attachmentControl = self->AttachmentsListControl();

   	// show file dialog and get file name
	TBool ok = EFalse;
	TRAPD( error, ok = attachmentControl->AppendAttachmentToListL(
                self->iAttachmentAddType) );
	if ( ok && error == KErrNone )
	    {
	    TRAPD( error, self->SetAttachmentLabelContentL() );
	    return error;
	    }
	return error;
    }

// -----------------------------------------------------------------------------
// RunFollowUpFlagDlgL()
// Query user for followup flag
// -----------------------------------------------------------------------------
//
void CNcsComposeView::RunFollowUpFlagDlgL()
    {
    FUNC_LOG;
    if ( iNewMessage && TFsEmailUiUtility::IsFollowUpSupported( *iMailBox ) )
        {
        TFollowUpNewState newState =
            TFsEmailUiUtility::SetMessageFollowupFlagL( 
                    *iNewMessage, EFalse );

        switch ( newState )
            {
            case EFollowUp:
                {
                iStatusPaneIndicators->SetFollowUpFlag( 
                        CCustomStatuspaneIndicators::EFollowUp );
                }
                break;
            case EFollowUpComplete:
                {
                iStatusPaneIndicators->SetFollowUpFlag( 
                        CCustomStatuspaneIndicators::EFollowUpComplete );
                }
                break;
            case EFollowUpClear:
                {
                iStatusPaneIndicators->SetFollowUpFlag( 
                        CCustomStatuspaneIndicators::EFollowUpNone );
                }
                break;
            default:
                {
                // do nothing.
                }
                break;
            }
        }
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::SetAttachmentLabelContentL()
// Open file dialog and add selected file as an attachment
// -----------------------------------------------------------------------------
//
void CNcsComposeView::SetAttachmentLabelContentL()
    {
    FUNC_LOG;
    if ( iFirstStartCompleted && iContainer )
        {
        CFreestyleEmailUiSendAttachmentsListControl* 
            attachmentControl = AttachmentsListControl();
        if ( !( attachmentControl && attachmentControl->Model() ) )
            {
            return;
            }
        
        // read number of attachments
        TInt count = attachmentControl->Model()->Count();
        if ( count > 0 )
            {
            // Fill in the name and size descriptor arrays
            CDesCArrayFlat* nameArray = new (ELeave) CDesCArrayFlat( count );
            CleanupStack::PushL( nameArray );
            CDesCArrayFlat* sizeArray = new (ELeave) CDesCArrayFlat( count );
            CleanupStack::PushL( sizeArray );

            for ( TInt i(0); i<count; ++i )
                {
                CFSEmailUiSendAttachmentsListModelItem* item =
                    static_cast<CFSEmailUiSendAttachmentsListModelItem*>
                    ( attachmentControl->Model()->Item( i ) );
                if ( item )
                    {
                    nameArray->AppendL( item->FileName() );
                    HBufC* sizeDesc = 
                        TFsEmailUiUtility::CreateSizeDescLC( 
                                item->FileSize() );
                    sizeArray->AppendL( *sizeDesc );
                    CleanupStack::PopAndDestroy( sizeDesc );
                    }
                }
            iContainer->SetAttachmentLabelTextsLD( nameArray, sizeArray );
            iContainer->SetFocusToAttachmentField();
            
            CleanupStack::Pop( sizeArray );
            CleanupStack::Pop( nameArray );
            }
        else
            {
            iContainer->SetAttachmentLabelTextsLD( NULL, NULL );
            iContainer->HideAttachmentLabel();
            }
        }
    }


// -----------------------------------------------------------------------------
// CNcsComposeView::AttachmentsListControl()
//
// -----------------------------------------------------------------------------
//
CFreestyleEmailUiSendAttachmentsListControl* 
CNcsComposeView::AttachmentsListControl()
	{
    FUNC_LOG;
    CFreestyleEmailUiSendAttachmentsListControl* attachmentControl( NULL );
    if ( iFirstStartCompleted ) // Safety
        {
        CFSEmailUiSendAttachmentsListVisualiser* attachmentView =
            static_cast<CFSEmailUiSendAttachmentsListVisualiser*>(
                iAvkonViewAppUi->View( SendAttachmentMngrViewId ) );
        if ( attachmentView )
            {
            attachmentControl = 
                static_cast<CFreestyleEmailUiSendAttachmentsListControl*>(
                    attachmentView->ViewerControl() );
            }
        }
	return attachmentControl;
	}

// -----------------------------------------------------------------------------
// CNcsComposeView::ProcessCommandL()
// -----------------------------------------------------------------------------
//
void CNcsComposeView::ProcessCommandL( TInt aCommand )
    {
    FUNC_LOG;

    // Block all the commands while we are exiting
    if ( !iExecutingDoExitL )
        {
        CFsEmailUiViewBase::ProcessCommandL( aCommand );
        }
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::HandleActivationCommandL()
//
// -----------------------------------------------------------------------------
//
void CNcsComposeView::HandleActivationCommandL( TUid aCustomMessageId )
    {
    FUNC_LOG;
    // Called from doactivate in which case first start is completed
    iMailFetchingErrCode = KErrNone;

    if ( aCustomMessageId == TUid::Uid( KEditorCmdCreateNew ) )
        {
        iOrigMessage = NULL;
        iFakeSyncGoingOn = ETrue;
        iNewMessage = iMailBox->CreateMessageToSend();
        iFakeSyncGoingOn = EFalse;
        if ( !iNewMessage )
            {
            User::Leave( KErrGeneral );
            }
        iFakeSyncGoingOn = ETrue;
        TFsEmailUiUtility::MoveMessageToDraftsL( *iMailBox, *iNewMessage );
        iFakeSyncGoingOn = EFalse;
        
        if ( iNewMessage->GetContentType() != 
             KFSMailContentTypeMultipartMixed )
            {
            iNewMessage->SetContentType( KFSMailContentTypeMultipartMixed );
            iNewMessage->SaveMessageL();
            }
        
        TFsEmailUiUtility::CreatePlainTextPartL( 
                *iNewMessage, iNewMessageTextPart );
        IncludeMessageTextL( ETrue );
        AttachmentsListControl()->Model()->Clear();
        iContainer->SelectAllToFieldTextL();
        }
    else if ( aCustomMessageId == TUid::Uid( KEditorCmdReply ) ||
              aCustomMessageId == TUid::Uid( KEditorCmdReplyAll ) )
        {

        iOrigMessage = iMailClient.GetMessageByUidL( 
                iLaunchParams.iMailboxId, iLaunchParams.iFolderId,
                iLaunchParams.iMsgId, EFSMsgDataStructure );
        if ( !iOrigMessage )
            {
            User::Leave( KErrNotFound );
            }

        SafeDelete( iFetchLogic );
        iFetchLogic = CFsComposerFetchLogic::NewL( 
                iMailClient, iLaunchParams.iMailboxId,
                iOrigMessage->GetFolderId(), iLaunchParams.iMsgId, 
                *this, iAppUi );
        ShowFetchingWaitNoteL();
        iFetchLogic->RunReplyLogicL();

        // now fetch logic object runs its tasks and gives callback
        // to CNcsComposeView::FetchLogicComplete when it is finished
        }
    else if ( aCustomMessageId == TUid::Uid( KEditorCmdForward ) )
        {

        iOrigMessage = iMailClient.GetMessageByUidL( 
                iLaunchParams.iMailboxId, iLaunchParams.iFolderId, 
                iLaunchParams.iMsgId, EFSMsgDataStructure );
        if ( !iOrigMessage )
            {
            User::Leave( KErrNotFound );
            }

        SafeDelete( iFetchLogic );
        iFetchLogic = CFsComposerFetchLogic::NewL( 
                iMailClient, iLaunchParams.iMailboxId,
                iOrigMessage->GetFolderId(), iLaunchParams.iMsgId, 
                *this, iAppUi );
        ShowFetchingWaitNoteL();
        iFetchLogic->RunForwardLogicL();

        // now fetch logic object runs its tasks and gives callback
        // to CNcsComposeView::FetchLogicComplete when it is finished
        }
    else if ( aCustomMessageId == TUid::Uid( KEditorCmdOpen ) ||
              aCustomMessageId == TUid::Uid( KEditorCmdReturnToPrevious ) )
        {
        // for now, we handle returning from attachments list just like 
        // any message opening
        iNewMessage = iMailClient.GetMessageByUidL( 
                iLaunchParams.iMailboxId, iLaunchParams.iFolderId, 
                iLaunchParams.iMsgId, EFSMsgDataStructure );
        if ( !iNewMessage )
            {
            User::Leave( KErrNotFound );
            }

        // Show "Opening" wait note if the message body is large
        TInt waitNoteId = KErrNotFound;
        if ( TFsEmailUiUtility::IsMessageBodyLargeL(iNewMessage) )
            {
            waitNoteId = TFsEmailUiUtility::ShowGlobalWaitNoteLC( 
                    R_FSE_WAIT_OPENING_TEXT );
            }

        iOrigMessage = NULL;
        iNewMessage->SetContentType( KFSMailContentTypeMultipartMixed );
        iNewMessage->SaveMessageL();
        TFsEmailUiUtility::CreatePlainTextPartL( 
                *iNewMessage, iNewMessageTextPart );
        InitFieldsL();
        IncludeMessageTextL();
        AttachmentsListControl()->Model()->Clear();
        GetAttachmentsFromMailL();
        SetAttachmentLabelContentL();
        iAttachmentListSaveDraft = ETrue;

        // Close the "Opening" wait note if it was shown
        if ( waitNoteId != KErrNotFound )
            {
            CleanupStack::PopAndDestroy( (TAny*)waitNoteId );
            }
        }
    else if ( aCustomMessageId == TUid::Uid( KEditorCmdInternalMailto ) )
        {
        FUNC_LOG;

        iOrigMessage = NULL;
        iFakeSyncGoingOn = ETrue;
        iNewMessage = iMailBox->CreateMessageToSend();
        iFakeSyncGoingOn = EFalse;
        if ( !iNewMessage )
            {
            User::Leave( KErrGeneral );
            }
        iNewMessage->SetContentType( KFSMailContentTypeMultipartMixed );
        iNewMessage->SaveMessageL();

        TFsEmailUiUtility::CreatePlainTextPartL( 
                *iNewMessage, iNewMessageTextPart );

        IncludeMessageTextL( ETrue );

        CFSMailAddress* toAddress = 
            static_cast<CFSMailAddress*>( iLaunchParams.iExtra ); // not owned
        RPointerArray<CNcsEmailAddressObject> toRecipients;
        CleanupResetAndDestroyClosePushL( toRecipients );
        CNcsEmailAddressObject* ncsToAddress = 
            NcsUtility::CreateNcsAddressL( *toAddress );
        CleanupStack::PushL( ncsToAddress );
        toRecipients.AppendL( ncsToAddress );
        CleanupStack::Pop( ncsToAddress ); // owned by toRecipients now
        iContainer->SetToFieldAddressesL( toRecipients );
        CleanupStack::PopAndDestroy( &toRecipients );

        iContainer->SetFocusToMessageFieldL();
        }
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::DoQuickTextL()
//
// -----------------------------------------------------------------------------
//
void CNcsComposeView::DoQuickTextL()
    {
    FUNC_LOG;

    __ASSERT_DEBUG( iContainer, Panic( ENcsBasicUi ) );

	HBufC* title = 
        iEikonEnv->AllocReadResourceLC( R_NCS_QUICK_TEXT_TITLE_TEXT );
	HBufC* buf( 0 );
	TRAPD( err, buf = CNotepadApi::FetchTemplateL( title ) );
	if ( err == KLeaveExit )
	    { 
		// If end key was pressed the dialog leaves with the above error code.
	    // In that case we must leave as well or the application will become
	    // stuck as the exit will be incomplete.
	    User::Leave( err );
	    }
		
	if ( buf && err == KErrNone ) // Safety check, 0 if user cancel
		{
		CleanupStack::PushL( buf );
		iContainer->AddQuickTextL( *buf );
		CleanupStack::PopAndDestroy( buf );
		}
	CleanupStack::PopAndDestroy( title );

    }

// -----------------------------------------------------------------------------
// CNcsComposeView::HandleDynamicVariantSwitchL()
//
// -----------------------------------------------------------------------------
//
void CNcsComposeView::HandleDynamicVariantSwitchL(
    CFsEmailUiViewBase::TDynamicSwitchType aType )
	{
    FUNC_LOG;

    if ( iFirstStartCompleted && iContainer )
        {
        if ( aType == CFsEmailUiViewBase::EScreenLayoutChanged )
            {
            iContainer->HandleLayoutChangeL();
            }
        else if ( aType == CFsEmailUiViewBase::ESkinChanged )
            {
            iContainer->HandleSkinChangeL();
            }
        else
            {
            }
        }

	}

// -----------------------------------------------------------------------------
// CNcsComposeView::InitReplyFieldsL()
// Initialises the reply fields from the reply message created by the plug-in.
// -----------------------------------------------------------------------------
//
void CNcsComposeView::InitReplyFieldsL( TBool /*aReplyAll*/ )
    {
    FUNC_LOG;

    __ASSERT_DEBUG( iContainer, Panic( ENcsBasicUi ) );

    // Get TO recipients
    RPointerArray<CFSMailAddress>& toRecipients = 
        iNewMessage->GetToRecipients();
    RPointerArray<CNcsEmailAddressObject> recipients;
    CleanupResetAndDestroyClosePushL( recipients );
    NcsUtility::ConvertAddressArrayL( toRecipients, recipients );
    iContainer->SetToFieldAddressesL( recipients );
    CleanupStack::PopAndDestroy( &recipients );

    // Get CC recipients
    RPointerArray<CFSMailAddress>& ccRecipients = 
        iNewMessage->GetCCRecipients();
    NcsUtility::ConvertAddressArrayL( ccRecipients, recipients );
    iContainer->SetCcFieldAddressesL( recipients );
    recipients.ResetAndDestroy();

    // Get BCC recipients
    RPointerArray<CFSMailAddress>& bccRecipients = 
        iNewMessage->GetBCCRecipients();
    NcsUtility::ConvertAddressArrayL( bccRecipients, recipients );
    iContainer->SetBccFieldAddressesL( recipients );
    recipients.ResetAndDestroy();

    // Get subject line from original message
    HBufC* prefix = StringLoader::LoadLC( R_NCS_ENGINE_EMAIL_REPLY_PREFIX );
    HBufC* formattedSubject = NcsUtility::FormatSubjectLineL(
        iOrigMessage->GetSubject(), *prefix );
    CleanupStack::PushL( formattedSubject );
    iContainer->SetSubjectL( *formattedSubject );
    CleanupStack::PopAndDestroy( formattedSubject );
    CleanupStack::PopAndDestroy( prefix );

    // clear attachments
    AttachmentsListControl()->Model()->Clear();

    }

// -----------------------------------------------------------------------------
// CNcsComposeView::RemoveOwnAddress()
//
// -----------------------------------------------------------------------------
//
void CNcsComposeView::RemoveOwnAddress( 
        RPointerArray<CNcsEmailAddressObject>& aAddressList )
    {
    FUNC_LOG;
    TInt index = 0;
    TDesC& ownAddress( iMailBox->OwnMailAddress().GetEmailAddress() );
	while ( index < aAddressList.Count() )
        {
        if ( !aAddressList[index]->EmailAddress().CompareC(ownAddress) )
            {
            // The entry will be removed from the arry.
            aAddressList.Remove(index);
            break;
            }
        index++;
        }
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::IncludeMessageTextL()
//
// -----------------------------------------------------------------------------
//
void CNcsComposeView::IncludeMessageTextL( 
        TBool aEnsureSpaceInBegin /*= EFalse*/ )
	{
    FUNC_LOG;

    __ASSERT_DEBUG( iContainer, Panic( ENcsBasicUi ) );

    HBufC* body = NULL;
    HBufC* rawBody = GetMessageBodyL();
    CleanupStack::PushL( rawBody );

    // Ensure there's free space in the beginning of the message if required
    if ( aEnsureSpaceInBegin && rawBody->Length() )
        {
        TText firstChar = (*rawBody)[0];
        _LIT( KNewLines, "\r\n\x2028\x2029" );
        if ( KNewLines().Locate( firstChar ) == KErrNotFound )
            {
            // First character is not a new line character. Insert one.
            body = HBufC::NewL( rawBody->Length() + KIMSLineFeed().Length() );
            TPtr ptr = body->Des();
            ptr.Append( KIMSLineFeed );
            ptr.Append( *rawBody );
            CleanupStack::PopAndDestroy( rawBody );
            rawBody = NULL;
            CleanupStack::PushL( body );
            }
        }
    // If no modifications were needed, then just set body pointer to point
    // the rawBody
    if ( !body )
        {
        body = rawBody;
        rawBody = NULL;
        }
    // Now we have possibly decorated message text in body pointer and
    // in cleanup stack

    // Divide the contents into normal body and the read-only quote fields
    // Convert bytes length to words length
    TInt readOnlyLength = iNewMessageTextPart->ReadOnlyPartSize() / 2;
    if ( body )
    	{
		TInt modifiableLength = body->Length() - readOnlyLength;
	
		// Remove one newline from the end of the modifiable body if there's
		// read-only quote present. This is because the field boundary appears
		// as newline on the screen. This newline is added back when saving
		// the message.
		TInt lfLength = KIMSLineFeed().Length();
		if ( readOnlyLength && modifiableLength >= lfLength &&
			 body->Mid( modifiableLength-lfLength, lfLength ) == 
			 KIMSLineFeed )
			{
			modifiableLength -= lfLength;
			}
	
		iContainer->SetBodyContentL( body->Left( modifiableLength ),
			body->Right( readOnlyLength ) );
    	}

    CleanupStack::PopAndDestroy( body );
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::InitForwardFieldsL()
//
// -----------------------------------------------------------------------------
//
void CNcsComposeView::InitForwardFieldsL()
	{
    FUNC_LOG;

    __ASSERT_DEBUG( iContainer, Panic( ENcsBasicUi ) );

	// set subject
	HBufC* prefix = StringLoader::LoadLC( R_NCS_ENGINE_EMAIL_FORWARD_PREFIX );
	HBufC* formattedSubject = NcsUtility::FormatSubjectLineL( 
	        iOrigMessage->GetSubject(), *prefix );
	CleanupStack::PushL( formattedSubject );
	iContainer->SetSubjectL( *formattedSubject );
	CleanupStack::PopAndDestroy( formattedSubject );
	CleanupStack::PopAndDestroy( prefix );

    // attachments
	AttachmentsListControl()->Model()->Clear();
	// <cmail>
	TInt error = KErrNone;
	TRAP( error, GetAttachmentsFromMailL() );
	// </cmail>
	SetAttachmentLabelContentL();

	}

// -----------------------------------------------------------------------------
// CNcsComposeView::SetPriority()
//
// -----------------------------------------------------------------------------
//
void CNcsComposeView::SetPriority()
    {
    FUNC_LOG;

    __ASSERT_DEBUG( iContainer, Panic( ENcsBasicUi ) );

    if ( iNewMessage && iNewMessage->IsFlagSet( EFSMsgFlag_Important ) )
        {
        iStatusPaneIndicators->SetPriorityFlag( EMsgPriorityHigh );
        }
    else if ( iNewMessage && iNewMessage->IsFlagSet( EFSMsgFlag_Low ) )
        {
        iStatusPaneIndicators->SetPriorityFlag( EMsgPriorityLow );
        }
    }

// -----------------------------------------------------------------------------
// Sets follow-up flags to status pane indicators
// -----------------------------------------------------------------------------
//
void CNcsComposeView::SetFollowUp()
    {
    if ( iNewMessage && iStatusPaneIndicators )
        {
        if ( iNewMessage->IsFlagSet( EFSMsgFlag_FollowUp ) )
            {
            iStatusPaneIndicators->SetFollowUpFlag(
                CCustomStatuspaneIndicators::EFollowUp );
            }
        else if ( iNewMessage->IsFlagSet( EFSMsgFlag_FollowUpComplete ) )
            {
            iStatusPaneIndicators->SetFollowUpFlag(
                CCustomStatuspaneIndicators::EFollowUpComplete );
            }
        }
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::InitFieldsL()
//
// -----------------------------------------------------------------------------
//
void CNcsComposeView::InitFieldsL()
	{
    FUNC_LOG;

    __ASSERT_DEBUG( iContainer, Panic( ENcsBasicUi ) );

	// to
 	RPointerArray<CFSMailAddress>& toRecipients = 
        iNewMessage->GetToRecipients();
	RPointerArray<CNcsEmailAddressObject> ncsToRecipients;
	CleanupResetAndDestroyClosePushL( ncsToRecipients );
	NcsUtility::ConvertAddressArrayL( toRecipients, ncsToRecipients );
 	iContainer->SetToFieldAddressesL( ncsToRecipients );
    CleanupStack::PopAndDestroy( &ncsToRecipients );

	// cc
 	RPointerArray<CFSMailAddress>& ccRecipients = 
        iNewMessage->GetCCRecipients();
	RPointerArray<CNcsEmailAddressObject> ncsCcRecipients;
    CleanupResetAndDestroyClosePushL( ncsCcRecipients );
	NcsUtility::ConvertAddressArrayL( ccRecipients, ncsCcRecipients );
 	iContainer->SetCcFieldAddressesL( ncsCcRecipients );
    CleanupStack::PopAndDestroy( &ncsCcRecipients );

	// bcc
 	RPointerArray<CFSMailAddress>& bccRecipients = 
        iNewMessage->GetBCCRecipients();
	RPointerArray<CNcsEmailAddressObject> ncsBccRecipients;
    CleanupResetAndDestroyClosePushL( ncsBccRecipients );
	NcsUtility::ConvertAddressArrayL( bccRecipients, ncsBccRecipients );
 	iContainer->SetBccFieldAddressesL( ncsBccRecipients );
    CleanupStack::PopAndDestroy( &ncsBccRecipients );

	// set subject line
	iContainer->SetSubjectL( iNewMessage->GetSubject() );

	}

// -----------------------------------------------------------------------------
// CNcsComposeView::GetMessageBodyL()
//
// -----------------------------------------------------------------------------
//
HBufC* CNcsComposeView::GetMessageBodyL()
	{
    FUNC_LOG;

    __ASSERT_DEBUG( iNewMessageTextPart, Panic( ENcsBasicUi ) );

    TInt messageSize = iNewMessageTextPart->FetchedContentSize();

    HBufC* data = NULL;

    if ( messageSize > 0 )
        {
        // fetch message body if there is something to fetch
        data = HBufC::NewLC( messageSize );
        TPtr dataPtr = data->Des();
        iNewMessageTextPart->GetContentToBufferL( dataPtr, 0 );
        CleanupStack::Pop( data );
        }
    else
        {
        data = KNullDesC().AllocL();
        }

	return data;
	}

// -----------------------------------------------------------------------------
// CNcsComposeView::CommitL()
//
// -----------------------------------------------------------------------------
//
void CNcsComposeView::CommitL( 
        TBool aParseAddresses, TFieldToCommit aFieldToCommit )
    {
    FUNC_LOG;
    __ASSERT_DEBUG( iNewMessage, Panic( ENcsBasicUi ) );
	__ASSERT_DEBUG( iNewMessageTextPart, Panic( ENcsBasicUi ) );

	TBool commitToField = EFalse;
	TBool commitCcField = EFalse;
	TBool commitBccField = EFalse;
	TBool commitSubjectField = EFalse;
	TBool commitBodyField = EFalse;

	switch ( aFieldToCommit )
	    {
	    case EAllFields:
	        commitToField = ETrue;
	        commitCcField = ETrue;
	        commitBccField = ETrue;
	        commitSubjectField = ETrue;
	        commitBodyField = ETrue;
	        break;
	    case EToField:
            commitToField = ETrue;
	        break;
	    case ECcField:
            commitCcField = ETrue;
	        break;
	    case EBccField:
            commitBccField = ETrue;
	        break;
        case EBodyField:
            commitBodyField = ETrue;
            break;
        case ESubjectField:
            commitSubjectField = ETrue;
            break;
	    default:
	        break;
	    }

	if ( commitToField )
		{
	    // get addresses from UI to MSG object
	    RPointerArray<CFSMailAddress> toAddresses;
	    CleanupResetAndDestroyClosePushL( toAddresses );
	    NcsUtility::ConvertAddressArrayL( 
	            iContainer->GetToFieldAddressesL( aParseAddresses ), 
	            toAddresses );
	    iNewMessage->GetToRecipients().ResetAndDestroy();
	    for ( TInt i = 0 ; i < toAddresses.Count() ; i++ )
	    	{
	    	iNewMessage->AppendToRecipient( toAddresses[i] );
	        // Ownership of the message pointer was transferred from our array
	    	// to iNewMessage
	        toAddresses[i] = NULL;
	    	}
	    CleanupStack::PopAndDestroy( &toAddresses );
		}

	if ( commitCcField )
		{
	    RPointerArray<CFSMailAddress> ccAddresses;
	    CleanupResetAndDestroyClosePushL( ccAddresses );
	    NcsUtility::ConvertAddressArrayL( 
	            iContainer->GetCcFieldAddressesL( aParseAddresses ), 
	            ccAddresses );
	    iNewMessage->GetCCRecipients().ResetAndDestroy();
	    for ( TInt i = 0 ; i < ccAddresses.Count() ; i++ )
	    	{
	    	iNewMessage->AppendCCRecipient( ccAddresses[i] );
	        // Ownership of the message pointer was transferred from 
	    	// our array to iNewMessage
	        ccAddresses[i] = NULL;
	    	}
	    CleanupStack::PopAndDestroy( &ccAddresses );
		}

	if ( commitBccField )
		{
	    RPointerArray<CFSMailAddress> bccAddresses;
	    CleanupResetAndDestroyClosePushL( bccAddresses );
	    NcsUtility::ConvertAddressArrayL( 
	            iContainer->GetBccFieldAddressesL( aParseAddresses ), 
	            bccAddresses );
	    iNewMessage->GetBCCRecipients().ResetAndDestroy();
	    for ( TInt i = 0; i < bccAddresses.Count() ; i++ )
	    	{
	    	iNewMessage->AppendBCCRecipient( bccAddresses[i] );
	        // Ownership of the message pointer was transferred from 
	    	// our array to iNewMessage
	        bccAddresses[i] = NULL;
	    	}
	    CleanupStack::PopAndDestroy( &bccAddresses );
		}

	if ( commitSubjectField )
	    {
	    // get subject from UI to MSG object
	    HBufC* subject = iContainer->GetSubjectLC();
	    TPtr ptr = subject->Des();
		// replace new line characters with spaces as Subject is normally
	    // one line only
	    AknTextUtils::ReplaceCharacters( 
	            ptr, KLineSeparators, KReplacementChar );
	    iNewMessage->SetSubject( *subject );
	    CleanupStack::PopAndDestroy( subject );
	    }

    if ( commitBodyField )
        {
        HBufC* body = iContainer->GetBodyContentLC();
        TPtr bodyPtr = body->Des(); // this TPtr is needed only because of
        // incorrect argument type in FW API, can be removed when API fixed
        iNewMessageTextPart->SetContent( bodyPtr );
        CleanupStack::PopAndDestroy( body );

        TInt error = KErrNone;
        if ( iNewMessageTextPart )
            {
            TRAP( error, iNewMessageTextPart->SaveL() );
            }
        }

	// Save message if at least one field committed
    if ( iNewMessage || commitToField || commitCcField || commitBccField
        || commitSubjectField || commitBodyField )
        {
        TInt error = KErrNone;
        if(iNewMessage) // Coverity error fix:
            {
            TRAP( error, iNewMessage->SaveMessageL() );
            }
        RefreshToolbar();
        }
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::DoSafeExit
// -----------------------------------------------------------------------------
void CNcsComposeView::DoSafeExit( TExitMode aMode )
    {
    FUNC_LOG;

    if ( !iExecutingDoExitL )
        {
        iExecutingDoExitL = ETrue;
        TRAP_IGNORE( DoExitL( aMode ) );
        iExecutingDoExitL = EFalse;
        }
    }


// -----------------------------------------------------------------------------
// CNcsComposeView::DoExitL
// -----------------------------------------------------------------------------
void CNcsComposeView::DoExitL( TExitMode aMode )
    {
    FUNC_LOG;

    TBool emptyMessage = ETrue;

    if ( iAutoSaver && iContainer )
        {
        iAutoSaver->Enable( EFalse );

        // check for some user input in some header field or in message body
    	TInt attaCount = AttachmentsListControl()->Model()->Count();
        emptyMessage =  iContainer->AreAddressFieldsEmpty() &&
            iContainer->IsSubjectFieldEmpty() &&
            iContainer->GetMessageFieldLength() < 1 &&
            attaCount <= 0;
	    }

    // Consider saving the draft if the message is not completely empty
    if ( !emptyMessage )
        {
        if ( aMode == ESaveDraftQuery && !iMailSent && !iMailSendFailed )
            {
            TBool actionSucceeded = EFalse;

            // DoSaveDraftL returns EFalse if the user query was cancelled
            // or saving to Drafts failed
            TRAPD( saveDraftError, actionSucceeded = DoSaveDraftL( ETrue ) );
            if ( saveDraftError == KErrNone )
                {
                if ( !actionSucceeded )
                    {
                    // return to normal action 
                    // (cancel was pressed in the query)
                    iAutoSaver->Enable( ETrue );
                    return;
                    }
                }
            else
                {
                }
            }
        else if ( aMode == ESaveDraft )
            {
            DoSaveDraftL( EFalse );
            }
        }
    else if ( iNewMessage ) // message is empty 
        {
        // delete the draft if it has been already saved earlier
        TInt err = NcsUtility::DeleteMessage( iMailClient, iMailBox->GetId(),
            iNewMessage->GetFolderId(), iNewMessage->GetMessageId() );
        if ( !err && iMailBox->HasCapability( 
                EFSMBoxCapaSupportsDeletedItemsFolder ) )
            {
            err = NcsUtility::DeleteMessage( iMailClient, iMailBox->GetId(),
                iMailBox->GetStandardFolderId( EFSDeleted ),
                iNewMessage->GetMessageId() );
            }

        if ( !err && !iAppUi.AppUiExitOngoing() )
            {
            // Simulate delete event so that drafts folder is
            // updated correctly.
            RArray<TFSMailMsgId> messageIds;
            CleanupClosePushL( messageIds );
            messageIds.AppendL( iNewMessage->GetMessageId() );
            TFSMailMsgId folderId = iNewMessage->GetFolderId();
            TFSMailMsgId mailboxId = iNewMessage->GetMailBoxId();
            iAppUi.EventL( TFSEventMailDeleted,
                mailboxId, &messageIds, &folderId, NULL );
            CleanupStack::PopAndDestroy( &messageIds );
            }
        }

    // Clear attachment control now that message has been sent
    // othewise this will kind of leak memory by leaving attachments
    // in the list, even if they have been sent.
    CFreestyleEmailUiSendAttachmentsListControl* attachmentControl;
    attachmentControl = AttachmentsListControl();
    if ( attachmentControl && attachmentControl->Model() )
        {
        attachmentControl->Model()->Clear();
        }
    ExitComposer();
    TIMESTAMP( "Editor exited" );
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::DoOpenAttachmentList
// Opens the currently focused attachment
// -----------------------------------------------------------------------------
void CNcsComposeView::DoOpenAttachmentListL()
	{
    FUNC_LOG;

    CFreestyleEmailUiSendAttachmentsListControl* attachmentControl
   		= AttachmentsListControl();

    TInt index( iContainer ? iContainer->FocusedAttachmentLabelIndex() 
            : KNoAttachmentLabelFocused );
    if ( KNoAttachmentLabelFocused != index && 
         attachmentControl && attachmentControl->Model() )
        {
        CFSEmailUiSendAttachmentsListModelItem* item =
            static_cast<CFSEmailUiSendAttachmentsListModelItem*>(
                    attachmentControl->Model()->Item( index ) );
            
        if ( item && !item->IsRemote() ) // cannot open remote attachments
            {
            CFSMailMessagePart* msgPart = 
                iNewMessage->ChildPartL( item->MailMsgPartId() );
            CleanupStack::PushL( msgPart );
            TFsEmailUiUtility::OpenAttachmentL( *msgPart );
            CleanupStack::PopAndDestroy( msgPart );
            }
        }
	}

// -----------------------------------------------------------------------------
// CNcsComposeView::LaunchStylusPopupMenu
// Show stylus popup menu for the attachments line
// -----------------------------------------------------------------------------
//
void CNcsComposeView::LaunchStylusPopupMenu( const TPoint& aPenEventScreenLocation )
    {
    FUNC_LOG;
    
    CFSEmailUiSendAttachmentsListModel* attachmentModel =
        ( AttachmentsListControl() ? 
                AttachmentsListControl()->Model() : NULL ); 
    TInt count( attachmentModel ? attachmentModel->Count() : 0 );
    TBool attachmentsInModel( count > 0 );
    CFSEmailUiSendAttachmentsListModelItem* item( NULL );
   
    if ( attachmentsInModel )
        {
        item = static_cast<CFSEmailUiSendAttachmentsListModelItem*>( 
                attachmentModel->Item( 
                    iContainer->FocusedAttachmentLabelIndex() ) );
        if ( !item || item->IsRemote() )
            {
            // Only non-remote attachments can be opened
            iStylusPopUpMenu->SetItemDimmed( EFsEmailUiCmdOpenAttachment, ETrue );
            }
        }

    if ( !item || item->IsReadOnly() )
        {
        // Only non-readonly attachments can be removed
        iStylusPopUpMenu->SetItemDimmed( EFsEmailUiCmdRemoveAttachment, ETrue );
        }

    // Set the position for the popup
	iStylusPopUpMenu->SetPosition( aPenEventScreenLocation );

	// Display the popup.
	iStylusPopUpMenu->ShowMenu();
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::GetAttachmentsFromMail
// -----------------------------------------------------------------------------
void CNcsComposeView::GetAttachmentsFromMailL()
	{
    FUNC_LOG;

    TInt error( KErrNone );

	RPointerArray<CFSMailMessagePart> attachments;
    CleanupResetAndDestroyClosePushL( attachments );
	TRAP( error, iNewMessage->AttachmentListL( attachments ) );
	User::LeaveIfError( error );

	for ( TInt i=0; i<attachments.Count(); ++i )
		{
        TFileType fileType = TFsEmailUiUtility::GetFileType( 
                attachments[i]->AttachmentNameL(),
                attachments[i]->GetContentType() );

        TBool isReadOnly = ( attachments[i]->ReadOnlyPartSize() > 0 );
        TBool isRemote = EFalse;

		if ( attachments[i]->FetchedContentSize() < 
		     attachments[i]->ContentSize() )
			{
			if ( iMailBox->HasCapability( EFSMBoxCapaSmartForward ) )
			    {
			    isRemote = ETrue;
			    }
			else
			    {
	            __ASSERT_DEBUG( EFalse, Panic(EFSEmailUiUnexpectedValue) );
	            User::Leave( KErrNotFound );
	            continue;
			    }
			}

		AttachmentsListControl()->AppendFileToModelL(
		        attachments[i]->GetPartId(),
		        attachments[i]->AttachmentNameL(),
		        attachments[i]->ContentSize(),
		        fileType,
		        isReadOnly,
		        isRemote );
		}

	CleanupStack::PopAndDestroy( &attachments );

	}

// -----------------------------------------------------------------------------
// CNcsComposeView::FileExistsInModel
// -----------------------------------------------------------------------------
TBool CNcsComposeView::FileExistsInModel( TFSMailMsgId aAttachmentId )
	{
    FUNC_LOG;

	TInt count( AttachmentsListControl()->Model()->Count() );

	for ( TInt i=0; i < count; ++i )
		{
		CFSEmailUiSendAttachmentsListModelItem* item =
			static_cast<CFSEmailUiSendAttachmentsListModelItem*>(
                AttachmentsListControl()->Model()->Item(i) );
		if ( aAttachmentId.Id() == item->MailMsgPartId().Id() )
			{
			return ETrue;
			}
		}

	return EFalse;
	}

// -----------------------------------------------------------------------------
// CNcsComposeView::GenerateReplyHeaderLC
// -----------------------------------------------------------------------------
HBufC* CNcsComposeView::GenerateReplyHeaderLC()
	{
    FUNC_LOG;

    __ASSERT_DEBUG( iOrigMessage, Panic( ENcsBasicUi ) );

	// separator line
	HBufC* separator = 
        StringLoader::LoadLC( R_NCS_ENGINE_EMAIL_MESSAGE_LINE_SEPARATOR ); //1

	// from line
	RPointerArray<CNcsEmailAddressObject> senderArray;
	CleanupResetAndDestroyClosePushL( senderArray );
    CFSMailAddress* sender = iOrigMessage->GetSender();
    if ( sender )
        {
    	CNcsEmailAddressObject* ncsSender = 
            NcsUtility::CreateNcsAddressL( *sender );
    	CleanupStack::PushL( ncsSender );
	    senderArray.AppendL( ncsSender );
	    CleanupStack::Pop( ncsSender ); // now owned by senderArray
        }
	HBufC* fromLine = 
        NcsUtility::GenerateFromLineToMessageBodyL( senderArray );
	CleanupStack::PopAndDestroy( &senderArray );
	CleanupStack::PushL( fromLine ); //2

	// sent line
	HBufC* sentLine = 
        NcsUtility::GenerateSentLineToMessageBodyL( *iOrigMessage );
	CleanupStack::PushL( sentLine ); //3

	// to line
	RPointerArray<CNcsEmailAddressObject> ncsToRecipients;
	CleanupResetAndDestroyClosePushL( ncsToRecipients );
	RPointerArray<CFSMailAddress>& toRecipients = 
        iOrigMessage->GetToRecipients();
	NcsUtility::ConvertAddressArrayL( toRecipients, ncsToRecipients );
	HBufC* toLine = NcsUtility::GenerateAddressLineToMessageBodyL( 
                ncsToRecipients, NcsUtility::ERecipientTypeTo );
    CleanupStack::PopAndDestroy( &ncsToRecipients );
	CleanupStack::PushL( toLine ); //4

	// cc line
	RPointerArray<CFSMailAddress>& ccRecipients = 
        iOrigMessage->GetCCRecipients();
	TBool hasCcLine = ( ccRecipients.Count() > 0 );
    HBufC* ccLine = NULL;
	if ( hasCcLine )
		{
	    RPointerArray<CNcsEmailAddressObject> ncsCcRecipients;
	    CleanupResetAndDestroyClosePushL( ncsCcRecipients );
		NcsUtility::ConvertAddressArrayL( ccRecipients, ncsCcRecipients );
		ccLine = NcsUtility::GenerateAddressLineToMessageBodyL( 
		        ncsCcRecipients, NcsUtility::ERecipientTypeCc );
	    CleanupStack::PopAndDestroy( &ncsCcRecipients );
		CleanupStack::PushL( ccLine ); //5
		}

	// subject line
	HBufC* subjectLine = NcsUtility::GenerateSubjectLineToMessageBodyL( 
	        iOrigMessage->GetSubject() );
	CleanupStack::PushL( subjectLine ); //6

    // Body
    HBufC* body = NULL;
    TBool hasBody = EFalse;
    CFSMailMessagePart* textBodyPart = iOrigMessage->PlainTextBodyPartL();
    if ( textBodyPart )
        {
        // Plain text body part present, no need
        // to generate it from HTML body part
        delete textBodyPart;
        }
    else
        {
        // Generate body part for reply
        CFSMailMessagePart* htmlBodyPart = iOrigMessage->HtmlBodyPartL();
        if ( htmlBodyPart )
            {
            CleanupStack::PushL( htmlBodyPart );

            HBufC* htmlData = 
                HBufC::NewLC( htmlBodyPart->FetchedContentSize() );
            TPtr pointer = htmlData->Des();
            htmlBodyPart->GetContentToBufferL( pointer, 0 );

            body = TFsEmailUiUtility::ConvertHtmlToTxtL( *htmlData );

            CleanupStack::PopAndDestroy( htmlData );
            CleanupStack::PopAndDestroy( htmlBodyPart );

            CleanupStack::PushL( body ); //7

            hasBody = ETrue;
            }
        }
	// calculate total length
	TInt length = 0;
	length += separator->Length();
	length += KIMSLineFeed().Length();
	length += fromLine->Length();
	length += KIMSLineFeed().Length();
	length += sentLine->Length();
	length += KIMSLineFeed().Length();
	length += toLine->Length();
	if ( hasCcLine )
		{
		length += KIMSLineFeed().Length();
		length += ccLine->Length();
		}
	length += KIMSLineFeed().Length();
	length += subjectLine->Length();
	length += KIMSLineFeed().Length();
    if ( hasBody )
        {
        length += body->Length();
        }
	length += KIMSLineFeed().Length();
	length += KIMSLineFeed().Length();

	// create buffer and write contents
	HBufC* header = HBufC::NewL( length );
	TPtr ptr = header->Des();
	ptr.Append( *separator );
	ptr.Append( KIMSLineFeed );
	ptr.Append( *fromLine );
	ptr.Append( KIMSLineFeed );
	ptr.Append( *sentLine );
	ptr.Append( KIMSLineFeed );
	ptr.Append( *toLine );
	if ( hasCcLine )
		{
		ptr.Append( KIMSLineFeed );
		ptr.Append( *ccLine );
		}
	ptr.Append( KIMSLineFeed );
	ptr.Append( *subjectLine );
	ptr.Append( KIMSLineFeed );
    if ( hasBody )
        {
        ptr.Append( *body );
        }
	ptr.Append( KIMSLineFeed );
	ptr.Append( KIMSLineFeed );

	// leave header on the cleanup stack
    if ( hasBody )
        {
        CleanupStack::PopAndDestroy( body ); //-7
        }
	CleanupStack::PopAndDestroy( subjectLine ); //-6
	if ( hasCcLine )
		{
		CleanupStack::PopAndDestroy( ccLine ); //-5
		}
	CleanupStack::PopAndDestroy( toLine ); //-4
	CleanupStack::PopAndDestroy( sentLine ); //-3
	CleanupStack::PopAndDestroy( fromLine ); //-2
	CleanupStack::PopAndDestroy( separator ); //-1

	CleanupStack::PushL( header );

	return header;
	}

// -----------------------------------------------------------------------------
// CNcsComposeView::GenerateSmartTagLC
// -----------------------------------------------------------------------------
HBufC* CNcsComposeView::GenerateSmartTagLC()
	{
    FUNC_LOG;

	HBufC* tag = StringLoader::LoadLC( R_FSE_EDITOR_SMART_TAG );

	return tag;
	}

// -----------------------------------------------------------------------------
// CNcsComposeView::InitReplyOrForwardUiL
// -----------------------------------------------------------------------------
//
void CNcsComposeView::InitReplyOrForwardUiL()
    {
    FUNC_LOG;
    // Show "Opening" wait note if the message body is large
    TInt waitNoteId = KErrNotFound;
    if ( TFsEmailUiUtility::IsMessageBodyLargeL(iOrigMessage) )
        {
        waitNoteId = TFsEmailUiUtility::ShowGlobalWaitNoteLC( 
                R_FSE_WAIT_OPENING_TEXT );
        }

    if ( iCustomMessageId == TUid::Uid( KEditorCmdReply ) )
        {
        GenerateReplyMessageL( EFalse );
        InitReplyUiL( EFalse );
        }
    else if ( iCustomMessageId == TUid::Uid( KEditorCmdReplyAll ) )
        {
        GenerateReplyMessageL( ETrue );
        InitReplyUiL( ETrue );
        }
    else if ( iCustomMessageId == TUid::Uid( KEditorCmdForward ) )
        {
        GenerateForwardMessageL();
        InitForwardUiL();
        }
    else
        {
        // This shouldn't ever happen. Panic in debug builds.
        ASSERT( EFalse );
        }

    // Close the "Opening" wait note if it was shown
    if ( waitNoteId != KErrNotFound )
        {
        CleanupStack::PopAndDestroy( (TAny*)waitNoteId );
        }
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::GenerateReplyMessageL
// -----------------------------------------------------------------------------
//
void CNcsComposeView::GenerateReplyMessageL( TBool aReplyAll )
	{
    FUNC_LOG;

    __ASSERT_DEBUG( iMailBox, Panic( ENcsBasicUi ) );

	TReplyForwardParams params;
	params.iHeader = GenerateReplyHeaderLC();
	params.iSmartTag = GenerateSmartTagLC();
	TPckgBuf<TReplyForwardParams> buf( params );
	HBufC* temp = HBufC::NewLC( buf.Length() );
	temp->Des().Copy( buf );

	//<cmail> this is actually a waited async method
	iFakeSyncGoingOn = ETrue;
    iNewMessage = iMailBox->CreateReplyMessage( 
            iLaunchParams.iMsgId, aReplyAll, *temp );
    iFakeSyncGoingOn = EFalse;
    //</cmail>
   	// Compose screen does not send cal messages, make sure
	// that cal event flag is not left active by some protocol
	if ( iNewMessage )
		{
		iNewMessage->ResetFlag( EFSMsgFlag_CalendarMsg );
		}
    CleanupStack::PopAndDestroy( temp );
    CleanupStack::PopAndDestroy( params.iSmartTag );
    CleanupStack::PopAndDestroy( params.iHeader );
    if ( !iNewMessage )
    	{
    	User::Leave( KErrGeneral );
    	}
    iFakeSyncGoingOn = ETrue; //<cmail>
    TRAPD( error, TFsEmailUiUtility::MoveMessageToDraftsL( 
            *iMailBox, *iNewMessage ) );
    iFakeSyncGoingOn = EFalse; //</cmail>
    User::LeaveIfError( error );

    if ( iNewMessage->GetContentType() != KFSMailContentTypeMultipartMixed )
        {
        iNewMessage->SetContentType( KFSMailContentTypeMultipartMixed );
        iNewMessage->SaveMessageL();
	    }
	
	TFsEmailUiUtility::CreatePlainTextPartL( *iNewMessage, iNewMessageTextPart );

	}

// -----------------------------------------------------------------------------
// CNcsComposeView::GenerateForwardMessageL
// -----------------------------------------------------------------------------
//
void CNcsComposeView::GenerateForwardMessageL()
	{
    FUNC_LOG;

    __ASSERT_DEBUG( iMailBox, Panic( ENcsBasicUi ) );

	TReplyForwardParams params;
	params.iHeader = GenerateReplyHeaderLC();
	params.iSmartTag = GenerateSmartTagLC();
	TPckgBuf<TReplyForwardParams> buf( params );
	HBufC* temp = HBufC::NewLC( buf.Length() );
	temp->Des().Copy( buf );

	//<cmail> this is actually a waited async call
	iFakeSyncGoingOn = ETrue;
    iNewMessage = iMailBox->CreateForwardMessage( iLaunchParams.iMsgId, *temp );
    iFakeSyncGoingOn = EFalse;
    //</cmail>
 	// Compose screen does not send cal messages, make sure
	// that cal event flag is not left active by some protocol
	if ( iNewMessage )
		{
		iNewMessage->ResetFlag( EFSMsgFlag_CalendarMsg );
		}
    CleanupStack::PopAndDestroy( temp );
    CleanupStack::PopAndDestroy( params.iSmartTag );
    CleanupStack::PopAndDestroy( params.iHeader );
    if ( !iNewMessage )
    	{
    	User::Leave( KErrGeneral );
    	}
    iFakeSyncGoingOn = ETrue; //<cmail>
    TRAPD( error, TFsEmailUiUtility::MoveMessageToDraftsL( 
            *iMailBox, *iNewMessage ) );
    iFakeSyncGoingOn = EFalse; //<cmail>
    User::LeaveIfError( error );

    if ( iNewMessage->GetContentType() != KFSMailContentTypeMultipartMixed )
        {
        iNewMessage->SetContentType( KFSMailContentTypeMultipartMixed );
        iNewMessage->SaveMessageL();
	    }
    
	TFsEmailUiUtility::CreatePlainTextPartL( 
	        *iNewMessage, iNewMessageTextPart );

    }

// -----------------------------------------------------------------------------
// CNcsComposeView::InitReplyUiL
// -----------------------------------------------------------------------------
//
void CNcsComposeView::InitReplyUiL( TBool aReplyAll )
	{
    FUNC_LOG;
    if ( iFirstStartCompleted ) // Safety check
        {
        InitReplyFieldsL( aReplyAll );
        IncludeMessageTextL( ETrue );
        iContainer->SetFocusToMessageFieldL();
        }
	}

// -----------------------------------------------------------------------------
// CNcsComposeView::InitUiGeneralL
// -----------------------------------------------------------------------------
//
void CNcsComposeView::InitUiGeneralL()
	{
    FUNC_LOG;
    if ( iFirstStartCompleted ) // Safety check
        {
        AppUi()->AddToStackL( iContainer );
        iContainer->SetMenuBar( Cba() );
        iContainer->UpdateScrollBarL();

        // Set title pane text
        const TDesC& mbName = iMailBox->GetName();
        iAppUi.SetTitlePaneTextL( mbName );

        // Set priority flag
        SetPriority();

        // Set follow-up flag
        SetFollowUp();
        }
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::InitForwardUiL
// -----------------------------------------------------------------------------
//
void CNcsComposeView::InitForwardUiL()
	{
    FUNC_LOG;
    if ( iFirstStartCompleted ) // Safety check
        {
        InitForwardFieldsL();
        IncludeMessageTextL( ETrue );
        iContainer->SetFocusToToField();
        iContainer->SelectAllToFieldTextL();
        }
	}

// -----------------------------------------------------------------------------
// CNcsComposeView::SetReplyForwardFlag
// -----------------------------------------------------------------------------
//
void CNcsComposeView::SetReplyForwardFlagL()
	{
    FUNC_LOG;

	if ( iFirstStartCompleted && iOrigMessage )
		{
		if ( iCustomMessageId == TUid::Uid( KEditorCmdReply ) ||
             iCustomMessageId == TUid::Uid( KEditorCmdReplyAll ) )
			{
			iOrigMessage->SetFlag( EFSMsgFlag_Answered );
			iOrigMessage->SaveMessageL();
			}
		else if ( iCustomMessageId == TUid::Uid( KEditorCmdForward ) )
			{
			iOrigMessage->SetFlag( EFSMsgFlag_Forwarded );
			iOrigMessage->SaveMessageL();
			}
		}

	}

// -----------------------------------------------------------------------------
// CNcsComposeView::MailBoxSupportsSmartReply
// -----------------------------------------------------------------------------
//
TBool CNcsComposeView::MailBoxSupportsSmartReply()
	{
    FUNC_LOG;

    __ASSERT_DEBUG( iMailBox, Panic( ENcsBasicUi ) );

	return iMailBox->HasCapability( EFSMBoxCapaSmartReply );
	}

// -----------------------------------------------------------------------------
// CNcsComposeView::MailBoxSupportsSmartForward
// -----------------------------------------------------------------------------
//
TBool CNcsComposeView::MailBoxSupportsSmartForward()
	{
    FUNC_LOG;
    __ASSERT_DEBUG( iMailBox, Panic( ENcsBasicUi ) );

	return iMailBox->HasCapability( EFSMBoxCapaSmartForward );
	}

// -----------------------------------------------------------------------------
// CNcsComposeView::HasUnfetchedAttachmentsL
// -----------------------------------------------------------------------------
//
TBool CNcsComposeView::HasUnfetchedAttachmentsL( CFSMailMessage& aMsg )
	{
    FUNC_LOG;

    __ASSERT_DEBUG( &aMsg, Panic( ENcsBasicUi ) );

    TBool ret = EFalse;

	RPointerArray<CFSMailMessagePart> attachments;
	CleanupResetAndDestroyClosePushL( attachments );
	aMsg.AttachmentListL( attachments );
	for ( TInt i=0; i<attachments.Count(); i++ )
		{
		if ( EFSFull != attachments[i]->FetchLoadState() )
			{
			ret = ETrue;
			break;
			}
		}
	CleanupStack::PopAndDestroy( &attachments );

	return ret;
	}

// -----------------------------------------------------------------------------
// CNcsComposeView::HandleActionL
// -----------------------------------------------------------------------------
//
void CNcsComposeView::HandleActionL( const TAlfActionCommand& aActionCommand )
    {
    FUNC_LOG;
    if ( iFirstStartCompleted && iNewMessage && iMailBox 
         && aActionCommand.Id() == KCmdEditorAutoSave )
        {
        CommitL( EFalse );
        }
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::SaveToDraftsL
// -----------------------------------------------------------------------------
//
void CNcsComposeView::SaveToDraftsL( TBool aParseAddresses )
	{
    FUNC_LOG;
    if ( iFirstStartCompleted ) // Safety
        {
        __ASSERT_DEBUG( iMailBox, Panic( ENcsBasicUi ) );
        __ASSERT_DEBUG( iNewMessage, Panic( ENcsBasicUi ) );

        iFakeSyncGoingOn = ETrue;
        TRAPD( error, CommitL( aParseAddresses ) );
        iFakeSyncGoingOn = EFalse;
        User::LeaveIfError( error );

        iFakeSyncGoingOn = ETrue;
        TRAP( error, TFsEmailUiUtility::MoveMessageToDraftsL(
            *iMailBox, *iNewMessage ) );
        iFakeSyncGoingOn = EFalse;
        User::LeaveIfError( error );

        if ( !iAppUi.AppUiExitOngoing() )
            {
            // Simulate a new mail event to ensure that saved message becomes
            // visible in the mail list. 
            // All protocols do not send event automatically in this case.
            RArray<TFSMailMsgId> messageIdArray;
            CleanupClosePushL( messageIdArray );
            messageIdArray.Append( iNewMessage->GetMessageId() );
            TFSMailMsgId folderId = iNewMessage->GetFolderId();
            TFSMailMsgId mailboxId = iNewMessage->GetMailBoxId();
            iAppUi.EventL(
                TFSEventNewMail, mailboxId, &messageIdArray, &folderId, NULL );
            // Update displayed mail info if the mail was created previously
            iAppUi.EventL(
                TFSEventMailChanged, mailboxId, &messageIdArray, 
                &folderId, NULL );
            CleanupStack::PopAndDestroy( &messageIdArray );
            }
        }
	}

// -----------------------------------------------------------------------------
// CNcsComposeView::FetchLogicComplete
// -----------------------------------------------------------------------------
//
TBool CNcsComposeView::FetchLogicComplete( 
        TComposerFetchState /*aState*/, TInt aError )
	{
    FUNC_LOG;
    TBool result = EFalse;
    if ( iFirstStartCompleted ) // Safety
        {
        if ( !aError )
            {
            TRAP( aError, InitReplyOrForwardUiL() );
            iAutoSaver->Enable( ETrue );
            }
        else
            {
            // something went wrong
            DoSafeExit( ENoSave );
            iMailFetchingErrCode = aError;
            result = ETrue;
            }
        }
    if ( iFetchWaitDialog && !iFetchDialogCancelled )
        {
        TRAP_IGNORE( iFetchWaitDialog->ProcessFinishedL() );
        iFetchWaitDialog = NULL;
        }
    return result;
	}

// -----------------------------------------------------------------------------
// CNcsComposeView::ExitComposer
// -----------------------------------------------------------------------------
//
void CNcsComposeView::ExitComposer()
    {
    FUNC_LOG;

    if ( iStatusPaneIndicators )
        {
        iStatusPaneIndicators->HideStatusPaneIndicators();
        }
    
    // lower flag to indicate that view is no longer 
    // able to handle user commands
    iViewReady = EFalse;

	// view switching and alfred operations should be avoided
	// when Appui exit has been initialised
	if ( !iAppUi.AppUiExitOngoing() )
		{
        // change to previous view
        TRAP_IGNORE( NavigateBackL() );
        }

    // Cleanup message contents to prevent ChildDoDeactivate() 
	// from saving the message to drafts again
    ResetComposer();

    SafeDelete( iFetchLogic );
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::CreateContainerL
// -----------------------------------------------------------------------------
//
void CNcsComposeView::CreateContainerL()
    {
    FUNC_LOG;
    TInt flags = NULL;
    if ( iCrHandler->EditorCCVisible() )
        {
        flags |= CNcsComposeViewContainer::ECcFieldVisible;
        }
    if ( iCrHandler->EditorBCVisible() )
        {
        flags |= CNcsComposeViewContainer::EBccFieldVisible;
        }
    TRect rect = ClientRect();
    iContainer = CNcsComposeViewContainer::NewL( *this, rect, *iMailBox,
        *iAutoSaver, flags );
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::ResetComposer
// -----------------------------------------------------------------------------
//
void CNcsComposeView::ResetComposer()
    {
    FUNC_LOG;

    delete iMailBox;
    iMailBox = NULL;
    delete iOrigMessage;
    iOrigMessage = NULL;
    delete iNewMessageTextPart;
    iNewMessageTextPart = NULL;
    delete iNewMessage;
    iNewMessage = NULL;
    iDlg = NULL;

    if ( iContainer )
        {
        AppUi()->RemoveFromStack( iContainer );
        delete iContainer;
        iContainer = NULL;
        }

    }

// -----------------------------------------------------------------------------
// CNcsComposeView::SaveAndCleanPreviousMessage
// -----------------------------------------------------------------------------
//
void CNcsComposeView::SaveAndCleanPreviousMessage()
    {
    FUNC_LOG;

    if ( iFirstStartCompleted && iContainer && iNewMessage && iMailBox )
        {

        TBool noAddrOrNoMesBody = iContainer->AreAddressFieldsEmpty() &&
            iContainer->IsSubjectFieldEmpty() &&
            (iContainer->GetMessageFieldLength() < 1);

        // save to Drafts if there's some user input in some header field 
        // or in message body
        if ( !noAddrOrNoMesBody )
            {
            TRAPD( error, DoSaveDraftL( EFalse ) );
            if ( error )
                {
                }
            }

        // store the message IDs to launch parameters to be able to return 
        // to same message if desired
        iLaunchParams.iMsgId = iNewMessage->GetMessageId();
        iLaunchParams.iFolderId = iNewMessage->GetFolderId();
        iLaunchParams.iMailboxId = iMailBox->GetId();
        }
    ResetComposer();
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::AsyncExit
// -----------------------------------------------------------------------------
//
TInt CNcsComposeView::AsyncExit( TAny* aSelfPtr )
    {
    FUNC_LOG;
    CNcsComposeView* self =
        static_cast<CNcsComposeView*>( aSelfPtr );

    TRAPD( err,self->AsyncExitL() );
    return err;
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::AsyncExitL
// -----------------------------------------------------------------------------
//
void CNcsComposeView::AsyncExitL()
    {
    FUNC_LOG;
    if ( iFakeSyncGoingOn || iExecutingDoExitL )
        {
        // if some sync method is still going on, we continue waiting
        iActiveHelper->Cancel();
        iActiveHelper->Start();
        }
    else
        {
        ExitComposer();
        // for some strange reason composer view is stuck and only option 
        // was to call ProcessCommandL with EAknCmdExit
        ProcessCommandL( EAknCmdExit );
        }
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::HandleContainerChangeRequiringToolbarRefresh
// -----------------------------------------------------------------------------
//
void CNcsComposeView::HandleContainerChangeRequiringToolbarRefresh()
    {
    RefreshToolbar();
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::ShowFetchingWaitNoteL
// -----------------------------------------------------------------------------
//
void CNcsComposeView::ShowFetchingWaitNoteL()
    {
    FUNC_LOG;
    if ( !iAppUi.AppUiExitOngoing() )
        {
        if ( !iFetchWaitDialog )
            {
            iFetchWaitDialog = new (ELeave) CAknWaitDialog(
                reinterpret_cast<CEikDialog**>( &iFetchWaitDialog ), EFalse);
            iFetchWaitDialog->SetCallback( this );
            iFetchDialogCancelled = EFalse;
            iFetchWaitDialog->ExecuteLD( R_FSE_FETCHING_WAIT_DIALOG );
            }
        }
    }

// -----------------------------------------------------------------------------
// CNcsComposeView::DialogDismissedL
// -----------------------------------------------------------------------------
//
void CNcsComposeView::DialogDismissedL( TInt aButtonId )
    {
    FUNC_LOG;
    if ( aButtonId == EAknSoftkeyCancel && iFetchLogic )
        {
        iFetchDialogCancelled = ETrue;
        iFetchLogic->CancelFetchings();
        }
    }

TBool CNcsComposeView::IsPreparedForExit()
    {
    return !( iFakeSyncGoingOn ||iExecutingDoExitL );
    }

// ---------------------------------------------------------------------------
// Returns the speficied button from the toolbar extension, or NULL, 
// if the button is not found.
// ---------------------------------------------------------------------------
//
CAknButton* CNcsComposeView::Button( TInt aCmdId, 
    CAknToolbarExtension* aExtension )
    {
    CAknButton* button = NULL;

    // Get toolbar extension.
    CAknToolbarExtension* extension = aExtension;
    if ( !aExtension )
        {
        CAknToolbar* toolbar = Toolbar();
        if ( toolbar )
            {
            extension = toolbar->ToolbarExtension();
            }
        }

    // Get specified button from the extension.
    if ( extension )
        {
        button = static_cast<CAknButton*>( extension->ControlOrNull( aCmdId ) );
        }

    return button;
    }

// ---------------------------------------------------------------------------
// CActiveHelper::NewL()
// ---------------------------------------------------------------------------
//
CActiveHelper* CActiveHelper::NewL( CNcsComposeView* aSession )
    {
    CActiveHelper* self = new(ELeave) CActiveHelper( aSession );
    CleanupStack::PushL( self );
    self->ConstructL( );
    CleanupStack::Pop( self );
    return self;
    }

// ---------------------------------------------------------------------------
// CActiveHelper::~CActiveHelper()
// ---------------------------------------------------------------------------
//
CActiveHelper::~CActiveHelper( )
    {
    Cancel();
    }

// ---------------------------------------------------------------------------
// CActiveHelper::Start()
// ---------------------------------------------------------------------------
//
void CActiveHelper::Start()
    {
    TRequestStatus* status = &iStatus;
    User::RequestComplete( status, KErrNone );
    SetActive();
    }

// ---------------------------------------------------------------------------
// CActiveHelper::CActiveHelper()
// ---------------------------------------------------------------------------
//
CActiveHelper::CActiveHelper( CNcsComposeView* aSession ) 
    : CActive( EPriorityLow )
    {
    iComposeView = aSession;
    }

// ---------------------------------------------------------------------------
// CActiveHelper::RunL()
// ---------------------------------------------------------------------------
//
void CActiveHelper::RunL()
    {
    if( iComposeView )
        iComposeView->AsyncExitL();
    }

// ---------------------------------------------------------------------------
// CActiveHelper::DoCancel()
// ---------------------------------------------------------------------------
//
void CActiveHelper::DoCancel()
    {
    // Empty
    }

// ---------------------------------------------------------------------------
// CActiveHelper::ConstructL()
// ---------------------------------------------------------------------------
//
void CActiveHelper::ConstructL()
    {
    CActiveScheduler::Add( this );
    }

